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.


cd7de187e6fe4da1c8d38b81f4eb9e603ec62cb8
[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, Jack Lange <jarusl@cs.northwestern.edu>
11  * Copyright (c) 2008, Lei Xia <lxia@northwestern.edu>
12  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Jack Lange <jarusl@cs.northwestern.edu>
16  *                Lei Xia <lxia@northwestern.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
29 #include <devices/pci.h>
30
31
32 #ifndef CONFIG_DEBUG_VIRTIO_NET
33 #undef PrintDebug
34 #define PrintDebug(fmt, args...)
35 #endif
36
37 /* The feature bitmap for virtio net */
38 #define VIRTIO_NET_F_CSUM       0       /* Host handles pkts w/ partial csum */
39 #define VIRTIO_NET_F_GUEST_CSUM 1       /* Guest handles pkts w/ partial csum */
40 #define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
41 #define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
42 #define VIRTIO_NET_F_GUEST_TSO4 7       /* Guest can handle TSOv4 in. */
43 #define VIRTIO_NET_F_GUEST_TSO6 8       /* Guest can handle TSOv6 in. */
44 #define VIRTIO_NET_F_GUEST_ECN  9       /* Guest can handle TSO[6] w/ ECN in. */
45 #define VIRTIO_NET_F_GUEST_UFO  10      /* Guest can handle UFO in. */
46 #define VIRTIO_NET_F_HOST_TSO4  11      /* Host can handle TSOv4 in. */
47 #define VIRTIO_NET_F_HOST_TSO6  12      /* Host can handle TSOv6 in. */
48 #define VIRTIO_NET_F_HOST_ECN   13      /* Host can handle TSO[6] w/ ECN in. */
49 #define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
50 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
51 #define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
52 #define VIRTIO_NET_F_CTRL_VQ    17      /* Control channel available */
53 #define VIRTIO_NET_F_CTRL_RX    18      /* Control channel RX mode support */
54 #define VIRTIO_NET_F_CTRL_VLAN  19      /* Control channel VLAN filtering */
55 #define VIRTIO_NET_F_CTRL_RX_EXTRA 20   /* Extra RX mode control support */
56 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
57
58 /* Maximum packet size we can receive from tap device: header + 64k */
59 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
60
61
62 struct virtio_net_hdr {
63         uint8_t flags;
64
65 #define VIRTIO_NET_HDR_GSO_NONE         0       /* Not a GSO frame */
66         uint8_t gso_type;
67
68         uint16_t hdr_len;               /* Ethernet + IP + tcp/udp hdrs */
69         uint16_t gso_size;              /* Bytes to append to hdr_len per frame */
70         uint16_t csum_start;    /* Position to start checksumming from */
71         uint16_t csum_offset;   /* Offset after that to place checksum */
72 }__attribute__((packed));
73
74         
75
76
77 #define QUEUE_SIZE 256
78 #define CTRL_QUEUE_SIZE 64
79
80 #define ETH_ALEN 6
81
82 struct virtio_net_config
83 {
84     uint8_t mac[ETH_ALEN];
85     // See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above
86     uint16_t status;
87 } __attribute__((packed));
88
89 struct virtio_dev_state {
90     struct vm_device * pci_bus;
91     struct list_head dev_list;
92     struct guest_info * vm;
93 };
94
95 struct virtio_net_state {
96     struct virtio_net_config net_cfg;
97     struct virtio_config virtio_cfg;
98
99     //struct vm_device * pci_bus;
100     struct pci_device * pci_dev;
101     
102     struct virtio_queue rx_vq;   //index 0, rvq in Linux virtio driver, handle packet to guest
103     struct virtio_queue tx_vq;   //index 1, svq in Linux virtio driver, handle packet from guest
104     struct virtio_queue ctrl_vq; //index 2, ctrol info from guest
105
106     struct v3_dev_net_ops * net_ops;
107
108     void * backend_data;
109
110     struct virtio_dev_state * virtio_dev;
111
112     struct list_head dev_link;
113
114     int io_range_size;
115
116     void *private_data;
117 };
118
119 #if 1
120 //Temporarly for debug
121 static void print_packet(uchar_t *pkt, int size) {
122     PrintDebug("Vnet: print_data_packet: size: %d\n", size);
123     v3_hexdump(pkt, size, NULL, 0);
124 }
125
126 static int send(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *dest_dev)
127 {
128    PrintDebug("Virito NIC: In sending stub\n");
129    print_packet(buf, count);
130
131    return count;
132 }
133
134 static int receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev)
135 {
136     PrintDebug("Virito NIC: In receiveing stub\n");
137
138     return 0;
139 }
140
141
142 #endif
143
144 static int virtio_free(struct vm_device * dev) 
145 {
146         
147     return -1;
148 }
149
150 static int virtio_reset(struct virtio_net_state * virtio) 
151 {
152     virtio->rx_vq.ring_desc_addr = 0;
153     virtio->rx_vq.ring_avail_addr = 0;
154     virtio->rx_vq.ring_used_addr = 0;
155     virtio->rx_vq.pfn = 0;
156     virtio->rx_vq.cur_avail_idx = 0;
157
158     virtio->tx_vq.ring_desc_addr = 0;
159     virtio->tx_vq.ring_avail_addr = 0;
160     virtio->tx_vq.ring_used_addr = 0;
161     virtio->tx_vq.pfn = 0;
162     virtio->tx_vq.cur_avail_idx = 0;
163
164     virtio->ctrl_vq.ring_desc_addr = 0;
165     virtio->ctrl_vq.ring_avail_addr = 0;
166     virtio->ctrl_vq.ring_used_addr = 0;
167     virtio->ctrl_vq.pfn = 0;
168     virtio->ctrl_vq.cur_avail_idx = 0;
169
170     virtio->virtio_cfg.host_features = 0;
171     //virtio->virtio_cfg.status = VIRTIO_NET_S_LINK_UP;
172     virtio->virtio_cfg.pci_isr = 0;
173     virtio->private_data = NULL;
174
175     return 0;
176 }
177
178
179 //sending guest's packet to network sink
180 static int pkt_write(struct virtio_net_state *virtio,  struct vring_desc *buf_desc) 
181 {
182     //struct virtio_net_state * virtio = (struct virtio_net_state *)dev->private_data; 
183     uint8_t *buf = NULL;
184     uint32_t len = buf_desc->length;
185
186     PrintDebug("Handling Virtio Net write\n");
187
188     if (guest_pa_to_host_va(virtio->virtio_dev->vm, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
189         PrintError("Could not translate buffer address\n");
190         return -1;
191     }
192
193     PrintDebug("Length=%d\n", buf_desc->length);
194     PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d, buf address: %p, send address: %p\n", buf_desc, 
195                        (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next, buf, virtio->net_ops->send);
196
197     if (virtio->net_ops->send(buf, len, (void *)virtio, NULL) == -1) {
198         return -1;
199     }
200
201     return 0;
202 }
203
204
205 static int build_receive_header(struct virtio_net_hdr *hdr, const void *buf, int raw)
206 {
207     hdr->flags = 0;
208
209     if (!raw) {
210         memcpy(hdr, buf, sizeof(struct virtio_net_hdr));
211     } else {
212         memset(hdr, 0, sizeof(struct virtio_net_hdr));
213     }
214
215     return 0;
216 }
217
218
219 //sending guest's packet to network sink
220 static int copy_data_to_desc(struct virtio_net_state * virtio_state, struct vring_desc *desc, uchar_t *buf, uint_t buf_len) 
221 {
222     uint32_t len;
223     uint8_t *desc_buf = NULL;
224
225     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
226         PrintError("Could not translate buffer address\n");
227         return -1;
228     }
229
230     len = (desc->length < buf_len)?desc->length:buf_len;
231
232     memcpy(desc_buf, buf, len);
233
234     PrintDebug("Length=%d\n", len);
235
236     return len;
237 }
238
239
240 //send data to guest
241 static int send_pkt_to_guest(struct vm_device *dev, uchar_t *buf, uint_t size, int raw, void *private_data) 
242 {
243    // TODO: This should not be like this
244     struct virtio_net_state *virtio = (struct virtio_net_state *)dev->private_data;    
245     struct virtio_queue *q = &(virtio->rx_vq);
246
247     PrintDebug("VIRTIO Handle RX: cur_index=%d (mod=%d), avail_index=%d\n", 
248                q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
249
250     struct virtio_net_hdr hdr;
251     uint32_t hdr_len = sizeof(struct virtio_net_hdr);
252
253     uint32_t data_len = size;
254     if (!raw)
255        data_len -=  hdr_len;
256
257     build_receive_header(&hdr, buf, 1);
258
259     //queue is not set yet
260     if (q->ring_avail_addr == 0)
261                 return -1;
262
263 \r uint32_t offset = 0;
264     if (q->cur_avail_idx < q->avail->index) {
265         struct vring_desc * hdr_desc = NULL;
266         addr_t hdr_addr = 0;
267         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
268
269         PrintDebug("Descriptor index=%d\n", q->cur_avail_idx % q->queue_size);
270
271         hdr_desc = &(q->desc[hdr_idx]);
272
273         PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
274                    (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
275
276         if (guest_pa_to_host_va(virtio->virtio_dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
277             PrintError("Could not translate receive buffer address\n");
278             return -1;
279         }
280
281         //copy header to the header descriptor
282         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
283
284         uint16_t buf_idx = 0;
285         struct vring_desc * buf_desc = NULL;
286         //copy data to the next descriptors
287         for (buf_idx = 0; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
288                 q->desc[buf_idx].flags = VIRTIO_NEXT_FLAG;
289                 buf_desc = &(q->desc[buf_idx]);
290                 uint32_t len = copy_data_to_desc(virtio, buf_desc, buf+offset, data_len - offset);
291                 offset += len;
292                 buf_desc->length = len;  // TODO: do we need this?
293         }
294         
295         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
296         q->used->ring[q->used->index % q->queue_size].length = data_len; // What do we set this to????
297
298         q->used->index++;
299         q->cur_avail_idx++;
300     }
301
302     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
303         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
304         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
305         virtio->virtio_cfg.pci_isr = 0x1;
306     }
307
308     return offset;
309 }
310
311
312 int virtio_send(struct vm_device * dev, uchar_t *buf, uint_t size)
313 {
314     return send_pkt_to_guest(dev, buf, size, 1, NULL);
315 }
316
317
318 static int get_desc_count(struct virtio_queue * q, int index) 
319 {
320     struct vring_desc * tmp_desc = &(q->desc[index]);
321     int cnt = 1;
322     
323     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
324         tmp_desc = &(q->desc[tmp_desc->next]);
325         cnt++;
326     }
327
328     return cnt;
329 }
330
331
332 static int handle_ctrl(struct virtio_net_state * dev) 
333 {
334
335
336     return 0;
337 }
338
339 //get packet from guest
340 static int handle_pkt_tx(struct virtio_net_state * virtio_state) 
341 {
342     //struct virtio_net_state *virtio = (struct virtio_net_state *)dev->private_data;    
343     struct virtio_queue *q = &(virtio_state->tx_vq);
344
345     PrintDebug("VIRTIO NIC pkt_tx: cur_index=%d (mod=%d), avail_index=%d\n", 
346                q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
347
348     struct virtio_net_hdr *hdr = NULL;
349
350     while (q->cur_avail_idx < q->avail->index) {
351         struct vring_desc * hdr_desc = NULL;
352         struct vring_desc * buf_desc = NULL;
353
354         addr_t hdr_addr = 0;
355         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
356         int desc_cnt = get_desc_count(q, desc_idx);
357         uint32_t req_len = 0;
358
359         PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % q->queue_size);
360
361         hdr_desc = &(q->desc[desc_idx]);
362
363         PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
364                    (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
365
366         if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
367             PrintError("Could not translate block header address\n");
368             return -1;
369         }
370
371         //memcpy(&hdr, (void *)hdr_addr, sizeof(struct virtio_net_hdr));
372         hdr = (struct virtio_net_hdr*)hdr_addr;
373         
374         PrintDebug("NIC Op Hdr (ptr=%p) header len =%x\n", (void *)hdr_addr, (int)hdr->hdr_len);
375
376       desc_idx= hdr_desc->next;
377         int i = 0;
378         for (i = 0; i < desc_cnt - 1; i++) {    
379             buf_desc = &(q->desc[desc_idx]);
380
381             PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
382                        (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
383
384             if (pkt_write(virtio_state, buf_desc) == -1) {
385                 PrintError("Error handling nic operation\n");
386                 return -1;
387             }
388
389             req_len += buf_desc->length;
390             desc_idx = buf_desc->next;
391         }
392
393         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
394         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
395
396         q->used->index++;
397         q->cur_avail_idx++;
398     }
399
400     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
401         PrintDebug("Raising IRQ %d\n",  virtio_state->pci_dev->config_header.intr_line);
402         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
403         virtio_state->virtio_cfg.pci_isr = 0x1;
404     }
405
406     return 0;
407 }
408
409
410 static int virtio_setup_queue(struct virtio_net_state *virtio_state, struct virtio_queue *queue, addr_t pfn, addr_t page_addr)
411 {
412     queue->pfn = pfn;
413                 
414     queue->ring_desc_addr = page_addr ;
415     queue->ring_avail_addr = page_addr + (queue->queue_size* sizeof(struct vring_desc));
416     queue->ring_used_addr = (queue->ring_avail_addr + \
417                                                  sizeof(struct vring_avail)    + \
418                                                  (queue->queue_size * sizeof(uint16_t)));
419                 
420     // round up to next page boundary.
421     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
422
423     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
424         PrintError("Could not translate ring descriptor address\n");
425          return -1;
426     }
427
428  
429     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
430         PrintError("Could not translate ring available address\n");
431         return -1;
432     }
433
434
435     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
436         PrintError("Could not translate ring used address\n");
437         return -1;
438     }
439
440     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
441                         (void *)(queue->ring_desc_addr),
442                            (void *)(queue->ring_avail_addr),
443                            (void *)(queue->ring_used_addr));
444
445     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
446                     queue->desc, queue->avail, queue->used);
447
448     return 0;
449 }
450
451
452
453 static int virtio_io_write(uint16_t port, void * src, uint_t length, void * private_data) 
454 {
455     //struct vm_device * dev = (struct vm_device *)private_data;
456     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
457     int port_idx = port % virtio->io_range_size;
458
459
460     PrintDebug("VIRTIO NIC Write for port %d (index=%d) len=%d, value=%x\n", 
461                port, port_idx,  length, *(uint32_t *)src);
462
463
464     switch (port_idx) {
465         case GUEST_FEATURES_PORT:
466             if (length != 4) {
467                 PrintError("Illegal write length for guest features\n");
468                 return -1;
469             }
470             
471             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
472             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
473
474             break;
475         case VRING_PG_NUM_PORT:
476             if (length == 4) {
477                 addr_t pfn = *(uint32_t *)src;
478                 addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
479
480                 uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
481                 switch (queue_idx) {
482                     case 0:
483                         virtio_setup_queue(virtio, &virtio->rx_vq, pfn, page_addr);
484                         break;
485                   case 1:
486                         virtio_setup_queue(virtio, &virtio->tx_vq, pfn, page_addr);
487                          break;
488                     case 2:
489                          virtio_setup_queue(virtio, &virtio->ctrl_vq, pfn, page_addr);
490                          break;
491
492                     default:
493                          break;
494                 }
495             } else {
496                 PrintError("Illegal write length for page frame number\n");
497                 return -1;
498             }
499             break;
500         case VRING_Q_SEL_PORT:
501             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
502
503             if (virtio->virtio_cfg.vring_queue_selector > 2) {
504                 PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
505                            virtio->virtio_cfg.vring_queue_selector);
506                 return -1;
507             }
508
509             break;
510         case VRING_Q_NOTIFY_PORT:
511             PrintDebug("Handling Kick\n");
512             uint16_t queue_idx = *(uint16_t *)src;
513             if (queue_idx == 0){
514                     PrintError("receive queue notification\n");
515             }else if (queue_idx == 1){
516                     if (handle_pkt_tx(virtio) == -1) {
517                         PrintError("Could not handle NIC Notification\n");
518                         return -1;
519                     }
520             }else if (queue_idx == 2){
521                     if (handle_ctrl(virtio) == -1) {
522                         PrintError("Could not handle NIC Notification\n");
523                         return -1;
524                     }
525             }else {
526                 PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
527                            queue_idx);
528             }
529             
530             break;
531         case VIRTIO_STATUS_PORT:
532             virtio->virtio_cfg.status = *(uint8_t *)src;
533
534             if (virtio->virtio_cfg.status == 0) {
535                 PrintDebug("Resetting device\n");
536                 virtio_reset(virtio);
537             }
538
539             break;
540
541         case VIRTIO_ISR_PORT:
542             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
543             break;
544         default:
545             return -1;
546             break;
547     }
548
549     return length;
550 }
551
552
553 static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * private_data) 
554 {
555    //struct vm_device * dev = (struct vm_device *)private_data;
556     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
557     int port_idx = port % virtio->io_range_size;
558     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
559
560     PrintDebug("VIRTIO NIC Read  for port %d (index =%d), length=%d", 
561                port, port_idx, length);
562         
563     switch (port_idx) {
564         case HOST_FEATURES_PORT:
565             if (length != 4) {
566                 PrintError("Illegal read length for host features\n");
567                 return -1;
568             }
569
570             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
571
572            PrintDebug("value=0x%x\n", (int)*(uint32_t *)dst);
573         
574             break;
575         case VRING_PG_NUM_PORT:
576
577             if (length != 4) {
578                 PrintError("Illegal read length for page frame number\n");
579                 return -1;
580             }
581
582             switch (queue_idx) {
583                 case 0:
584                       *(uint32_t *)dst = virtio->rx_vq.pfn;
585                         break;
586                  case 1:
587                       *(uint32_t *)dst = virtio->tx_vq.pfn;
588                         break;  
589                  case 2:
590                       *(uint32_t *)dst = virtio->ctrl_vq.pfn;
591                         break;
592                  default:
593                         break;
594            }
595             PrintDebug(", value=0x%x\n", (int)*(uint32_t *)dst);
596
597             break;
598         case VRING_SIZE_PORT:
599             if (length != 2) {
600                 PrintError("Illegal read length for vring size\n");
601                 return -1;
602             }
603
604             switch (queue_idx) {
605                 case 0:
606                       *(uint16_t *)dst = virtio->rx_vq.queue_size;
607                         break;
608                  case 1:
609                       *(uint16_t *)dst = virtio->tx_vq.queue_size;
610                         break;  
611                  case 2:
612                       *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
613                         break;
614                  default:
615                         break;
616            }
617
618             PrintDebug("queue index: %d, value=0x%x\n", (int)queue_idx, (int)(int)*(uint16_t *)dst);
619
620             break;
621         case VIRTIO_STATUS_PORT:
622             if (length != 1) {
623                 PrintError("Illegal read length for status\n");
624                 return -1;
625             }
626
627             *(uint8_t *)dst = virtio->virtio_cfg.status;
628
629            PrintDebug(", value=0x%x\n", (int)*(uint8_t *)dst);
630             break;
631
632         case VIRTIO_ISR_PORT:
633             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
634             virtio->virtio_cfg.pci_isr = 0;
635             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
636
637             PrintDebug(", value=0x%x\n", (int)*(uint8_t *)dst);
638                 
639             break;
640
641         default:
642             PrintError("Read of Unhandled Virtio Read\n");
643            return -1;
644     }
645
646     return length;
647 }
648
649
650 static struct v3_device_ops dev_ops = {
651     .free = virtio_free,
652     .reset = NULL,
653     .start = NULL,
654     .stop = NULL,
655 };
656
657
658 static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_state * net_state) 
659 {
660     struct pci_device * pci_dev = NULL;
661     struct v3_pci_bar bars[6];
662     int num_ports = sizeof(struct virtio_config);
663     int tmp_ports = num_ports;
664     int i;
665
666     // This gets the number of ports, rounded up to a power of 2
667     net_state->io_range_size = 1; // must be a power of 2
668     
669     while (tmp_ports > 0) {
670         tmp_ports >>= 1;
671         net_state->io_range_size <<= 1;
672     }
673         
674     // this is to account for any low order bits being set in num_ports
675     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
676     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
677         net_state->io_range_size >>= 1;
678     }
679     
680     
681     for (i = 0; i < 6; i++) {
682         bars[i].type = PCI_BAR_NONE;
683     }
684     
685     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
686     
687     bars[0].type = PCI_BAR_IO;
688     bars[0].default_base_port = -1;
689     bars[0].num_ports = net_state->io_range_size;
690     
691     bars[0].io_read = virtio_io_read;
692     bars[0].io_write = virtio_io_write;
693     bars[0].private_data = net_state;
694     
695     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
696                                      0, PCI_AUTO_DEV_NUM, 0,
697                                      "LNX_VIRTIO_NIC", bars,
698                                      NULL, NULL, NULL, net_state);
699     
700     if (!pci_dev) {
701         PrintError("Could not register PCI Device\n");
702         return -1;
703     }
704
705     PrintDebug("Virtio-NIC registered to PCI bus\n");
706     
707     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
708     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
709         
710
711     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
712     pci_dev->config_header.class = PCI_CLASS_NETWORK;
713     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;
714     
715     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;;
716
717     pci_dev->config_header.intr_pin = 1;
718
719     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
720
721
722     net_state->pci_dev = pci_dev;
723     //net_state->pci_bus = pci_bus;
724     
725     net_state->virtio_cfg.host_features = 0; //no features support now
726
727     net_state->rx_vq.queue_size = QUEUE_SIZE;
728     net_state->tx_vq.queue_size = QUEUE_SIZE;
729     net_state->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
730
731     net_state->virtio_dev = virtio;
732
733     virtio_reset(net_state);
734
735     return 0;
736 }
737
738
739
740 static int connect_fn(struct guest_info * info, 
741                       void * frontend_data, 
742                       struct v3_dev_net_ops * ops, 
743                       v3_cfg_tree_t * cfg, 
744                       void * private_data) 
745 {
746     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
747
748     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
749     memset(net_state, 0, sizeof(struct virtio_net_state));
750
751     register_dev(virtio, net_state);
752
753     net_state->net_ops = ops;
754     net_state->backend_data = private_data;
755
756     return 0;
757 }
758
759
760 struct net_frontend {
761     int (*connect)(struct guest_info * info, 
762                     void * frontend_data, 
763                     struct v3_dev_net_ops * ops, 
764                     v3_cfg_tree_t * cfg, 
765                     void * priv_data);
766         
767
768     struct list_head net_node;
769
770     void * priv_data;
771 };
772
773
774 int v3_dev_add_net_frontend(struct guest_info * info, 
775                             char * name, 
776                             int (*connect)(struct guest_info * info, 
777                                             void * frontend_data, 
778                                             struct v3_dev_net_ops * ops, 
779                                             v3_cfg_tree_t * cfg, 
780                                             void * private_data), 
781                             void * priv_data)
782 {
783     struct net_frontend * frontend = NULL;
784
785     frontend = (struct net_frontend *)V3_Malloc(sizeof(struct net_frontend));
786     memset(frontend, 0, sizeof(struct net_frontend));
787     
788     frontend->connect = connect;
789     frontend->priv_data = priv_data;
790         
791     list_add(&(frontend->net_node), &(info->dev_mgr.net_list));
792     v3_htable_insert(info->dev_mgr.net_table, (addr_t)(name), (addr_t)frontend);
793
794     return 0;
795 }
796
797
798 int v3_dev_connect_net(struct guest_info * info, 
799                        char * frontend_name, 
800                        struct v3_dev_net_ops * ops, 
801                        v3_cfg_tree_t * cfg, 
802                        void * private_data)
803 {
804     struct net_frontend * frontend = NULL;
805
806     frontend = (struct net_frontend *)v3_htable_search(info->dev_mgr.net_table,
807                                                        (addr_t)frontend_name);
808     
809     if (frontend == NULL) {
810         PrintError("Could not find frontend net device %s\n", frontend_name);
811         return 0;
812     }
813
814     if (frontend->connect(info, frontend->priv_data, ops, cfg, private_data) == -1) {
815         PrintError("Error connecting to net frontend %s\n", frontend_name);
816         return -1;
817     }
818
819     return 0;
820 }
821
822 static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
823     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
824     struct virtio_dev_state * virtio_state = NULL;
825     char * name = v3_cfg_val(cfg, "name");
826
827     PrintDebug("Initializing VIRTIO Network device\n");
828
829     if (pci_bus == NULL) {
830         PrintError("VirtIO devices require a PCI Bus");
831         return -1;
832     }
833
834     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
835     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
836
837     INIT_LIST_HEAD(&(virtio_state->dev_list));
838     virtio_state->pci_bus = pci_bus;
839     virtio_state->vm = vm;
840
841     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
842     if (v3_attach_device(vm, dev) == -1) {
843         PrintError("Could not attach device %s\n", name);
844         return -1;
845     }
846
847     if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
848         PrintError("Could not register %s as net frontend\n", name);
849         return -1;
850     }
851
852
853     //for temporary testing, add a backend
854     #if 1
855    
856     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
857     memset(net_state, 0, sizeof(struct virtio_net_state));
858
859     net_state->net_ops = (struct v3_dev_net_ops *)V3_Malloc(sizeof(struct v3_dev_net_ops));
860
861     net_state->net_ops->send = &send;
862     net_state->net_ops->receive = &receive;
863
864     register_dev(virtio_state, net_state);
865         
866     PrintDebug("Virtio NIC After register Device: queue size: %d, %d\n", 
867                net_state->rx_vq.queue_size, net_state->tx_vq.queue_size);
868
869
870     #endif
871
872     return 0;
873 }
874
875 device_register("LNX_VIRTIO_NIC", virtio_init)
876