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.


added back in 32 bit support
[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", 
146                        tmp_desc, 
147                        (void *)(addr_t)(tmp_desc->addr_gpa), tmp_desc->length, 
148                        tmp_desc->flags, tmp_desc->next);
149         
150
151             if (guest_pa_to_host_va(dev->vm, tmp_desc->addr_gpa, (addr_t *)&(page_addr)) == -1) {
152                 PrintError("Could not translate block header address\n");
153                 return -1;
154             }
155
156             /*      
157                if (handle_balloon_op(dev, tmp_desc, buf_desc, status_desc) == -1) {
158                PrintError("Error handling balloon operation\n");
159                return -1;
160                }
161             */
162
163             PrintDebug("Guest Balloon Currently Ignored\n");
164             PrintDebug("\t Requested=%d, Allocated=%d\n", 
165                        virtio->balloon_cfg.requested_pages, 
166                        virtio->balloon_cfg.allocated_pages);
167
168             req_len += tmp_desc->length;
169             desc_idx = tmp_desc->next;
170         }
171
172         q->used->ring[q->used->index % QUEUE_SIZE].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
173         q->used->ring[q->used->index % QUEUE_SIZE].length = req_len; // What do we set this to????
174
175         q->used->index++;
176         q->cur_avail_idx++;
177     }
178
179     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
180         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
181         v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
182         virtio->virtio_cfg.pci_isr = VIRTIO_ISR_ACTIVE;
183     }
184
185     return 0;
186 }
187
188 static int virtio_io_write(uint16_t port, void * src, uint_t length, void * private_data) {
189     struct vm_device * dev = (struct vm_device *)private_data;
190     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
191     int port_idx = port % virtio->io_range_size;
192
193
194     PrintDebug("VIRTIO BALLOON Write for port %d (index=%d) len=%d, value=%x\n", 
195                port, port_idx,  length, *(uint32_t *)src);
196
197
198
199     switch (port_idx) {
200         case GUEST_FEATURES_PORT:
201             if (length != 4) {
202                 PrintError("Illegal write length for guest features\n");
203                 return -1;
204             }
205             
206             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
207
208             break;
209         case VRING_PG_NUM_PORT:
210             if (length == 4) {
211                 addr_t pfn = *(uint32_t *)src;
212                 addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
213
214
215                 virtio->cur_queue->pfn = pfn;
216                 
217                 virtio->cur_queue->ring_desc_addr = page_addr ;
218                 virtio->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
219                 virtio->cur_queue->ring_used_addr = ( virtio->cur_queue->ring_avail_addr + \
220                                                  sizeof(struct vring_avail)    + \
221                                                  (QUEUE_SIZE * sizeof(uint16_t)));
222                 
223                 // round up to next page boundary.
224                 virtio->cur_queue->ring_used_addr = (virtio->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
225
226                 if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_desc_addr, (addr_t *)&(virtio->cur_queue->desc)) == -1) {
227                     PrintError("Could not translate ring descriptor address\n");
228                     return -1;
229                 }
230
231
232                 if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_avail_addr, (addr_t *)&(virtio->cur_queue->avail)) == -1) {
233                     PrintError("Could not translate ring available address\n");
234                     return -1;
235                 }
236
237
238                 if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_used_addr, (addr_t *)&(virtio->cur_queue->used)) == -1) {
239                     PrintError("Could not translate ring used address\n");
240                     return -1;
241                 }
242
243                 PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
244                            (void *)(virtio->cur_queue->ring_desc_addr),
245                            (void *)(virtio->cur_queue->ring_avail_addr),
246                            (void *)(virtio->cur_queue->ring_used_addr));
247
248                 PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
249                            virtio->cur_queue->desc, virtio->cur_queue->avail, virtio->cur_queue->used);
250
251             } else {
252                 PrintError("Illegal write length for page frame number\n");
253                 return -1;
254             }
255             break;
256         case VRING_Q_SEL_PORT:
257             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
258
259             if (virtio->virtio_cfg.vring_queue_selector > 1) {
260                 PrintError("Virtio Balloon device only uses 2 queue, selected %d\n", 
261                            virtio->virtio_cfg.vring_queue_selector);
262                 return -1;
263             }
264             
265             virtio->cur_queue = &(virtio->queue[virtio->virtio_cfg.vring_queue_selector]);
266
267             break;
268         case VRING_Q_NOTIFY_PORT:
269             PrintDebug("Handling Kick\n");
270             if (handle_kick(dev) == -1) {
271                 PrintError("Could not handle Balloon Notification\n");
272                 return -1;
273             }
274             break;
275         case VIRTIO_STATUS_PORT:
276             virtio->virtio_cfg.status = *(uint8_t *)src;
277
278             if (virtio->virtio_cfg.status == 0) {
279                 PrintDebug("Resetting device\n");
280                 virtio_reset(dev);
281             }
282
283             break;
284
285         case VIRTIO_ISR_PORT:
286             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
287             break;
288         default:
289             return -1;
290             break;
291     }
292
293     return length;
294 }
295
296
297 static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * private_data) {
298     struct vm_device * dev = (struct vm_device *)private_data;
299     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
300     int port_idx = port % virtio->io_range_size;
301
302
303     PrintDebug("VIRTIO BALLOON Read  for port %d (index =%d), length=%d\n", 
304                port, port_idx, length);
305
306     switch (port_idx) {
307         case HOST_FEATURES_PORT:
308             if (length != 4) {
309                 PrintError("Illegal read length for host features\n");
310                 return -1;
311             }
312
313             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
314         
315             break;
316         case VRING_PG_NUM_PORT:
317             if (length != 4) {
318                 PrintError("Illegal read length for page frame number\n");
319                 return -1;
320             }
321
322             *(uint32_t *)dst = virtio->cur_queue->pfn;
323
324             break;
325         case VRING_SIZE_PORT:
326             if (length != 2) {
327                 PrintError("Illegal read length for vring size\n");
328                 return -1;
329             }
330                 
331             *(uint16_t *)dst = virtio->cur_queue->queue_size;
332
333             break;
334
335         case VIRTIO_STATUS_PORT:
336             if (length != 1) {
337                 PrintError("Illegal read length for status\n");
338                 return -1;
339             }
340
341             *(uint8_t *)dst = virtio->virtio_cfg.status;
342             break;
343
344         case VIRTIO_ISR_PORT:
345             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
346             virtio->virtio_cfg.pci_isr = 0;
347             v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
348             break;
349
350         default:
351             if ( (port_idx >= sizeof(struct virtio_config)) && 
352                  (port_idx < (sizeof(struct virtio_config) + sizeof(struct balloon_config))) ) {
353                 int cfg_offset = port_idx - sizeof(struct virtio_config);
354                 uint8_t * cfg_ptr = (uint8_t *)&(virtio->balloon_cfg);
355
356                 memcpy(dst, cfg_ptr + cfg_offset, length);
357                 
358             } else {
359                 PrintError("Read of Unhandled Virtio Read\n");
360                 return -1;
361             }
362           
363             break;
364     }
365
366     return length;
367 }
368
369
370
371
372 static struct v3_device_ops dev_ops = {
373     .free = virtio_free,
374     .reset = NULL,
375     .start = NULL,
376     .stop = NULL,
377 };
378
379
380 static int set_size(struct vm_device * dev, addr_t size) {
381     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
382
383     virtio->balloon_cfg.requested_pages = size / PAGE_SIZE; // number of pages
384
385     PrintDebug("Requesting %d pages\n", virtio->balloon_cfg.requested_pages);
386
387     v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
388     virtio->virtio_cfg.pci_isr = VIRTIO_ISR_ACTIVE | VIRTIO_ISR_CFG_CHANGED;
389     
390     return 0;
391 }
392
393
394 static int handle_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
395     struct vm_device * dev = (struct vm_device *)priv_data;
396     int tgt_size = info->vm_regs.rcx;
397
398     
399     return set_size(dev, tgt_size);
400 }
401
402
403
404 static int handle_query_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
405     struct vm_device * dev = (struct vm_device *)priv_data;
406     struct virtio_balloon_state * virtio = (struct virtio_balloon_state *)dev->private_data;
407     
408     info->vm_regs.rcx = virtio->balloon_cfg.requested_pages;
409     info->vm_regs.rdx = virtio->balloon_cfg.allocated_pages;
410
411     
412     return 0;
413 }
414
415
416
417
418
419 static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
420     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
421     struct virtio_balloon_state * virtio_state = NULL;
422     struct pci_device * pci_dev = NULL;
423     char * name = v3_cfg_val(cfg, "name");
424
425     PrintDebug("Initializing VIRTIO Balloon device\n");
426
427     if (pci_bus == NULL) {
428         PrintError("VirtIO devices require a PCI Bus");
429         return -1;
430     }
431
432     
433     virtio_state  = (struct virtio_balloon_state *)V3_Malloc(sizeof(struct virtio_balloon_state));
434     memset(virtio_state, 0, sizeof(struct virtio_balloon_state));
435
436
437     struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
438     if (v3_attach_device(vm, dev) == -1) {
439         PrintError("Could not attach device %s\n", name);
440         return -1;
441     }
442
443
444
445
446     // PCI initialization
447     {
448         struct v3_pci_bar bars[6];
449         int num_ports = sizeof(struct virtio_config) + sizeof(struct balloon_config);
450         int tmp_ports = num_ports;
451         int i;
452
453
454
455         // This gets the number of ports, rounded up to a power of 2
456         virtio_state->io_range_size = 1; // must be a power of 2
457
458         while (tmp_ports > 0) {
459             tmp_ports >>= 1;
460             virtio_state->io_range_size <<= 1;
461         }
462         
463         // this is to account for any low order bits being set in num_ports
464         // if there are none, then num_ports was already a power of 2 so we shift right to reset it
465         if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
466             virtio_state->io_range_size >>= 1;
467         }
468
469
470         for (i = 0; i < 6; i++) {
471             bars[i].type = PCI_BAR_NONE;
472         }
473
474         bars[0].type = PCI_BAR_IO;
475         bars[0].default_base_port = -1;
476         bars[0].num_ports = virtio_state->io_range_size;
477
478         bars[0].io_read = virtio_io_read;
479         bars[0].io_write = virtio_io_write;
480         bars[0].private_data = dev;
481         
482
483         pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
484                                          0, PCI_AUTO_DEV_NUM, 0,
485                                          "LNX_VIRTIO_BALLOON", bars,
486                                          NULL, NULL, NULL, dev);
487
488         if (!pci_dev) {
489             PrintError("Could not register PCI Device\n");
490             return -1;
491         }
492         
493         pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
494         pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
495         
496
497         pci_dev->config_header.device_id = VIRTIO_BALLOON_DEV_ID;
498         pci_dev->config_header.class = PCI_CLASS_MEMORY;
499         pci_dev->config_header.subclass = PCI_MEM_SUBCLASS_RAM;
500     
501         pci_dev->config_header.subsystem_id = VIRTIO_BALLOON_SUBDEVICE_ID;
502
503
504         pci_dev->config_header.intr_pin = 1;
505
506         pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
507
508
509         virtio_state->pci_dev = pci_dev;
510         virtio_state->pci_bus = pci_bus;
511     }
512
513     virtio_reset(dev);
514
515     v3_register_hypercall(vm, BALLOON_START_HCALL, handle_hcall, dev);
516     v3_register_hypercall(vm, BALLOON_QUERY_HCALL, handle_query_hcall, dev);
517
518     return 0;
519 }
520
521
522 device_register("LNX_VIRTIO_BALLOON", virtio_init)