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.


Minimize the copies for vnet and Virtio bridge
[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) 2008, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2008, Cui Zheng <cuizheng@cs.unm.edu>
12  * Copyright (c) 2008, 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
32 #include <devices/pci.h>
33
34
35 #ifndef CONFIG_DEBUG_VIRTIO_NET
36 #undef PrintDebug
37 #define PrintDebug(fmt, args...)
38 #endif
39
40 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
41 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
42
43 struct virtio_net_hdr {
44         uint8_t flags;
45
46 #define VIRTIO_NET_HDR_GSO_NONE         0       /* Not a GSO frame */
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 #define QUEUE_SIZE 1024
56 #define CTRL_QUEUE_SIZE 64
57 #define ETH_ALEN 6
58
59 struct virtio_net_config
60 {
61     uint8_t mac[ETH_ALEN]; //VIRTIO_NET_F_MAC
62     uint16_t status;
63 } __attribute__((packed));
64
65 struct virtio_dev_state {
66     struct vm_device * pci_bus;
67     struct list_head dev_list;
68     struct v3_vm_info *vm;
69 };
70
71 struct virtio_net_state {
72     struct virtio_net_config net_cfg;
73     struct virtio_config virtio_cfg;
74
75     struct vm_device * dev;
76     struct pci_device * pci_dev; 
77     int io_range_size;
78     
79     struct virtio_queue rx_vq;   //index 0, rvq in Linux virtio driver, handle packet to guest
80     struct virtio_queue tx_vq;   //index 1, svq in Linux virtio driver, handle packet from guest
81     struct virtio_queue ctrl_vq; //index 2, ctrol info from guest
82
83     ulong_t pkt_sent, pkt_recv, pkt_drop;
84
85     struct v3_dev_net_ops * net_ops;
86
87     v3_lock_t lock;
88
89     void * backend_data;
90     struct virtio_dev_state * virtio_dev;
91     struct list_head dev_link;
92 };
93
94 static int virtio_free(struct vm_device * dev) 
95 {
96         
97     return -1;
98 }
99
100 static int virtio_init_state(struct virtio_net_state * virtio) 
101 {
102     virtio->rx_vq.ring_desc_addr = 0;
103     virtio->rx_vq.ring_avail_addr = 0;
104     virtio->rx_vq.ring_used_addr = 0;
105     virtio->rx_vq.pfn = 0;
106     virtio->rx_vq.cur_avail_idx = 0;
107
108     virtio->tx_vq.ring_desc_addr = 0;
109     virtio->tx_vq.ring_avail_addr = 0;
110     virtio->tx_vq.ring_used_addr = 0;
111     virtio->tx_vq.pfn = 0;
112     virtio->tx_vq.cur_avail_idx = 0;
113
114     virtio->ctrl_vq.ring_desc_addr = 0;
115     virtio->ctrl_vq.ring_avail_addr = 0;
116     virtio->ctrl_vq.ring_used_addr = 0;
117     virtio->ctrl_vq.pfn = 0;
118     virtio->ctrl_vq.cur_avail_idx = 0;
119
120     virtio->virtio_cfg.host_features = 0;
121     //virtio->virtio_cfg.status = VIRTIO_NET_S_LINK_UP;
122     virtio->virtio_cfg.pci_isr = 0;
123
124     if (v3_lock_init(&(virtio->lock)) == -1){
125         PrintError("Virtio NIC: Failure to init lock for net_state\n");
126     }
127
128     virtio->pkt_sent = virtio->pkt_recv = virtio->pkt_drop = 0;
129
130     return 0;
131 }
132
133 static int pkt_tx(struct guest_info *core, struct virtio_net_state * virtio, struct vring_desc * buf_desc) 
134 {
135     uint8_t * buf = NULL;
136     uint32_t len = buf_desc->length;
137
138     PrintDebug("Virtio NIC: Virtio Pkt Sending, net_state: %p, pkt size: %d\n", virtio, len);
139
140     if (guest_pa_to_host_va(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
141         PrintError("Could not translate buffer address\n");
142         return -1;
143     }
144
145     if (virtio->net_ops->send(buf, len, virtio->backend_data, NULL) == -1) {
146         return -1;
147     }
148
149     return 0;
150 }
151
152 static int build_receive_header(struct virtio_net_hdr * hdr, const void * buf, int raw) {
153     hdr->flags = 0;
154
155     if (!raw) {
156         memcpy(hdr, buf, sizeof(struct virtio_net_hdr));
157     } else {
158         memset(hdr, 0, sizeof(struct virtio_net_hdr));
159     }
160
161     return 0;
162 }
163
164 static int copy_data_to_desc(struct guest_info *core, 
165                                         struct virtio_net_state * virtio_state, 
166                                         struct vring_desc * desc, 
167                                         uchar_t * buf, 
168                                         uint_t buf_len) 
169 {
170     uint32_t len;
171     uint8_t * desc_buf = NULL;
172
173     if (guest_pa_to_host_va(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
174         PrintError("Could not translate buffer address\n");
175         return -1;
176     }
177     len = (desc->length < buf_len)?desc->length:buf_len;
178     memcpy(desc_buf, buf, len);
179
180     return len;
181 }
182
183
184
185
186 static int get_desc_count(struct virtio_queue * q, int index) {
187     struct vring_desc * tmp_desc = &(q->desc[index]);
188     int cnt = 1;
189     
190     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
191         tmp_desc = &(q->desc[tmp_desc->next]);
192         cnt++;
193     }
194
195     return cnt;
196 }
197
198 static int handle_ctrl(struct guest_info *core, struct virtio_net_state * dev) {
199     return 0;
200 }
201
202 static int handle_pkt_tx(struct guest_info *core, struct virtio_net_state * virtio_state) 
203 {
204     struct virtio_queue * q = &(virtio_state->tx_vq);
205     struct virtio_net_hdr * hdr = NULL;
206
207
208     while (q->cur_avail_idx != q->avail->index) {
209         struct vring_desc * hdr_desc = NULL;
210         addr_t hdr_addr = 0;
211         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
212         int desc_cnt = get_desc_count(q, desc_idx);
213         uint32_t req_len = 0;
214         int i = 0;
215
216         hdr_desc = &(q->desc[desc_idx]);
217         if (guest_pa_to_host_va(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
218             PrintError("Could not translate block header address\n");
219             return -1;
220         }
221
222         hdr = (struct virtio_net_hdr*)hdr_addr;
223         desc_idx = hdr_desc->next;
224         
225         for (i = 0; i < desc_cnt - 1; i++) {    
226             struct vring_desc * buf_desc = &(q->desc[desc_idx]);
227             if (pkt_tx(core, virtio_state, buf_desc) == -1) {
228                 PrintError("Error handling nic operation\n");
229                 return -1;
230             }
231
232             req_len += buf_desc->length;
233             desc_idx = buf_desc->next;
234         }
235         virtio_state->pkt_sent ++;
236
237         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
238         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
239         q->used->index++;
240
241         q->cur_avail_idx ++;
242     }
243
244     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
245         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
246         virtio_state->virtio_cfg.pci_isr = 0x1;
247     }
248
249     return 0;
250 }
251
252
253 static int virtio_setup_queue(struct guest_info *core, 
254                                                         struct virtio_net_state * virtio_state, 
255                                                         struct virtio_queue * queue, 
256                                                         addr_t pfn, 
257                                                         addr_t page_addr) {
258     queue->pfn = pfn;
259                 
260     queue->ring_desc_addr = page_addr;
261     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
262     queue->ring_used_addr = ((queue->ring_avail_addr) + 
263                              (sizeof(struct vring_avail)) + 
264                              (queue->queue_size * sizeof(uint16_t)));
265
266     // round up to next page boundary.
267     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
268     if (guest_pa_to_host_va(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
269         PrintError("Could not translate ring descriptor address\n");
270          return -1;
271     }
272  
273     if (guest_pa_to_host_va(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
274         PrintError("Could not translate ring available address\n");
275         return -1;
276     }
277
278     if (guest_pa_to_host_va(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
279         PrintError("Could not translate ring used address\n");
280         return -1;
281     }
282
283     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
284                (void *)(queue->ring_desc_addr),
285                (void *)(queue->ring_avail_addr),
286                (void *)(queue->ring_used_addr));
287     
288     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
289                queue->desc, queue->avail, queue->used);
290     
291     return 0;
292 }
293
294 static int virtio_io_write(struct guest_info *core, uint16_t port, void * src, uint_t length, void * private_data) 
295 {
296     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
297     int port_idx = port % virtio->io_range_size;
298
299
300     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
301                port, port_idx,  length, *(uint32_t *)src);
302
303     switch (port_idx) {
304         case GUEST_FEATURES_PORT:
305             if (length != 4) {
306                 PrintError("Illegal write length for guest features\n");
307                 return -1;
308             }       
309             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
310             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
311             break;
312                 
313         case VRING_PG_NUM_PORT:
314             if (length != 4) {
315                 PrintError("Illegal write length for page frame number\n");
316                 return -1;
317             }
318             addr_t pfn = *(uint32_t *)src;
319             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
320             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
321
322             PrintDebug("Virtio Write: pfn: %p, page_addr %p, queue_idx %d\n", (void *)pfn, (void *)page_addr, queue_idx);
323
324             switch (queue_idx) {
325                 case 0:
326                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
327                     break;
328                 case 1:
329                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
330                     break;
331                 case 2:
332                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
333                     break;          
334                 default:
335                     break;
336             }
337             break;
338                 
339         case VRING_Q_SEL_PORT:
340             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
341             if (virtio->virtio_cfg.vring_queue_selector > 2) {
342                 PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
343                            virtio->virtio_cfg.vring_queue_selector);
344                 return -1;
345             }
346             break;
347                 
348         case VRING_Q_NOTIFY_PORT: 
349             {
350                 uint16_t queue_idx = *(uint16_t *)src;                  
351                 if (queue_idx == 0){
352                     PrintDebug("receive queue notification 0, packet get by Guest\n");
353                 } else if (queue_idx == 1){
354                     if (handle_pkt_tx(core, virtio) == -1) {
355                         PrintError("Could not handle NIC Notification\n");
356                         return -1;
357                     }
358                 } else if (queue_idx == 2){
359                     if (handle_ctrl(core, virtio) == -1) {
360                         PrintError("Could not handle NIC Notification\n");
361                         return -1;
362                     }
363                 } else {
364                     PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
365                                queue_idx);
366                 }       
367                 break;          
368             }
369         
370         case VIRTIO_STATUS_PORT:
371             virtio->virtio_cfg.status = *(uint8_t *)src;
372             if (virtio->virtio_cfg.status == 0) {
373                 PrintDebug("Resetting device\n");
374                 virtio_init_state(virtio);
375             }
376             break;
377
378         case VIRTIO_ISR_PORT:
379             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
380             break;
381         default:
382             return -1;
383             break;
384     }
385
386     return length;
387 }
388
389 static int virtio_io_read(struct guest_info *core, uint16_t port, void * dst, uint_t length, void * private_data) 
390 {
391     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
392     int port_idx = port % virtio->io_range_size;
393     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
394
395     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d\n", private_data,
396                port, port_idx, length);
397         
398     switch (port_idx) {
399         case HOST_FEATURES_PORT:
400             if (length != 4) {
401                 PrintError("Illegal read length for host features\n");
402                 return -1;
403             }
404             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
405             break;
406
407         case VRING_PG_NUM_PORT:
408             if (length != 4) {
409                 PrintError("Illegal read length for page frame number\n");
410                 return -1;
411             }
412             switch (queue_idx) {
413                 case 0:
414                     *(uint32_t *)dst = virtio->rx_vq.pfn;
415                     break;
416                 case 1:
417                     *(uint32_t *)dst = virtio->tx_vq.pfn;
418                     break;      
419                 case 2:
420                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
421                     break;
422                 default:
423                     break;
424             }
425             break;
426
427         case VRING_SIZE_PORT:
428             if (length != 2) {
429                 PrintError("Illegal read length for vring size\n");
430                 return -1;
431             }
432             switch (queue_idx) {
433                 case 0:
434                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
435                     break;
436                 case 1:
437                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
438                     break;      
439                 case 2:
440                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
441                     break;
442                 default:
443                     break;
444             }
445             PrintDebug("queue index: %d, value=0x%x\n", (int)queue_idx, *(uint16_t *)dst);
446             break;
447
448         case VIRTIO_STATUS_PORT:
449             if (length != 1) {
450                 PrintError("Illegal read length for status\n");
451                 return -1;
452             }
453             *(uint8_t *)dst = virtio->virtio_cfg.status;
454             break;
455                 
456         case VIRTIO_ISR_PORT:
457             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
458             virtio->virtio_cfg.pci_isr = 0;
459             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
460             break;
461
462         default:
463             PrintError("Virtio NIC: Read of Unhandled Virtio Read\n");
464             return -1;
465     }
466
467     return length;
468 }
469
470
471
472
473 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
474     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
475     struct virtio_queue * q = &(virtio->rx_vq);
476     struct virtio_net_hdr hdr;
477     uint32_t hdr_len = sizeof(struct virtio_net_hdr);
478     uint32_t data_len = size;
479     uint32_t offset = 0;
480     unsigned long flags;
481     int ret_val = -1;
482     int raw = 1;
483
484     flags = v3_lock_irqsave(virtio->lock);
485         
486     PrintDebug("VIRTIO NIC: receiving packet to virtio nic %p, size:%d\n", virtio, size);
487
488     virtio->pkt_recv ++;
489
490     if (!raw){
491         data_len -= hdr_len;
492     }
493
494     build_receive_header(&hdr, buf, raw);
495
496     if (q->ring_avail_addr == 0) {
497         PrintError("Queue is not set\n");
498         goto exit;
499     }
500
501     if (q->cur_avail_idx != q->avail->index){
502         addr_t hdr_addr = 0;
503         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
504         uint16_t buf_idx = 0;
505         struct vring_desc * hdr_desc = NULL;
506
507         hdr_desc = &(q->desc[hdr_idx]);
508         if (guest_pa_to_host_va(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
509             PrintError("Could not translate receive buffer address\n");
510             ret_val = -1;
511             goto exit;
512         }
513
514         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
515         if (offset >= data_len) {
516             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
517         }
518
519         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
520             struct vring_desc * buf_desc = &(q->desc[buf_idx]);
521             uint32_t len = 0;
522
523             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset);        
524             offset += len;
525             if (offset < data_len) {
526                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
527             }
528             buf_desc->length = len;
529         }
530         
531         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
532         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)
533         q->used->index++;
534
535         q->cur_avail_idx++;
536     } else {
537         virtio->pkt_drop++;
538     }
539
540     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
541         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
542         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
543         virtio->virtio_cfg.pci_isr = 0x1;
544     }
545
546     ret_val = offset;
547
548 exit:
549
550     v3_unlock_irqrestore(virtio->lock, flags);
551  
552     return ret_val;
553 }
554
555
556 static struct v3_device_ops dev_ops = {
557     .free = virtio_free,
558     .reset = NULL,
559     .start = NULL,
560     .stop = NULL,
561 };
562
563 static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_state * net_state) 
564 {
565     struct pci_device * pci_dev = NULL;
566     struct v3_pci_bar bars[6];
567     int num_ports = sizeof(struct virtio_config);
568     int tmp_ports = num_ports;
569     int i;
570
571     // This gets the number of ports, rounded up to a power of 2
572     net_state->io_range_size = 1; // must be a power of 2
573     while (tmp_ports > 0) {
574         tmp_ports >>= 1;
575         net_state->io_range_size <<= 1;
576     }
577         
578     // this is to account for any low order bits being set in num_ports
579     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
580     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
581         net_state->io_range_size >>= 1;
582     }
583     
584     for (i = 0; i < 6; i++) {
585         bars[i].type = PCI_BAR_NONE;
586     }
587     
588     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
589     
590     bars[0].type = PCI_BAR_IO;
591     bars[0].default_base_port = -1;
592     bars[0].num_ports = net_state->io_range_size;
593     bars[0].io_read = virtio_io_read;
594     bars[0].io_write = virtio_io_write;
595     bars[0].private_data = net_state;
596     
597     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
598                                      0, PCI_AUTO_DEV_NUM, 0,
599                                      "LNX_VIRTIO_NIC", bars,
600                                      NULL, NULL, NULL, net_state);
601     
602     if (!pci_dev) {
603         PrintError("Virtio NIC: Could not register PCI Device\n");
604         return -1;
605     }
606
607     PrintDebug("Virtio NIC:  registered to PCI bus\n");
608     
609     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
610     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
611         
612
613     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
614     pci_dev->config_header.class = PCI_CLASS_NETWORK;
615     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
616     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
617     pci_dev->config_header.intr_pin = 1;
618     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
619
620     net_state->pci_dev = pci_dev;   
621     net_state->virtio_cfg.host_features = 0; //no features support now
622     net_state->rx_vq.queue_size = QUEUE_SIZE;
623     net_state->tx_vq.queue_size = QUEUE_SIZE;
624     net_state->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
625     net_state->virtio_dev = virtio;
626    
627     virtio_init_state(net_state);
628
629     return 0;
630 }
631
632 static int connect_fn(struct v3_vm_info * info, 
633                       void * frontend_data, 
634                       struct v3_dev_net_ops * ops, 
635                       v3_cfg_tree_t * cfg, 
636                       void * private_data) {
637     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
638     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
639
640     memset(net_state, 0, sizeof(struct virtio_net_state));
641     register_dev(virtio, net_state);
642
643     net_state->net_ops = ops;
644     net_state->backend_data = private_data;
645
646     ops->recv = virtio_rx;
647     ops->frontend_data = net_state;
648
649     return 0;
650 }
651
652 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
653     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
654     struct virtio_dev_state * virtio_state = NULL;
655     char * name = v3_cfg_val(cfg, "name");
656
657     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", name);
658
659     if (pci_bus == NULL) {
660         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
661         return -1;
662     }
663
664     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
665     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
666
667     INIT_LIST_HEAD(&(virtio_state->dev_list));
668     virtio_state->pci_bus = pci_bus;
669     virtio_state->vm = vm;
670
671     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
672     if (v3_attach_device(vm, dev) == -1) {
673         PrintError("Virtio NIC: Could not attach device %s\n", name);
674         return -1;
675     }
676
677     if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
678         PrintError("Virtio NIC: Could not register %s as net frontend\n", name);
679         return -1;
680     }
681         
682     return 0;
683 }
684
685 device_register("LNX_VIRTIO_NIC", virtio_init)
686