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.


Clear 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) 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;
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         ret_val = -1;
499         goto exit;
500     }
501
502     if (q->cur_avail_idx != q->avail->index){
503         addr_t hdr_addr = 0;
504         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
505         uint16_t buf_idx = 0;
506         struct vring_desc * hdr_desc = NULL;
507
508         hdr_desc = &(q->desc[hdr_idx]);
509         if (guest_pa_to_host_va(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
510             PrintError("Could not translate receive buffer address\n");
511             ret_val = -1;
512             goto exit;
513         }
514
515         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
516         if (offset >= data_len) {
517             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
518         }
519
520         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
521             struct vring_desc * buf_desc = &(q->desc[buf_idx]);
522             uint32_t len = 0;
523
524             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset);        
525             offset += len;
526             if (offset < data_len) {
527                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
528             }
529             buf_desc->length = len;
530         }
531         
532         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
533         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)
534         q->used->index++;
535
536         q->cur_avail_idx++;
537     } else {
538         virtio->pkt_drop++;
539     }
540
541     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
542         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
543         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
544         virtio->virtio_cfg.pci_isr = 0x1;
545     }
546
547     ret_val = offset;
548
549 exit:
550
551     v3_unlock_irqrestore(virtio->lock, flags);
552  
553     return ret_val;
554 }
555
556
557 static struct v3_device_ops dev_ops = {
558     .free = virtio_free,
559     .reset = NULL,
560     .start = NULL,
561     .stop = NULL,
562 };
563
564 static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_state * net_state) 
565 {
566     struct pci_device * pci_dev = NULL;
567     struct v3_pci_bar bars[6];
568     int num_ports = sizeof(struct virtio_config);
569     int tmp_ports = num_ports;
570     int i;
571
572     // This gets the number of ports, rounded up to a power of 2
573     net_state->io_range_size = 1; // must be a power of 2
574     while (tmp_ports > 0) {
575         tmp_ports >>= 1;
576         net_state->io_range_size <<= 1;
577     }
578         
579     // this is to account for any low order bits being set in num_ports
580     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
581     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
582         net_state->io_range_size >>= 1;
583     }
584     
585     for (i = 0; i < 6; i++) {
586         bars[i].type = PCI_BAR_NONE;
587     }
588     
589     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
590     
591     bars[0].type = PCI_BAR_IO;
592     bars[0].default_base_port = -1;
593     bars[0].num_ports = net_state->io_range_size;
594     bars[0].io_read = virtio_io_read;
595     bars[0].io_write = virtio_io_write;
596     bars[0].private_data = net_state;
597     
598     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
599                                      0, PCI_AUTO_DEV_NUM, 0,
600                                      "LNX_VIRTIO_NIC", bars,
601                                      NULL, NULL, NULL, net_state);
602     
603     if (!pci_dev) {
604         PrintError("Virtio NIC: Could not register PCI Device\n");
605         return -1;
606     }
607
608     PrintDebug("Virtio NIC:  registered to PCI bus\n");
609     
610     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
611     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
612         
613
614     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
615     pci_dev->config_header.class = PCI_CLASS_NETWORK;
616     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
617     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
618     pci_dev->config_header.intr_pin = 1;
619     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
620
621     net_state->pci_dev = pci_dev;   
622     net_state->virtio_cfg.host_features = 0; //no features support now
623     net_state->rx_vq.queue_size = QUEUE_SIZE;
624     net_state->tx_vq.queue_size = QUEUE_SIZE;
625     net_state->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
626     net_state->virtio_dev = virtio;
627    
628     virtio_init_state(net_state);
629
630     return 0;
631 }
632
633 static int connect_fn(struct v3_vm_info * info, 
634                       void * frontend_data, 
635                       struct v3_dev_net_ops * ops, 
636                       v3_cfg_tree_t * cfg, 
637                       void * private_data) {
638     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
639     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
640
641     memset(net_state, 0, sizeof(struct virtio_net_state));
642     register_dev(virtio, net_state);
643
644     net_state->net_ops = ops;
645     net_state->backend_data = private_data;
646
647     ops->recv = virtio_rx;
648     ops->frontend_data = net_state;
649
650     return 0;
651 }
652
653 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
654     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
655     struct virtio_dev_state * virtio_state = NULL;
656     char * name = v3_cfg_val(cfg, "name");
657
658     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", name);
659
660     if (pci_bus == NULL) {
661         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
662         return -1;
663     }
664
665     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
666     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
667
668     INIT_LIST_HEAD(&(virtio_state->dev_list));
669     virtio_state->pci_bus = pci_bus;
670     virtio_state->vm = vm;
671
672     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
673     if (v3_attach_device(vm, dev) == -1) {
674         PrintError("Virtio NIC: Could not attach device %s\n", name);
675         return -1;
676     }
677
678     if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
679         PrintError("Virtio NIC: Could not register %s as net frontend\n", name);
680         return -1;
681     }
682         
683     return 0;
684 }
685
686 device_register("LNX_VIRTIO_NIC", virtio_init)
687