From: Peng Fan <peng....@nxp.com> If early_loader set to 1, it means jailhouse hypervisor booted by an bootloader before Linux, so when "jailhouse enable [x].cell", we need to bypass some operations.
Signed-off-by: Peng Fan <peng....@nxp.com> --- driver/main.c | 89 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/driver/main.c b/driver/main.c index ec302639..28c65f90 100644 --- a/driver/main.c +++ b/driver/main.c @@ -103,6 +103,7 @@ static int error_code; static struct jailhouse_virt_console* volatile console_page; static bool console_available; static struct resource *hypervisor_mem_res; +static u32 early_loader = 0; static typeof(ioremap_page_range) *ioremap_page_range_sym; #ifdef CONFIG_X86 @@ -363,6 +364,7 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) unsigned int clock_gates; const char *fw_name; long max_cpus; + int cpu; int err; fw_name = jailhouse_get_fw_name(); @@ -474,46 +476,46 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) (hypervisor_mem + header->console_page); last_console.valid = false; - /* Copy hypervisor's binary image at beginning of the memory region - * and clear the rest to zero. */ - memcpy(hypervisor_mem, hypervisor->data, hypervisor->size); - memset(hypervisor_mem + hypervisor->size, 0, - hv_mem->size - hypervisor->size); - header = (struct jailhouse_header *)hypervisor_mem; - header->max_cpus = max_cpus; + /* Copy system configuration to its target address in hypervisor memory + * region. */ + config = (struct jailhouse_system *) + (hypervisor_mem + hv_core_and_percpu_size); + if (!early_loader) { + /* Copy hypervisor's binary image at beginning of the memory region + * and clear the rest to zero. */ + memcpy(hypervisor_mem, hypervisor->data, hypervisor->size); + memset(hypervisor_mem + hypervisor->size, 0, + hv_mem->size - hypervisor->size); + header->max_cpus = max_cpus; #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) - header->arm_linux_hyp_vectors = virt_to_phys(*__hyp_stub_vectors_sym); + header->arm_linux_hyp_vectors = virt_to_phys(*__hyp_stub_vectors_sym); #if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) - header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY; + header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY; #else - header->arm_linux_hyp_abi = HYP_STUB_ABI_OPCODE; + header->arm_linux_hyp_abi = HYP_STUB_ABI_OPCODE; #endif #endif + /* + * ARMv8 requires to clean D-cache and invalidate I-cache for memory + * containing new instructions. On x86 this is a NOP. On ARMv7 the + * firmware does its own cache maintenance, so it is an + * extraneous (but harmless) flush. + */ + flush_icache_range((unsigned long)hypervisor_mem, + (unsigned long)(hypervisor_mem + header->core_size)); + + if (copy_from_user(config, arg, config_size)) { + err = -EFAULT; + goto error_unmap; + } + } err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size); if (err) goto error_unmap; - /* - * ARMv8 requires to clean D-cache and invalidate I-cache for memory - * containing new instructions. On x86 this is a NOP. On ARMv7 the - * firmware does its own cache maintenance, so it is an - * extraneous (but harmless) flush. - */ - flush_icache_range((unsigned long)hypervisor_mem, - (unsigned long)(hypervisor_mem + header->core_size)); - - /* Copy system configuration to its target address in hypervisor memory - * region. */ - config = (struct jailhouse_system *) - (hypervisor_mem + hv_core_and_percpu_size); - if (copy_from_user(config, arg, config_size)) { - err = -EFAULT; - goto error_unmap; - } - if (config->debug_console.clock_reg) { clock_reg = ioremap(config->debug_console.clock_reg, sizeof(clock_gates)); @@ -548,7 +550,8 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) } /* The hypervisor has no notion of address spaces, so we need * to enforce conversion. */ - header->debug_console_base = (void * __force)console; + if (!early_loader) + header->debug_console_base = (void * __force)console; } #endif @@ -570,17 +573,24 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) preempt_disable(); - header->online_cpus = num_online_cpus(); + if (!early_loader) { + header->online_cpus = num_online_cpus(); - /* - * Cannot use wait=true here because all CPUs have to enter the - * hypervisor to start the handover while on_each_cpu holds the calling - * CPU back. - */ - atomic_set(&call_done, 0); - on_each_cpu(enter_hypervisor, header, 0); - while (atomic_read(&call_done) != num_online_cpus()) - cpu_relax(); + /* + * Cannot use wait=true here because all CPUs have to enter the + * hypervisor to start the handover while on_each_cpu holds the calling + * CPU back. + */ + atomic_set(&call_done, 0); + on_each_cpu(enter_hypervisor, header, 0); + while (atomic_read(&call_done) != num_online_cpus()) + cpu_relax(); + } else { + for_each_cpu(cpu, &root_cell->cpus_assigned) { + if (!cpu_online(cpu)) + cpumask_clear_cpu(cpu, &root_cell->cpus_assigned); + } + } preempt_enable(); @@ -964,5 +974,6 @@ static void __exit jailhouse_exit(void) root_device_unregister(jailhouse_dev); } +module_param(early_loader, uint, S_IRUGO); module_init(jailhouse_init); module_exit(jailhouse_exit); -- 2.16.4 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to jailhouse-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/jailhouse-dev/20200807030632.28259-11-peng.fan%40nxp.com.