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.


VNET code clean and rearrangement
[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 static int virtio_free(struct vm_device * dev) 
119 {
120         
121     return 0;
122 }
123
124 static int virtio_init_state(struct virtio_net_state * virtio) 
125 {
126     virtio->rx_vq.queue_size = RX_QUEUE_SIZE;
127     virtio->tx_vq.queue_size = TX_QUEUE_SIZE;
128     virtio->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
129
130     virtio->rx_vq.ring_desc_addr = 0;
131     virtio->rx_vq.ring_avail_addr = 0;
132     virtio->rx_vq.ring_used_addr = 0;
133     virtio->rx_vq.pfn = 0;
134     virtio->rx_vq.cur_avail_idx = 0;
135
136     virtio->tx_vq.ring_desc_addr = 0;
137     virtio->tx_vq.ring_avail_addr = 0;
138     virtio->tx_vq.ring_used_addr = 0;
139     virtio->tx_vq.pfn = 0;
140     virtio->tx_vq.cur_avail_idx = 0;
141
142     virtio->ctrl_vq.ring_desc_addr = 0;
143     virtio->ctrl_vq.ring_avail_addr = 0;
144     virtio->ctrl_vq.ring_used_addr = 0;
145     virtio->ctrl_vq.pfn = 0;
146     virtio->ctrl_vq.cur_avail_idx = 0;
147
148     virtio->virtio_cfg.pci_isr = 0;
149         
150     virtio->virtio_cfg.host_features = 0; // (1 << VIRTIO_NET_F_MAC);
151
152     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
153           (v3_lock_init(&(virtio->tx_lock)) == -1)){
154         PrintError("Virtio NIC: Failure to init locks for net_state\n");
155     }
156
157     virtio->pkt_sent = virtio->pkt_recv = virtio->pkt_drop = 0;
158     virtio->buffed_rx = 0;
159
160     return 0;
161 }
162
163 static int pkt_tx(struct guest_info * core, struct virtio_net_state * virtio, struct vring_desc * buf_desc) 
164 {
165     uint8_t * buf = NULL;
166     uint32_t len = buf_desc->length;
167
168     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
169         PrintError("Could not translate buffer address\n");
170         return -ERR_VIRTIO_OTHER;
171     }
172
173     return virtio->net_ops->send(buf, len, virtio->backend_data, NULL);
174 }
175
176
177 static int 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, struct virtio_net_state * virtio) 
229 {
230     unsigned long flags;
231
232     flags = v3_lock_irqsave(virtio->rx_lock);
233
234     virtio->net_ops->start_rx(virtio->backend_data);
235     disable_cb(&virtio->rx_vq);
236
237     v3_unlock_irqrestore(virtio->rx_lock, flags);
238         
239     return 0;
240 }
241
242
243 static int handle_ctrl(struct guest_info *core, struct virtio_net_state * virtio) {
244         
245     return 0;
246 }
247
248 static int handle_pkt_tx(struct guest_info *core, struct virtio_net_state * virtio_state) 
249 {
250     struct virtio_queue * q = &(virtio_state->tx_vq);
251     struct virtio_net_hdr * hdr = NULL;
252     int recved = 0;
253     unsigned long flags;
254
255     if (!q->ring_avail_addr) 
256         return -ERR_VIRTIO_TXQ_NOSET;
257
258     if(virtio_state->tx_disabled)
259         return -ERR_VIRTIO_TXQ_DISABLED;
260
261     flags = v3_lock_irqsave(virtio_state->tx_lock);
262     while (q->cur_avail_idx != q->avail->index) {
263         struct vring_desc * hdr_desc = NULL;
264         addr_t hdr_addr = 0;
265         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
266         int desc_cnt = get_desc_count(q, desc_idx);
267         uint32_t req_len = 0;
268         int i = 0;
269
270         hdr_desc = &(q->desc[desc_idx]);
271         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
272             PrintError("Could not translate block header address\n");
273             goto exit_error;
274         }
275
276         hdr = (struct virtio_net_hdr*)hdr_addr;
277         desc_idx = hdr_desc->next;
278
279         if(desc_cnt > 2){
280             PrintError("VNIC: merged rx buffer not supported\n");
281             goto exit_error;
282         }
283
284         /* here we assumed that one ethernet pkt is not splitted into multiple virtio buffer */
285         for (i = 0; i < desc_cnt - 1; i++) {    
286             struct vring_desc * buf_desc = &(q->desc[desc_idx]);
287             if (pkt_tx(core, virtio_state, buf_desc) == -1) {
288                 PrintError("Error handling nic operation\n");
289                 goto exit_error;
290             }
291
292             req_len += buf_desc->length;
293             desc_idx = buf_desc->next;
294         }
295         virtio_state->pkt_sent ++;
296         recved ++;
297
298         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
299         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
300         q->used->index ++;
301         
302         q->cur_avail_idx ++;
303     }
304
305     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
306
307     if(!recved)
308         return 0;
309         
310     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
311         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
312         virtio_state->virtio_cfg.pci_isr = 0x1;
313     }
314
315     return 0;
316
317 exit_error:
318         
319     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
320     return -ERR_VIRTIO_OTHER;
321 }
322
323
324 static int virtio_setup_queue(struct guest_info *core, 
325                                 struct virtio_net_state * virtio_state, 
326                                 struct virtio_queue * queue, 
327                                                         addr_t pfn, 
328                                                         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, uint16_t port, void * src, uint_t length, void * private_data) 
366 {
367     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
368     int port_idx = port % virtio->io_range_size;
369
370
371     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
372                port, port_idx,  length, *(uint32_t *)src);
373
374     switch (port_idx) {
375         case GUEST_FEATURES_PORT:
376             if (length != 4) {
377                 PrintError("Illegal write length for guest features\n");
378                 return -1;
379             }       
380             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
381             break;
382                 
383         case VRING_PG_NUM_PORT:
384             if (length != 4) {
385                 PrintError("Illegal write length for page frame number\n");
386                 return -1;
387             }
388             addr_t pfn = *(uint32_t *)src;
389             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
390             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
391             switch (queue_idx) {
392                 case 0:
393                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
394                     disable_cb(&virtio->rx_vq);
395                     break;
396                 case 1:
397                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
398                     disable_cb(&virtio->tx_vq);
399                     break;
400                 case 2:
401                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
402                     break;          
403                 default:
404                     break;
405             }
406             break;
407                 
408         case VRING_Q_SEL_PORT:
409             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
410             if (virtio->virtio_cfg.vring_queue_selector > 2) {
411                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
412                            virtio->virtio_cfg.vring_queue_selector);
413                 return -1;
414             }
415             break;
416                 
417         case VRING_Q_NOTIFY_PORT: 
418             {
419                 uint16_t queue_idx = *(uint16_t *)src;                  
420                 if (queue_idx == 0){
421                     handle_rx_kick(core, virtio);
422                     PrintError("rx kick\n");
423                 } else if (queue_idx == 1){
424                     PrintError("tx kick\n");
425                     if (handle_pkt_tx(core, virtio) == -1) {
426                         PrintError("Could not handle NIC Notification\n");
427                         return -1;
428                     }
429                 } else if (queue_idx == 2){
430                     if (handle_ctrl(core, virtio) == -1) {
431                         PrintError("Could not handle NIC Notification\n");
432                         return -1;
433                     }
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                 PrintDebug("Resetting device\n");
444                 virtio_init_state(virtio);
445             }
446             break;
447
448         case VIRTIO_ISR_PORT:
449             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
450             break;
451                 
452         default:
453             return -1;
454             break;
455     }
456
457     return length;
458 }
459
460 static int virtio_io_read(struct guest_info *core, uint16_t port, void * dst, uint_t length, void * private_data) 
461 {
462     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
463     int port_idx = port % virtio->io_range_size;
464     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
465
466     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d\n", private_data,
467                port, port_idx, length);
468         
469     switch (port_idx) {
470         case HOST_FEATURES_PORT:
471             if (length != 4) {
472                 PrintError("Illegal read length for host features\n");
473                 return -1;
474             }
475             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
476             break;
477
478         case VRING_PG_NUM_PORT:
479             if (length != 4) {
480                 PrintError("Illegal read length for page frame number\n");
481                 return -1;
482             }
483             switch (queue_idx) {
484                 case 0:
485                     *(uint32_t *)dst = virtio->rx_vq.pfn;
486                     break;
487                 case 1:
488                     *(uint32_t *)dst = virtio->tx_vq.pfn;
489                     break;      
490                 case 2:
491                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
492                     break;
493                 default:
494                     break;
495             }
496             break;
497
498         case VRING_SIZE_PORT:
499             if (length != 2) {
500                 PrintError("Illegal read length for vring size\n");
501                 return -1;
502             }
503             switch (queue_idx) {
504                 case 0:
505                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
506                     break;
507                 case 1:
508                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
509                     break;      
510                 case 2:
511                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
512                     break;
513                 default:
514                     break;
515             }
516             break;
517
518         case VIRTIO_STATUS_PORT:
519             if (length != 1) {
520                 PrintError("Illegal read length for status\n");
521                 return -1;
522             }
523             *(uint8_t *)dst = virtio->virtio_cfg.status;
524             break;
525                 
526         case VIRTIO_ISR_PORT:
527             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
528             virtio->virtio_cfg.pci_isr = 0;
529             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
530             break;
531
532         default:
533             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", port_idx);
534             return -1;
535     }
536
537     return length;
538 }
539
540
541 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
542     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
543     struct virtio_queue * q = &(virtio->rx_vq);
544     struct virtio_net_hdr_mrg_rxbuf hdr;
545     uint32_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
546     uint32_t data_len = size;
547     uint32_t offset = 0;
548     unsigned long flags;
549     int ret_val = -ERR_VIRTIO_OTHER;
550     int raw = 1;
551
552     flags = v3_lock_irqsave(virtio->rx_lock);
553
554     virtio->pkt_recv ++;
555     if (!raw)
556         data_len -= hdr_len;
557
558     if (!raw)
559         memcpy(&hdr, buf, sizeof(struct virtio_net_hdr_mrg_rxbuf));
560     else
561         memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
562
563     if (q->ring_avail_addr == 0) {
564         PrintError("Queue is not set\n");
565         ret_val = -ERR_VIRTIO_RXQ_NOSET;
566         goto exit;
567     }
568
569     if (q->cur_avail_idx != q->avail->index){
570         addr_t hdr_addr = 0;
571         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
572         uint16_t buf_idx = 0;
573         struct vring_desc * hdr_desc = NULL;
574
575         hdr_desc = &(q->desc[hdr_idx]);
576         if (v3_gpa_to_hva(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
577             PrintError("Could not translate receive buffer address\n");
578             goto exit;
579         }
580         hdr.num_buffers = 1;
581         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr_mrg_rxbuf));
582         if (offset >= data_len) {
583             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
584         }
585
586         struct vring_desc * buf_desc = NULL;
587         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
588             uint32_t len = 0;
589             buf_desc = &(q->desc[buf_idx]);
590
591             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset, 0);     
592             offset += len;
593             if (offset < data_len) {
594                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
595             }
596             buf_desc->length = len;
597         }
598         buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
599         
600         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
601         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) */
602         q->used->index++;
603         q->cur_avail_idx++;
604
605         /* if there are certain num of pkts in the RX queue, notify guest 
606           * so guest will exit to palacios
607          * when it returns, guest gets the virtio rx interrupt */
608         if((++virtio->buffed_rx > q->queue_size/5) &&
609             (q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
610             if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
611                   notify_guest(virtio);
612             }
613             virtio->buffed_rx = 0;
614         }
615     } else {
616         virtio->pkt_drop++;
617         /* RX queue is full,  tell backend to stop RX on this device */
618         virtio->net_ops->stop_rx(virtio->backend_data);
619         enable_cb(&virtio->rx_vq);
620         
621         ret_val = -ERR_VIRTIO_RXQ_FULL;
622         goto exit;
623     }
624
625     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
626         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
627         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
628         virtio->virtio_cfg.pci_isr = 0x1;
629     }
630
631     ret_val = offset;
632
633 exit:
634
635     v3_unlock_irqrestore(virtio->rx_lock, flags);
636  
637     return ret_val;
638 }
639
640
641 static struct v3_device_ops dev_ops = {
642     .free = virtio_free,
643     .reset = NULL,
644     .start = NULL,
645     .stop = NULL,
646 };
647
648
649 /* TODO: Issue here: which vm info it needs? calling VM or the device's own VM? */
650 static void virtio_nic_poll(struct v3_vm_info * vm, void * data){
651     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
652         
653     handle_pkt_tx(&(vm->cores[0]), virtio);
654 }
655
656 static void virtio_start_tx(void * data){
657     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
658     unsigned long flags;
659
660     flags = v3_lock_irqsave(virtio->tx_lock);
661     virtio->tx_disabled = 0;
662
663     /* notify the device's guest to start sending pkt */
664     if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
665         notify_guest(virtio);
666     }
667     v3_unlock_irqrestore(virtio->tx_lock, flags);       
668 }
669
670 static void virtio_stop_tx(void * data){
671     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
672     unsigned long flags;
673
674     flags = v3_lock_irqsave(virtio->tx_lock);
675     virtio->tx_disabled = 1;
676
677     /* stop the guest to exit to palacios for sending pkt? */
678     if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
679        disable_cb(&virtio->tx_vq);
680     }
681
682     v3_unlock_irqrestore(virtio->tx_lock, flags);
683 }
684
685         
686
687
688 static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_state * net_state) 
689 {
690     struct pci_device * pci_dev = NULL;
691     struct v3_pci_bar bars[6];
692     int num_ports = sizeof(struct virtio_config);
693     int tmp_ports = num_ports;
694     int i;
695
696     // This gets the number of ports, rounded up to a power of 2
697     net_state->io_range_size = 1; // must be a power of 2
698     while (tmp_ports > 0) {
699         tmp_ports >>= 1;
700         net_state->io_range_size <<= 1;
701     }
702         
703     // this is to account for any low order bits being set in num_ports
704     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
705     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
706         net_state->io_range_size >>= 1;
707     }
708     
709     for (i = 0; i < 6; i++) {
710         bars[i].type = PCI_BAR_NONE;
711     }
712     
713     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
714     
715     bars[0].type = PCI_BAR_IO;
716     bars[0].default_base_port = -1;
717     bars[0].num_ports = net_state->io_range_size;
718     bars[0].io_read = virtio_io_read;
719     bars[0].io_write = virtio_io_write;
720     bars[0].private_data = net_state;
721     
722     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
723                                      0, 4/*PCI_AUTO_DEV_NUM*/, 0,
724                                      "LNX_VIRTIO_NIC", bars,
725                                      NULL, NULL, NULL, net_state);
726     
727     if (!pci_dev) {
728         PrintError("Virtio NIC: Could not register PCI Device\n");
729         return -1;
730     }
731
732     PrintDebug("Virtio NIC:  registered to PCI bus\n");
733     
734     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
735     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
736         
737
738     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
739     pci_dev->config_header.class = PCI_CLASS_NETWORK;
740     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
741     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
742     pci_dev->config_header.intr_pin = 1;
743     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
744
745     net_state->pci_dev = pci_dev;
746     net_state->virtio_dev = virtio;
747
748     uchar_t mac[6] = {0x11,0x11,0x11,0x11,0x11,0x11};
749     memcpy(net_state->net_cfg.mac, mac, 6);
750                                                                                                            
751     memcpy(pci_dev->config_data, net_state->net_cfg.mac, ETH_ALEN);
752     
753     virtio_init_state(net_state);
754
755     return 0;
756 }
757
758 static int connect_fn(struct v3_vm_info * info, 
759                       void * frontend_data, 
760                       struct v3_dev_net_ops * ops, 
761                       v3_cfg_tree_t * cfg, 
762                       void * private_data) {
763     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
764     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
765
766     memset(net_state, 0, sizeof(struct virtio_net_state));
767     register_dev(virtio, net_state);
768
769     net_state->net_ops = ops;
770     net_state->backend_data = private_data;
771
772     ops->recv = virtio_rx;
773     ops->poll = virtio_nic_poll;
774     ops->start_tx = virtio_start_tx;
775     ops->stop_tx = virtio_stop_tx;
776     ops->frontend_data = net_state;
777
778     return 0;
779 }
780
781 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
782     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
783     struct virtio_dev_state * virtio_state = NULL;
784     char * name = v3_cfg_val(cfg, "name");
785
786     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", name);
787
788     if (pci_bus == NULL) {
789         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
790         return -1;
791     }
792
793     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
794     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
795
796     INIT_LIST_HEAD(&(virtio_state->dev_list));
797     virtio_state->pci_bus = pci_bus;
798     virtio_state->vm = vm;
799
800     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
801     if (v3_attach_device(vm, dev) == -1) {
802         PrintError("Virtio NIC: Could not attach device %s\n", name);
803         return -1;
804     }
805
806     if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
807         PrintError("Virtio NIC: Could not register %s as net frontend\n", name);
808         return -1;
809     }
810         
811     return 0;
812 }
813
814 device_register("LNX_VIRTIO_NIC", virtio_init)
815