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.


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