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.


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