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.

Reply via email to