2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2013
7 * Jan Kiszka <jan.kiszka@siemens.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #include <jailhouse/entry.h>
14 #include <jailhouse/control.h>
15 #include <jailhouse/printk.h>
16 #include <jailhouse/paging.h>
17 #include <jailhouse/processor.h>
18 #include <jailhouse/string.h>
19 #include <asm/bitops.h>
20 #include <asm/spinlock.h>
22 enum msg_type {MSG_REQUEST, MSG_INFORMATION};
23 enum management_task {CELL_START, CELL_DESTROY};
25 struct jailhouse_system *system_config;
27 static DEFINE_SPINLOCK(shutdown_lock);
28 static unsigned int num_cells = 1;
30 #define for_each_cell(c) for ((c) = &root_cell; (c); (c) = (c)->next)
31 #define for_each_non_root_cell(c) \
32 for ((c) = root_cell.next; (c); (c) = (c)->next)
34 unsigned int next_cpu(unsigned int cpu, struct cpu_set *cpu_set, int exception)
38 while (cpu <= cpu_set->max_cpu_id &&
39 (cpu == exception || !test_bit(cpu, cpu_set->bitmap)));
43 bool cpu_id_valid(unsigned long cpu_id)
45 const unsigned long *system_cpu_set =
46 jailhouse_cell_cpu_set(&system_config->system);
48 return (cpu_id < system_config->system.cpu_set_size * 8 &&
49 test_bit(cpu_id, system_cpu_set));
52 static void cell_suspend(struct cell *cell, struct per_cpu *cpu_data)
56 for_each_cpu_except(cpu, cell->cpu_set, cpu_data->cpu_id)
57 arch_suspend_cpu(cpu);
60 static void cell_resume(struct per_cpu *cpu_data)
64 for_each_cpu_except(cpu, cpu_data->cell->cpu_set, cpu_data->cpu_id)
69 * cell_send_message - Deliver a message to cell and wait for the reply
71 * @message: message code to be sent (JAILHOUSE_MSG_*)
72 * @type: message type, defines the valid replies
74 * Returns true if a request message was approved or reception of an
75 * information message was acknowledged by the target cell. It also return true
76 * of the target cell does not support a communication region, is shut down or
77 * in failed state. Return false on request denial or invalid replies.
79 static bool cell_send_message(struct cell *cell, u32 message,
82 if (cell->config->flags & JAILHOUSE_CELL_PASSIVE_COMMREG)
85 jailhouse_send_msg_to_cell(&cell->comm_page.comm_region, message);
88 u32 reply = cell->comm_page.comm_region.reply_from_cell;
89 u32 cell_state = cell->comm_page.comm_region.cell_state;
91 if (cell_state == JAILHOUSE_CELL_SHUT_DOWN ||
92 cell_state == JAILHOUSE_CELL_FAILED)
95 if ((type == MSG_REQUEST &&
96 reply == JAILHOUSE_MSG_REQUEST_APPROVED) ||
97 (type == MSG_INFORMATION &&
98 reply == JAILHOUSE_MSG_RECEIVED))
101 if (reply != JAILHOUSE_MSG_NONE)
108 static bool cell_reconfig_ok(struct cell *excluded_cell)
112 for_each_non_root_cell(cell)
113 if (cell != excluded_cell &&
114 cell->comm_page.comm_region.cell_state ==
115 JAILHOUSE_CELL_RUNNING_LOCKED)
120 static void cell_reconfig_completed(void)
124 for_each_non_root_cell(cell)
125 cell_send_message(cell, JAILHOUSE_MSG_RECONFIG_COMPLETED,
129 static unsigned int get_free_cell_id(void)
136 if (cell->id == id) {
144 /* cell must be zero-initialized */
145 int cell_init(struct cell *cell, bool copy_cpu_set)
147 const unsigned long *config_cpu_set =
148 jailhouse_cell_cpu_set(cell->config);
149 unsigned long cpu_set_size = cell->config->cpu_set_size;
150 struct cpu_set *cpu_set;
152 cell->id = get_free_cell_id();
154 if (cpu_set_size > PAGE_SIZE)
156 else if (cpu_set_size > sizeof(cell->small_cpu_set.bitmap)) {
157 cpu_set = page_alloc(&mem_pool, 1);
160 cpu_set->max_cpu_id =
161 ((PAGE_SIZE - sizeof(unsigned long)) * 8) - 1;
163 cpu_set = &cell->small_cpu_set;
164 cpu_set->max_cpu_id =
165 (sizeof(cell->small_cpu_set.bitmap) * 8) - 1;
167 cell->cpu_set = cpu_set;
169 memcpy(cell->cpu_set->bitmap, config_cpu_set, cpu_set_size);
174 static void destroy_cpu_set(struct cell *cell)
176 if (cell->cpu_set != &cell->small_cpu_set)
177 page_free(&mem_pool, cell->cpu_set, 1);
180 int check_mem_regions(const struct jailhouse_cell_desc *config)
182 const struct jailhouse_memory *mem =
183 jailhouse_cell_mem_regions(config);
186 for (n = 0; n < config->num_memory_regions; n++, mem++) {
187 if (mem->phys_start & ~PAGE_MASK ||
188 mem->virt_start & ~PAGE_MASK ||
189 mem->size & ~PAGE_MASK ||
190 mem->flags & ~JAILHOUSE_MEM_VALID_FLAGS) {
191 printk("FATAL: Invalid memory bar (%p, %p, %p, %x)\n",
192 mem->phys_start, mem->virt_start, mem->size,
200 static bool address_in_region(unsigned long addr,
201 const struct jailhouse_memory *region)
203 return addr >= region->phys_start &&
204 addr < (region->phys_start + region->size);
207 static void remap_to_root_cell(const struct jailhouse_memory *mem)
209 const struct jailhouse_memory *root_mem =
210 jailhouse_cell_mem_regions(root_cell.config);
211 struct jailhouse_memory overlap;
214 for (n = 0; n < root_cell.config->num_memory_regions;
216 if (address_in_region(mem->phys_start, root_mem)) {
217 overlap.phys_start = mem->phys_start;
218 overlap.size = root_mem->size -
219 (overlap.phys_start - root_mem->phys_start);
220 if (overlap.size > mem->size)
221 overlap.size = mem->size;
222 } else if (address_in_region(root_mem->phys_start, mem)) {
223 overlap.phys_start = root_mem->phys_start;
224 overlap.size = mem->size -
225 (overlap.phys_start - mem->phys_start);
226 if (overlap.size > root_mem->size)
227 overlap.size = root_mem->size;
231 overlap.virt_start = root_mem->virt_start +
232 overlap.phys_start - root_mem->phys_start;
233 overlap.flags = root_mem->flags;
235 if (arch_map_memory_region(&root_cell, &overlap) != 0)
236 printk("WARNING: Failed to re-assign memory region "
241 static int cell_create(struct per_cpu *cpu_data, unsigned long config_address)
243 unsigned long mapping_addr = TEMPORARY_MAPPING_CPU_BASE(cpu_data);
244 unsigned long cfg_page_offs = config_address & ~PAGE_MASK;
245 unsigned long cfg_header_size, cfg_total_size;
246 const struct jailhouse_memory *mem;
247 struct jailhouse_cell_desc *cfg;
248 unsigned int cell_pages, cpu, n;
249 struct cpu_set *shrinking_set;
250 struct jailhouse_memory tmp;
251 struct cell *cell, *last;
254 /* We do not support creation over non-root cells. */
255 if (cpu_data->cell != &root_cell)
258 cell_suspend(&root_cell, cpu_data);
260 if (!cell_reconfig_ok(NULL)) {
265 cfg_header_size = (config_address & ~PAGE_MASK) +
266 sizeof(struct jailhouse_cell_desc);
268 err = page_map_create(&hv_paging_structs, config_address & PAGE_MASK,
269 cfg_header_size, mapping_addr,
270 PAGE_READONLY_FLAGS, PAGE_MAP_NON_COHERENT);
274 cfg = (struct jailhouse_cell_desc *)(mapping_addr + cfg_page_offs);
275 cfg_total_size = jailhouse_cell_config_size(cfg);
276 if (cfg_total_size + cfg_page_offs > NUM_TEMPORARY_PAGES * PAGE_SIZE) {
282 if (strcmp(cell->config->name, cfg->name) == 0) {
287 err = page_map_create(&hv_paging_structs, config_address & PAGE_MASK,
288 cfg_total_size + cfg_page_offs, mapping_addr,
289 PAGE_READONLY_FLAGS, PAGE_MAP_NON_COHERENT);
293 err = check_mem_regions(cfg);
297 cell_pages = PAGE_ALIGN(sizeof(*cell) + cfg_total_size) / PAGE_SIZE;
298 cell = page_alloc(&mem_pool, cell_pages);
304 cell->data_pages = cell_pages;
305 cell->config = ((void *)cell) + sizeof(*cell);
306 memcpy(cell->config, cfg, cfg_total_size);
308 err = cell_init(cell, true);
312 /* don't assign the CPU we are currently running on */
313 if (cpu_data->cpu_id <= cell->cpu_set->max_cpu_id &&
314 test_bit(cpu_data->cpu_id, cell->cpu_set->bitmap)) {
316 goto err_free_cpu_set;
319 shrinking_set = cpu_data->cell->cpu_set;
321 /* shrinking set must be super-set of new cell's cpu set */
322 if (shrinking_set->max_cpu_id < cell->cpu_set->max_cpu_id) {
324 goto err_free_cpu_set;
326 for_each_cpu(cpu, cell->cpu_set)
327 if (!test_bit(cpu, shrinking_set->bitmap)) {
329 goto err_free_cpu_set;
332 for_each_cpu(cpu, cell->cpu_set)
333 clear_bit(cpu, shrinking_set->bitmap);
335 /* unmap the new cell's memory regions from the root cell */
336 mem = jailhouse_cell_mem_regions(cell->config);
337 for (n = 0; n < cell->config->num_memory_regions; n++, mem++)
340 * - the communication region is not backed by root memory
342 if (!(mem->flags & JAILHOUSE_MEM_COMM_REGION)) {
344 * arch_unmap_memory_region uses the virtual address of
345 * the memory region. As only the root cell has a
346 * guaranteed 1:1 mapping, make a copy where we ensure
350 tmp.virt_start = tmp.phys_start;
351 err = arch_unmap_memory_region(&root_cell, &tmp);
353 goto err_restore_root;
356 err = arch_cell_create(cpu_data, cell);
358 goto err_restore_root;
360 cell->comm_page.comm_region.cell_state = JAILHOUSE_CELL_SHUT_DOWN;
368 for_each_cpu(cpu, cell->cpu_set) {
369 per_cpu(cpu)->cell = cell;
373 cell_reconfig_completed();
375 printk("Created cell \"%s\"\n", cell->config->name);
377 page_map_dump_stats("after cell creation");
379 cell_resume(cpu_data);
384 mem = jailhouse_cell_mem_regions(cell->config);
385 for (n = 0; n < cell->config->num_memory_regions; n++, mem++)
386 remap_to_root_cell(mem);
387 for_each_cpu(cpu, cell->cpu_set)
388 set_bit(cpu, shrinking_set->bitmap);
390 destroy_cpu_set(cell);
392 page_free(&mem_pool, cell, cell_pages);
395 cell_resume(cpu_data);
400 static bool cell_shutdown_ok(struct cell *cell)
402 return cell_send_message(cell, JAILHOUSE_MSG_SHUTDOWN_REQUEST,
406 static int cell_management_prologue(enum management_task task,
407 struct per_cpu *cpu_data, unsigned long id,
408 struct cell **cell_ptr)
410 /* We do not support management commands over non-root cells. */
411 if (cpu_data->cell != &root_cell)
414 cell_suspend(&root_cell, cpu_data);
416 for_each_cell(*cell_ptr)
417 if ((*cell_ptr)->id == id)
421 cell_resume(cpu_data);
425 /* root cell cannot be managed */
426 if (*cell_ptr == &root_cell) {
427 cell_resume(cpu_data);
431 if ((task == CELL_DESTROY && !cell_reconfig_ok(*cell_ptr)) ||
432 !cell_shutdown_ok(*cell_ptr)) {
433 cell_resume(cpu_data);
437 cell_suspend(*cell_ptr, cpu_data);
442 static int cell_start(struct per_cpu *cpu_data, unsigned long id)
448 err = cell_management_prologue(CELL_START, cpu_data, id, &cell);
452 /* present a consistent Communication Region state to the cell */
453 cell->comm_page.comm_region.cell_state = JAILHOUSE_CELL_RUNNING;
454 cell->comm_page.comm_region.msg_to_cell = JAILHOUSE_MSG_NONE;
456 for_each_cpu(cpu, cell->cpu_set) {
457 per_cpu(cpu)->failed = false;
461 printk("Started cell \"%s\"\n", cell->config->name);
463 cell_resume(cpu_data);
468 static int cell_destroy(struct per_cpu *cpu_data, unsigned long id)
470 const struct jailhouse_memory *mem;
471 struct cell *cell, *previous;
475 err = cell_management_prologue(CELL_DESTROY, cpu_data, id, &cell);
479 printk("Closing cell \"%s\"\n", cell->config->name);
481 for_each_cpu(cpu, cell->cpu_set) {
484 set_bit(cpu, root_cell.cpu_set->bitmap);
485 per_cpu(cpu)->cell = &root_cell;
486 per_cpu(cpu)->failed = false;
489 mem = jailhouse_cell_mem_regions(cell->config);
490 for (n = 0; n < cell->config->num_memory_regions; n++, mem++) {
492 * This cannot fail. The region was mapped as a whole before,
493 * thus no hugepages need to be broken up to unmap it.
495 arch_unmap_memory_region(cell, mem);
496 if (!(mem->flags & JAILHOUSE_MEM_COMM_REGION))
497 remap_to_root_cell(mem);
500 arch_cell_destroy(cpu_data, cell);
502 previous = &root_cell;
503 while (previous->next != cell)
504 previous = previous->next;
505 previous->next = cell->next;
508 page_free(&mem_pool, cell, cell->data_pages);
509 page_map_dump_stats("after cell destruction");
511 cell_reconfig_completed();
513 cell_resume(cpu_data);
518 static int cell_get_state(struct per_cpu *cpu_data, unsigned long id)
522 if (cpu_data->cell != &root_cell)
526 * We do not need explicit synchronization with cell_create/destroy
527 * because their cell_suspend(root_cell) will not return before we left
531 if (cell->id == id) {
532 u32 state = cell->comm_page.comm_region.cell_state;
535 case JAILHOUSE_CELL_RUNNING:
536 case JAILHOUSE_CELL_RUNNING_LOCKED:
537 case JAILHOUSE_CELL_SHUT_DOWN:
538 case JAILHOUSE_CELL_FAILED:
547 static int shutdown(struct per_cpu *cpu_data)
549 unsigned int this_cpu = cpu_data->cpu_id;
554 /* We do not support shutdown over non-root cells. */
555 if (cpu_data->cell != &root_cell)
558 spin_lock(&shutdown_lock);
560 if (cpu_data->shutdown_state == SHUTDOWN_NONE) {
561 state = SHUTDOWN_STARTED;
562 for_each_non_root_cell(cell)
563 if (!cell_shutdown_ok(cell))
566 if (state == SHUTDOWN_STARTED) {
567 printk("Shutting down hypervisor\n");
569 for_each_non_root_cell(cell) {
570 cell_suspend(cell, cpu_data);
572 printk("Closing cell \"%s\"\n",
575 for_each_cpu(cpu, cell->cpu_set) {
576 printk(" Releasing CPU %d\n", cpu);
577 arch_shutdown_cpu(cpu);
581 printk("Closing root cell \"%s\"\n",
582 root_cell.config->name);
586 for_each_cpu(cpu, root_cell.cpu_set)
587 per_cpu(cpu)->shutdown_state = state;
590 if (cpu_data->shutdown_state == SHUTDOWN_STARTED) {
591 printk(" Releasing CPU %d\n", this_cpu);
594 ret = cpu_data->shutdown_state;
595 cpu_data->shutdown_state = SHUTDOWN_NONE;
597 spin_unlock(&shutdown_lock);
602 static long hypervisor_get_info(struct per_cpu *cpu_data, unsigned long type)
605 case JAILHOUSE_INFO_MEM_POOL_SIZE:
606 return mem_pool.pages;
607 case JAILHOUSE_INFO_MEM_POOL_USED:
608 return mem_pool.used_pages;
609 case JAILHOUSE_INFO_REMAP_POOL_SIZE:
610 return remap_pool.pages;
611 case JAILHOUSE_INFO_REMAP_POOL_USED:
612 return remap_pool.used_pages;
613 case JAILHOUSE_INFO_NUM_CELLS:
620 static int cpu_get_state(struct per_cpu *cpu_data, unsigned long cpu_id)
622 if (!cpu_id_valid(cpu_id))
626 * We do not need explicit synchronization with cell_destroy because
627 * its cell_suspend(root_cell + this_cell) will not return before we
628 * left this hypercall.
630 if (cpu_data->cell != &root_cell &&
631 (cpu_id > cpu_data->cell->cpu_set->max_cpu_id ||
632 !test_bit(cpu_id, cpu_data->cell->cpu_set->bitmap)))
635 return per_cpu(cpu_id)->failed ? JAILHOUSE_CPU_FAILED :
636 JAILHOUSE_CPU_RUNNING;
639 long hypercall(struct per_cpu *cpu_data, unsigned long code, unsigned long arg)
642 case JAILHOUSE_HC_DISABLE:
643 return shutdown(cpu_data);
644 case JAILHOUSE_HC_CELL_CREATE:
645 return cell_create(cpu_data, arg);
646 case JAILHOUSE_HC_CELL_START:
647 return cell_start(cpu_data, arg);
648 case JAILHOUSE_HC_CELL_DESTROY:
649 return cell_destroy(cpu_data, arg);
650 case JAILHOUSE_HC_HYPERVISOR_GET_INFO:
651 return hypervisor_get_info(cpu_data, arg);
652 case JAILHOUSE_HC_CELL_GET_STATE:
653 return cell_get_state(cpu_data, arg);
654 case JAILHOUSE_HC_CPU_GET_STATE:
655 return cpu_get_state(cpu_data, arg);
661 void panic_stop(struct per_cpu *cpu_data)
663 panic_printk("Stopping CPU");
665 panic_printk(" %d", cpu_data->cpu_id);
666 cpu_data->cpu_stopped = true;
670 if (phys_processor_id() == panic_cpu)
671 panic_in_progress = 0;
673 arch_panic_stop(cpu_data);
676 void panic_halt(struct per_cpu *cpu_data)
678 struct cell *cell = cpu_data->cell;
679 bool cell_failed = true;
682 panic_printk("Parking CPU %d\n", cpu_data->cpu_id);
684 cpu_data->failed = true;
685 for_each_cpu(cpu, cell->cpu_set)
686 if (!per_cpu(cpu)->failed) {
691 cell->comm_page.comm_region.cell_state = JAILHOUSE_CELL_FAILED;
693 arch_panic_halt(cpu_data);
695 if (phys_processor_id() == panic_cpu)
696 panic_in_progress = 0;