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.


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