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.


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