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.


change to device configuration syntax
[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 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
41 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
42
43 struct virtio_net_hdr {
44         uint8_t flags;
45
46 #define VIRTIO_NET_HDR_GSO_NONE         0       /* Not a GSO frame */
47         uint8_t gso_type;
48         uint16_t hdr_len;               /* Ethernet + IP + tcp/udp hdrs */
49         uint16_t gso_size;              /* Bytes to append to hdr_len per frame */
50         uint16_t csum_start;    /* Position to start checksumming from */
51         uint16_t csum_offset;   /* Offset after that to place checksum */
52 }__attribute__((packed));
53
54         
55 #define QUEUE_SIZE 1024
56 #define CTRL_QUEUE_SIZE 64
57 #define ETH_ALEN 6
58
59 struct virtio_net_config
60 {
61     uint8_t mac[ETH_ALEN]; //VIRTIO_NET_F_MAC
62     uint16_t status;
63 } __attribute__((packed));
64
65 struct virtio_dev_state {
66     struct vm_device * pci_bus;
67     struct list_head dev_list;
68     struct v3_vm_info *vm;
69 };
70
71 struct virtio_net_state {
72     struct virtio_net_config net_cfg;
73     struct virtio_config virtio_cfg;
74
75     struct vm_device * dev;
76     struct pci_device * pci_dev; 
77     int io_range_size;
78     
79     struct virtio_queue rx_vq;   //index 0, rvq in Linux virtio driver, handle packet to guest
80     struct virtio_queue tx_vq;   //index 1, svq in Linux virtio driver, handle packet from guest
81     struct virtio_queue ctrl_vq; //index 2, ctrol info from guest
82
83     ulong_t pkt_sent, pkt_recv, pkt_drop;
84
85 #if 1 //for temporary performance testing purpose
86     long last_sent_time, last_recv_time;        
87 #endif
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 (v3_gpa_to_hva(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 (v3_gpa_to_hva(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     PrintDebug("Virtio NIC: TX: running on cpu: %d\n", V3_Get_CPU());
212
213     while (q->cur_avail_idx != q->avail->index) {
214         struct vring_desc * hdr_desc = NULL;
215         addr_t hdr_addr = 0;
216         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
217         int desc_cnt = get_desc_count(q, desc_idx);
218         uint32_t req_len = 0;
219         int i = 0;
220
221         hdr_desc = &(q->desc[desc_idx]);
222         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
223             PrintError("Could not translate block header address\n");
224             return -1;
225         }
226
227         hdr = (struct virtio_net_hdr*)hdr_addr;
228         desc_idx = hdr_desc->next;
229
230         for (i = 0; i < desc_cnt - 1; i++) {    
231             struct vring_desc * buf_desc = &(q->desc[desc_idx]);
232             if (pkt_tx(core, virtio_state, buf_desc) == -1) {
233                 PrintError("Error handling nic operation\n");
234                 return -1;
235             }
236
237             req_len += buf_desc->length;
238             desc_idx = buf_desc->next;
239         }
240         virtio_state->pkt_sent ++;
241
242         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
243         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
244         q->used->index++;
245
246         q->cur_avail_idx ++;
247     }
248
249     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
250         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
251         virtio_state->virtio_cfg.pci_isr = 0x1;
252     }
253
254 #ifdef CONFIG_VNET_PROFILE
255     if (virtio_state->pkt_sent % 50000 == 0){
256             long cur_time, time;
257             rdtscll(cur_time);
258             time = cur_time - virtio_state->last_sent_time;
259             PrintError("Virtio NIC: last sent 50000 cycles: %ld\n",time);
260             //PrintError("Virtio NIC: sent: %ld, rxed: %ld, dropped: %ld\n",
261                 //      virtio_state->pkt_sent,
262                 //      virtio_state->pkt_recv,
263                 //      virtio_state->pkt_drop);
264             rdtscll(virtio_state->last_sent_time);
265     }
266 #endif
267
268     return 0;
269 }
270
271
272 static int virtio_setup_queue(struct guest_info *core, 
273                                                         struct virtio_net_state * virtio_state, 
274                                                         struct virtio_queue * queue, 
275                                                         addr_t pfn, 
276                                                         addr_t page_addr) {
277     queue->pfn = pfn;
278                 
279     queue->ring_desc_addr = page_addr;
280     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
281     queue->ring_used_addr = ((queue->ring_avail_addr) + 
282                              (sizeof(struct vring_avail)) + 
283                              (queue->queue_size * sizeof(uint16_t)));
284
285     // round up to next page boundary.
286     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
287     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
288         PrintError("Could not translate ring descriptor address\n");
289          return -1;
290     }
291  
292     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
293         PrintError("Could not translate ring available address\n");
294         return -1;
295     }
296
297     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
298         PrintError("Could not translate ring used address\n");
299         return -1;
300     }
301
302     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
303                (void *)(queue->ring_desc_addr),
304                (void *)(queue->ring_avail_addr),
305                (void *)(queue->ring_used_addr));
306     
307     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
308                queue->desc, queue->avail, queue->used);
309     
310     return 0;
311 }
312
313 static int virtio_io_write(struct guest_info *core, uint16_t port, void * src, uint_t length, void * private_data) 
314 {
315     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
316     int port_idx = port % virtio->io_range_size;
317
318
319     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
320                port, port_idx,  length, *(uint32_t *)src);
321
322     switch (port_idx) {
323         case GUEST_FEATURES_PORT:
324             if (length != 4) {
325                 PrintError("Illegal write length for guest features\n");
326                 return -1;
327             }       
328             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
329             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
330             break;
331                 
332         case VRING_PG_NUM_PORT:
333             if (length != 4) {
334                 PrintError("Illegal write length for page frame number\n");
335                 return -1;
336             }
337             addr_t pfn = *(uint32_t *)src;
338             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
339             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
340
341             PrintDebug("Virtio Write: pfn: %p, page_addr %p, queue_idx %d\n", (void *)pfn, (void *)page_addr, queue_idx);
342
343             switch (queue_idx) {
344                 case 0:
345                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
346                     break;
347                 case 1:
348                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
349                     break;
350                 case 2:
351                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
352                     break;          
353                 default:
354                     break;
355             }
356             break;
357                 
358         case VRING_Q_SEL_PORT:
359             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
360             if (virtio->virtio_cfg.vring_queue_selector > 2) {
361                 PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
362                            virtio->virtio_cfg.vring_queue_selector);
363                 return -1;
364             }
365             break;
366                 
367         case VRING_Q_NOTIFY_PORT: 
368             {
369                 uint16_t queue_idx = *(uint16_t *)src;                  
370                 if (queue_idx == 0){
371                     PrintDebug("receive queue notification 0, packet get by Guest\n");
372                 } else if (queue_idx == 1){
373                     if (handle_pkt_tx(core, virtio) == -1) {
374                         PrintError("Could not handle NIC Notification\n");
375                         return -1;
376                     }
377                 } else if (queue_idx == 2){
378                     if (handle_ctrl(core, virtio) == -1) {
379                         PrintError("Could not handle NIC Notification\n");
380                         return -1;
381                     }
382                 } else {
383                     PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
384                                queue_idx);
385                 }       
386                 break;          
387             }
388         
389         case VIRTIO_STATUS_PORT:
390             virtio->virtio_cfg.status = *(uint8_t *)src;
391             if (virtio->virtio_cfg.status == 0) {
392                 PrintDebug("Resetting device\n");
393                 virtio_init_state(virtio);
394             }
395             break;
396
397         case VIRTIO_ISR_PORT:
398             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
399             break;
400         default:
401             return -1;
402             break;
403     }
404
405     return length;
406 }
407
408 static int virtio_io_read(struct guest_info *core, uint16_t port, void * dst, uint_t length, void * private_data) 
409 {
410     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
411     int port_idx = port % virtio->io_range_size;
412     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
413
414     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d\n", private_data,
415                port, port_idx, length);
416         
417     switch (port_idx) {
418         case HOST_FEATURES_PORT:
419             if (length != 4) {
420                 PrintError("Illegal read length for host features\n");
421                 return -1;
422             }
423             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
424             break;
425
426         case VRING_PG_NUM_PORT:
427             if (length != 4) {
428                 PrintError("Illegal read length for page frame number\n");
429                 return -1;
430             }
431             switch (queue_idx) {
432                 case 0:
433                     *(uint32_t *)dst = virtio->rx_vq.pfn;
434                     break;
435                 case 1:
436                     *(uint32_t *)dst = virtio->tx_vq.pfn;
437                     break;      
438                 case 2:
439                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
440                     break;
441                 default:
442                     break;
443             }
444             break;
445
446         case VRING_SIZE_PORT:
447             if (length != 2) {
448                 PrintError("Illegal read length for vring size\n");
449                 return -1;
450             }
451             switch (queue_idx) {
452                 case 0:
453                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
454                     break;
455                 case 1:
456                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
457                     break;      
458                 case 2:
459                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
460                     break;
461                 default:
462                     break;
463             }
464             PrintDebug("queue index: %d, value=0x%x\n", (int)queue_idx, *(uint16_t *)dst);
465             break;
466
467         case VIRTIO_STATUS_PORT:
468             if (length != 1) {
469                 PrintError("Illegal read length for status\n");
470                 return -1;
471             }
472             *(uint8_t *)dst = virtio->virtio_cfg.status;
473             break;
474                 
475         case VIRTIO_ISR_PORT:
476             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
477             virtio->virtio_cfg.pci_isr = 0;
478             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
479             break;
480
481         default:
482             PrintError("Virtio NIC: Read of Unhandled Virtio Read\n");
483             return -1;
484     }
485
486     return length;
487 }
488
489
490
491
492 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
493     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
494     struct virtio_queue * q = &(virtio->rx_vq);
495     struct virtio_net_hdr hdr;
496     uint32_t hdr_len = sizeof(struct virtio_net_hdr);
497     uint32_t data_len = size;
498     uint32_t offset = 0;
499     unsigned long flags;
500     int ret_val = -1;
501     int raw = 1;
502
503     flags = v3_lock_irqsave(virtio->lock);
504
505     PrintDebug("VIRTIO NIC: RX on cpu %d to virtio nic %p, size:%d\n", V3_Get_CPU(), virtio, size);
506
507     virtio->pkt_recv ++;
508
509     if (!raw){
510         data_len -= hdr_len;
511     }
512
513     build_receive_header(&hdr, buf, raw);
514
515     if (q->ring_avail_addr == 0) {
516         PrintError("Queue is not set\n");
517         goto exit;
518     }
519
520     if (q->cur_avail_idx != q->avail->index){
521         addr_t hdr_addr = 0;
522         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
523         uint16_t buf_idx = 0;
524         struct vring_desc * hdr_desc = NULL;
525
526         hdr_desc = &(q->desc[hdr_idx]);
527         if (v3_gpa_to_hva(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
528             PrintError("Could not translate receive buffer address\n");
529             ret_val = -1;
530             goto exit;
531         }
532
533         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
534         if (offset >= data_len) {
535             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
536         }
537
538         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
539             struct vring_desc * buf_desc = &(q->desc[buf_idx]);
540             uint32_t len = 0;
541
542             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset);        
543             offset += len;
544             if (offset < data_len) {
545                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
546             }
547             buf_desc->length = len;
548         }
549         
550         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
551         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)
552         q->used->index++;
553
554         q->cur_avail_idx++;
555     } else {
556         virtio->pkt_drop++;
557         goto exit;
558     }
559
560     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
561         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
562         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
563         virtio->virtio_cfg.pci_isr = 0x1;
564     }
565
566     ret_val = offset;
567
568 exit:
569         
570 #ifdef CONFIG_VNET_PROFILE
571     if (virtio->pkt_recv % 50000 == 0){
572             long cur_time, time;
573             rdtscll(cur_time);
574             time = cur_time - virtio->last_recv_time;
575             PrintError("Virtio NIC: last recv 50000 cycles: %ld\n",time);
576             //PrintError("Virtio NIC: sent: %ld, rxed: %ld, dropped: %ld\n",
577                 //virtio->pkt_sent,
578                 //virtio->pkt_recv,
579                 //virtio->pkt_drop);
580             rdtscll(virtio->last_recv_time);
581     }
582 #endif
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 * dev_id = v3_cfg_val(cfg, "ID");
690
691     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", dev_id);
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(dev_id, &dev_ops, virtio_state);
706     if (v3_attach_device(vm, dev) == -1) {
707         PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
708         return -1;
709     }
710
711     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
712         PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
713         return -1;
714     }
715         
716     return 0;
717 }
718
719 device_register("LNX_VIRTIO_NIC", virtio_init)
720