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