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