Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Fix to direct host network bridge
[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) 2010, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2010, Cui Zheng <cuizheng@cs.unm.edu>
12  * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Lei Xia <lxia@northwestern.edu>
16  *         Cui Zheng <cuizheng@cs.unm.edu>
17  *               
18  *
19  * This is free software.  You are permitted to use,
20  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21  */
22  
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_dev_mgr.h>
25 #include <devices/lnx_virtio_pci.h>
26 #include <palacios/vm_guest_mem.h>
27 #include <palacios/vmm_sprintf.h>
28 #include <palacios/vmm_vnet.h>
29 #include <palacios/vmm_lock.h>
30 #include <palacios/vmm_util.h>
31 #include <devices/pci.h>
32
33
34 #ifndef CONFIG_DEBUG_VIRTIO_NET
35 #undef PrintDebug
36 #define PrintDebug(fmt, args...)
37 #endif
38
39 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
40 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
41
42 struct virtio_net_hdr {
43         uint8_t flags;
44
45 #define VIRTIO_NET_HDR_GSO_NONE         0       /* Not a GSO frame */
46         uint8_t gso_type;
47         uint16_t hdr_len;               /* Ethernet + IP + tcp/udp hdrs */
48         uint16_t gso_size;              /* Bytes to append to hdr_len per frame */
49         uint16_t csum_start;            /* Position to start checksumming from */
50         uint16_t csum_offset;           /* Offset after that to place checksum */
51 }__attribute__((packed));
52
53
54 /* This is the version of the header to use when the MRG_RXBUF
55  * feature has been negotiated. */
56 struct virtio_net_hdr_mrg_rxbuf {
57         struct virtio_net_hdr hdr;
58         uint16_t num_buffers;   /* Number of merged rx buffers */
59 };
60
61         
62 #define TX_QUEUE_SIZE 64
63 #define RX_QUEUE_SIZE 1024
64 #define CTRL_QUEUE_SIZE 64
65 #define ETH_ALEN 6
66
67 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
68 #define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
69 #define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
70 #define VIRTIO_NET_F_HOST_TSO4  11      /* Host can handle TSOv4 in. */
71
72 struct virtio_net_config
73 {
74     uint8_t mac[ETH_ALEN];      /* VIRTIO_NET_F_MAC */
75     uint16_t status;
76 } __attribute__((packed));
77
78 struct virtio_dev_state {
79     struct vm_device * pci_bus;
80     struct list_head dev_list;
81     struct v3_vm_info *vm;
82 };
83
84 struct virtio_net_state {
85     struct virtio_net_config net_cfg;
86     struct virtio_config virtio_cfg;
87
88     struct vm_device * dev;
89     struct pci_device * pci_dev; 
90     int io_range_size;
91     
92     struct virtio_queue rx_vq;          /* idx 0, pkts to guest */
93     struct virtio_queue tx_vq;          /* idx 1, pkts from guest */
94     struct virtio_queue ctrl_vq;        /* idx 2 */
95
96     int buffed_rx;
97     int tx_disabled;                    /* stop TX pkts from guest */
98
99     uint64_t pkt_sent, pkt_recv, pkt_drop;
100
101     struct v3_dev_net_ops * net_ops;
102     v3_lock_t rx_lock, tx_lock;
103
104     void * backend_data;
105     struct virtio_dev_state * virtio_dev;
106     struct list_head dev_link;
107 };
108
109 /* virtio nic error type */
110 #define ERR_VIRTIO_OTHER  1
111 #define ERR_VIRTIO_RXQ_FULL  2
112 #define ERR_VIRTIO_RXQ_NOSET  3
113 #define ERR_VIRTIO_TXQ_NOSET 4
114 #define ERR_VIRTIO_TXQ_FULL 5
115 #define ERR_VIRTIO_TXQ_DISABLED 6
116
117
118
119
120 static int virtio_init_state(struct virtio_net_state * virtio) 
121 {
122     virtio->rx_vq.queue_size = RX_QUEUE_SIZE;
123     virtio->tx_vq.queue_size = TX_QUEUE_SIZE;
124     virtio->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
125
126     virtio->rx_vq.ring_desc_addr = 0;
127     virtio->rx_vq.ring_avail_addr = 0;
128     virtio->rx_vq.ring_used_addr = 0;
129     virtio->rx_vq.pfn = 0;
130     virtio->rx_vq.cur_avail_idx = 0;
131
132     virtio->tx_vq.ring_desc_addr = 0;
133     virtio->tx_vq.ring_avail_addr = 0;
134     virtio->tx_vq.ring_used_addr = 0;
135     virtio->tx_vq.pfn = 0;
136     virtio->tx_vq.cur_avail_idx = 0;
137
138     virtio->ctrl_vq.ring_desc_addr = 0;
139     virtio->ctrl_vq.ring_avail_addr = 0;
140     virtio->ctrl_vq.ring_used_addr = 0;
141     virtio->ctrl_vq.pfn = 0;
142     virtio->ctrl_vq.cur_avail_idx = 0;
143
144     virtio->virtio_cfg.pci_isr = 0;
145         
146     virtio->virtio_cfg.host_features = 0; // (1 << VIRTIO_NET_F_MAC);
147
148     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
149         (v3_lock_init(&(virtio->tx_lock)) == -1)){
150         PrintError("Virtio NIC: Failure to init locks for net_state\n");
151     }
152
153     virtio->pkt_sent = virtio->pkt_recv = virtio->pkt_drop = 0;
154     virtio->buffed_rx = 0;
155
156     return 0;
157 }
158
159 static int 
160 pkt_tx(struct guest_info * core, 
161        struct virtio_net_state * virtio, 
162        struct vring_desc * buf_desc) 
163 {
164     uint8_t * buf = NULL;
165     uint32_t len = buf_desc->length;
166
167     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
168         PrintError("Could not translate buffer address\n");
169         return -ERR_VIRTIO_OTHER;
170     }
171
172     return virtio->net_ops->send(buf, len, virtio->backend_data);
173 }
174
175
176 static int 
177 copy_data_to_desc(struct guest_info * core, 
178                   struct virtio_net_state * virtio_state, 
179                   struct vring_desc * desc, 
180                   uchar_t * buf, 
181                   uint_t buf_len,
182                   uint_t offset)
183 {
184     uint32_t len;
185     uint8_t * desc_buf = NULL;
186
187     if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
188         PrintError("Could not translate buffer address\n");
189         return -1;
190     }
191     len = (desc->length < buf_len)?(desc->length - offset):buf_len;
192     memcpy(desc_buf+offset, buf, len);
193
194     return len;
195 }
196
197
198 static int get_desc_count(struct virtio_queue * q, int index) {
199     struct vring_desc * tmp_desc = &(q->desc[index]);
200     int cnt = 1;
201     
202     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
203         tmp_desc = &(q->desc[tmp_desc->next]);
204         cnt++;
205     }
206
207     return cnt;
208 }
209
210 static inline void enable_cb(struct virtio_queue *queue){
211     queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
212 }
213
214 static inline void disable_cb(struct virtio_queue *queue) {
215     queue->used->flags |= VRING_NO_NOTIFY_FLAG;
216 }
217
218
219 /* interrupt the guest, so the guest core get EXIT to Palacios
220  * this happens when there are either incoming pkts for the guest
221  * or the guest can start TX pkts again */
222 static inline void notify_guest(struct virtio_net_state * virtio){
223     v3_interrupt_cpu(virtio->virtio_dev->vm, virtio->virtio_dev->vm->cores[0].cpu_id, 0);
224 }
225
226
227 /* guest free some pkts from rx queue */
228 static int handle_rx_kick(struct guest_info *core, 
229                           struct virtio_net_state * virtio) 
230 {
231     unsigned long flags;
232
233     flags = v3_lock_irqsave(virtio->rx_lock);
234
235     if(virtio->net_ops->start_rx != NULL){
236         virtio->net_ops->start_rx(virtio->backend_data);
237     }
238         //disable_cb(&virtio->rx_vq);
239
240     v3_unlock_irqrestore(virtio->rx_lock, flags);
241         
242     return 0;
243 }
244
245
246 static int handle_ctrl(struct guest_info *core, 
247                        struct virtio_net_state * virtio) {
248         
249     return 0;
250 }
251
252 static int handle_pkt_tx(struct guest_info *core, 
253                          struct virtio_net_state * virtio_state) 
254 {
255     struct virtio_queue * q = &(virtio_state->tx_vq);
256     struct virtio_net_hdr * hdr = NULL;
257     int recved = 0;
258     unsigned long flags;
259
260     if (!q->ring_avail_addr) 
261         return -ERR_VIRTIO_TXQ_NOSET;
262
263     if(virtio_state->tx_disabled)
264         return -ERR_VIRTIO_TXQ_DISABLED;
265
266     flags = v3_lock_irqsave(virtio_state->tx_lock);
267     while (q->cur_avail_idx != q->avail->index) {
268         struct vring_desc * hdr_desc = NULL;
269         addr_t hdr_addr = 0;
270         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
271         int desc_cnt = get_desc_count(q, desc_idx);
272         uint32_t req_len = 0;
273         int i = 0;
274
275         hdr_desc = &(q->desc[desc_idx]);
276         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
277             PrintError("Could not translate block header address\n");
278             goto exit_error;
279         }
280
281         hdr = (struct virtio_net_hdr*)hdr_addr;
282         desc_idx = hdr_desc->next;
283
284         if(desc_cnt > 2){
285             PrintError("VNIC: merged rx buffer not supported\n");
286             goto exit_error;
287         }
288
289         /* here we assumed that one ethernet pkt is not splitted into multiple virtio buffer */
290         for (i = 0; i < desc_cnt - 1; i++) {    
291             struct vring_desc * buf_desc = &(q->desc[desc_idx]);
292             if (pkt_tx(core, virtio_state, buf_desc) == -1) {
293                 PrintError("Error handling nic operation\n");
294                 goto exit_error;
295             }
296
297             req_len += buf_desc->length;
298             desc_idx = buf_desc->next;
299         }
300         virtio_state->pkt_sent ++;
301         recved ++;
302
303         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
304         q->used->ring[q->used->index % q->queue_size].length = req_len; // What do we set this to????
305         q->used->index ++;
306         
307         q->cur_avail_idx ++;
308     }
309
310     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
311
312     if(!recved)
313         return 0;
314         
315     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
316         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
317         virtio_state->virtio_cfg.pci_isr = 0x1;
318     }
319
320     return 0;
321
322 exit_error:
323         
324     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
325     return -ERR_VIRTIO_OTHER;
326 }
327
328
329 static int virtio_setup_queue(struct guest_info *core, 
330                               struct virtio_net_state * virtio_state, 
331                               struct virtio_queue * queue, 
332                               addr_t pfn, addr_t page_addr) {
333     queue->pfn = pfn;
334                 
335     queue->ring_desc_addr = page_addr;
336     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
337     queue->ring_used_addr = ((queue->ring_avail_addr) + 
338                              (sizeof(struct vring_avail)) + 
339                              (queue->queue_size * sizeof(uint16_t)));
340
341     // round up to next page boundary.
342     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
343     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
344         PrintError("Could not translate ring descriptor address\n");
345          return -1;
346     }
347  
348     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
349         PrintError("Could not translate ring available address\n");
350         return -1;
351     }
352
353     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
354         PrintError("Could not translate ring used address\n");
355         return -1;
356     }
357
358     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
359                (void *)(queue->ring_desc_addr),
360                (void *)(queue->ring_avail_addr),
361                (void *)(queue->ring_used_addr));
362     
363     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
364                queue->desc, queue->avail, queue->used);
365     
366     return 0;
367 }
368
369 static int virtio_io_write(struct guest_info *core, 
370                            uint16_t port, void * src, 
371                            uint_t length, void * private_data) 
372 {
373     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
374     int port_idx = port % virtio->io_range_size;
375
376     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
377                port, port_idx,  length, *(uint32_t *)src);
378
379     switch (port_idx) {
380         case GUEST_FEATURES_PORT:
381             if (length != 4) {
382                 PrintError("Illegal write length for guest features\n");
383                 return -1;
384             }       
385             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
386             break;
387                 
388         case VRING_PG_NUM_PORT:
389             if (length != 4) {
390                 PrintError("Illegal write length for page frame number\n");
391                 return -1;
392             }
393             addr_t pfn = *(uint32_t *)src;
394             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
395             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
396             switch (queue_idx) {
397                 case 0:
398                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
399                     //disable_cb(&virtio->rx_vq);
400                     break;
401                 case 1:
402                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
403                     //disable_cb(&virtio->tx_vq);
404                     break;
405                 case 2:
406                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
407                     break;          
408                 default:
409                     break;
410             }
411             break;
412                 
413         case VRING_Q_SEL_PORT:
414             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
415             if (virtio->virtio_cfg.vring_queue_selector > 2) {
416                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
417                            virtio->virtio_cfg.vring_queue_selector);
418                 return -1;
419             }
420             break;
421                 
422         case VRING_Q_NOTIFY_PORT: 
423             {
424                 uint16_t queue_idx = *(uint16_t *)src;                  
425                 if (queue_idx == 0){
426                     handle_rx_kick(core, virtio);
427                 } else if (queue_idx == 1){
428                     if (handle_pkt_tx(core, virtio) == -1) {
429                         PrintError("Could not handle NIC Notification\n");
430                         return -1;
431                     }
432                 } else if (queue_idx == 2){
433                     if (handle_ctrl(core, virtio) == -1) {
434                         PrintError("Could not handle NIC Notification\n");
435                         return -1;
436                     }
437                 } else {
438                     PrintError("Wrong queue index %d\n", queue_idx);
439                 }       
440                 break;          
441             }
442         
443         case VIRTIO_STATUS_PORT:
444             virtio->virtio_cfg.status = *(uint8_t *)src;
445             if (virtio->virtio_cfg.status == 0) {
446                 PrintDebug("Resetting device\n");
447                 virtio_init_state(virtio);
448             }
449             break;
450
451         case VIRTIO_ISR_PORT:
452             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
453             break;
454                 
455         default:
456             return -1;
457             break;
458     }
459
460     return length;
461 }
462
463 static int virtio_io_read(struct guest_info *core, 
464                           uint16_t port, void * dst, 
465                           uint_t length, void * private_data) 
466 {
467     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
468     int port_idx = port % virtio->io_range_size;
469     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
470
471     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d\n", private_data,
472                port, port_idx, length);
473         
474     switch (port_idx) {
475         case HOST_FEATURES_PORT:
476             if (length != 4) {
477                 PrintError("Illegal read length for host features\n");
478                 return -1;
479             }
480             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
481             break;
482
483         case VRING_PG_NUM_PORT:
484             if (length != 4) {
485                 PrintError("Illegal read length for page frame number\n");
486                 return -1;
487             }
488             switch (queue_idx) {
489                 case 0:
490                     *(uint32_t *)dst = virtio->rx_vq.pfn;
491                     break;
492                 case 1:
493                     *(uint32_t *)dst = virtio->tx_vq.pfn;
494                     break;      
495                 case 2:
496                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
497                     break;
498                 default:
499                     break;
500             }
501             break;
502
503         case VRING_SIZE_PORT:
504             if (length != 2) {
505                 PrintError("Illegal read length for vring size\n");
506                 return -1;
507             }
508             switch (queue_idx) {
509                 case 0:
510                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
511                     break;
512                 case 1:
513                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
514                     break;      
515                 case 2:
516                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
517                     break;
518                 default:
519                     break;
520             }
521             break;
522
523         case VIRTIO_STATUS_PORT:
524             if (length != 1) {
525                 PrintError("Illegal read length for status\n");
526                 return -1;
527             }
528             *(uint8_t *)dst = virtio->virtio_cfg.status;
529             break;
530                 
531         case VIRTIO_ISR_PORT:
532             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
533             virtio->virtio_cfg.pci_isr = 0;
534             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
535             break;
536
537         default:
538             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", port_idx);
539             return -1;
540     }
541
542     return length;
543 }
544
545
546 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
547     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
548     struct virtio_queue * q = &(virtio->rx_vq);
549     struct virtio_net_hdr_mrg_rxbuf hdr;
550     uint32_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
551     uint32_t data_len = size;
552     uint32_t offset = 0;
553     unsigned long flags;
554     int ret_val = -ERR_VIRTIO_OTHER;
555     int raw = 1;
556
557 #ifndef CONFIG_DEBUG_VIRTIO_NET
558    {
559         PrintDebug("Virtio-NIC: virtio_rx: size: %d\n", size);  
560         //v3_hexdump(buf, size, NULL, 0);
561    }
562 #endif
563
564     flags = v3_lock_irqsave(virtio->rx_lock);
565
566     virtio->pkt_recv ++;
567     if (!raw)
568         data_len -= hdr_len;
569
570     if (!raw)
571         memcpy(&hdr, buf, sizeof(struct virtio_net_hdr_mrg_rxbuf));
572     else
573         memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
574
575     if (q->ring_avail_addr == 0) {
576         PrintError("Queue is not set\n");
577         ret_val = -ERR_VIRTIO_RXQ_NOSET;
578         goto exit;
579     }
580
581     if (q->cur_avail_idx != q->avail->index){
582         addr_t hdr_addr = 0;
583         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
584         uint16_t buf_idx = 0;
585         struct vring_desc * hdr_desc = NULL;
586
587         hdr_desc = &(q->desc[hdr_idx]);
588         if (v3_gpa_to_hva(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
589             PrintError("Could not translate receive buffer address\n");
590             goto exit;
591         }
592         hdr.num_buffers = 1;
593         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr_mrg_rxbuf));
594         if (offset >= data_len) {
595             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
596         }
597
598         struct vring_desc * buf_desc = NULL;
599         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
600             uint32_t len = 0;
601             buf_desc = &(q->desc[buf_idx]);
602
603             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset, 0);     
604             offset += len;
605             if (offset < data_len) {
606                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
607             }
608             buf_desc->length = len;
609         }
610         buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
611         
612         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
613         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) */
614         q->used->index++;
615         q->cur_avail_idx++;
616
617         /* if there are certain num of pkts in the RX queue, notify guest 
618           * so guest will exit to palacios
619          * when it returns, guest gets the virtio rx interrupt */
620         if((++virtio->buffed_rx > q->queue_size/5) &&
621             (q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
622             if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
623                   notify_guest(virtio);
624             }
625             virtio->buffed_rx = 0;
626         }
627     } else {
628         virtio->pkt_drop++;
629         /* RX queue is full,  tell backend to stop RX on this device */
630         virtio->net_ops->stop_rx(virtio->backend_data);
631         enable_cb(&virtio->rx_vq);
632         
633         ret_val = -ERR_VIRTIO_RXQ_FULL;
634         goto exit;
635     }
636
637     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
638         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
639         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
640         virtio->virtio_cfg.pci_isr = 0x1;
641     }
642
643     ret_val = offset;
644
645 exit:
646
647     v3_unlock_irqrestore(virtio->rx_lock, flags);
648  
649     return ret_val;
650 }
651
652 static int virtio_free(struct virtio_net_state * virtio) {
653         
654     // unregister from PCI
655
656     V3_Free(virtio);
657     return 0;
658 }
659
660
661 static struct v3_device_ops dev_ops = {
662     .free = (int (*)(void *))virtio_free,
663 };
664
665
666 /* TODO: Issue here: which vm info it needs? calling VM or the device's own VM? */
667 static void virtio_nic_poll(struct v3_vm_info * vm, void * data){
668     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
669         
670     handle_pkt_tx(&(vm->cores[0]), virtio);
671 }
672
673 static void virtio_start_tx(void * data){
674     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
675     unsigned long flags;
676
677     flags = v3_lock_irqsave(virtio->tx_lock);
678     virtio->tx_disabled = 0;
679
680     /* notify the device's guest to start sending pkt */
681     if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
682         notify_guest(virtio);
683     }
684     v3_unlock_irqrestore(virtio->tx_lock, flags);       
685 }
686
687 static void virtio_stop_tx(void * data){
688     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
689     unsigned long flags;
690
691     flags = v3_lock_irqsave(virtio->tx_lock);
692     virtio->tx_disabled = 1;
693
694     /* stop the guest to exit to palacios for sending pkt? */
695     if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
696        disable_cb(&virtio->tx_vq);
697     }
698
699     v3_unlock_irqrestore(virtio->tx_lock, flags);
700 }
701
702         
703
704
705 static int register_dev(struct virtio_dev_state * virtio, 
706                         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     while (tmp_ports > 0) {
717         tmp_ports >>= 1;
718         net_state->io_range_size <<= 1;
719     }
720         
721     // this is to account for any low order bits being set in num_ports
722     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
723     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
724         net_state->io_range_size >>= 1;
725     }
726     
727     for (i = 0; i < 6; i++) {
728         bars[i].type = PCI_BAR_NONE;
729     }
730     
731     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
732     
733     bars[0].type = PCI_BAR_IO;
734     bars[0].default_base_port = -1;
735     bars[0].num_ports = net_state->io_range_size;
736     bars[0].io_read = virtio_io_read;
737     bars[0].io_write = virtio_io_write;
738     bars[0].private_data = net_state;
739     
740     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
741                                      0, 4/*PCI_AUTO_DEV_NUM*/, 0,
742                                      "LNX_VIRTIO_NIC", bars,
743                                      NULL, NULL, NULL, net_state);
744     
745     if (!pci_dev) {
746         PrintError("Virtio NIC: Could not register PCI Device\n");
747         return -1;
748     }
749
750     PrintDebug("Virtio NIC:  registered to PCI bus\n");
751     
752     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
753     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
754         
755
756     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
757     pci_dev->config_header.class = PCI_CLASS_NETWORK;
758     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
759     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
760     pci_dev->config_header.intr_pin = 1;
761     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
762
763     net_state->pci_dev = pci_dev;
764     net_state->virtio_dev = virtio;
765
766     uchar_t mac[6] = {0x11,0x11,0x11,0x11,0x11,0x11};
767     memcpy(net_state->net_cfg.mac, mac, 6);
768                                                                                                            
769     memcpy(pci_dev->config_data, net_state->net_cfg.mac, ETH_ALEN);
770     
771     virtio_init_state(net_state);
772
773     return 0;
774 }
775
776 static int connect_fn(struct v3_vm_info * info, 
777                       void * frontend_data, 
778                       struct v3_dev_net_ops * ops, 
779                       v3_cfg_tree_t * cfg, 
780                       void * private_data) {
781     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
782     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
783
784     memset(net_state, 0, sizeof(struct virtio_net_state));
785     register_dev(virtio, net_state);
786
787     net_state->net_ops = ops;
788     net_state->backend_data = private_data;
789     net_state->virtio_dev = virtio;
790         
791
792     ops->recv = virtio_rx;
793     ops->poll = virtio_nic_poll;
794     ops->start_tx = virtio_start_tx;
795     ops->stop_tx = virtio_stop_tx;
796     ops->frontend_data = net_state;
797
798     return 0;
799 }
800
801 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
802     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
803     struct virtio_dev_state * virtio_state = NULL;
804     char * dev_id = v3_cfg_val(cfg, "ID");
805
806     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", dev_id);
807
808     if (pci_bus == NULL) {
809         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
810         return -1;
811     }
812
813     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
814     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
815
816     INIT_LIST_HEAD(&(virtio_state->dev_list));
817     virtio_state->pci_bus = pci_bus;
818     virtio_state->vm = vm;
819
820     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
821
822     if (dev == NULL) {
823         PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
824         V3_Free(virtio_state);
825         return -1;
826     }
827
828     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
829         PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
830         v3_remove_device(dev);
831         return -1;
832     }
833         
834     return 0;
835 }
836
837 device_register("LNX_VIRTIO_NIC", virtio_init)
838