Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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