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.


fixes for the virtio block device
[palacios.git] / palacios / src / devices / lnx_virtio_balloon.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_dev_mgr.h>
22 #include <devices/lnx_virtio_pci.h>
23 #include <palacios/vm_guest_mem.h>
24
25 #include <devices/pci.h>
26
27
28 #define BLN_REQUESTED_PORT     20
29 #define BLN_ALLOCATED_PORT     28
30
31
32 #define PAGE_SIZE 4096
33
34 #define BALLOON_START_HCALL 0xba00 // size in rax
35 #define BALLOON_QUERY_HCALL 0xba01 // req_pgs in rcx, alloc_pgs in rdx
36
37 struct balloon_config {
38     uint32_t requested_pages;
39     uint32_t allocated_pages;
40 } __attribute__((packed));
41
42
43
44 /* How this works:
45  * A ballooning request is made by specifying the new memory size of the guest. The guest 
46  * will then shrink the amount of of memory it uses to target. The target size is stored in the 
47  * Virtio PCI configuration space in the requested pages field. 
48  * The device raises its irq, to notify the guest
49  * 
50  * The guest might not be able to shrink to target, so it stores the size it was able to shrink to 
51  * into the allocate_pages field of the pci configuration space.
52  * 
53  * When the guest frees pages it writes the addresses to the deflation queue (the 2nd one), 
54  * and does a kick.
55  * When pages are given back to the host they are fed in via the inflation queue (the 1st one), 
56  * and raises an irq.
57  */
58
59
60 #define QUEUE_SIZE 128
61
62 /* Host Feature flags */
63 #define VIRTIO_NOTIFY_HOST       0x01     
64
65
66 struct virtio_balloon_state {
67     struct balloon_config balloon_cfg;
68     struct virtio_config virtio_cfg;
69
70     struct vm_device * pci_bus;
71     struct pci_device * pci_dev;
72     
73     struct virtio_queue queue[2];
74
75
76     struct virtio_queue * cur_queue;
77
78     int io_range_size;
79 };
80
81
82 static int virtio_free(struct vm_device * dev) {
83     return -1;
84 }
85
86 static int virtio_reset(struct vm_device * dev) {
87     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
88
89     memset(virtio->queue, 0, sizeof(struct virtio_queue) * 2);
90
91     virtio->cur_queue = &(virtio->queue[0]);
92
93
94     virtio->virtio_cfg.status = 0;
95     virtio->virtio_cfg.pci_isr = 0;
96
97
98     /* Balloon configuration */
99     virtio->virtio_cfg.host_features = VIRTIO_NOTIFY_HOST;
100
101     // Virtio Balloon uses two queues
102     virtio->queue[0].queue_size = QUEUE_SIZE;
103     virtio->queue[1].queue_size = QUEUE_SIZE;
104
105
106     memset(&(virtio->balloon_cfg), 0, sizeof(struct balloon_config));
107
108     return 0;
109 }
110
111 static int get_desc_count(struct virtio_queue * q, int index) {
112     struct vring_desc * tmp_desc = &(q->desc[index]);
113     int cnt = 1;
114     
115     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
116         tmp_desc = &(q->desc[tmp_desc->next]);
117         cnt++;
118     }
119
120     return cnt;
121 }
122
123
124 static int handle_kick(struct vm_device * dev) {
125     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;    
126     struct virtio_queue * q = virtio->cur_queue;
127
128     PrintDebug("VIRTIO BALLOON KICK: cur_index=%d (mod=%d), avail_index=%d\n", 
129                q->cur_avail_idx, q->cur_avail_idx % QUEUE_SIZE, q->avail->index);
130
131     while (q->cur_avail_idx < q->avail->index) {
132         struct vring_desc * tmp_desc = NULL;
133         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
134         int desc_cnt = get_desc_count(q, desc_idx);
135         int i = 0;
136         uint32_t req_len = 0;
137
138
139         PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
140
141         for (i = 0; i < desc_cnt; i++) {
142             addr_t page_addr;
143             tmp_desc = &(q->desc[desc_idx]);
144             
145             PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", tmp_desc, 
146                        (void *)(tmp_desc->addr_gpa), tmp_desc->length, 
147                        tmp_desc->flags, tmp_desc->next);
148         
149
150             if (guest_pa_to_host_va(dev->vm, tmp_desc->addr_gpa, (addr_t *)&(page_addr)) == -1) {
151                 PrintError("Could not translate block header address\n");
152                 return -1;
153             }
154
155             /*      
156                if (handle_balloon_op(dev, tmp_desc, buf_desc, status_desc) == -1) {
157                PrintError("Error handling balloon operation\n");
158                return -1;
159                }
160             */
161
162             PrintDebug("Guest Balloon Currently Ignored\n");
163             PrintDebug("\t Requested=%d, Allocated=%d\n", 
164                        virtio->balloon_cfg.requested_pages, 
165                        virtio->balloon_cfg.allocated_pages);
166
167             req_len += tmp_desc->length;
168             desc_idx = tmp_desc->next;
169         }
170
171         q->used->ring[q->used->index % QUEUE_SIZE].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
172         q->used->ring[q->used->index % QUEUE_SIZE].length = req_len; // What do we set this to????
173
174         q->used->index++;
175         q->cur_avail_idx++;
176     }
177
178     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
179         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
180         v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
181         virtio->virtio_cfg.pci_isr = VIRTIO_ISR_ACTIVE;
182     }
183
184     return 0;
185 }
186
187 static int virtio_io_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
188     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
189     int port_idx = port % virtio->io_range_size;
190
191
192     PrintDebug("VIRTIO BALLOON Write for port %d (index=%d) len=%d, value=%x\n", 
193                port, port_idx,  length, *(uint32_t *)src);
194
195
196
197     switch (port_idx) {
198         case GUEST_FEATURES_PORT:
199             if (length != 4) {
200                 PrintError("Illegal write length for guest features\n");
201                 return -1;
202             }
203             
204             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
205
206             break;
207         case VRING_PG_NUM_PORT:
208             if (length == 4) {
209                 addr_t pfn = *(uint32_t *)src;
210                 addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
211
212
213                 virtio->cur_queue->pfn = pfn;
214                 
215                 virtio->cur_queue->ring_desc_addr = page_addr ;
216                 virtio->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
217                 virtio->cur_queue->ring_used_addr = ( virtio->cur_queue->ring_avail_addr + \
218                                                  sizeof(struct vring_avail)    + \
219                                                  (QUEUE_SIZE * sizeof(uint16_t)));
220                 
221                 // round up to next page boundary.
222                 virtio->cur_queue->ring_used_addr = (virtio->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
223
224                 if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_desc_addr, (addr_t *)&(virtio->cur_queue->desc)) == -1) {
225                     PrintError("Could not translate ring descriptor address\n");
226                     return -1;
227                 }
228
229
230                 if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_avail_addr, (addr_t *)&(virtio->cur_queue->avail)) == -1) {
231                     PrintError("Could not translate ring available address\n");
232                     return -1;
233                 }
234
235
236                 if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_used_addr, (addr_t *)&(virtio->cur_queue->used)) == -1) {
237                     PrintError("Could not translate ring used address\n");
238                     return -1;
239                 }
240
241                 PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
242                            (void *)(virtio->cur_queue->ring_desc_addr),
243                            (void *)(virtio->cur_queue->ring_avail_addr),
244                            (void *)(virtio->cur_queue->ring_used_addr));
245
246                 PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
247                            virtio->cur_queue->desc, virtio->cur_queue->avail, virtio->cur_queue->used);
248
249             } else {
250                 PrintError("Illegal write length for page frame number\n");
251                 return -1;
252             }
253             break;
254         case VRING_Q_SEL_PORT:
255             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
256
257             if (virtio->virtio_cfg.vring_queue_selector > 1) {
258                 PrintError("Virtio Balloon device only uses 2 queue, selected %d\n", 
259                            virtio->virtio_cfg.vring_queue_selector);
260                 return -1;
261             }
262             
263             virtio->cur_queue = &(virtio->queue[virtio->virtio_cfg.vring_queue_selector]);
264
265             break;
266         case VRING_Q_NOTIFY_PORT:
267             PrintDebug("Handling Kick\n");
268             if (handle_kick(dev) == -1) {
269                 PrintError("Could not handle Balloon Notification\n");
270                 return -1;
271             }
272             break;
273         case VIRTIO_STATUS_PORT:
274             virtio->virtio_cfg.status = *(uint8_t *)src;
275
276             if (virtio->virtio_cfg.status == 0) {
277                 PrintDebug("Resetting device\n");
278                 virtio_reset(dev);
279             }
280
281             break;
282
283         case VIRTIO_ISR_PORT:
284             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
285             break;
286         default:
287             return -1;
288             break;
289     }
290
291     return length;
292 }
293
294
295 static int virtio_io_read(uint16_t port, void * dst, uint_t length, struct vm_device * dev) {
296     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
297     int port_idx = port % virtio->io_range_size;
298
299
300     PrintDebug("VIRTIO BALLOON Read  for port %d (index =%d), length=%d\n", 
301                port, port_idx, length);
302
303     switch (port_idx) {
304         case HOST_FEATURES_PORT:
305             if (length != 4) {
306                 PrintError("Illegal read length for host features\n");
307                 return -1;
308             }
309
310             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
311         
312             break;
313         case VRING_PG_NUM_PORT:
314             if (length != 4) {
315                 PrintError("Illegal read length for page frame number\n");
316                 return -1;
317             }
318
319             *(uint32_t *)dst = virtio->cur_queue->pfn;
320
321             break;
322         case VRING_SIZE_PORT:
323             if (length != 2) {
324                 PrintError("Illegal read length for vring size\n");
325                 return -1;
326             }
327                 
328             *(uint16_t *)dst = virtio->cur_queue->queue_size;
329
330             break;
331
332         case VIRTIO_STATUS_PORT:
333             if (length != 1) {
334                 PrintError("Illegal read length for status\n");
335                 return -1;
336             }
337
338             *(uint8_t *)dst = virtio->virtio_cfg.status;
339             break;
340
341         case VIRTIO_ISR_PORT:
342             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
343             virtio->virtio_cfg.pci_isr = 0;
344             v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
345             break;
346
347         default:
348             if ( (port_idx >= sizeof(struct virtio_config)) && 
349                  (port_idx < (sizeof(struct virtio_config) + sizeof(struct balloon_config))) ) {
350                 int cfg_offset = port_idx - sizeof(struct virtio_config);
351                 uint8_t * cfg_ptr = (uint8_t *)&(virtio->balloon_cfg);
352
353                 memcpy(dst, cfg_ptr + cfg_offset, length);
354                 
355             } else {
356                 PrintError("Read of Unhandled Virtio Read\n");
357                 return -1;
358             }
359           
360             break;
361     }
362
363     return length;
364 }
365
366
367
368
369 static struct v3_device_ops dev_ops = {
370     .free = virtio_free,
371     .reset = NULL,
372     .start = NULL,
373     .stop = NULL,
374 };
375
376
377 static int set_size(struct vm_device * dev, addr_t size) {
378     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
379
380     virtio->balloon_cfg.requested_pages = size / PAGE_SIZE; // number of pages
381
382     PrintDebug("Requesting %d pages\n", virtio->balloon_cfg.requested_pages);
383
384     v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
385     virtio->virtio_cfg.pci_isr = VIRTIO_ISR_ACTIVE | VIRTIO_ISR_CFG_CHANGED;
386     
387     return 0;
388 }
389
390
391 static int handle_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
392     struct vm_device * dev = (struct vm_device *)priv_data;
393     int tgt_size = info->vm_regs.rcx;
394
395     
396     return set_size(dev, tgt_size);
397 }
398
399
400
401 static int handle_query_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
402     struct vm_device * dev = (struct vm_device *)priv_data;
403     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
404     
405     info->vm_regs.rcx = virtio->balloon_cfg.requested_pages;
406     info->vm_regs.rdx = virtio->balloon_cfg.allocated_pages;
407
408     
409     return 0;
410 }
411
412
413
414
415
416 static int virtio_init(struct guest_info * vm, void * cfg_data) {
417     struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
418     struct virtio_balloon_state * virtio_state = NULL;
419     struct pci_device * pci_dev = NULL;
420
421     PrintDebug("Initializing VIRTIO Balloon device\n");
422
423     if (pci_bus == NULL) {
424         PrintError("VirtIO devices require a PCI Bus");
425         return -1;
426     }
427
428     
429     virtio_state  = (struct virtio_balloon_state *)V3_Malloc(sizeof(struct virtio_balloon_state));
430     memset(virtio_state, 0, sizeof(struct virtio_balloon_state));
431
432
433     struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BALLOON", &dev_ops, virtio_state);
434     if (v3_attach_device(vm, dev) == -1) {
435         PrintError("Could not attach device %s\n", "LNX_VIRTIO_BALLOON");
436         return -1;
437     }
438
439
440
441
442     // PCI initialization
443     {
444         struct v3_pci_bar bars[6];
445         int num_ports = sizeof(struct virtio_config) + sizeof(struct balloon_config);
446         int tmp_ports = num_ports;
447         int i;
448
449
450
451         // This gets the number of ports, rounded up to a power of 2
452         virtio_state->io_range_size = 1; // must be a power of 2
453
454         while (tmp_ports > 0) {
455             tmp_ports >>= 1;
456             virtio_state->io_range_size <<= 1;
457         }
458         
459         // this is to account for any low order bits being set in num_ports
460         // if there are none, then num_ports was already a power of 2 so we shift right to reset it
461         if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
462             virtio_state->io_range_size >>= 1;
463         }
464
465
466         for (i = 0; i < 6; i++) {
467             bars[i].type = PCI_BAR_NONE;
468         }
469
470         bars[0].type = PCI_BAR_IO;
471         bars[0].default_base_port = -1;
472         bars[0].num_ports = virtio_state->io_range_size;
473
474         bars[0].io_read = virtio_io_read;
475         bars[0].io_write = virtio_io_write;
476
477         pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
478                                          0, PCI_AUTO_DEV_NUM, 0,
479                                          "LNX_VIRTIO_BALLOON", bars,
480                                          NULL, NULL, NULL, dev);
481
482         if (!pci_dev) {
483             PrintError("Could not register PCI Device\n");
484             return -1;
485         }
486         
487         pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
488         pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
489         
490
491         pci_dev->config_header.device_id = VIRTIO_BALLOON_DEV_ID;
492         pci_dev->config_header.class = PCI_CLASS_MEMORY;
493         pci_dev->config_header.subclass = PCI_MEM_SUBCLASS_RAM;
494     
495         pci_dev->config_header.subsystem_id = VIRTIO_BALLOON_SUBDEVICE_ID;
496
497
498         pci_dev->config_header.intr_pin = 1;
499
500         pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
501
502
503         virtio_state->pci_dev = pci_dev;
504         virtio_state->pci_bus = pci_bus;
505     }
506
507     virtio_reset(dev);
508
509     v3_register_hypercall(vm, BALLOON_START_HCALL, handle_hcall, dev);
510     v3_register_hypercall(vm, BALLOON_QUERY_HCALL, handle_query_hcall, dev);
511
512     return 0;
513 }
514
515
516 device_register("LNX_VIRTIO_BALLOON", virtio_init)