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.


636d8a5b194045bcc16c1d91837c00eed03c31af
[palacios.git] / palacios / src / devices / lnx_virtio_nic.c
1
2 /* 
3  * This file is part of the Palacios Virtual Machine Monitor developed
4  * by the V3VEE Project with funding from the United States National 
5  * Science Foundation and the Department of Energy.  
6  *
7  * The V3VEE Project is a joint project between Northwestern University
8  * and the University of New Mexico.  You can find out more at 
9  * http://www.v3vee.org
10  *
11  * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu>
12  * Copyright (c) 2010, Cui Zheng <cuizheng@cs.unm.edu>
13  * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org> 
14  * All rights reserved.
15  *
16  * Author: Lei Xia <lxia@northwestern.edu>
17  *         Cui Zheng <cuizheng@cs.unm.edu>
18  *               
19  *
20  * This is free software.  You are permitted to use,
21  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22  */
23  
24 #include <palacios/vmm.h>
25 #include <palacios/vmm_dev_mgr.h>
26 #include <devices/lnx_virtio_pci.h>
27 #include <palacios/vm_guest_mem.h>
28 #include <palacios/vmm_sprintf.h>
29 #include <vnet/vnet.h>
30 #include <palacios/vmm_lock.h>
31 #include <palacios/vmm_util.h>
32 #include <devices/pci.h>
33 #include <palacios/vmm_ethernet.h>
34 #include <palacios/vmm_time.h>
35
36
37 #ifndef V3_CONFIG_DEBUG_VIRTIO_NET
38 #undef PrintDebug
39 #define PrintDebug(fmt, args...)
40 #endif
41
42 #ifndef V3_CONFIG_VNET
43 static int net_debug = 0;
44 #endif
45
46 #define TX_QUEUE_SIZE 4096
47 #define RX_QUEUE_SIZE 4096
48 #define CTRL_QUEUE_SIZE 64
49
50 /* The feature bitmap for virtio nic
51   * from Linux */
52 #define VIRTIO_NET_F_CSUM       0       /* Host handles pkts w/ partial csum */
53 #define VIRTIO_NET_F_GUEST_CSUM 1       /* Guest handles pkts w/ partial csum */
54 #define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
55 #define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
56 #define VIRTIO_NET_F_GUEST_TSO4 7       /* Guest can handle TSOv4 in. */
57 #define VIRTIO_NET_F_GUEST_TSO6 8       /* Guest can handle TSOv6 in. */
58 #define VIRTIO_NET_F_GUEST_ECN  9       /* Guest can handle TSO[6] w/ ECN in. */
59 #define VIRTIO_NET_F_GUEST_UFO  10      /* Guest can handle UFO in. */
60 #define VIRTIO_NET_F_HOST_TSO4  11      /* Host can handle TSOv4 in. */
61 #define VIRTIO_NET_F_HOST_TSO6  12      /* Host can handle TSOv6 in. */
62 #define VIRTIO_NET_F_HOST_ECN   13      /* Host can handle TSO[6] w/ ECN in. */
63 #define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
64 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
65 #define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
66
67 /* Port to get virtio config */
68 #define VIRTIO_NET_CONFIG 20  
69
70 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
71
72 /* for gso_type in virtio_net_hdr */
73 #define VIRTIO_NET_HDR_GSO_NONE         0      
74 #define VIRTIO_NET_HDR_GSO_TCPV4        1     /* GSO frame, IPv4 TCP (TSO) */
75 #define VIRTIO_NET_HDR_GSO_UDP          3       /* GSO frame, IPv4 UDP (UFO) */
76 #define VIRTIO_NET_HDR_GSO_TCPV6        4       /* GSO frame, IPv6 TCP */
77 #define VIRTIO_NET_HDR_GSO_ECN          0x80    /* TCP has ECN set */   
78
79
80 /* for flags in virtio_net_hdr */
81 #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1       /* Use csum_start, csum_offset */
82
83
84 /* First element of the scatter-gather list, used with GSO or CSUM features */
85 struct virtio_net_hdr
86 {
87     uint8_t flags;
88     uint8_t gso_type;
89     uint16_t hdr_len;           /* Ethernet + IP + tcp/udp hdrs */
90     uint16_t gso_size;          /* Bytes to append to hdr_len per frame */
91     uint16_t csum_start;        /* Position to start checksumming from */
92     uint16_t csum_offset;       /* Offset after that to place checksum */
93 }__attribute__((packed));
94
95
96 /* The header to use when the MRG_RXBUF 
97  * feature has been negotiated. */
98 struct virtio_net_hdr_mrg_rxbuf {
99     struct virtio_net_hdr hdr;
100     uint16_t num_buffers;       /* Number of merged rx buffers */
101 };
102
103 struct virtio_net_config
104 {
105     uint8_t mac[ETH_ALEN];      /* VIRTIO_NET_F_MAC */
106     uint16_t status;
107 } __attribute__((packed));
108
109 struct virtio_dev_state {
110
111     struct vm_device * pci_bus;
112     struct list_head dev_list;
113     struct v3_vm_info *vm;
114
115     enum {GUEST_DRIVEN=0, VMM_DRIVEN, ADAPTIVE} model;
116     uint64_t  lower_thresh_pps, upper_thresh_pps, period_us;
117
118     uint8_t mac[ETH_ALEN];
119 };
120
121 struct virtio_net_state {
122
123     struct virtio_net_config net_cfg;
124     struct virtio_config virtio_cfg;
125
126     struct v3_vm_info * vm;
127     struct vm_device * dev;
128     struct pci_device * pci_dev; 
129     int io_range_size;
130
131     uint16_t status;
132     
133     struct virtio_queue rx_vq;          /* idx 0*/
134     struct virtio_queue tx_vq;          /* idx 1*/
135     struct virtio_queue ctrl_vq;        /* idx 2*/
136
137     uint8_t mergeable_rx_bufs;
138
139     struct v3_timer * timer;
140     struct nic_statistics stats;
141
142     struct v3_dev_net_ops * net_ops;
143     v3_lock_t rx_lock, tx_lock;
144
145     uint8_t tx_notify, rx_notify;
146     uint32_t tx_pkts, rx_pkts;
147     uint64_t past_us;
148
149     void * backend_data;
150     struct virtio_dev_state * virtio_dev;
151     struct list_head dev_link;
152 };
153
154
155 static int virtio_init_state(struct virtio_net_state * virtio) 
156 {
157     virtio->rx_vq.queue_size = RX_QUEUE_SIZE;
158     virtio->tx_vq.queue_size = TX_QUEUE_SIZE;
159     virtio->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
160
161     virtio->rx_vq.ring_desc_addr = 0;
162     virtio->rx_vq.ring_avail_addr = 0;
163     virtio->rx_vq.ring_used_addr = 0;
164     virtio->rx_vq.pfn = 0;
165     virtio->rx_vq.cur_avail_idx = 0;
166
167     virtio->tx_vq.ring_desc_addr = 0;
168     virtio->tx_vq.ring_avail_addr = 0;
169     virtio->tx_vq.ring_used_addr = 0;
170     virtio->tx_vq.pfn = 0;
171     virtio->tx_vq.cur_avail_idx = 0;
172
173     virtio->ctrl_vq.ring_desc_addr = 0;
174     virtio->ctrl_vq.ring_avail_addr = 0;
175     virtio->ctrl_vq.ring_used_addr = 0;
176     virtio->ctrl_vq.pfn = 0;
177     virtio->ctrl_vq.cur_avail_idx = 0;
178
179     virtio->virtio_cfg.pci_isr = 0;
180
181     virtio->mergeable_rx_bufs = 1;
182         
183     virtio->virtio_cfg.host_features = 0 | (1 << VIRTIO_NET_F_MAC);
184     if(virtio->mergeable_rx_bufs) {
185         virtio->virtio_cfg.host_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
186     }
187
188     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
189         (v3_lock_init(&(virtio->tx_lock)) == -1)){
190         PrintError(VM_NONE, VCORE_NONE, "Virtio NIC: Failure to init locks for net_state\n");
191     }
192
193     return 0;
194 }
195
196 static int virtio_deinit_state(struct guest_info *core, struct virtio_net_state *ns) 
197 {
198     if (ns->timer) { 
199         v3_remove_timer(core,ns->timer);
200     }
201
202     v3_lock_deinit(&(ns->rx_lock));
203     v3_lock_deinit(&(ns->tx_lock));
204
205
206     return 0;
207 }
208
209 static int tx_one_pkt(struct guest_info * core, 
210                       struct virtio_net_state * virtio, 
211                       struct vring_desc * buf_desc) 
212 {
213     uint8_t * buf = NULL;
214     uint32_t len = buf_desc->length;
215
216     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
217         PrintDebug(core->vm_info, core, "Could not translate buffer address\n");
218         return -1;
219     }
220     
221     V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len);
222     if(net_debug >= 4){
223         v3_hexdump(buf, len, NULL, 0);
224     }
225
226     if(virtio->net_ops->send(buf, len, virtio->backend_data) < 0){
227         virtio->stats.tx_dropped ++;
228         return -1;
229     }
230     
231     virtio->stats.tx_pkts ++;
232     virtio->stats.tx_bytes += len;
233     
234     return 0;
235 }
236
237
238 /*copy data into ring buffer */
239 static inline int copy_data_to_desc(struct guest_info * core, 
240                                     struct virtio_net_state * virtio_state, 
241                                     struct vring_desc * desc, 
242                                     uchar_t * buf, 
243                                     uint_t buf_len,
244                                     uint_t dst_offset){
245     uint32_t len;
246     uint8_t * desc_buf = NULL;
247     
248     if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
249         PrintDebug(core->vm_info, core, "Could not translate buffer address\n");
250         return -1;
251     }
252     len = (desc->length < (buf_len+dst_offset))?(desc->length - dst_offset):buf_len;
253     memcpy(desc_buf + dst_offset, buf, len);
254
255     return len;
256 }
257
258
259 static inline int get_desc_count(struct virtio_queue * q, int index) {
260     struct vring_desc * tmp_desc = &(q->desc[index]);
261     int cnt = 1;
262     
263     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
264         tmp_desc = &(q->desc[tmp_desc->next]);
265         cnt++;
266     }
267
268     return cnt;
269 }
270
271 static inline void enable_cb(struct virtio_queue *queue){
272     if(queue->used){
273         queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
274     }
275 }
276
277 static inline void disable_cb(struct virtio_queue *queue) {
278     if(queue->used){
279         queue->used->flags |= VRING_NO_NOTIFY_FLAG;
280     }
281 }
282
283 static int handle_pkt_tx(struct guest_info * core, 
284                          struct virtio_net_state * virtio_state,
285                          int quote)
286 {
287     struct virtio_queue * q;
288     int txed = 0, left = 0;
289     unsigned long flags;
290
291     q = &(virtio_state->tx_vq);
292     if (!q->ring_avail_addr) {
293         return -1;
294     }
295
296     while (1) {
297         struct vring_desc * hdr_desc = NULL;
298         addr_t hdr_addr = 0;
299         uint16_t desc_idx, tmp_idx;
300         int desc_cnt;
301         
302         flags = v3_lock_irqsave(virtio_state->tx_lock);
303
304         if(q->cur_avail_idx == q->avail->index ||
305             (quote > 0 && txed >= quote)) {
306             left = (q->cur_avail_idx != q->avail->index);
307             v3_unlock_irqrestore(virtio_state->tx_lock, flags);
308             break;
309         }
310         
311         desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
312         tmp_idx = q->cur_avail_idx ++;
313         
314         v3_unlock_irqrestore(virtio_state->tx_lock, flags);
315
316         desc_cnt = get_desc_count(q, desc_idx);
317         if(desc_cnt != 2){
318             PrintError(core->vm_info, core, "VNIC: merged rx buffer not supported, desc_cnt %d\n", desc_cnt);
319         }
320
321         hdr_desc = &(q->desc[desc_idx]);
322         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) != -1) {
323             struct virtio_net_hdr_mrg_rxbuf * hdr;
324             struct vring_desc * buf_desc;
325
326             hdr = (struct virtio_net_hdr_mrg_rxbuf *)hdr_addr;
327             desc_idx = hdr_desc->next;
328
329             /* here we assumed that one ethernet pkt is not splitted into multiple buffer */    
330             buf_desc = &(q->desc[desc_idx]);
331             if (tx_one_pkt(core, virtio_state, buf_desc) == -1) {
332                 PrintError(core->vm_info, core, "Virtio NIC: Fails to send packet\n");
333             }
334         } else {
335             PrintError(core->vm_info, core, "Could not translate block header address\n");
336         }
337
338         flags = v3_lock_irqsave(virtio_state->tx_lock);
339         
340         q->used->ring[q->used->index % q->queue_size].id = 
341             q->avail->ring[tmp_idx % q->queue_size];
342         
343         q->used->index ++;
344         
345         v3_unlock_irqrestore(virtio_state->tx_lock, flags);
346
347         txed ++;
348     }
349         
350     if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
351         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 
352                          virtio_state->pci_dev, 0);
353         virtio_state->virtio_cfg.pci_isr = 0x1;
354         virtio_state->stats.rx_interrupts ++;
355     }
356
357     return left;
358 }
359
360
361 static int virtio_setup_queue(struct guest_info *core, 
362                               struct virtio_net_state * virtio_state, 
363                               struct virtio_queue * queue, 
364                               addr_t pfn, addr_t page_addr) {
365     queue->pfn = pfn;
366                 
367     queue->ring_desc_addr = page_addr;
368     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
369     queue->ring_used_addr = ((queue->ring_avail_addr) + 
370                              (sizeof(struct vring_avail)) + 
371                              (queue->queue_size * sizeof(uint16_t)));
372
373     // round up to next page boundary.
374     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
375     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
376         PrintError(core->vm_info, core, "Could not translate ring descriptor address\n");
377          return -1;
378     }
379  
380     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
381         PrintError(core->vm_info, core, "Could not translate ring available address\n");
382         return -1;
383     }
384
385     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
386         PrintError(core->vm_info, core, "Could not translate ring used address\n");
387         return -1;
388     }
389
390     PrintDebug(core->vm_info, core, "RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
391                (void *)(queue->ring_desc_addr),
392                (void *)(queue->ring_avail_addr),
393                (void *)(queue->ring_used_addr));
394     
395     PrintDebug(core->vm_info, core, "RingDesc=%p, Avail=%p, Used=%p\n", 
396                queue->desc, queue->avail, queue->used);
397     
398     return 0;
399 }
400
401 static int virtio_io_write(struct guest_info *core, 
402                            uint16_t port, void * src, 
403                            uint_t length, void * private_data) 
404 {
405     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
406     int port_idx = port % virtio->io_range_size;
407
408     PrintDebug(core->vm_info, core, "VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n",
409                private_data, port, port_idx,  
410                length, *(uint32_t *)src);
411
412     switch (port_idx) {
413         case GUEST_FEATURES_PORT:
414             if (length != 4) {
415                 PrintError(core->vm_info, core, "Illegal write length for guest features\n");
416                 return -1;
417             }       
418             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
419             break;
420                 
421         case VRING_PG_NUM_PORT:
422             if (length != 4) {
423                 PrintError(core->vm_info, core, "Illegal write length for page frame number\n");
424                 return -1;
425             }
426             addr_t pfn = *(uint32_t *)src;
427             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
428             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
429             switch (queue_idx) {
430                 case 0:
431                     virtio_setup_queue(core, virtio,
432                                        &virtio->rx_vq, 
433                                        pfn, page_addr);
434                     break;
435                 case 1:
436                     virtio_setup_queue(core, virtio, 
437                                        &virtio->tx_vq, 
438                                        pfn, page_addr);
439                     if(virtio->tx_notify == 0){
440                         disable_cb(&virtio->tx_vq);
441                     }
442                     virtio->status = 1;
443                     break;
444                 case 2:
445                     virtio_setup_queue(core, virtio, 
446                                        &virtio->ctrl_vq, 
447                                        pfn, page_addr);
448                     break;          
449                 default:
450                     break;
451             }
452             break;
453                 
454         case VRING_Q_SEL_PORT:
455             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
456             if (virtio->virtio_cfg.vring_queue_selector > 2) {
457                 PrintError(core->vm_info, core, "Virtio NIC: wrong queue idx: %d\n", 
458                            virtio->virtio_cfg.vring_queue_selector);
459                 return -1;
460             }
461             break;
462                 
463         case VRING_Q_NOTIFY_PORT: 
464             {
465                 uint16_t queue_idx = *(uint16_t *)src;                  
466                 if (queue_idx == 0){
467                     /* receive queue refill */
468                     virtio->stats.tx_interrupts ++;
469                 } else if (queue_idx == 1){
470                     if (handle_pkt_tx(core, virtio, 0) < 0) {
471                         PrintError(core->vm_info, core, "Virtio NIC: Error to handle packet TX\n");
472                         return -1;
473                     }
474                     virtio->stats.tx_interrupts ++;
475                 } else if (queue_idx == 2){
476                     /* ctrl */
477                 } else {
478                     PrintError(core->vm_info, core, "Virtio NIC: Wrong queue index %d\n", queue_idx);
479                 }       
480                 break;          
481             }
482         
483         case VIRTIO_STATUS_PORT:
484             virtio->virtio_cfg.status = *(uint8_t *)src;
485             if (virtio->virtio_cfg.status == 0) {
486                 virtio_init_state(virtio);
487             }
488             break;
489
490         case VIRTIO_ISR_PORT:
491             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
492             break;
493                 
494         default:
495             return -1;
496             break;
497     }
498
499     return length;
500 }
501
502 static int virtio_io_read(struct guest_info *core, 
503                           uint16_t port, void * dst, 
504                           uint_t length, void * private_data) 
505 {
506     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
507     int port_idx = port % virtio->io_range_size;
508     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
509
510     PrintDebug(core->vm_info, core, "Virtio NIC %p: Read  for port 0x%x (index =%d), length=%d\n", 
511                private_data, port, port_idx, length);
512         
513     switch (port_idx) {
514         case HOST_FEATURES_PORT:
515             if (length != 4) {
516                 PrintError(core->vm_info, core, "Virtio NIC: Illegal read length for host features\n");
517                 //return -1;
518             }
519             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
520             break;
521
522         case VRING_PG_NUM_PORT:
523             if (length != 4) {
524                 PrintError(core->vm_info, core, "Virtio NIC: Illegal read length for page frame number\n");
525                 return -1;
526             }
527             switch (queue_idx) {
528                 case 0:
529                     *(uint32_t *)dst = virtio->rx_vq.pfn;
530                     break;
531                 case 1:
532                     *(uint32_t *)dst = virtio->tx_vq.pfn;
533                     break;      
534                 case 2:
535                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
536                     break;
537                 default:
538                     break;
539             }
540             break;
541
542         case VRING_SIZE_PORT:
543             if (length != 2) {
544                 PrintError(core->vm_info, core, "Virtio NIC: Illegal read length for vring size\n");
545                 return -1;
546             }
547             switch (queue_idx) {
548                 case 0:
549                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
550                     break;
551                 case 1:
552                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
553                     break;      
554                 case 2:
555                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
556                     break;
557                 default:
558                     break;
559             }
560             break;
561
562         case VIRTIO_STATUS_PORT:
563             if (length != 1) {
564                 PrintError(core->vm_info, core, "Virtio NIC: Illegal read length for status\n");
565                 return -1;
566             }
567             *(uint8_t *)dst = virtio->virtio_cfg.status;
568             break;
569                 
570         case VIRTIO_ISR_PORT:
571             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
572             virtio->virtio_cfg.pci_isr = 0;
573             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 
574                              virtio->pci_dev, 0);
575             break;
576
577         case VIRTIO_NET_CONFIG ... VIRTIO_NET_CONFIG + ETH_ALEN:
578             *(uint8_t *)dst = virtio->net_cfg.mac[port_idx-VIRTIO_NET_CONFIG];
579             break;
580
581         default:
582             PrintError(core->vm_info, core, "Virtio NIC: Read of Unhandled Virtio Read:%d\n", 
583                        port_idx);
584             return -1;
585     }
586
587     return length;
588 }
589
590
591 /* receiving raw ethernet pkt from backend */
592 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
593     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
594     struct virtio_queue * q = &(virtio->rx_vq);
595     struct virtio_net_hdr_mrg_rxbuf hdr;
596     unsigned long flags;
597     uint8_t kick_guest = 0;
598
599     V3_Net_Print(2, "Virtio NIC: virtio_rx: size: %d\n", size);
600
601     if (!q->ring_avail_addr) {
602         V3_Net_Print(2, "Virtio NIC: RX Queue not set\n");
603         virtio->stats.rx_dropped ++;
604         
605         return -1;
606     }
607
608     memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
609
610     flags = v3_lock_irqsave(virtio->rx_lock);
611
612     if (q->cur_avail_idx != q->avail->index){
613         uint16_t buf_idx;
614         struct vring_desc * buf_desc;
615         uint32_t hdr_len, len;
616         uint32_t offset = 0;
617
618         hdr_len = (virtio->mergeable_rx_bufs)?
619             sizeof(struct virtio_net_hdr_mrg_rxbuf):
620             sizeof(struct virtio_net_hdr);
621
622         if(virtio->mergeable_rx_bufs){/* merged buffer */
623             struct vring_desc * hdr_desc;
624             uint16_t old_idx = q->cur_avail_idx;
625
626             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
627             hdr_desc = &(q->desc[buf_idx]);
628
629             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
630                                     virtio, hdr_desc, buf, size, hdr_len);
631             if(len < 0){
632                 goto err_exit;
633             }
634             offset += len;
635
636             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
637             q->used->ring[q->used->index % q->queue_size].length = hdr_len + offset;
638             q->cur_avail_idx ++;
639             hdr.num_buffers ++;
640
641             while(offset < size) {
642                 buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
643                 buf_desc = &(q->desc[buf_idx]);
644
645                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
646                                         virtio, buf_desc, buf+offset, size-offset, 0);  
647                 if (len < 0){
648                     V3_Net_Print(2, "Virtio NIC: merged buffer, %d buffer size %d\n", 
649                                  hdr.num_buffers, len);
650                     q->cur_avail_idx = old_idx;
651                     goto err_exit;
652                 }
653                 offset += len;
654                 buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
655
656                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
657                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].length = len;
658                 q->cur_avail_idx ++;   
659
660                 hdr.num_buffers ++;
661             }
662
663             copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
664                               virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
665             q->used->index += hdr.num_buffers;
666         }else{
667             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
668             buf_desc = &(q->desc[buf_idx]);
669
670             /* copy header */
671             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
672                                     virtio, buf_desc, (uchar_t *)&(hdr.hdr), hdr_len, 0);
673             if(len < hdr_len){
674                 V3_Net_Print(2, "Virtio NIC: rx copy header error %d, hdr_len %d\n", 
675                              len, hdr_len);
676                 goto err_exit;
677             }
678
679             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
680                                     virtio, buf_desc, buf, size, hdr_len);
681             if(len < 0){
682                 V3_Net_Print(2, "Virtio NIC: rx copy data error %d\n", len);
683                 goto err_exit;
684             }
685             offset += len;
686
687             /* copy rest of data */
688             while(offset < size && 
689                   (buf_desc->flags & VIRTIO_NEXT_FLAG)){
690                 buf_desc = &(q->desc[buf_desc->next]);
691                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
692                                         virtio, buf_desc, buf+offset, size-offset, 0);      
693                 if (len < 0) {
694                     break;
695                 }
696                 offset += len;
697             }
698             buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
699
700             if(offset < size){
701                 V3_Net_Print(2, "Virtio NIC: rx not enough ring buffer, buffer size %d\n", 
702                              len);
703                 goto err_exit;
704             }
705                 
706             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
707             q->used->ring[q->used->index % q->queue_size].length = size + hdr_len; /* This should be the total length of data sent to guest (header+pkt_data) */
708             q->used->index ++;
709             q->cur_avail_idx ++;
710         } 
711
712         virtio->stats.rx_pkts ++;
713         virtio->stats.rx_bytes += size;
714     } else {
715         V3_Net_Print(2, "Virtio NIC: Guest RX queue is full\n");
716         virtio->stats.rx_dropped ++;
717
718         /* kick guest to refill RX queue */
719         kick_guest = 1;
720     }
721
722     v3_unlock_irqrestore(virtio->rx_lock, flags);
723
724     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG) || kick_guest) {
725         V3_Net_Print(2, "Virtio NIC: RX Raising IRQ %d\n",  
726                      virtio->pci_dev->config_header.intr_line);
727
728         virtio->virtio_cfg.pci_isr = 0x1;       
729         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, virtio->pci_dev, 0);
730         virtio->stats.rx_interrupts ++;
731     }
732
733     /* notify guest if it is in guest mode */
734     if((kick_guest || virtio->rx_notify == 1) && 
735         V3_Get_CPU() != virtio->virtio_dev->vm->cores[0].pcpu_id){
736         v3_interrupt_cpu(virtio->virtio_dev->vm, 
737                          virtio->virtio_dev->vm->cores[0].pcpu_id, 
738                          0);
739     }
740
741     return 0;
742
743 err_exit:
744     virtio->stats.rx_dropped ++;
745     v3_unlock_irqrestore(virtio->rx_lock, flags);
746  
747     return -1;
748 }
749
750 static int virtio_free(struct virtio_dev_state * virtio) {
751     struct virtio_net_state * backend = NULL;
752     struct virtio_net_state * tmp = NULL;
753
754
755     list_for_each_entry_safe(backend, tmp, &(virtio->dev_list), dev_link) {
756         virtio_deinit_state(&(virtio->vm->cores[0]),backend);
757         list_del(&(backend->dev_link));
758         V3_Free(backend);
759     }
760
761     V3_Free(virtio);
762
763     return 0;
764 }
765
766
767 static struct v3_device_ops dev_ops = {
768     .free = (int (*)(void *))virtio_free,
769 };
770
771
772 static int virtio_poll(int quote, void * data){
773     struct virtio_net_state * virtio  = (struct virtio_net_state *)data;
774
775     if (virtio->status) {
776
777         return handle_pkt_tx(&(virtio->vm->cores[0]), virtio, quote);
778     } 
779
780     return 0;
781 }
782
783 static int register_dev(struct virtio_dev_state * virtio, 
784                         struct virtio_net_state * net_state) 
785 {
786     struct pci_device * pci_dev = NULL;
787     struct v3_pci_bar bars[6];
788     int num_ports = sizeof(struct virtio_config);
789     int tmp_ports = num_ports;
790     int i;
791
792     /* This gets the number of ports, rounded up to a power of 2 */
793     net_state->io_range_size = 1;
794     while (tmp_ports > 0) {
795         tmp_ports >>= 1;
796         net_state->io_range_size <<= 1;
797     }
798         
799     /* this is to account for any low order bits being set in num_ports
800      * if there are none, then num_ports was already a power of 2 so we shift right to reset it
801      */
802     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
803         net_state->io_range_size >>= 1;
804     }
805     
806     for (i = 0; i < 6; i++) {
807         bars[i].type = PCI_BAR_NONE;
808     }
809     
810     PrintDebug(VM_NONE, VCORE_NONE, "Virtio NIC: io_range_size = %d\n", 
811                net_state->io_range_size);
812     
813     bars[0].type = PCI_BAR_IO;
814     bars[0].default_base_port = -1;
815     bars[0].num_ports = net_state->io_range_size;
816     bars[0].io_read = virtio_io_read;
817     bars[0].io_write = virtio_io_write;
818     bars[0].private_data = net_state;
819     
820     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
821                                      0, PCI_AUTO_DEV_NUM, 0,
822                                      "LNX_VIRTIO_NIC", bars,
823                                      NULL, NULL, NULL, NULL, net_state);
824     
825     if (!pci_dev) {
826         PrintError(VM_NONE, VCORE_NONE, "Virtio NIC: Could not register PCI Device\n");
827         return -1;
828     }
829
830     PrintDebug(VM_NONE, VCORE_NONE, "Virtio NIC:  registered to PCI bus\n");
831     
832     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
833     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
834         
835
836     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
837     pci_dev->config_header.class = PCI_CLASS_NETWORK;
838     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
839     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
840     pci_dev->config_header.intr_pin = 1;
841     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
842
843     net_state->pci_dev = pci_dev;
844     net_state->virtio_dev = virtio;
845
846     memcpy(net_state->net_cfg.mac, virtio->mac, 6);                           
847         
848     virtio_init_state(net_state);
849
850     V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: Registered Intr Line %d\n", pci_dev->config_header.intr_line);
851
852     /* Add backend to list of devices */
853     list_add(&(net_state->dev_link), &(virtio->dev_list));
854
855     return 0;
856 }
857
858 #define RATE_UPPER_THRESHOLD_DEFAULT 10000  /* 10000 pkts per second, around 100Mbits */
859 #define RATE_LOWER_THRESHOLD_DEFAULT 1000   /* 1000 pkts per second, around 10Mbits */
860 #define PROFILE_PERIOD_DEFAULT       10000  /* us */
861
862 static void virtio_nic_timer(struct guest_info * core, 
863                              uint64_t cpu_cycles, uint64_t cpu_freq, 
864                              void * priv_data) {
865     struct virtio_net_state * net_state = (struct virtio_net_state *)priv_data;
866     uint64_t period_us;
867     static int profile_ms = 0;
868     uint64_t target_period_us = net_state->virtio_dev->period_us;
869     uint64_t upper_thresh_pps = net_state->virtio_dev->upper_thresh_pps;
870     uint64_t lower_thresh_pps = net_state->virtio_dev->lower_thresh_pps;
871     
872
873     if(!net_state->status){ /* VNIC is not in working status */
874         return;
875     }
876
877     period_us = (1000*cpu_cycles)/cpu_freq;
878     net_state->past_us += period_us;
879
880     if (net_state->past_us > target_period_us) { 
881
882         uint64_t tx_count, rx_count;
883         uint64_t lb_tx_count, lb_rx_count;
884         uint64_t ub_tx_count, ub_rx_count;
885
886         lb_tx_count = lb_rx_count = (lower_thresh_pps * 1000000) / net_state->past_us;  // packets expected in this interval
887         ub_tx_count = ub_rx_count = (upper_thresh_pps * 1000000) / net_state->past_us;  
888
889         tx_count = net_state->stats.tx_pkts - net_state->tx_pkts;
890         rx_count = net_state->stats.rx_pkts - net_state->rx_pkts;
891
892         net_state->tx_pkts = net_state->stats.tx_pkts;
893         net_state->rx_pkts = net_state->stats.rx_pkts;
894
895         if(tx_count > ub_tx_count && net_state->tx_notify == 1) {
896             PrintDebug(core->vm_info, core, "Virtio NIC: Switch TX to VMM driven mode\n");
897             disable_cb(&(net_state->tx_vq));
898             net_state->tx_notify = 0;
899         }
900
901         if(tx_count < lb_tx_count && net_state->tx_notify == 0) {
902             PrintDebug(core->vm_info, core, "Virtio NIC: Switch TX to Guest  driven mode\n");
903             enable_cb(&(net_state->tx_vq));
904             net_state->tx_notify = 1;
905         }
906
907         if(rx_count > ub_rx_count && net_state->rx_notify == 1) {
908             PrintDebug(core->vm_info, core, "Virtio NIC: Switch RX to VMM None notify mode\n");
909             net_state->rx_notify = 0;
910         }
911
912         if(rx_count < lb_rx_count && net_state->rx_notify == 0) {
913             V3_Print(core->vm_info, core, "Virtio NIC: Switch RX to VMM notify mode\n");
914             net_state->rx_notify = 1;
915         }
916
917         net_state->past_us = 0;
918     }
919
920     profile_ms += period_us/1000;
921     if(profile_ms > 20000){
922         PrintDebug(core->vm_info, core, "Virtio NIC: TX: Pkt: %lld, Bytes: %lld\n\t\tRX Pkt: %lld. Bytes: %lld\n\t\tDropped: tx %lld, rx %lld\nInterrupts: tx %d, rx %d\nTotal Exit: %lld\n",
923                 net_state->stats.tx_pkts, net_state->stats.tx_bytes,
924                 net_state->stats.rx_pkts, net_state->stats.rx_bytes,
925                 net_state->stats.tx_dropped, net_state->stats.rx_dropped,
926                 net_state->stats.tx_interrupts, net_state->stats.rx_interrupts,
927                 net_state->vm->cores[0].num_exits);
928         profile_ms = 0;
929     }
930 }
931
932 static struct v3_timer_ops timer_ops = {
933     .update_timer = virtio_nic_timer,
934 };
935
936 static int connect_fn(struct v3_vm_info * info, 
937                       void * frontend_data, 
938                       struct v3_dev_net_ops * ops, 
939                       v3_cfg_tree_t * cfg, 
940                       void * private_data) {
941     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
942     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
943
944     if (!net_state) {
945         PrintError(info, VCORE_NONE, "Cannot allocate in connect\n");
946         return -1;
947     }
948
949     memset(net_state, 0, sizeof(struct virtio_net_state));
950     register_dev(virtio, net_state);
951
952     net_state->vm = info;
953     net_state->net_ops = ops;
954     net_state->backend_data = private_data;
955     net_state->virtio_dev = virtio;
956     
957     switch (virtio->model) { 
958         case GUEST_DRIVEN:
959             V3_Print(info, VCORE_NONE, "Virtio NIC: Guest-driven operation\n");
960             net_state->tx_notify = 1;
961             net_state->rx_notify = 1;
962             break;
963         case VMM_DRIVEN:
964             V3_Print(info, VCORE_NONE, "Virtio NIC: VMM-driven operation\n");
965             net_state->tx_notify = 0;
966             net_state->rx_notify = 0;
967             break;
968         case ADAPTIVE: {
969             V3_Print(info, VCORE_NONE, "Virtio NIC: Adaptive operation (begins in guest-driven mode)\n");
970             net_state->tx_notify = 1;
971             net_state->rx_notify = 1;
972
973             net_state->timer = v3_add_timer(&(info->cores[0]), &timer_ops,net_state);
974
975         }
976             break;
977
978         default:
979             V3_Print(info, VCORE_NONE, "Virtio NIC: Unknown model, using GUEST_DRIVEN\n");
980             net_state->tx_notify = 1;
981             net_state->rx_notify = 1;
982             break;
983     }
984
985
986     ops->recv = virtio_rx;
987     ops->poll = virtio_poll;
988     ops->config.frontend_data = net_state;
989     ops->config.poll = 1;
990     ops->config.quote = 64;
991     ops->config.fnt_mac = V3_Malloc(ETH_ALEN);  
992
993     if (!ops->config.fnt_mac) { 
994         PrintError(info, VCORE_NONE, "Cannot allocate in connect\n");
995         // should unregister here
996         return -1;
997     }
998
999     memcpy(ops->config.fnt_mac, virtio->mac, ETH_ALEN);
1000
1001     return 0;
1002 }
1003
1004 static int setup_perf_model(struct virtio_dev_state *virtio_state, v3_cfg_tree_t *t)
1005 {
1006     char *mode = v3_cfg_val(t,"mode");
1007
1008     // defaults
1009     virtio_state->model = GUEST_DRIVEN;
1010     virtio_state->lower_thresh_pps = RATE_LOWER_THRESHOLD_DEFAULT;
1011     virtio_state->upper_thresh_pps = RATE_UPPER_THRESHOLD_DEFAULT;
1012     virtio_state->period_us = PROFILE_PERIOD_DEFAULT;
1013     
1014     
1015     // overrides
1016     if (mode) { 
1017         if (!strcasecmp(mode,"guest-driven")) { 
1018             V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: Setting static GUEST_DRIVEN mode of operation (latency optimized)\n");
1019             virtio_state->model=GUEST_DRIVEN;
1020         } else if (!strcasecmp(mode, "vmm-driven")) { 
1021             V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: Setting static VMM_DRIVEN mode of operation (throughput optimized)\n");
1022             virtio_state->model=VMM_DRIVEN;
1023         } else if (!strcasecmp(mode, "adaptive")) { 
1024             char *s;
1025
1026             V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: Setting dynamic ADAPTIVE mode of operation\n");
1027             virtio_state->model=ADAPTIVE;
1028             
1029             if (!(s=v3_cfg_val(t,"upper"))) { 
1030                 V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: No upper bound given, using default\n");
1031             } else {
1032                 virtio_state->upper_thresh_pps = atoi(s);
1033             }
1034             if (!(s=v3_cfg_val(t,"lower"))) { 
1035                 V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: No lower bound given, using default\n");
1036             } else {
1037                 virtio_state->lower_thresh_pps = atoi(s);
1038             }
1039             if (!(s=v3_cfg_val(t,"period"))) { 
1040                 V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: No period given, using default\n");
1041             } else {
1042                 virtio_state->period_us = atoi(s);
1043             }
1044
1045             V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: lower_thresh_pps=%llu, upper_thresh_pps=%llu, period_us=%llu\n",
1046                      virtio_state->lower_thresh_pps,
1047                      virtio_state->upper_thresh_pps,
1048                      virtio_state->period_us);
1049         } else {
1050             PrintError(VM_NONE, VCORE_NONE, "Virtio NIC: Unknown mode of operation '%s', using default (guest-driven)\n",mode);
1051             virtio_state->model=GUEST_DRIVEN;
1052         }
1053     } else {
1054         V3_Print(VM_NONE, VCORE_NONE, "Virtio NIC: No model given, using default (guest-driven)\n");
1055     }
1056
1057     return 0;
1058
1059 }
1060
1061 /*
1062   <device class="LNX_VIRTIO_NIC" id="nic">
1063      <bus>pci-bus-to-attach-to</bus>  // required
1064      <mac>mac address</mac>  // if ommited with pic one
1065      <model mode="guest-driven|vmm-driven|adaptive" upper="pkts_per_sec" lower="pkts" period="us" />
1066   </device>
1067 */
1068 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1069     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
1070     struct virtio_dev_state * virtio_state = NULL;
1071     char * dev_id = v3_cfg_val(cfg, "ID");
1072     char * mac = v3_cfg_val(cfg, "mac");
1073     v3_cfg_tree_t *model = v3_cfg_subtree(cfg,"model");
1074     
1075     if (pci_bus == NULL) {
1076         PrintError(vm, VCORE_NONE, "Virtio NIC: Virtio device require a PCI Bus");
1077         return -1;
1078     }
1079
1080     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
1081
1082     if (!virtio_state) {
1083         PrintError(vm, VCORE_NONE, "Cannot allocate in init\n");
1084         return -1;
1085     }
1086
1087     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
1088
1089     INIT_LIST_HEAD(&(virtio_state->dev_list));
1090     virtio_state->pci_bus = pci_bus;
1091     virtio_state->vm = vm;
1092
1093     if (mac) { 
1094         if (!str2mac(mac, virtio_state->mac)) { 
1095             PrintDebug(vm, VCORE_NONE, "Virtio NIC: Mac specified %s\n", mac);
1096         } else {
1097             PrintError(vm, VCORE_NONE, "Virtio NIC: Mac specified is incorrect, picking a randoom mac\n");
1098             random_ethaddr(virtio_state->mac);
1099         }
1100     } else {
1101         PrintDebug(vm, VCORE_NONE, "Virtio NIC: no mac specified, so picking a random mac\n");
1102         random_ethaddr(virtio_state->mac);
1103     }
1104
1105     if (setup_perf_model(virtio_state,model)<0) { 
1106         PrintError(vm, VCORE_NONE, "Cannnot setup performance model\n");
1107         V3_Free(virtio_state);
1108         return -1;
1109     }
1110             
1111     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
1112
1113     if (dev == NULL) {
1114         PrintError(vm, VCORE_NONE, "Virtio NIC: Could not attach device %s\n", dev_id);
1115         V3_Free(virtio_state);
1116         return -1;
1117     }
1118
1119     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
1120         PrintError(vm, VCORE_NONE, "Virtio NIC: Could not register %s as net frontend\n", dev_id);
1121         v3_remove_device(dev);
1122         return -1;
1123     }
1124         
1125     return 0;
1126 }
1127
1128 device_register("LNX_VIRTIO_NIC", virtio_init)
1129