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.


changed device registration interface
[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
379     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
380                port, port_idx,  length, *(uint32_t *)src);
381
382     switch (port_idx) {
383         case GUEST_FEATURES_PORT:
384             if (length != 4) {
385                 PrintError("Illegal write length for guest features\n");
386                 return -1;
387             }       
388             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
389             break;
390                 
391         case VRING_PG_NUM_PORT:
392             if (length != 4) {
393                 PrintError("Illegal write length for page frame number\n");
394                 return -1;
395             }
396             addr_t pfn = *(uint32_t *)src;
397             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
398             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
399             switch (queue_idx) {
400                 case 0:
401                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
402                     disable_cb(&virtio->rx_vq);
403                     break;
404                 case 1:
405                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
406                     disable_cb(&virtio->tx_vq);
407                     break;
408                 case 2:
409                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
410                     break;          
411                 default:
412                     break;
413             }
414             break;
415                 
416         case VRING_Q_SEL_PORT:
417             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
418             if (virtio->virtio_cfg.vring_queue_selector > 2) {
419                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
420                            virtio->virtio_cfg.vring_queue_selector);
421                 return -1;
422             }
423             break;
424                 
425         case VRING_Q_NOTIFY_PORT: 
426             {
427                 uint16_t queue_idx = *(uint16_t *)src;                  
428                 if (queue_idx == 0){
429                     handle_rx_kick(core, virtio);
430                     PrintError("rx kick\n");
431                 } else if (queue_idx == 1){
432                     PrintError("tx kick\n");
433                     if (handle_pkt_tx(core, virtio) == -1) {
434                         PrintError("Could not handle NIC Notification\n");
435                         return -1;
436                     }
437                 } else if (queue_idx == 2){
438                     if (handle_ctrl(core, virtio) == -1) {
439                         PrintError("Could not handle NIC Notification\n");
440                         return -1;
441                     }
442                 } else {
443                     PrintError("Wrong queue index %d\n", queue_idx);
444                 }       
445                 break;          
446             }
447         
448         case VIRTIO_STATUS_PORT:
449             virtio->virtio_cfg.status = *(uint8_t *)src;
450             if (virtio->virtio_cfg.status == 0) {
451                 PrintDebug("Resetting device\n");
452                 virtio_init_state(virtio);
453             }
454             break;
455
456         case VIRTIO_ISR_PORT:
457             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
458             break;
459                 
460         default:
461             return -1;
462             break;
463     }
464
465     return length;
466 }
467
468 static int virtio_io_read(struct guest_info *core, 
469                           uint16_t port, void * dst, 
470                           uint_t length, void * private_data) 
471 {
472     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
473     int port_idx = port % virtio->io_range_size;
474     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
475
476     PrintDebug("Virtio NIC %p: Read  for port %d (index =%d), length=%d\n", private_data,
477                port, port_idx, length);
478         
479     switch (port_idx) {
480         case HOST_FEATURES_PORT:
481             if (length != 4) {
482                 PrintError("Illegal read length for host features\n");
483                 return -1;
484             }
485             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
486             break;
487
488         case VRING_PG_NUM_PORT:
489             if (length != 4) {
490                 PrintError("Illegal read length for page frame number\n");
491                 return -1;
492             }
493             switch (queue_idx) {
494                 case 0:
495                     *(uint32_t *)dst = virtio->rx_vq.pfn;
496                     break;
497                 case 1:
498                     *(uint32_t *)dst = virtio->tx_vq.pfn;
499                     break;      
500                 case 2:
501                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
502                     break;
503                 default:
504                     break;
505             }
506             break;
507
508         case VRING_SIZE_PORT:
509             if (length != 2) {
510                 PrintError("Illegal read length for vring size\n");
511                 return -1;
512             }
513             switch (queue_idx) {
514                 case 0:
515                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
516                     break;
517                 case 1:
518                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
519                     break;      
520                 case 2:
521                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
522                     break;
523                 default:
524                     break;
525             }
526             break;
527
528         case VIRTIO_STATUS_PORT:
529             if (length != 1) {
530                 PrintError("Illegal read length for status\n");
531                 return -1;
532             }
533             *(uint8_t *)dst = virtio->virtio_cfg.status;
534             break;
535                 
536         case VIRTIO_ISR_PORT:
537             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
538             virtio->virtio_cfg.pci_isr = 0;
539             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
540             break;
541
542         default:
543             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", port_idx);
544             return -1;
545     }
546
547     return length;
548 }
549
550
551 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
552     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
553     struct virtio_queue * q = &(virtio->rx_vq);
554     struct virtio_net_hdr_mrg_rxbuf hdr;
555     uint32_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
556     uint32_t data_len = size;
557     uint32_t offset = 0;
558     unsigned long flags;
559     int ret_val = -ERR_VIRTIO_OTHER;
560     int raw = 1;
561
562     flags = v3_lock_irqsave(virtio->rx_lock);
563
564     virtio->pkt_recv ++;
565     if (!raw)
566         data_len -= hdr_len;
567
568     if (!raw)
569         memcpy(&hdr, buf, sizeof(struct virtio_net_hdr_mrg_rxbuf));
570     else
571         memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
572
573     if (q->ring_avail_addr == 0) {
574         PrintError("Queue is not set\n");
575         ret_val = -ERR_VIRTIO_RXQ_NOSET;
576         goto exit;
577     }
578
579     if (q->cur_avail_idx != q->avail->index){
580         addr_t hdr_addr = 0;
581         uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
582         uint16_t buf_idx = 0;
583         struct vring_desc * hdr_desc = NULL;
584
585         hdr_desc = &(q->desc[hdr_idx]);
586         if (v3_gpa_to_hva(&(virtio->virtio_dev->vm->cores[0]), hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
587             PrintError("Could not translate receive buffer address\n");
588             goto exit;
589         }
590         hdr.num_buffers = 1;
591         memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr_mrg_rxbuf));
592         if (offset >= data_len) {
593             hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
594         }
595
596         struct vring_desc * buf_desc = NULL;
597         for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
598             uint32_t len = 0;
599             buf_desc = &(q->desc[buf_idx]);
600
601             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset, 0);     
602             offset += len;
603             if (offset < data_len) {
604                 buf_desc->flags = VIRTIO_NEXT_FLAG;             
605             }
606             buf_desc->length = len;
607         }
608         buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
609         
610         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
611         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) */
612         q->used->index++;
613         q->cur_avail_idx++;
614
615         /* if there are certain num of pkts in the RX queue, notify guest 
616           * so guest will exit to palacios
617          * when it returns, guest gets the virtio rx interrupt */
618         if((++virtio->buffed_rx > q->queue_size/5) &&
619             (q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
620             if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
621                   notify_guest(virtio);
622             }
623             virtio->buffed_rx = 0;
624         }
625     } else {
626         virtio->pkt_drop++;
627         /* RX queue is full,  tell backend to stop RX on this device */
628         virtio->net_ops->stop_rx(virtio->backend_data);
629         enable_cb(&virtio->rx_vq);
630         
631         ret_val = -ERR_VIRTIO_RXQ_FULL;
632         goto exit;
633     }
634
635     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
636         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
637         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
638         virtio->virtio_cfg.pci_isr = 0x1;
639     }
640
641     ret_val = offset;
642
643 exit:
644
645     v3_unlock_irqrestore(virtio->rx_lock, flags);
646  
647     return ret_val;
648 }
649
650
651 static struct v3_device_ops dev_ops = {
652     .free = virtio_free,
653 };
654
655
656 /* TODO: Issue here: which vm info it needs? calling VM or the device's own VM? */
657 static void virtio_nic_poll(struct v3_vm_info * vm, void * data){
658     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
659         
660     handle_pkt_tx(&(vm->cores[0]), virtio);
661 }
662
663 static void virtio_start_tx(void * data){
664     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
665     unsigned long flags;
666
667     flags = v3_lock_irqsave(virtio->tx_lock);
668     virtio->tx_disabled = 0;
669
670     /* notify the device's guest to start sending pkt */
671     if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
672         notify_guest(virtio);
673     }
674     v3_unlock_irqrestore(virtio->tx_lock, flags);       
675 }
676
677 static void virtio_stop_tx(void * data){
678     struct virtio_net_state * virtio = (struct virtio_net_state *)data;
679     unsigned long flags;
680
681     flags = v3_lock_irqsave(virtio->tx_lock);
682     virtio->tx_disabled = 1;
683
684     /* stop the guest to exit to palacios for sending pkt? */
685     if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){
686        disable_cb(&virtio->tx_vq);
687     }
688
689     v3_unlock_irqrestore(virtio->tx_lock, flags);
690 }
691
692         
693
694
695 static int register_dev(struct virtio_dev_state * virtio, 
696                         struct virtio_net_state * net_state) 
697 {
698     struct pci_device * pci_dev = NULL;
699     struct v3_pci_bar bars[6];
700     int num_ports = sizeof(struct virtio_config);
701     int tmp_ports = num_ports;
702     int i;
703
704     // This gets the number of ports, rounded up to a power of 2
705     net_state->io_range_size = 1; // must be a power of 2
706     while (tmp_ports > 0) {
707         tmp_ports >>= 1;
708         net_state->io_range_size <<= 1;
709     }
710         
711     // this is to account for any low order bits being set in num_ports
712     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
713     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
714         net_state->io_range_size >>= 1;
715     }
716     
717     for (i = 0; i < 6; i++) {
718         bars[i].type = PCI_BAR_NONE;
719     }
720     
721     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
722     
723     bars[0].type = PCI_BAR_IO;
724     bars[0].default_base_port = -1;
725     bars[0].num_ports = net_state->io_range_size;
726     bars[0].io_read = virtio_io_read;
727     bars[0].io_write = virtio_io_write;
728     bars[0].private_data = net_state;
729     
730     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
731                                      0, 4/*PCI_AUTO_DEV_NUM*/, 0,
732                                      "LNX_VIRTIO_NIC", bars,
733                                      NULL, NULL, NULL, net_state);
734     
735     if (!pci_dev) {
736         PrintError("Virtio NIC: Could not register PCI Device\n");
737         return -1;
738     }
739
740     PrintDebug("Virtio NIC:  registered to PCI bus\n");
741     
742     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
743     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
744         
745
746     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
747     pci_dev->config_header.class = PCI_CLASS_NETWORK;
748     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
749     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
750     pci_dev->config_header.intr_pin = 1;
751     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
752
753     net_state->pci_dev = pci_dev;
754     net_state->virtio_dev = virtio;
755
756     uchar_t mac[6] = {0x11,0x11,0x11,0x11,0x11,0x11};
757     memcpy(net_state->net_cfg.mac, mac, 6);
758                                                                                                            
759     memcpy(pci_dev->config_data, net_state->net_cfg.mac, ETH_ALEN);
760     
761     virtio_init_state(net_state);
762
763     return 0;
764 }
765
766 static int connect_fn(struct v3_vm_info * info, 
767                       void * frontend_data, 
768                       struct v3_dev_net_ops * ops, 
769                       v3_cfg_tree_t * cfg, 
770                       void * private_data) {
771     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
772     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
773
774     memset(net_state, 0, sizeof(struct virtio_net_state));
775     register_dev(virtio, net_state);
776
777     net_state->net_ops = ops;
778     net_state->backend_data = private_data;
779
780     ops->recv = virtio_rx;
781     ops->poll = virtio_nic_poll;
782     ops->start_tx = virtio_start_tx;
783     ops->stop_tx = virtio_stop_tx;
784     ops->frontend_data = net_state;
785
786     return 0;
787 }
788
789 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
790     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
791     struct virtio_dev_state * virtio_state = NULL;
792     char * dev_id = v3_cfg_val(cfg, "ID");
793
794     PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", dev_id);
795
796     if (pci_bus == NULL) {
797         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
798         return -1;
799     }
800
801     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
802     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
803
804     INIT_LIST_HEAD(&(virtio_state->dev_list));
805     virtio_state->pci_bus = pci_bus;
806     virtio_state->vm = vm;
807
808     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
809
810     if (dev == NULL) {
811         PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
812         V3_Free(virtio_state);
813         return -1;
814     }
815
816     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
817         PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
818         v3_remove_device(dev);
819         return -1;
820     }
821         
822     return 0;
823 }
824
825 device_register("LNX_VIRTIO_NIC", virtio_init)
826