Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Virtio NIC's guest-driven, vmm-driven, or adaptive modes can now
[palacios.git] / palacios / src / devices / lnx_virtio_nic.c
1
2 /* 
3  * This file is part of the Palacios Virtual Machine Monitor developed
4  * by the V3VEE Project with funding from the United States National 
5  * Science Foundation and the Department of Energy.  
6  *
7  * The V3VEE Project is a joint project between Northwestern University
8  * and the University of New Mexico.  You can find out more at 
9  * http://www.v3vee.org
10  *
11  * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu>
12  * Copyright (c) 2010, Cui Zheng <cuizheng@cs.unm.edu>
13  * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org> 
14  * All rights reserved.
15  *
16  * Author: Lei Xia <lxia@northwestern.edu>
17  *         Cui Zheng <cuizheng@cs.unm.edu>
18  *               
19  *
20  * This is free software.  You are permitted to use,
21  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22  */
23  
24 #include <palacios/vmm.h>
25 #include <palacios/vmm_dev_mgr.h>
26 #include <devices/lnx_virtio_pci.h>
27 #include <palacios/vm_guest_mem.h>
28 #include <palacios/vmm_sprintf.h>
29 #include <vnet/vnet.h>
30 #include <palacios/vmm_lock.h>
31 #include <palacios/vmm_util.h>
32 #include <devices/pci.h>
33 #include <palacios/vmm_ethernet.h>
34 #include <palacios/vmm_time.h>
35
36
37 #ifndef V3_CONFIG_DEBUG_VIRTIO_NET
38 #undef PrintDebug
39 #define PrintDebug(fmt, args...)
40 #endif
41
42 #ifndef V3_CONFIG_VNET
43 static int net_debug = 0;
44 #endif
45
46 #define TX_QUEUE_SIZE 4096
47 #define RX_QUEUE_SIZE 4096
48 #define CTRL_QUEUE_SIZE 64
49
50 /* The feature bitmap for virtio nic
51   * from Linux */
52 #define VIRTIO_NET_F_CSUM       0       /* Host handles pkts w/ partial csum */
53 #define VIRTIO_NET_F_GUEST_CSUM 1       /* Guest handles pkts w/ partial csum */
54 #define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
55 #define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
56 #define VIRTIO_NET_F_GUEST_TSO4 7       /* Guest can handle TSOv4 in. */
57 #define VIRTIO_NET_F_GUEST_TSO6 8       /* Guest can handle TSOv6 in. */
58 #define VIRTIO_NET_F_GUEST_ECN  9       /* Guest can handle TSO[6] w/ ECN in. */
59 #define VIRTIO_NET_F_GUEST_UFO  10      /* Guest can handle UFO in. */
60 #define VIRTIO_NET_F_HOST_TSO4  11      /* Host can handle TSOv4 in. */
61 #define VIRTIO_NET_F_HOST_TSO6  12      /* Host can handle TSOv6 in. */
62 #define VIRTIO_NET_F_HOST_ECN   13      /* Host can handle TSO[6] w/ ECN in. */
63 #define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
64 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
65 #define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
66
67 /* Port to get virtio config */
68 #define VIRTIO_NET_CONFIG 20  
69
70 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
71
72 /* for gso_type in virtio_net_hdr */
73 #define VIRTIO_NET_HDR_GSO_NONE         0      
74 #define VIRTIO_NET_HDR_GSO_TCPV4        1     /* GSO frame, IPv4 TCP (TSO) */
75 #define VIRTIO_NET_HDR_GSO_UDP          3       /* GSO frame, IPv4 UDP (UFO) */
76 #define VIRTIO_NET_HDR_GSO_TCPV6        4       /* GSO frame, IPv6 TCP */
77 #define VIRTIO_NET_HDR_GSO_ECN          0x80    /* TCP has ECN set */   
78
79
80 /* for flags in virtio_net_hdr */
81 #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1       /* Use csum_start, csum_offset */
82
83
84 /* First element of the scatter-gather list, used with GSO or CSUM features */
85 struct virtio_net_hdr
86 {
87     uint8_t flags;
88     uint8_t gso_type;
89     uint16_t hdr_len;           /* Ethernet + IP + tcp/udp hdrs */
90     uint16_t gso_size;          /* Bytes to append to hdr_len per frame */
91     uint16_t csum_start;        /* Position to start checksumming from */
92     uint16_t csum_offset;       /* Offset after that to place checksum */
93 }__attribute__((packed));
94
95
96 /* The header to use when the MRG_RXBUF 
97  * feature has been negotiated. */
98 struct virtio_net_hdr_mrg_rxbuf {
99     struct virtio_net_hdr hdr;
100     uint16_t num_buffers;       /* Number of merged rx buffers */
101 };
102
103 struct virtio_net_config
104 {
105     uint8_t mac[ETH_ALEN];      /* VIRTIO_NET_F_MAC */
106     uint16_t status;
107 } __attribute__((packed));
108
109 struct virtio_dev_state {
110
111     struct vm_device * pci_bus;
112     struct list_head dev_list;
113     struct v3_vm_info *vm;
114
115     enum {GUEST_DRIVEN=0, VMM_DRIVEN, ADAPTIVE} model;
116     uint64_t  lower_thresh_pps, upper_thresh_pps, period_us;
117
118     uint8_t mac[ETH_ALEN];
119 };
120
121 struct virtio_net_state {
122
123     struct virtio_net_config net_cfg;
124     struct virtio_config virtio_cfg;
125
126     struct v3_vm_info * vm;
127     struct vm_device * dev;
128     struct pci_device * pci_dev; 
129     int io_range_size;
130
131     uint16_t status;
132     
133     struct virtio_queue rx_vq;          /* idx 0*/
134     struct virtio_queue tx_vq;          /* idx 1*/
135     struct virtio_queue ctrl_vq;        /* idx 2*/
136
137     uint8_t mergeable_rx_bufs;
138
139     struct v3_timer * timer;
140     struct nic_statistics stats;
141
142     struct v3_dev_net_ops * net_ops;
143     v3_lock_t rx_lock, tx_lock;
144
145     uint8_t tx_notify, rx_notify;
146     uint32_t tx_pkts, rx_pkts;
147     uint64_t past_us;
148
149     void * backend_data;
150     struct virtio_dev_state * virtio_dev;
151     struct list_head dev_link;
152 };
153
154
155 static int virtio_init_state(struct virtio_net_state * virtio) 
156 {
157     virtio->rx_vq.queue_size = RX_QUEUE_SIZE;
158     virtio->tx_vq.queue_size = TX_QUEUE_SIZE;
159     virtio->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
160
161     virtio->rx_vq.ring_desc_addr = 0;
162     virtio->rx_vq.ring_avail_addr = 0;
163     virtio->rx_vq.ring_used_addr = 0;
164     virtio->rx_vq.pfn = 0;
165     virtio->rx_vq.cur_avail_idx = 0;
166
167     virtio->tx_vq.ring_desc_addr = 0;
168     virtio->tx_vq.ring_avail_addr = 0;
169     virtio->tx_vq.ring_used_addr = 0;
170     virtio->tx_vq.pfn = 0;
171     virtio->tx_vq.cur_avail_idx = 0;
172
173     virtio->ctrl_vq.ring_desc_addr = 0;
174     virtio->ctrl_vq.ring_avail_addr = 0;
175     virtio->ctrl_vq.ring_used_addr = 0;
176     virtio->ctrl_vq.pfn = 0;
177     virtio->ctrl_vq.cur_avail_idx = 0;
178
179     virtio->virtio_cfg.pci_isr = 0;
180
181     virtio->mergeable_rx_bufs = 1;
182         
183     virtio->virtio_cfg.host_features = 0 | (1 << VIRTIO_NET_F_MAC);
184     if(virtio->mergeable_rx_bufs) {
185         virtio->virtio_cfg.host_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
186     }
187
188     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
189         (v3_lock_init(&(virtio->tx_lock)) == -1)){
190         PrintError("Virtio NIC: Failure to init locks for net_state\n");
191     }
192
193     return 0;
194 }
195
196 static int virtio_deinit_state(struct guest_info *core, struct virtio_net_state *ns) 
197 {
198     if (ns->timer) { 
199         v3_remove_timer(core,ns->timer);
200     }
201     return 0;
202 }
203
204 static int tx_one_pkt(struct guest_info * core, 
205                       struct virtio_net_state * virtio, 
206                       struct vring_desc * buf_desc) 
207 {
208     uint8_t * buf = NULL;
209     uint32_t len = buf_desc->length;
210
211     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
212         PrintDebug("Could not translate buffer address\n");
213         return -1;
214     }
215     
216     V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len);
217     if(net_debug >= 4){
218         v3_hexdump(buf, len, NULL, 0);
219     }
220
221     if(virtio->net_ops->send(buf, len, virtio->backend_data) < 0){
222         virtio->stats.tx_dropped ++;
223         return -1;
224     }
225     
226     virtio->stats.tx_pkts ++;
227     virtio->stats.tx_bytes += len;
228     
229     return 0;
230 }
231
232
233 /*copy data into ring buffer */
234 static inline int copy_data_to_desc(struct guest_info * core, 
235                                     struct virtio_net_state * virtio_state, 
236                                     struct vring_desc * desc, 
237                                     uchar_t * buf, 
238                                     uint_t buf_len,
239                                     uint_t dst_offset){
240     uint32_t len;
241     uint8_t * desc_buf = NULL;
242     
243     if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
244         PrintDebug("Could not translate buffer address\n");
245         return -1;
246     }
247     len = (desc->length < (buf_len+dst_offset))?(desc->length - dst_offset):buf_len;
248     memcpy(desc_buf + dst_offset, buf, len);
249
250     return len;
251 }
252
253
254 static inline int get_desc_count(struct virtio_queue * q, int index) {
255     struct vring_desc * tmp_desc = &(q->desc[index]);
256     int cnt = 1;
257     
258     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
259         tmp_desc = &(q->desc[tmp_desc->next]);
260         cnt++;
261     }
262
263     return cnt;
264 }
265
266 static inline void enable_cb(struct virtio_queue *queue){
267     if(queue->used){
268         queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
269     }
270 }
271
272 static inline void disable_cb(struct virtio_queue *queue) {
273     if(queue->used){
274         queue->used->flags |= VRING_NO_NOTIFY_FLAG;
275     }
276 }
277
278 static int handle_pkt_tx(struct guest_info * core, 
279                          struct virtio_net_state * virtio_state,
280                          int quote)
281 {
282     struct virtio_queue * q;
283     int txed = 0, left = 0;
284     unsigned long flags;
285
286     q = &(virtio_state->tx_vq);
287     if (!q->ring_avail_addr) {
288         return -1;
289     }
290
291     while (1) {
292         struct vring_desc * hdr_desc = NULL;
293         addr_t hdr_addr = 0;
294         uint16_t desc_idx, tmp_idx;
295         int desc_cnt;
296         
297         flags = v3_lock_irqsave(virtio_state->tx_lock);
298
299         if(q->cur_avail_idx == q->avail->index ||
300             (quote > 0 && txed >= quote)) {
301             left = (q->cur_avail_idx != q->avail->index);
302             v3_unlock_irqrestore(virtio_state->tx_lock, flags);
303             break;
304         }
305         
306         desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
307         tmp_idx = q->cur_avail_idx ++;
308         
309         v3_unlock_irqrestore(virtio_state->tx_lock, flags);
310
311         desc_cnt = get_desc_count(q, desc_idx);
312         if(desc_cnt != 2){
313             PrintError("VNIC: merged rx buffer not supported, desc_cnt %d\n", desc_cnt);
314         }
315
316         hdr_desc = &(q->desc[desc_idx]);
317         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) != -1) {
318             struct virtio_net_hdr_mrg_rxbuf * hdr;
319             struct vring_desc * buf_desc;
320
321             hdr = (struct virtio_net_hdr_mrg_rxbuf *)hdr_addr;
322             desc_idx = hdr_desc->next;
323
324             /* here we assumed that one ethernet pkt is not splitted into multiple buffer */    
325             buf_desc = &(q->desc[desc_idx]);
326             if (tx_one_pkt(core, virtio_state, buf_desc) == -1) {
327                 PrintError("Virtio NIC: Fails to send packet\n");
328             }
329         } else {
330             PrintError("Could not translate block header address\n");
331         }
332
333         flags = v3_lock_irqsave(virtio_state->tx_lock);
334         
335         q->used->ring[q->used->index % q->queue_size].id = 
336             q->avail->ring[tmp_idx % q->queue_size];
337         
338         q->used->index ++;
339         
340         v3_unlock_irqrestore(virtio_state->tx_lock, flags);
341
342         txed ++;
343     }
344         
345     if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
346         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 
347                          virtio_state->pci_dev, 0);
348         virtio_state->virtio_cfg.pci_isr = 0x1;
349         virtio_state->stats.rx_interrupts ++;
350     }
351
352     return left;
353 }
354
355
356 static int virtio_setup_queue(struct guest_info *core, 
357                               struct virtio_net_state * virtio_state, 
358                               struct virtio_queue * queue, 
359                               addr_t pfn, addr_t page_addr) {
360     queue->pfn = pfn;
361                 
362     queue->ring_desc_addr = page_addr;
363     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
364     queue->ring_used_addr = ((queue->ring_avail_addr) + 
365                              (sizeof(struct vring_avail)) + 
366                              (queue->queue_size * sizeof(uint16_t)));
367
368     // round up to next page boundary.
369     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
370     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
371         PrintError("Could not translate ring descriptor address\n");
372          return -1;
373     }
374  
375     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
376         PrintError("Could not translate ring available address\n");
377         return -1;
378     }
379
380     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
381         PrintError("Could not translate ring used address\n");
382         return -1;
383     }
384
385     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
386                (void *)(queue->ring_desc_addr),
387                (void *)(queue->ring_avail_addr),
388                (void *)(queue->ring_used_addr));
389     
390     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
391                queue->desc, queue->avail, queue->used);
392     
393     return 0;
394 }
395
396 static int virtio_io_write(struct guest_info *core, 
397                            uint16_t port, void * src, 
398                            uint_t length, void * private_data) 
399 {
400     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
401     int port_idx = port % virtio->io_range_size;
402
403     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n",
404                private_data, port, port_idx,  
405                length, *(uint32_t *)src);
406
407     switch (port_idx) {
408         case GUEST_FEATURES_PORT:
409             if (length != 4) {
410                 PrintError("Illegal write length for guest features\n");
411                 return -1;
412             }       
413             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
414             break;
415                 
416         case VRING_PG_NUM_PORT:
417             if (length != 4) {
418                 PrintError("Illegal write length for page frame number\n");
419                 return -1;
420             }
421             addr_t pfn = *(uint32_t *)src;
422             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
423             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
424             switch (queue_idx) {
425                 case 0:
426                     virtio_setup_queue(core, virtio,
427                                        &virtio->rx_vq, 
428                                        pfn, page_addr);
429                     break;
430                 case 1:
431                     virtio_setup_queue(core, virtio, 
432                                        &virtio->tx_vq, 
433                                        pfn, page_addr);
434                     if(virtio->tx_notify == 0){
435                         disable_cb(&virtio->tx_vq);
436                     }
437                     virtio->status = 1;
438                     break;
439                 case 2:
440                     virtio_setup_queue(core, virtio, 
441                                        &virtio->ctrl_vq, 
442                                        pfn, page_addr);
443                     break;          
444                 default:
445                     break;
446             }
447             break;
448                 
449         case VRING_Q_SEL_PORT:
450             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
451             if (virtio->virtio_cfg.vring_queue_selector > 2) {
452                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
453                            virtio->virtio_cfg.vring_queue_selector);
454                 return -1;
455             }
456             break;
457                 
458         case VRING_Q_NOTIFY_PORT: 
459             {
460                 uint16_t queue_idx = *(uint16_t *)src;                  
461                 if (queue_idx == 0){
462                     /* receive queue refill */
463                     virtio->stats.tx_interrupts ++;
464                 } else if (queue_idx == 1){
465                     if (handle_pkt_tx(core, virtio, 0) < 0) {
466                         PrintError("Virtio NIC: Error to handle packet TX\n");
467                         return -1;
468                     }
469                     virtio->stats.tx_interrupts ++;
470                 } else if (queue_idx == 2){
471                     /* ctrl */
472                 } else {
473                     PrintError("Virtio NIC: Wrong queue index %d\n", queue_idx);
474                 }       
475                 break;          
476             }
477         
478         case VIRTIO_STATUS_PORT:
479             virtio->virtio_cfg.status = *(uint8_t *)src;
480             if (virtio->virtio_cfg.status == 0) {
481                 virtio_init_state(virtio);
482             }
483             break;
484
485         case VIRTIO_ISR_PORT:
486             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
487             break;
488                 
489         default:
490             return -1;
491             break;
492     }
493
494     return length;
495 }
496
497 static int virtio_io_read(struct guest_info *core, 
498                           uint16_t port, void * dst, 
499                           uint_t length, void * private_data) 
500 {
501     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
502     int port_idx = port % virtio->io_range_size;
503     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
504
505     PrintDebug("Virtio NIC %p: Read  for port 0x%x (index =%d), length=%d\n", 
506                private_data, port, port_idx, length);
507         
508     switch (port_idx) {
509         case HOST_FEATURES_PORT:
510             if (length != 4) {
511                 PrintError("Virtio NIC: Illegal read length for host features\n");
512                 //return -1;
513             }
514             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
515             break;
516
517         case VRING_PG_NUM_PORT:
518             if (length != 4) {
519                 PrintError("Virtio NIC: Illegal read length for page frame number\n");
520                 return -1;
521             }
522             switch (queue_idx) {
523                 case 0:
524                     *(uint32_t *)dst = virtio->rx_vq.pfn;
525                     break;
526                 case 1:
527                     *(uint32_t *)dst = virtio->tx_vq.pfn;
528                     break;      
529                 case 2:
530                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
531                     break;
532                 default:
533                     break;
534             }
535             break;
536
537         case VRING_SIZE_PORT:
538             if (length != 2) {
539                 PrintError("Virtio NIC: Illegal read length for vring size\n");
540                 return -1;
541             }
542             switch (queue_idx) {
543                 case 0:
544                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
545                     break;
546                 case 1:
547                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
548                     break;      
549                 case 2:
550                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
551                     break;
552                 default:
553                     break;
554             }
555             break;
556
557         case VIRTIO_STATUS_PORT:
558             if (length != 1) {
559                 PrintError("Virtio NIC: Illegal read length for status\n");
560                 return -1;
561             }
562             *(uint8_t *)dst = virtio->virtio_cfg.status;
563             break;
564                 
565         case VIRTIO_ISR_PORT:
566             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
567             virtio->virtio_cfg.pci_isr = 0;
568             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 
569                              virtio->pci_dev, 0);
570             break;
571
572         case VIRTIO_NET_CONFIG ... VIRTIO_NET_CONFIG + ETH_ALEN:
573             *(uint8_t *)dst = virtio->net_cfg.mac[port_idx-VIRTIO_NET_CONFIG];
574             break;
575
576         default:
577             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", 
578                        port_idx);
579             return -1;
580     }
581
582     return length;
583 }
584
585
586 /* receiving raw ethernet pkt from backend */
587 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
588     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
589     struct virtio_queue * q = &(virtio->rx_vq);
590     struct virtio_net_hdr_mrg_rxbuf hdr;
591     unsigned long flags;
592     uint8_t kick_guest = 0;
593
594     V3_Net_Print(2, "Virtio NIC: virtio_rx: size: %d\n", size);
595
596     if (!q->ring_avail_addr) {
597         V3_Net_Print(2, "Virtio NIC: RX Queue not set\n");
598         virtio->stats.rx_dropped ++;
599         
600         return -1;
601     }
602
603     memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
604
605     flags = v3_lock_irqsave(virtio->rx_lock);
606
607     if (q->cur_avail_idx != q->avail->index){
608         uint16_t buf_idx;
609         struct vring_desc * buf_desc;
610         uint32_t hdr_len, len;
611         uint32_t offset = 0;
612
613         hdr_len = (virtio->mergeable_rx_bufs)?
614             sizeof(struct virtio_net_hdr_mrg_rxbuf):
615             sizeof(struct virtio_net_hdr);
616
617         if(virtio->mergeable_rx_bufs){/* merged buffer */
618             struct vring_desc * hdr_desc;
619             uint16_t old_idx = q->cur_avail_idx;
620
621             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
622             hdr_desc = &(q->desc[buf_idx]);
623
624             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
625                                     virtio, hdr_desc, buf, size, hdr_len);
626             if(len < 0){
627                 goto err_exit;
628             }
629             offset += len;
630
631             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
632             q->used->ring[q->used->index % q->queue_size].length = hdr_len + offset;
633             q->cur_avail_idx ++;
634             hdr.num_buffers ++;
635
636             while(offset < size) {
637                 buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
638                 buf_desc = &(q->desc[buf_idx]);
639
640                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
641                                         virtio, buf_desc, buf+offset, size-offset, 0);  
642                 if (len < 0){
643                     V3_Net_Print(2, "Virtio NIC: merged buffer, %d buffer size %d\n", 
644                                  hdr.num_buffers, len);
645                     q->cur_avail_idx = old_idx;
646                     goto err_exit;
647                 }
648                 offset += len;
649                 buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
650
651                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
652                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].length = len;
653                 q->cur_avail_idx ++;   
654
655                 hdr.num_buffers ++;
656             }
657
658             copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
659                               virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
660             q->used->index += hdr.num_buffers;
661         }else{
662             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
663             buf_desc = &(q->desc[buf_idx]);
664
665             /* copy header */
666             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
667                                     virtio, buf_desc, (uchar_t *)&(hdr.hdr), hdr_len, 0);
668             if(len < hdr_len){
669                 V3_Net_Print(2, "Virtio NIC: rx copy header error %d, hdr_len %d\n", 
670                              len, hdr_len);
671                 goto err_exit;
672             }
673
674             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
675                                     virtio, buf_desc, buf, size, hdr_len);
676             if(len < 0){
677                 V3_Net_Print(2, "Virtio NIC: rx copy data error %d\n", len);
678                 goto err_exit;
679             }
680             offset += len;
681
682             /* copy rest of data */
683             while(offset < size && 
684                   (buf_desc->flags & VIRTIO_NEXT_FLAG)){
685                 buf_desc = &(q->desc[buf_desc->next]);
686                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
687                                         virtio, buf_desc, buf+offset, size-offset, 0);      
688                 if (len < 0) {
689                     break;
690                 }
691                 offset += len;
692             }
693             buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
694
695             if(offset < size){
696                 V3_Net_Print(2, "Virtio NIC: rx not enough ring buffer, buffer size %d\n", 
697                              len);
698                 goto err_exit;
699             }
700                 
701             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
702             q->used->ring[q->used->index % q->queue_size].length = size + hdr_len; /* This should be the total length of data sent to guest (header+pkt_data) */
703             q->used->index ++;
704             q->cur_avail_idx ++;
705         } 
706
707         virtio->stats.rx_pkts ++;
708         virtio->stats.rx_bytes += size;
709     } else {
710         V3_Net_Print(2, "Virtio NIC: Guest RX queue is full\n");
711         virtio->stats.rx_dropped ++;
712
713         /* kick guest to refill RX queue */
714         kick_guest = 1;
715     }
716
717     v3_unlock_irqrestore(virtio->rx_lock, flags);
718
719     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG) || kick_guest) {
720         V3_Net_Print(2, "Virtio NIC: RX Raising IRQ %d\n",  
721                      virtio->pci_dev->config_header.intr_line);
722
723         virtio->virtio_cfg.pci_isr = 0x1;       
724         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, virtio->pci_dev, 0);
725         virtio->stats.rx_interrupts ++;
726     }
727
728     /* notify guest if it is in guest mode */
729     if((kick_guest || virtio->rx_notify == 1) && 
730         V3_Get_CPU() != virtio->virtio_dev->vm->cores[0].pcpu_id){
731         v3_interrupt_cpu(virtio->virtio_dev->vm, 
732                          virtio->virtio_dev->vm->cores[0].pcpu_id, 
733                          0);
734     }
735
736     return 0;
737
738 err_exit:
739     virtio->stats.rx_dropped ++;
740     v3_unlock_irqrestore(virtio->rx_lock, flags);
741  
742     return -1;
743 }
744
745 static int virtio_free(struct virtio_dev_state * virtio) {
746     struct virtio_net_state * backend = NULL;
747     struct virtio_net_state * tmp = NULL;
748
749
750     list_for_each_entry_safe(backend, tmp, &(virtio->dev_list), dev_link) {
751         virtio_deinit_state(&(virtio->vm->cores[0]),backend);
752         list_del(&(backend->dev_link));
753         V3_Free(backend);
754     }
755
756     V3_Free(virtio);
757
758     return 0;
759 }
760
761
762 static struct v3_device_ops dev_ops = {
763     .free = (int (*)(void *))virtio_free,
764 };
765
766
767 static int virtio_poll(int quote, void * data){
768     struct virtio_net_state * virtio  = (struct virtio_net_state *)data;
769
770     if (virtio->status) {
771
772         return handle_pkt_tx(&(virtio->vm->cores[0]), virtio, quote);
773     } 
774
775     return 0;
776 }
777
778 static int register_dev(struct virtio_dev_state * virtio, 
779                         struct virtio_net_state * net_state) 
780 {
781     struct pci_device * pci_dev = NULL;
782     struct v3_pci_bar bars[6];
783     int num_ports = sizeof(struct virtio_config);
784     int tmp_ports = num_ports;
785     int i;
786
787     /* This gets the number of ports, rounded up to a power of 2 */
788     net_state->io_range_size = 1;
789     while (tmp_ports > 0) {
790         tmp_ports >>= 1;
791         net_state->io_range_size <<= 1;
792     }
793         
794     /* this is to account for any low order bits being set in num_ports
795      * if there are none, then num_ports was already a power of 2 so we shift right to reset it
796      */
797     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
798         net_state->io_range_size >>= 1;
799     }
800     
801     for (i = 0; i < 6; i++) {
802         bars[i].type = PCI_BAR_NONE;
803     }
804     
805     PrintDebug("Virtio NIC: io_range_size = %d\n", 
806                net_state->io_range_size);
807     
808     bars[0].type = PCI_BAR_IO;
809     bars[0].default_base_port = -1;
810     bars[0].num_ports = net_state->io_range_size;
811     bars[0].io_read = virtio_io_read;
812     bars[0].io_write = virtio_io_write;
813     bars[0].private_data = net_state;
814     
815     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
816                                      0, PCI_AUTO_DEV_NUM, 0,
817                                      "LNX_VIRTIO_NIC", bars,
818                                      NULL, NULL, NULL, NULL, net_state);
819     
820     if (!pci_dev) {
821         PrintError("Virtio NIC: Could not register PCI Device\n");
822         return -1;
823     }
824
825     PrintDebug("Virtio NIC:  registered to PCI bus\n");
826     
827     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
828     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
829         
830
831     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
832     pci_dev->config_header.class = PCI_CLASS_NETWORK;
833     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
834     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
835     pci_dev->config_header.intr_pin = 1;
836     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
837
838     net_state->pci_dev = pci_dev;
839     net_state->virtio_dev = virtio;
840
841     memcpy(net_state->net_cfg.mac, virtio->mac, 6);                           
842         
843     virtio_init_state(net_state);
844
845     V3_Print("Virtio NIC: Registered Intr Line %d\n", pci_dev->config_header.intr_line);
846
847     /* Add backend to list of devices */
848     list_add(&(net_state->dev_link), &(virtio->dev_list));
849
850     return 0;
851 }
852
853 #define RATE_UPPER_THRESHOLD_DEFAULT 10000  /* 10000 pkts per second, around 100Mbits */
854 #define RATE_LOWER_THRESHOLD_DEFAULT 1000   /* 1000 pkts per second, around 10Mbits */
855 #define PROFILE_PERIOD_DEFAULT       10000  /* us */
856
857 static void virtio_nic_timer(struct guest_info * core, 
858                              uint64_t cpu_cycles, uint64_t cpu_freq, 
859                              void * priv_data) {
860     struct virtio_net_state * net_state = (struct virtio_net_state *)priv_data;
861     uint64_t period_us;
862     static int profile_ms = 0;
863     uint64_t target_period_us = net_state->virtio_dev->period_us;
864     uint64_t upper_thresh_pps = net_state->virtio_dev->upper_thresh_pps;
865     uint64_t lower_thresh_pps = net_state->virtio_dev->lower_thresh_pps;
866     
867
868     if(!net_state->status){ /* VNIC is not in working status */
869         return;
870     }
871
872     period_us = (1000*cpu_cycles)/cpu_freq;
873     net_state->past_us += period_us;
874
875     if (net_state->past_us > target_period_us) { 
876
877         uint64_t tx_count, rx_count;
878         uint64_t lb_tx_count, lb_rx_count;
879         uint64_t ub_tx_count, ub_rx_count;
880
881         lb_tx_count = lb_rx_count = (lower_thresh_pps * 1000000) / net_state->past_us;  // packets expected in this interval
882         ub_tx_count = ub_rx_count = (upper_thresh_pps * 1000000) / net_state->past_us;  
883
884         tx_count = net_state->stats.tx_pkts - net_state->tx_pkts;
885         rx_count = net_state->stats.rx_pkts - net_state->rx_pkts;
886
887         net_state->tx_pkts = net_state->stats.tx_pkts;
888         net_state->rx_pkts = net_state->stats.rx_pkts;
889
890         if(tx_count > ub_tx_count && net_state->tx_notify == 1) {
891             PrintDebug("Virtio NIC: Switch TX to VMM driven mode\n");
892             disable_cb(&(net_state->tx_vq));
893             net_state->tx_notify = 0;
894         }
895
896         if(tx_count < lb_tx_count && net_state->tx_notify == 0) {
897             PrintDebug("Virtio NIC: Switch TX to Guest  driven mode\n");
898             enable_cb(&(net_state->tx_vq));
899             net_state->tx_notify = 1;
900         }
901
902         if(rx_count > ub_rx_count && net_state->rx_notify == 1) {
903             PrintDebug("Virtio NIC: Switch RX to VMM None notify mode\n");
904             net_state->rx_notify = 0;
905         }
906
907         if(rx_count < lb_rx_count && net_state->rx_notify == 0) {
908             V3_Print("Virtio NIC: Switch RX to VMM notify mode\n");
909             net_state->rx_notify = 1;
910         }
911
912         net_state->past_us = 0;
913     }
914
915     profile_ms += period_us/1000;
916     if(profile_ms > 20000){
917         PrintDebug("Virtio NIC: TX: Pkt: %lld, Bytes: %lld\n\t\tRX Pkt: %lld. Bytes: %lld\n\t\tDropped: tx %lld, rx %lld\nInterrupts: tx %d, rx %d\nTotal Exit: %lld\n",
918                 net_state->stats.tx_pkts, net_state->stats.tx_bytes,
919                 net_state->stats.rx_pkts, net_state->stats.rx_bytes,
920                 net_state->stats.tx_dropped, net_state->stats.rx_dropped,
921                 net_state->stats.tx_interrupts, net_state->stats.rx_interrupts,
922                 net_state->vm->cores[0].num_exits);
923         profile_ms = 0;
924     }
925 }
926
927 static struct v3_timer_ops timer_ops = {
928     .update_timer = virtio_nic_timer,
929 };
930
931 static int connect_fn(struct v3_vm_info * info, 
932                       void * frontend_data, 
933                       struct v3_dev_net_ops * ops, 
934                       v3_cfg_tree_t * cfg, 
935                       void * private_data) {
936     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
937     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
938
939     if (!net_state) {
940         PrintError("Cannot allocate in connect\n");
941         return -1;
942     }
943
944     memset(net_state, 0, sizeof(struct virtio_net_state));
945     register_dev(virtio, net_state);
946
947     net_state->vm = info;
948     net_state->net_ops = ops;
949     net_state->backend_data = private_data;
950     net_state->virtio_dev = virtio;
951     
952     switch (virtio->model) { 
953         case GUEST_DRIVEN:
954             V3_Print("Virtio NIC: Guest-driven operation\n");
955             net_state->tx_notify = 1;
956             net_state->rx_notify = 1;
957             break;
958         case VMM_DRIVEN:
959             V3_Print("Virtio NIC: VMM-driven operation\n");
960             net_state->tx_notify = 0;
961             net_state->rx_notify = 0;
962             break;
963         case ADAPTIVE: {
964             V3_Print("Virtio NIC: Adaptive operation (begins in guest-driven mode)\n");
965             net_state->tx_notify = 1;
966             net_state->rx_notify = 1;
967
968             net_state->timer = v3_add_timer(&(info->cores[0]), &timer_ops,net_state);
969
970         }
971             break;
972
973         default:
974             V3_Print("Virtio NIC: Unknown model, using GUEST_DRIVEN\n");
975             net_state->tx_notify = 1;
976             net_state->rx_notify = 1;
977             break;
978     }
979
980
981     ops->recv = virtio_rx;
982     ops->poll = virtio_poll;
983     ops->config.frontend_data = net_state;
984     ops->config.poll = 1;
985     ops->config.quote = 64;
986     ops->config.fnt_mac = V3_Malloc(ETH_ALEN);  
987
988     if (!ops->config.fnt_mac) { 
989         PrintError("Cannot allocate in connect\n");
990         // should unregister here
991         return -1;
992     }
993
994     memcpy(ops->config.fnt_mac, virtio->mac, ETH_ALEN);
995
996     return 0;
997 }
998
999 static int setup_perf_model(struct virtio_dev_state *virtio_state, v3_cfg_tree_t *t)
1000 {
1001     char *mode = v3_cfg_val(t,"mode");
1002
1003     // defaults
1004     virtio_state->model = GUEST_DRIVEN;
1005     virtio_state->lower_thresh_pps = RATE_LOWER_THRESHOLD_DEFAULT;
1006     virtio_state->upper_thresh_pps = RATE_UPPER_THRESHOLD_DEFAULT;
1007     virtio_state->period_us = PROFILE_PERIOD_DEFAULT;
1008     
1009     
1010     // overrides
1011     if (mode) { 
1012         if (!strcasecmp(mode,"guest-driven")) { 
1013             V3_Print("Virtio NIC: Setting static GUEST_DRIVEN mode of operation (latency optimized)\n");
1014             virtio_state->model=GUEST_DRIVEN;
1015         } else if (!strcasecmp(mode, "vmm-driven")) { 
1016             V3_Print("Virtio NIC: Setting static VMM_DRIVEN mode of operation (throughput optimized)\n");
1017             virtio_state->model=VMM_DRIVEN;
1018         } else if (!strcasecmp(mode, "adaptive")) { 
1019             char *s;
1020
1021             V3_Print("Virtio NIC: Setting dynamic ADAPTIVE mode of operation\n");
1022             virtio_state->model=ADAPTIVE;
1023             
1024             if (!(s=v3_cfg_val(t,"upper"))) { 
1025                 V3_Print("Virtio NIC: No upper bound given, using default\n");
1026             } else {
1027                 virtio_state->upper_thresh_pps = atoi(s);
1028             }
1029             if (!(s=v3_cfg_val(t,"lower"))) { 
1030                 V3_Print("Virtio NIC: No lower bound given, using default\n");
1031             } else {
1032                 virtio_state->lower_thresh_pps = atoi(s);
1033             }
1034             if (!(s=v3_cfg_val(t,"period"))) { 
1035                 V3_Print("Virtio NIC: No period given, using default\n");
1036             } else {
1037                 virtio_state->period_us = atoi(s);
1038             }
1039
1040             V3_Print("Virtio NIC: lower_thresh_pps=%llu, upper_thresh_pps=%llu, period_us=%llu\n",
1041                      virtio_state->lower_thresh_pps,
1042                      virtio_state->upper_thresh_pps,
1043                      virtio_state->period_us);
1044         } else {
1045             PrintError("Virtio NIC: Unknown mode of operation '%s', using default (guest-driven)\n",mode);
1046             virtio_state->model=GUEST_DRIVEN;
1047         }
1048     } else {
1049         V3_Print("Virtio NIC: No model given, using default (guest-driven)\n");
1050     }
1051
1052     return 0;
1053
1054 }
1055
1056 /*
1057   <device class="LNX_VIRTIO_NIC" id="nic">
1058      <bus>pci-bus-to-attach-to</bus>  // required
1059      <mac>mac address</mac>  // if ommited with pic one
1060      <model mode="guest-driven|vmm-driven|adaptive" upper="pkts_per_sec" lower="pkts" period="us" />
1061   </device>
1062 */
1063 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1064     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
1065     struct virtio_dev_state * virtio_state = NULL;
1066     char * dev_id = v3_cfg_val(cfg, "ID");
1067     char * mac = v3_cfg_val(cfg, "mac");
1068     v3_cfg_tree_t *model = v3_cfg_subtree(cfg,"model");
1069     
1070     if (pci_bus == NULL) {
1071         PrintError("Virtio NIC: Virtio device require a PCI Bus");
1072         return -1;
1073     }
1074
1075     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
1076
1077     if (!virtio_state) {
1078         PrintError("Cannot allocate in init\n");
1079         return -1;
1080     }
1081
1082     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
1083
1084     INIT_LIST_HEAD(&(virtio_state->dev_list));
1085     virtio_state->pci_bus = pci_bus;
1086     virtio_state->vm = vm;
1087
1088     if (mac) { 
1089         if (!str2mac(mac, virtio_state->mac)) { 
1090             PrintDebug("Virtio NIC: Mac specified %s\n", mac);
1091         } else {
1092             PrintError("Virtio NIC: Mac specified is incorrect, picking a randoom mac\n");
1093             random_ethaddr(virtio_state->mac);
1094         }
1095     } else {
1096         PrintDebug("Virtio NIC: no mac specified, so picking a random mac\n");
1097         random_ethaddr(virtio_state->mac);
1098     }
1099
1100     if (setup_perf_model(virtio_state,model)<0) { 
1101         PrintError("Cannnot setup performance model\n");
1102         V3_Free(virtio_state);
1103         return -1;
1104     }
1105             
1106     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
1107
1108     if (dev == NULL) {
1109         PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
1110         V3_Free(virtio_state);
1111         return -1;
1112     }
1113
1114     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
1115         PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
1116         v3_remove_device(dev);
1117         return -1;
1118     }
1119         
1120     return 0;
1121 }
1122
1123 device_register("LNX_VIRTIO_NIC", virtio_init)
1124