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.


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