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