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.


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