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.


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