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.


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