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.


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