This allows us to boot secondary CPUs. There some difference between armv7 and armv8 systems: v7 uses a separate IRQ stack, while v8 shares stacks by exception level.
No need to set up an IRQ stack for armv8. Signed-off-by: Ralf Ramsauer <[email protected]> --- inmates/lib/arm-common/include/psci.h | 30 +++++++++++++++++++ inmates/lib/arm-common/psci.c | 26 +++++++++++++++++ inmates/lib/arm/header.S | 35 ++++++++++++++++++++++ inmates/lib/arm/include/arch/asm/psci_call.h | 4 +++ inmates/lib/arm64/header.S | 40 ++++++++++++++++++++++++++ inmates/lib/arm64/include/arch/asm/psci_call.h | 4 +++ 6 files changed, 139 insertions(+) diff --git a/inmates/lib/arm-common/include/psci.h b/inmates/lib/arm-common/include/psci.h index a367beb4..c850fbd8 100644 --- a/inmates/lib/arm-common/include/psci.h +++ b/inmates/lib/arm-common/include/psci.h @@ -36,4 +36,34 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +struct stack_sp { + void *stack_bottom; + unsigned int size; +}; + +struct stack { + struct stack_sp cpu; + struct stack_sp irq; +}; + +#define INIT_STACK(num_pages) \ + { \ + .stack_bottom = (u8 __attribute__((aligned(PAGE_SIZE))) \ + [num_pages * PAGE_SIZE]) {}, \ + .size = num_pages * PAGE_SIZE, \ + } + +#define DEFINE_STACK(name, cpu_pages, irq_pages) \ + struct stack name = { \ + .cpu = INIT_STACK(cpu_pages), \ + .irq = INIT_STACK(irq_pages), \ + } + +static inline void *stack_top(struct stack_sp *stack_sp) +{ + return stack_sp->stack_bottom + stack_sp->size; +} + unsigned int psci_version(void); +int psci_cpu_on(unsigned int cpu_id, void (*c_entry)(unsigned int), + struct stack *stack); diff --git a/inmates/lib/arm-common/psci.c b/inmates/lib/arm-common/psci.c index c01ac43e..25b4a102 100644 --- a/inmates/lib/arm-common/psci.c +++ b/inmates/lib/arm-common/psci.c @@ -40,7 +40,33 @@ #include <asm/psci_defs.h> #include <arch/asm/psci_call.h> +volatile void *__cpu_stack_top, *__irq_stack_top; +void (* volatile __c_entry)(unsigned int); + +extern void secondary_startup(void); + unsigned int psci_version(void) { return (unsigned int)psci_call(PSCI_VERSION, 0, 0, 0); } + +int psci_cpu_on(unsigned int cpu_id, void (*c_entry)(unsigned int), + struct stack *stack) +{ + int err; + + __cpu_stack_top = stack_top(&stack->cpu); + __irq_stack_top = stack_top(&stack->irq); + __c_entry = c_entry; + memory_barrier(); + + err = psci_call(PSCI_CPU_ON, cpu_id, (uintptr_t)secondary_startup, 0); + if (err) + return err; + + /* spin while CPU is not up */ + while (__cpu_stack_top && __irq_stack_top) + cpu_relax(); + + return 0; +} diff --git a/inmates/lib/arm/header.S b/inmates/lib/arm/header.S index d0a8f219..ea2c4566 100644 --- a/inmates/lib/arm/header.S +++ b/inmates/lib/arm/header.S @@ -2,10 +2,12 @@ * Jailhouse, a Linux-based partitioning hypervisor * * Copyright (c) ARM Limited, 2014 + * Copyright (c) OTH Regensburg, 2017 * Copyright (c) Siemens AG, 2016 * * Authors: * Jean-Philippe Brucker <[email protected]> + * Ralf Ramsauer <[email protected]> * Jan Kiszka <[email protected]> * * This work is licensed under the terms of the GNU GPL, version 2. See @@ -41,6 +43,7 @@ #include <asm/sysregs.h> .arm + .arch_extension virt .section ".boot", "ax" .align 5 @@ -87,4 +90,36 @@ __reset_entry: b inmate_main + .globl secondary_startup +secondary_startup: + /* prepare vector base address */ + ldr r2, =vectors + arm_write_sysreg(VBAR, r2) + + /* prepare CPU stack */ + ldr r1, =__cpu_stack_top + ldr sp, [r1] + + /* prepare IRQ stack */ + ldr r2, =__irq_stack_top + ldr r3, [r2] + msr SP_IRQ, r3 + /* only enable interrupts if __irq_stack_top is set */ + cmp r3, #0 + beq 1 + cpsie i + +1: + /* signal cpu ready by zeroing __cpu_stack_top */ + mov r0, #0 + str r0, [r1] /* zero __cpu_stack_top */ + str r0, [r2] /* zero __irq_stack_top */ + + /* get cpu id */ + arm_read_sysreg(MPIDR_EL1, r0) + and r0, r0, #MPIDR_CPUID_MASK + + ldr r1, =__c_entry + ldr pc, [r1] + .ltorg diff --git a/inmates/lib/arm/include/arch/asm/psci_call.h b/inmates/lib/arm/include/arch/asm/psci_call.h index ae09e43e..e0d58ae5 100644 --- a/inmates/lib/arm/include/arch/asm/psci_call.h +++ b/inmates/lib/arm/include/arch/asm/psci_call.h @@ -38,6 +38,10 @@ #include <asm/processor.h> +#define PSCI_CPU_ON PSCI_CPU_ON_32 + +typedef unsigned long uintptr_t; + static inline long psci_call(unsigned long function_id, unsigned long arg0, unsigned long arg1, unsigned long arg2) { diff --git a/inmates/lib/arm64/header.S b/inmates/lib/arm64/header.S index e284aa5a..26af4c20 100644 --- a/inmates/lib/arm64/header.S +++ b/inmates/lib/arm64/header.S @@ -2,9 +2,11 @@ * Jailhouse AArch64 support * * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH + * Copyright (C) 2017 OTH Regensburg * * Authors: * Antonios Motakis <[email protected]> + * Ralf Ramsauer <[email protected]> * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. @@ -36,6 +38,8 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#include <asm/sysregs.h> + .macro ventry label .align 7 b \label @@ -63,6 +67,42 @@ handle_irq: bl vector_irq eret + + .globl secondary_startup +secondary_startup: + /* prepare vector base address */ + ldr x0, =vectors + msr vbar_el1, x0 + + /* prepare CPU stack */ + ldr x0, =__cpu_stack_top + ldr x1, [x0] + mov sp, x1 + + mov x1, #(3 << 20) + msr cpacr_el1, x1 + msr daif, xzr + isb + +1: + /* signal cpu ready by zeroing __cpu_stack_top */ + mov x1, #0 + str x1, [x0] /* zero __cpu_stack_top */ + + /* get cpu id */ + mrs x0, MPIDR_EL1 + ldr x1, mpidr_mask + and x0, x0, x1 + + ldr x1, =__c_entry + ldr x2, [x1] + br x2 + +mpidr_mask: + #MPIDR_CPUID_MASK + + .ltorg + .weak vector_irq b . diff --git a/inmates/lib/arm64/include/arch/asm/psci_call.h b/inmates/lib/arm64/include/arch/asm/psci_call.h index 3242ea04..695d2ab3 100644 --- a/inmates/lib/arm64/include/arch/asm/psci_call.h +++ b/inmates/lib/arm64/include/arch/asm/psci_call.h @@ -38,6 +38,10 @@ #include <asm/processor.h> +#define PSCI_CPU_ON PSCI_CPU_ON_64 + +typedef unsigned long long uintptr_t; + static inline long long psci_call(unsigned long function_id, unsigned long long arg0, unsigned long long arg1, -- 2.14.1 -- 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
