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.


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