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.


4874b73878e3f4311cdd7a3c397a350577d26ae3
[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, Cui Zheng <cuizheng@cs.unm.edu>
13  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
14  * All rights reserved.
15  *
16  * Author: Jack Lange <jarusl@cs.northwestern.edu>
17  *                Lei Xia <lxia@northwestern.edu>
18  *             Cui Zheng <cuizheng@cs.unm.edu>
19  *               
20  *
21  * This is free software.  You are permitted to use,
22  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
23  */
24  
25 #include <palacios/vmm.h>
26 #include <palacios/vmm_dev_mgr.h>
27 #include <devices/lnx_virtio_pci.h>
28 #include <palacios/vm_guest_mem.h>
29 #include <palacios/vmm_sprintf.h>
30 #include <palacios/vmm_vnet.h>
31
32 #include <devices/pci.h>
33
34
35 #ifndef CONFIG_DEBUG_VIRTIO_NET
36 #undef PrintDebug
37 #define PrintDebug(fmt, args...)
38 #endif
39
40 /* 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 1024
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
111
112 #ifdef CONFIG_DEBUG_VIRTIO_NET
113
114 static void print_packet(uchar_t *pkt, int size) {
115     PrintDebug("Virtio Nic: print_data_packet: size: %d\n", size);
116     v3_hexdump(pkt, size, NULL, 0);
117 }
118
119 #endif
120
121 #if 0
122 //Temporarly for debug
123
124 static struct virtio_net_state *temp_net_states[3]; 
125 static int net_idx = 0;
126
127 static int __virtio_dev_send(uchar_t * buf, uint32_t size, void *private_data);
128
129 static int send(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *dest_dev)
130 {
131    PrintDebug("Virito NIC: In sending stub, guest %p, count %d\n", private_data, count);
132
133 #ifdef CONFIG_DEBUG_VIRTIO_NET
134    print_packet(buf, 20);
135 #endif
136
137    struct virtio_net_state *virtio_state = (struct virtio_net_state *)private_data;
138
139    if (virtio_state == temp_net_states[0])
140        __virtio_dev_send(buf, count, temp_net_states[1]);
141  
142    if (virtio_state == temp_net_states[1]){ //return a RARP packet
143        __virtio_dev_send(buf, count, temp_net_states[0]);
144    }
145    
146    return count;
147 }
148
149 static int receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev)
150 {
151     PrintDebug("Virito NIC: In receiveing stub\n");
152
153     return 0;
154 }
155
156 #endif
157
158 static int virtio_free(struct vm_device * dev) 
159 {
160         
161     return -1;
162 }
163
164 static int virtio_reset(struct virtio_net_state * virtio) 
165 {
166     virtio->rx_vq.ring_desc_addr = 0;
167     virtio->rx_vq.ring_avail_addr = 0;
168     virtio->rx_vq.ring_used_addr = 0;
169     virtio->rx_vq.pfn = 0;
170     virtio->rx_vq.cur_avail_idx = 0;
171
172     virtio->tx_vq.ring_desc_addr = 0;
173     virtio->tx_vq.ring_avail_addr = 0;
174     virtio->tx_vq.ring_used_addr = 0;
175     virtio->tx_vq.pfn = 0;
176     virtio->tx_vq.cur_avail_idx = 0;
177
178     virtio->ctrl_vq.ring_desc_addr = 0;
179     virtio->ctrl_vq.ring_avail_addr = 0;
180     virtio->ctrl_vq.ring_used_addr = 0;
181     virtio->ctrl_vq.pfn = 0;
182     virtio->ctrl_vq.cur_avail_idx = 0;
183
184     virtio->virtio_cfg.host_features = 0;
185     //virtio->virtio_cfg.status = VIRTIO_NET_S_LINK_UP;
186     virtio->virtio_cfg.pci_isr = 0;
187
188     return 0;
189 }
190
191
192 //sending guest's packet to network sink
193 static int pkt_write(struct virtio_net_state * virtio, struct vring_desc * buf_desc) 
194 {
195     //struct virtio_net_state * virtio = (struct virtio_net_state *)dev->private_data; 
196     uint8_t * buf = NULL;
197     uint32_t len = buf_desc->length;
198
199     PrintDebug("Virtio NIC: Handling Virtio Write, net_state: %p\n", virtio);
200
201     if (guest_pa_to_host_va(virtio->virtio_dev->vm, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
202         PrintError("Could not translate buffer address\n");
203         return -1;
204     }
205
206     PrintDebug("Length=%d\n", buf_desc->length);
207     //PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d, buf address: %p, send address: %p\n", buf_desc, 
208                //(void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next, buf, virtio->net_ops->send);
209
210     if (virtio->net_ops->send(buf, len, (void *)virtio, NULL) == -1) {
211         return -1;
212     }
213
214     return 0;
215 }
216
217
218 static int build_receive_header(struct virtio_net_hdr * hdr, const void * buf, int raw) {
219     hdr->flags = 0;
220
221     if (!raw) {
222         memcpy(hdr, buf, sizeof(struct virtio_net_hdr));
223     } else {
224         memset(hdr, 0, sizeof(struct virtio_net_hdr));
225     }
226
227     return 0;
228 }
229
230
231 //sending guest's packet to network sink
232 static int copy_data_to_desc(struct virtio_net_state * virtio_state, struct vring_desc * desc, uchar_t * buf, uint_t buf_len) 
233 {
234     uint32_t len;
235     uint8_t * desc_buf = NULL;
236
237     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
238         PrintError("Could not translate buffer address\n");
239         return -1;
240     }
241
242     len = (desc->length < buf_len)?desc->length:buf_len;
243     memcpy(desc_buf, buf, len);
244
245     return len;
246 }
247
248
249 //send data to guest
250 static int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, uint_t size, int raw, void * private_data) 
251 {
252     struct virtio_queue * q = &(virtio->rx_vq);
253     struct virtio_net_hdr hdr;
254     uint32_t hdr_len = sizeof(struct virtio_net_hdr);
255     uint32_t data_len = size;
256     uint32_t offset = 0;
257
258     //PrintDebug("VIRTIO NIC:  Handle RX: cur_index=%d (mod=%d), avail_index=%d\n", 
259                //q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
260
261     PrintError("VIRTIO NIC:  sending packet to net_state %p, size:%d", virtio, size);
262
263     if (!raw) {
264         data_len -= hdr_len;
265     }
266
267     build_receive_header(&hdr, buf, 1);
268
269     //queue is not set yet
270     if (q->ring_avail_addr == 0) {
271         PrintError("Queue is not set\n");
272         return -1;
273     }
274
275     if (q->cur_avail_idx < q->avail->index) {
276         addr_t hdr_addr = 0;
277         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
278         uint16_t buf_idx = 0;
279         struct vring_desc * hdr_desc = NULL;
280
281         //PrintDebug("Descriptor index=%d\n", q->cur_avail_idx % q->queue_size);
282
283         hdr_desc = &(q->desc[hdr_idx]);
284
285         //PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
286                    //(void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);  
287
288         if (guest_pa_to_host_va(virtio->virtio_dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
289             PrintError("Could not translate receive buffer address\n");
290             return -1;
291         }
292
293         //copy header to the header descriptor
294         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
295
296         //Zheng 01/02/2010: zero payload
297         if (offset >= data_len) {
298             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
299         }
300
301         //copy data to the next descriptors
302         //Zheng 01/02/2010: put data into the next descriptor, rather than 0! 
303         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
304         //      for (buf_idx = 0; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
305             struct vring_desc * buf_desc = &(q->desc[buf_idx]);
306             uint32_t len = 0;
307
308             //Zheng 01/02/2010: commented this - we need to check 
309             //       if there still is some data left
310             //buf_desc->flags = VIRTIO_NEXT_FLAG;
311          
312             //PrintError("JACK: copying packet to up desc (len = %d)\n", data_len - offset);
313             //v3_hexdump(buf + offset, data_len - offset, NULL, 0);
314
315             len = copy_data_to_desc(virtio, buf_desc, buf + offset, data_len - offset);
316             
317             offset += len;
318
319             //Zheng 01/02/2010: check if there still is some data left 
320             if (offset < data_len) {
321                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
322             }
323
324             buf_desc->length = len;  // TODO: do we need this?
325             //PrintError("JACK: setting buffer descriptor length to %d)\n", buf_desc->length);
326         }
327
328         
329         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
330         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)
331
332         q->used->index++;
333         q->cur_avail_idx++;
334     }
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_net_state *virtio = (struct virtio_net_state *)dev->private_data;    
385     struct virtio_queue * q = &(virtio_state->tx_vq);
386
387     //PrintDebug("VIRTIO NIC pkt_tx: cur_index=%d (mod=%d), avail_index=%d\n", 
388               // q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
389
390     struct virtio_net_hdr * hdr = NULL;
391
392     while (q->cur_avail_idx < q->avail->index) {
393         struct vring_desc * hdr_desc = NULL;
394         addr_t hdr_addr = 0;
395         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
396         int desc_cnt = get_desc_count(q, desc_idx);
397         uint32_t req_len = 0;
398         int i = 0;
399
400         //PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % q->queue_size);
401
402         hdr_desc = &(q->desc[desc_idx]);
403
404         //PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
405                    //(void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);  
406
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         
414         //PrintDebug("NIC Op Hdr (ptr=%p) header len =%x\n", (void *)hdr_addr, (int)hdr->hdr_len);
415
416         desc_idx = hdr_desc->next;
417         
418         for (i = 0; i < desc_cnt - 1; i++) {    
419             struct vring_desc * buf_desc = &(q->desc[desc_idx]);
420
421             //PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
422                        //(void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
423
424             if (pkt_write(virtio_state, buf_desc) == -1) {
425                 PrintError("Error handling nic operation\n");
426                 return -1;
427             }
428
429             req_len += buf_desc->length;
430             desc_idx = buf_desc->next;
431         }
432
433         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
434         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
435
436         q->used->index++;
437         q->cur_avail_idx++;
438     }
439
440     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
441         //PrintDebug("Raising IRQ %d\n",  virtio_state->pci_dev->config_header.intr_line);
442         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
443         virtio_state->virtio_cfg.pci_isr = 0x1;
444     }
445
446     return 0;
447 }
448
449
450 static int virtio_setup_queue(struct virtio_net_state * virtio_state, struct virtio_queue * queue, addr_t pfn, addr_t page_addr) {
451     queue->pfn = pfn;
452                 
453     queue->ring_desc_addr = page_addr;
454     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
455     queue->ring_used_addr = ((queue->ring_avail_addr) + 
456                              (sizeof(struct vring_avail)) + 
457                              (queue->queue_size * sizeof(uint16_t)));
458                 
459     // round up to next page boundary.
460     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
461
462     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
463         PrintError("Could not translate ring descriptor address\n");
464          return -1;
465     }
466
467  
468     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
469         PrintError("Could not translate ring available address\n");
470         return -1;
471     }
472
473
474     if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
475         PrintError("Could not translate ring used address\n");
476         return -1;
477     }
478
479     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
480                (void *)(queue->ring_desc_addr),
481                (void *)(queue->ring_avail_addr),
482                (void *)(queue->ring_used_addr));
483     
484     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
485                queue->desc, queue->avail, queue->used);
486     
487     return 0;
488 }
489
490
491
492 static int virtio_io_write(uint16_t port, void * src, uint_t length, void * private_data) 
493 {
494     //struct vm_device * dev = (struct vm_device *)private_data;
495     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
496     int port_idx = port % virtio->io_range_size;
497
498
499     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
500                port, port_idx,  length, *(uint32_t *)src);
501
502
503     switch (port_idx) {
504         case GUEST_FEATURES_PORT:
505             if (length != 4) {
506                 PrintError("Illegal write length for guest features\n");
507                 return -1;
508             }
509             
510             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
511             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
512
513             break;
514         case VRING_PG_NUM_PORT:
515
516             if (length != 4) {
517                 PrintError("Illegal write length for page frame number\n");
518                 return -1;
519             }
520
521             addr_t pfn = *(uint32_t *)src;
522             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
523             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
524
525             switch (queue_idx) {
526                 case 0:
527                     virtio_setup_queue(virtio, &virtio->rx_vq, pfn, page_addr);
528                     break;
529                 case 1:
530                     virtio_setup_queue(virtio, &virtio->tx_vq, pfn, page_addr);
531                     break;
532                 case 2:
533                     virtio_setup_queue(virtio, &virtio->ctrl_vq, pfn, page_addr);
534                     break;
535                     
536                 default:
537                     break;
538             }
539             
540             break;
541         case VRING_Q_SEL_PORT:
542             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
543
544             if (virtio->virtio_cfg.vring_queue_selector > 2) {
545                 PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
546                            virtio->virtio_cfg.vring_queue_selector);
547                 return -1;
548             }
549
550             break;
551         case VRING_Q_NOTIFY_PORT: 
552             {
553                 uint16_t queue_idx = *(uint16_t *)src;     
554                 
555                 //PrintDebug("Handling Kick\n");
556                 
557                 if (queue_idx == 0){
558                     PrintDebug("receive queue notification 0, packet get by Guest\n");
559                 } else if (queue_idx == 1){
560                     if (handle_pkt_tx(virtio) == -1) {
561                         PrintError("Could not handle NIC Notification\n");
562                         return -1;
563                     }
564                 } else if (queue_idx == 2){
565                     if (handle_ctrl(virtio) == -1) {
566                         PrintError("Could not handle NIC Notification\n");
567                         return -1;
568                     }
569                 } else {
570                     PrintError("Virtio NIC device only uses 3 queue, selected %d\n", 
571                                queue_idx);
572                 }
573                 
574                 break;          
575             }
576         case VIRTIO_STATUS_PORT:
577             virtio->virtio_cfg.status = *(uint8_t *)src;
578
579             if (virtio->virtio_cfg.status == 0) {
580                 PrintDebug("Resetting device\n");
581                 virtio_reset(virtio);
582             }
583
584             break;
585
586         case VIRTIO_ISR_PORT:
587             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
588             break;
589         default:
590             return -1;
591             break;
592     }
593
594     return length;
595 }
596
597
598 static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * private_data) 
599 {
600    //struct vm_device * dev = (struct vm_device *)private_data;
601     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
602     int port_idx = port % virtio->io_range_size;
603     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
604
605     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d", private_data,
606                port, port_idx, length);
607         
608     switch (port_idx) {
609         case HOST_FEATURES_PORT:
610             if (length != 4) {
611                 PrintError("Illegal read length for host features\n");
612                 return -1;
613             }
614
615             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
616
617             PrintDebug("value=0x%x\n", *(uint32_t *)dst);
618         
619             break;
620         case VRING_PG_NUM_PORT:
621
622             if (length != 4) {
623                 PrintError("Illegal read length for page frame number\n");
624                 return -1;
625             }
626
627             switch (queue_idx) {
628                 case 0:
629                     *(uint32_t *)dst = virtio->rx_vq.pfn;
630                     break;
631                 case 1:
632                     *(uint32_t *)dst = virtio->tx_vq.pfn;
633                     break;      
634                 case 2:
635                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
636                     break;
637                 default:
638                     break;
639             }
640
641             PrintDebug(", value=0x%x\n", *(uint32_t *)dst);
642
643             break;
644         case VRING_SIZE_PORT:
645
646             if (length != 2) {
647                 PrintError("Illegal read length for vring size\n");
648                 return -1;
649             }
650
651             switch (queue_idx) {
652                 case 0:
653                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
654                     break;
655                 case 1:
656                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
657                     break;      
658                 case 2:
659                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
660                     break;
661                 default:
662                     break;
663             }
664
665             PrintDebug("queue index: %d, value=0x%x\n", (int)queue_idx, *(uint16_t *)dst);
666
667             break;
668         case VIRTIO_STATUS_PORT:
669
670             if (length != 1) {
671                 PrintError("Illegal read length for status\n");
672                 return -1;
673             }
674
675             *(uint8_t *)dst = virtio->virtio_cfg.status;
676
677             PrintDebug(", value=0x%x\n", *(uint8_t *)dst);
678             break;
679
680         case VIRTIO_ISR_PORT:
681             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
682             virtio->virtio_cfg.pci_isr = 0;
683             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
684
685             PrintDebug(", value=0x%x\n", *(uint8_t *)dst);
686                 
687             break;
688
689         default:
690             PrintError("Virtio NIC: Read of Unhandled Virtio Read\n");
691             return -1;
692     }
693
694     return length;
695 }
696
697
698 static struct v3_device_ops dev_ops = {
699     .free = virtio_free,
700     .reset = NULL,
701     .start = NULL,
702     .stop = NULL,
703 };
704
705
706 static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_state * net_state) 
707 {
708     struct pci_device * pci_dev = NULL;
709     struct v3_pci_bar bars[6];
710     int num_ports = sizeof(struct virtio_config);
711     int tmp_ports = num_ports;
712     int i;
713
714     // This gets the number of ports, rounded up to a power of 2
715     net_state->io_range_size = 1; // must be a power of 2
716     
717     while (tmp_ports > 0) {
718         tmp_ports >>= 1;
719         net_state->io_range_size <<= 1;
720     }
721         
722     // this is to account for any low order bits being set in num_ports
723     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
724     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
725         net_state->io_range_size >>= 1;
726     }
727     
728     
729     for (i = 0; i < 6; i++) {
730         bars[i].type = PCI_BAR_NONE;
731     }
732     
733     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
734     
735     bars[0].type = PCI_BAR_IO;
736     bars[0].default_base_port = -1;
737     bars[0].num_ports = net_state->io_range_size;
738     
739     bars[0].io_read = virtio_io_read;
740     bars[0].io_write = virtio_io_write;
741     bars[0].private_data = net_state;
742     
743     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
744                                      0, PCI_AUTO_DEV_NUM, 0,
745                                      "LNX_VIRTIO_NIC", bars,
746                                      NULL, NULL, NULL, net_state);
747     
748     if (!pci_dev) {
749         PrintError("Virtio NIC: Could not register PCI Device\n");
750         return -1;
751     }
752
753     PrintDebug("Virtio NIC:  registered to PCI bus\n");
754     
755     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
756     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
757         
758
759     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
760     pci_dev->config_header.class = PCI_CLASS_NETWORK;
761     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;
762     
763     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;;
764
765     pci_dev->config_header.intr_pin = 1;
766
767     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
768
769
770     net_state->pci_dev = pci_dev;
771     //net_state->pci_bus = pci_bus;
772     
773     net_state->virtio_cfg.host_features = 0; //no features support now
774
775     net_state->rx_vq.queue_size = QUEUE_SIZE;
776     net_state->tx_vq.queue_size = QUEUE_SIZE;
777     net_state->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
778
779     net_state->virtio_dev = virtio;
780
781     virtio_reset(net_state);
782
783     return 0;
784 }
785
786
787
788 static int connect_fn(struct guest_info * info, 
789                       void * frontend_data, 
790                       struct v3_dev_net_ops * ops, 
791                       v3_cfg_tree_t * cfg, 
792                       void * private_data) {
793     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
794     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
795
796     memset(net_state, 0, sizeof(struct virtio_net_state));
797
798     register_dev(virtio, net_state);
799
800     net_state->net_ops = ops;
801     net_state->backend_data = private_data;
802
803     return 0;
804 }
805
806 #if 1 
807 //temporary interface between Virtio-NIC and Vnet
808 //Treat vnet as backend, and virtio nic as frontend
809
810 //used when virtio_nic get a packet from guest and send it to the backend
811 // send packet to all of the virtio nic devices other than the sender
812 static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){
813
814     PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data);
815
816 #ifdef CONFIG_DEBUG_VIRTIO_NET
817     print_packet(buf, len);
818 #endif
819
820     v3_vnet_send_rawpkt(buf, len, private_data);
821     return 0;
822 }
823
824 //used to send packet to guest by a virtio nic
825 static int vnet_receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev){
826
827     return 0;
828 }
829
830 static int virtio_input(uchar_t * buf, uint_t len, void * private_data){
831     PrintDebug("Virito NIC: In virtio_input: guest net state %p\n", private_data);
832
833 #ifdef CONFIG_DEBUG_VIRTIO_NET
834     print_packet(buf, len);
835 #endif
836
837     return __virtio_dev_send(buf, len, private_data);
838 }
839
840
841 //register a virtio device to the vnet as backend
842 void register_virtio_to_vnet(struct vm_device  *dev, 
843                                                 char *dev_name,
844                                                 uchar_t mac[6]){
845     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
846     memset(net_state, 0, sizeof(struct virtio_net_state));
847
848     struct virtio_dev_state *virtio_state =  (struct virtio_dev_state *)dev->private_data;
849
850     net_state->net_ops = (struct v3_dev_net_ops *)V3_Malloc(sizeof(struct v3_dev_net_ops));
851
852     net_state->net_ops->send = &vnet_send;
853     net_state->net_ops->receive = &vnet_receive;
854
855     register_dev(virtio_state, net_state);
856         
857     PrintDebug("Virtio NIC After register Device %s: queue size: %d, %d\n", dev->name,
858                net_state->rx_vq.queue_size, net_state->tx_vq.queue_size);
859
860     PrintDebug("VNET: connect virtio nic state %p to vnet\n", net_state);
861
862     //add a device link to link table
863     int idx = vnet_register_device(dev, dev_name, mac, &virtio_input, net_state);
864
865     uchar_t srcmac[6] = {0x00,0x02,0x55,0x67,0x42,0x39};
866     uchar_t dstmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
867     uchar_t zeromac[6] = {0,0,0,0,0,0};
868
869     vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
870     if (idx == 0)
871         vnet_add_route_entry(zeromac, srcmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
872     if (idx == 1)
873         vnet_add_route_entry(srcmac, zeromac, MAC_NONE, MAC_ANY, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
874                 
875 }
876
877 #endif
878
879 static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
880     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
881     struct virtio_dev_state * virtio_state = NULL;
882     char * name = v3_cfg_val(cfg, "name");
883
884     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", name);
885
886     if (pci_bus == NULL) {
887         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
888         return -1;
889     }
890
891     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
892     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
893
894     INIT_LIST_HEAD(&(virtio_state->dev_list));
895     virtio_state->pci_bus = pci_bus;
896     virtio_state->vm = vm;
897
898     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
899     if (v3_attach_device(vm, dev) == -1) {
900         PrintError("Virtio NIC: Could not attach device %s\n", name);
901         return -1;
902     }
903
904     if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
905         PrintError("Virtio NIC: Could not register %s as net frontend\n", name);
906         return -1;
907     }
908
909
910     //for temporary testing, add a backend
911 #if 0
912         
913     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
914     memset(net_state, 0, sizeof(struct virtio_net_state));
915
916     net_state->net_ops = (struct v3_dev_net_ops *)V3_Malloc(sizeof(struct v3_dev_net_ops));
917
918     net_state->net_ops->send = &send;
919     net_state->net_ops->receive = &receive;
920
921     register_dev(virtio_state, net_state);
922         
923     PrintDebug("Virtio NIC After register Device %s: queue size: %d, %d\n", dev->name,
924                net_state->rx_vq.queue_size, net_state->tx_vq.queue_size);
925
926     temp_net_states[net_idx ++] = net_state;
927
928     PrintDebug("Net_states: 0: %p, 1: %p, 2: %p\n", temp_net_states[0], temp_net_states[1], temp_net_states[2]);
929
930 #endif
931
932 #if 1  //test interface between vnet & virtio-nic
933
934     uchar_t mac[6] = {0,0,0,0,0,0};
935     register_virtio_to_vnet(dev, name,mac);
936
937 #endif
938         
939     return 0;
940 }
941
942 device_register("LNX_VIRTIO_NIC", virtio_init)
943