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.


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