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.


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