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.


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