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