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.


Minor fix
[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     PrintDebug("Virtio NIC: TX: running on cpu: %d\n", V3_Get_CPU());
208
209     while (q->cur_avail_idx != q->avail->index) {
210         struct vring_desc * hdr_desc = NULL;
211         addr_t hdr_addr = 0;
212         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
213         int desc_cnt = get_desc_count(q, desc_idx);
214         uint32_t req_len = 0;
215         int i = 0;
216
217         hdr_desc = &(q->desc[desc_idx]);
218         if (guest_pa_to_host_va(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
219             PrintError("Could not translate block header address\n");
220             return -1;
221         }
222
223         hdr = (struct virtio_net_hdr*)hdr_addr;
224         desc_idx = hdr_desc->next;
225
226         for (i = 0; i < desc_cnt - 1; i++) {    
227             struct vring_desc * buf_desc = &(q->desc[desc_idx]);
228             if (pkt_tx(core, virtio_state, buf_desc) == -1) {
229                 PrintError("Error handling nic operation\n");
230                 return -1;
231             }
232
233             req_len += buf_desc->length;
234             desc_idx = buf_desc->next;
235         }
236         virtio_state->pkt_sent ++;
237
238         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
239         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
240         q->used->index++;
241
242         q->cur_avail_idx ++;
243     }
244
245     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
246         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
247         virtio_state->virtio_cfg.pci_isr = 0x1;
248     }
249
250 #ifdef CONFIG_VNET_PROFILE
251     if (virtio_state->pkt_sent % 10000 == 0){
252             PrintError("Virtio NIC: sent: %ld, rxed: %ld, dropped: %ld\n",
253                         virtio_state->pkt_sent,
254                         virtio_state->pkt_recv,
255                         virtio_state->pkt_drop);
256     }
257 #endif
258
259     return 0;
260 }
261
262
263 static int virtio_setup_queue(struct guest_info *core, 
264                                                         struct virtio_net_state * virtio_state, 
265                                                         struct virtio_queue * queue, 
266                                                         addr_t pfn, 
267                                                         addr_t page_addr) {
268     queue->pfn = pfn;
269                 
270     queue->ring_desc_addr = page_addr;
271     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
272     queue->ring_used_addr = ((queue->ring_avail_addr) + 
273                              (sizeof(struct vring_avail)) + 
274                              (queue->queue_size * sizeof(uint16_t)));
275
276     // round up to next page boundary.
277     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
278     if (guest_pa_to_host_va(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
279         PrintError("Could not translate ring descriptor address\n");
280          return -1;
281     }
282  
283     if (guest_pa_to_host_va(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
284         PrintError("Could not translate ring available address\n");
285         return -1;
286     }
287
288     if (guest_pa_to_host_va(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
289         PrintError("Could not translate ring used address\n");
290         return -1;
291     }
292
293     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
294                (void *)(queue->ring_desc_addr),
295                (void *)(queue->ring_avail_addr),
296                (void *)(queue->ring_used_addr));
297     
298     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
299                queue->desc, queue->avail, queue->used);
300     
301     return 0;
302 }
303
304 static int virtio_io_write(struct guest_info *core, uint16_t port, void * src, uint_t length, void * private_data) 
305 {
306     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
307     int port_idx = port % virtio->io_range_size;
308
309
310     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
311                port, port_idx,  length, *(uint32_t *)src);
312
313     switch (port_idx) {
314         case GUEST_FEATURES_PORT:
315             if (length != 4) {
316                 PrintError("Illegal write length for guest features\n");
317                 return -1;
318             }       
319             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
320             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
321             break;
322                 
323         case VRING_PG_NUM_PORT:
324             if (length != 4) {
325                 PrintError("Illegal write length for page frame number\n");
326                 return -1;
327             }
328             addr_t pfn = *(uint32_t *)src;
329             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
330             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
331
332             PrintDebug("Virtio Write: pfn: %p, page_addr %p, queue_idx %d\n", (void *)pfn, (void *)page_addr, queue_idx);
333
334             switch (queue_idx) {
335                 case 0:
336                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
337                     break;
338                 case 1:
339                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
340                     break;
341                 case 2:
342                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
343                     break;          
344                 default:
345                     break;
346             }
347             break;
348                 
349         case VRING_Q_SEL_PORT:
350             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
351             if (virtio->virtio_cfg.vring_queue_selector > 2) {
352                 PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
353                            virtio->virtio_cfg.vring_queue_selector);
354                 return -1;
355             }
356             break;
357                 
358         case VRING_Q_NOTIFY_PORT: 
359             {
360                 uint16_t queue_idx = *(uint16_t *)src;                  
361                 if (queue_idx == 0){
362                     PrintDebug("receive queue notification 0, packet get by Guest\n");
363                 } else if (queue_idx == 1){
364                     if (handle_pkt_tx(core, virtio) == -1) {
365                         PrintError("Could not handle NIC Notification\n");
366                         return -1;
367                     }
368                 } else if (queue_idx == 2){
369                     if (handle_ctrl(core, virtio) == -1) {
370                         PrintError("Could not handle NIC Notification\n");
371                         return -1;
372                     }
373                 } else {
374                     PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
375                                queue_idx);
376                 }       
377                 break;          
378             }
379         
380         case VIRTIO_STATUS_PORT:
381             virtio->virtio_cfg.status = *(uint8_t *)src;
382             if (virtio->virtio_cfg.status == 0) {
383                 PrintDebug("Resetting device\n");
384                 virtio_init_state(virtio);
385             }
386             break;
387
388         case VIRTIO_ISR_PORT:
389             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
390             break;
391         default:
392             return -1;
393             break;
394     }
395
396     return length;
397 }
398
399 static int virtio_io_read(struct guest_info *core, uint16_t port, void * dst, uint_t length, void * private_data) 
400 {
401     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
402     int port_idx = port % virtio->io_range_size;
403     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
404
405     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d\n", private_data,
406                port, port_idx, length);
407         
408     switch (port_idx) {
409         case HOST_FEATURES_PORT:
410             if (length != 4) {
411                 PrintError("Illegal read length for host features\n");
412                 return -1;
413             }
414             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
415             break;
416
417         case VRING_PG_NUM_PORT:
418             if (length != 4) {
419                 PrintError("Illegal read length for page frame number\n");
420                 return -1;
421             }
422             switch (queue_idx) {
423                 case 0:
424                     *(uint32_t *)dst = virtio->rx_vq.pfn;
425                     break;
426                 case 1:
427                     *(uint32_t *)dst = virtio->tx_vq.pfn;
428                     break;      
429                 case 2:
430                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
431                     break;
432                 default:
433                     break;
434             }
435             break;
436
437         case VRING_SIZE_PORT:
438             if (length != 2) {
439                 PrintError("Illegal read length for vring size\n");
440                 return -1;
441             }
442             switch (queue_idx) {
443                 case 0:
444                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
445                     break;
446                 case 1:
447                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
448                     break;      
449                 case 2:
450                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
451                     break;
452                 default:
453                     break;
454             }
455             PrintDebug("queue index: %d, value=0x%x\n", (int)queue_idx, *(uint16_t *)dst);
456             break;
457
458         case VIRTIO_STATUS_PORT:
459             if (length != 1) {
460                 PrintError("Illegal read length for status\n");
461                 return -1;
462             }
463             *(uint8_t *)dst = virtio->virtio_cfg.status;
464             break;
465                 
466         case VIRTIO_ISR_PORT:
467             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
468             virtio->virtio_cfg.pci_isr = 0;
469             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
470             break;
471
472         default:
473             PrintError("Virtio NIC: Read of Unhandled Virtio Read\n");
474             return -1;
475     }
476
477     return length;
478 }
479
480
481
482
483 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
484     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
485     struct virtio_queue * q = &(virtio->rx_vq);
486     struct virtio_net_hdr hdr;
487     uint32_t hdr_len = sizeof(struct virtio_net_hdr);
488     uint32_t data_len = size;
489     uint32_t offset = 0;
490     unsigned long flags;
491     int ret_val = -1;
492     int raw = 1;
493
494     flags = v3_lock_irqsave(virtio->lock);
495
496     PrintDebug("VIRTIO NIC: RX on cpu %d to virtio nic %p, size:%d\n", V3_Get_CPU(), virtio, size);
497
498     virtio->pkt_recv ++;
499
500     if (!raw){
501         data_len -= hdr_len;
502     }
503
504     build_receive_header(&hdr, buf, raw);
505
506     if (q->ring_avail_addr == 0) {
507         PrintError("Queue is not set\n");
508         goto exit;
509     }
510
511     if (q->cur_avail_idx != q->avail->index){
512         addr_t hdr_addr = 0;
513         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
514         uint16_t buf_idx = 0;
515         struct vring_desc * hdr_desc = NULL;
516
517         hdr_desc = &(q->desc[hdr_idx]);
518         if (guest_pa_to_host_va(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
519             PrintError("Could not translate receive buffer address\n");
520             ret_val = -1;
521             goto exit;
522         }
523
524         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
525         if (offset >= data_len) {
526             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
527         }
528
529         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
530             struct vring_desc * buf_desc = &(q->desc[buf_idx]);
531             uint32_t len = 0;
532
533             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset);        
534             offset += len;
535             if (offset < data_len) {
536                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
537             }
538             buf_desc->length = len;
539         }
540         
541         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
542         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)
543         q->used->index++;
544
545         q->cur_avail_idx++;
546     } else {
547         virtio->pkt_drop++;
548         goto exit;
549     }
550
551     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
552         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
553         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
554         virtio->virtio_cfg.pci_isr = 0x1;
555     }
556
557     ret_val = offset;
558
559 exit:
560         
561 #ifdef CONFIG_VNET_PROFILE
562     if (virtio->pkt_recv % 100000 == 0){
563         PrintError("Virtio NIC: sent: %ld, rxed: %ld, dropped: %ld\n",
564                 virtio->pkt_sent,
565                 virtio->pkt_recv,
566                 virtio->pkt_drop);
567     }
568 #endif
569
570     v3_unlock_irqrestore(virtio->lock, flags);
571  
572     return ret_val;
573 }
574
575
576 static struct v3_device_ops dev_ops = {
577     .free = virtio_free,
578     .reset = NULL,
579     .start = NULL,
580     .stop = NULL,
581 };
582
583 static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_state * net_state) 
584 {
585     struct pci_device * pci_dev = NULL;
586     struct v3_pci_bar bars[6];
587     int num_ports = sizeof(struct virtio_config);
588     int tmp_ports = num_ports;
589     int i;
590
591     // This gets the number of ports, rounded up to a power of 2
592     net_state->io_range_size = 1; // must be a power of 2
593     while (tmp_ports > 0) {
594         tmp_ports >>= 1;
595         net_state->io_range_size <<= 1;
596     }
597         
598     // this is to account for any low order bits being set in num_ports
599     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
600     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
601         net_state->io_range_size >>= 1;
602     }
603     
604     for (i = 0; i < 6; i++) {
605         bars[i].type = PCI_BAR_NONE;
606     }
607     
608     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
609     
610     bars[0].type = PCI_BAR_IO;
611     bars[0].default_base_port = -1;
612     bars[0].num_ports = net_state->io_range_size;
613     bars[0].io_read = virtio_io_read;
614     bars[0].io_write = virtio_io_write;
615     bars[0].private_data = net_state;
616     
617     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
618                                      0, PCI_AUTO_DEV_NUM, 0,
619                                      "LNX_VIRTIO_NIC", bars,
620                                      NULL, NULL, NULL, net_state);
621     
622     if (!pci_dev) {
623         PrintError("Virtio NIC: Could not register PCI Device\n");
624         return -1;
625     }
626
627     PrintDebug("Virtio NIC:  registered to PCI bus\n");
628     
629     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
630     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
631         
632
633     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
634     pci_dev->config_header.class = PCI_CLASS_NETWORK;
635     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
636     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
637     pci_dev->config_header.intr_pin = 1;
638     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
639
640     net_state->pci_dev = pci_dev;   
641     net_state->virtio_cfg.host_features = 0; //no features support now
642     net_state->rx_vq.queue_size = QUEUE_SIZE;
643     net_state->tx_vq.queue_size = QUEUE_SIZE;
644     net_state->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
645     net_state->virtio_dev = virtio;
646    
647     virtio_init_state(net_state);
648
649     return 0;
650 }
651
652 static int connect_fn(struct v3_vm_info * info, 
653                       void * frontend_data, 
654                       struct v3_dev_net_ops * ops, 
655                       v3_cfg_tree_t * cfg, 
656                       void * private_data) {
657     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
658     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
659
660     memset(net_state, 0, sizeof(struct virtio_net_state));
661     register_dev(virtio, net_state);
662
663     net_state->net_ops = ops;
664     net_state->backend_data = private_data;
665
666     ops->recv = virtio_rx;
667     ops->frontend_data = net_state;
668
669     return 0;
670 }
671
672 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
673     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
674     struct virtio_dev_state * virtio_state = NULL;
675     char * name = v3_cfg_val(cfg, "name");
676
677     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", name);
678
679     if (pci_bus == NULL) {
680         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
681         return -1;
682     }
683
684     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
685     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
686
687     INIT_LIST_HEAD(&(virtio_state->dev_list));
688     virtio_state->pci_bus = pci_bus;
689     virtio_state->vm = vm;
690
691     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
692     if (v3_attach_device(vm, dev) == -1) {
693         PrintError("Virtio NIC: Could not attach device %s\n", name);
694         return -1;
695     }
696
697     if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
698         PrintError("Virtio NIC: Could not register %s as net frontend\n", name);
699         return -1;
700     }
701         
702     return 0;
703 }
704
705 device_register("LNX_VIRTIO_NIC", virtio_init)
706