diff options
author | Jean-Philippe Brucker <jean-philippe.brucker@arm.com> | 2015-09-22 10:42:15 +0100 |
---|---|---|
committer | Mark Rutland <mark.rutland@arm.com> | 2016-06-15 10:27:35 +0100 |
commit | 259bef910fee48a927e4700e9e82f99e94962098 (patch) | |
tree | 480a6ea46677c13399639827bd781435a7b2be1f | |
parent | c311db0c5821f72604bfdaf40c6cbb0b672017c1 (diff) | |
download | boot-wrapper-aarch64-259bef910fee48a927e4700e9e82f99e94962098.tar.gz |
Add support for 32-bit kernel
This patch adds an --enable-aarch32-kernel parameter to ./configure,
which enables dropping into AArch32 state at EL2. Notable differences
with AArch64 boot are:
* SCR.RW is set to 0, to declare all lower levels as AArch32,
* SPSR_EL2 has a 32-bit M[4:0] field,
* kernel parameters are different, but we can still put them into x0-x2,
because those registers are mapped to r0-r2 (ARM ARM v8 D1.20.1)
* SCTLR.CP15BEN is set, to allow the Linux decompressor to keep using
its legacy CP15 barriers.
* We also need to make sure MMU is disabled at EL1: hyp-stub in arm64
resets SCTLR_EL1, but the 32-bit hyp-stub doesn't. Leaving SCTRL.M set
would break hotplug when no hypervisor is present.
* PSCI function ID for CPU_ON differs.
We don't plan to support spin method on 32-bit. PSCI is automatically
enabled by ./configure, and this patch forbids disabling it.
Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
-rw-r--r-- | Makefile.am | 18 | ||||
-rw-r--r-- | arch/aarch64/boot.S | 12 | ||||
-rw-r--r-- | arch/aarch64/include/asm/cpu.h | 11 | ||||
-rw-r--r-- | arch/aarch64/psci.S | 6 | ||||
-rw-r--r-- | boot_common.c | 4 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | include/psci.h | 1 |
7 files changed, 63 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am index af0d7a6..0e2b92a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,6 +22,14 @@ DEFINES += -DSYSREGS_BASE=$(SYSREGS_BASE) DEFINES += -DUART_BASE=$(UART_BASE) DEFINES += -DSTACK_SIZE=256 +if KERNEL_32 +DEFINES += -DKERNEL_32 +PSCI_CPU_ON := 0x84000003 +else +PSCI_CPU_ON := 0xc4000003 +endif +PSCI_CPU_OFF := 0x84000002 + OFILES = CFLAGS += -mgeneral-regs-only -mstrict-align @@ -33,8 +41,8 @@ OFILES += psci.o PSCI_NODE := psci { \ compatible = \"arm,psci\"; \ method = \"smc\"; \ - cpu_on = <0xc4000003>; \ - cpu_off = <0x84000002>; \ + cpu_on = <$(PSCI_CPU_ON)>; \ + cpu_off = <$(PSCI_CPU_OFF)>; \ }; CPU_NODES := $(shell $(top_srcdir)/gen-cpu-nodes.sh $(CPU_IDS)) CPUS_NODE := cpus { \ @@ -60,8 +68,14 @@ DEFINES += -DGIC_DIST_BASE=$(GIC_DIST_BASE) GIC := gic.o endif +if KERNEL_32 +MBOX_OFFSET := 0x7ff8 +KERNEL_OFFSET := 0x8000 +else MBOX_OFFSET := 0xfff8 KERNEL_OFFSET := 0x80000 +endif + LD_SCRIPT := model.lds.S IMAGE := linux-system.axf diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S index 1602807..ceeee76 100644 --- a/arch/aarch64/boot.S +++ b/arch/aarch64/boot.S @@ -38,7 +38,9 @@ _start: 1: mov x0, #0x30 // RES1 orr x0, x0, #(1 << 0) // Non-secure EL1 orr x0, x0, #(1 << 8) // HVC enable +#ifndef KERNEL_32 orr x0, x0, #(1 << 10) // 64-bit EL2 +#endif msr scr_el3, x0 msr cptr_el3, xzr // Disable copro. traps to EL3 @@ -65,6 +67,9 @@ jump_kernel: mov x22, x3 mov x23, x4 + ldr x0, =SCTLR_EL1_RESET + msr sctlr_el1, x0 + ldr x0, =SCTLR_EL2_RESET msr sctlr_el2, x0 @@ -84,6 +89,13 @@ jump_kernel: br x19 // No EL3 1: mov x4, #SPSR_KERNEL + + /* + * If bit 0 of the kernel address is set, we're entering in AArch32 + * thumb mode. Set SPSR.T accordingly. + */ + bfi x4, x19, #5, #1 + msr elr_el3, x19 msr spsr_el3, x4 eret diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h index eb3d8d7..66726ef 100644 --- a/arch/aarch64/include/asm/cpu.h +++ b/arch/aarch64/include/asm/cpu.h @@ -25,8 +25,19 @@ #define SPSR_F (1 << 6) /* FIQ masked */ #define SPSR_T (1 << 5) /* Thumb */ #define SPSR_EL2H (9 << 0) /* EL2 Handler mode */ +#define SPSR_HYP (0x1a << 0) /* M[3:0] = hyp, M[4] = AArch32 */ +#define SCTLR_EL1_CP15BEN (1 << 5) +#define SCTLR_EL1_RES1 (3 << 28 | 3 << 22 | 1 << 11) + +#ifdef KERNEL_32 +/* 32-bit kernel decompressor uses CP15 barriers */ +#define SCTLR_EL1_RESET (SCTLR_EL1_RES1 | SCTLR_EL1_CP15BEN) +#define SPSR_KERNEL (SPSR_A | SPSR_I | SPSR_F | SPSR_HYP) +#else +#define SCTLR_EL1_RESET SCTLR_EL1_RES1 #define SPSR_KERNEL (SPSR_A | SPSR_D | SPSR_I | SPSR_F | SPSR_EL2H) +#endif #ifndef __ASSEMBLY__ diff --git a/arch/aarch64/psci.S b/arch/aarch64/psci.S index 5f7e2d7..01ebe7d 100644 --- a/arch/aarch64/psci.S +++ b/arch/aarch64/psci.S @@ -59,8 +59,9 @@ err_exception: .endm smc_entry32: - mov w0, PSCI_RET_NOT_SUPPORTED - eret + /* Clear upper bits */ + mov w0, w0 + /* Pass through */ smc_entry64: /* SMC entry uses 112 bytes of stack */ @@ -74,6 +75,7 @@ smc_entry64: stp x30, xzr, [sp, #-16]! /* If function ID matches, do_call with procedure address in x7 */ + branch_if PSCI_CPU_ON_32, psci_cpu_on branch_if PSCI_CPU_ON_64, psci_cpu_on branch_if PSCI_CPU_OFF, psci_cpu_off diff --git a/boot_common.c b/boot_common.c index daf3198..4947fe3 100644 --- a/boot_common.c +++ b/boot_common.c @@ -40,7 +40,11 @@ void __noreturn spin(unsigned long *mbox, unsigned long invalid, int is_entry) } if (is_entry) +#ifdef KERNEL_32 + jump_kernel(addr, 0, ~0, (unsigned long)&dtb, 0); +#else jump_kernel(addr, (unsigned long)&dtb, 0, 0, 0); +#endif jump_kernel(addr, 0, 0, 0, 0); diff --git a/configure.ac b/configure.ac index 929da13..bc35515 100644 --- a/configure.ac +++ b/configure.ac @@ -16,12 +16,21 @@ fi AM_INIT_AUTOMAKE([foreign]) +AC_ARG_ENABLE([aarch32-kernel], + AC_HELP_STRING([--enable-aarch32-kernel], + [start kernel in AArch32 instead of AArch64]), + [KERNEL_ES=32 USE_PSCI=yes AC_SUBST([KERNEL_32], [1]) AC_DEFINE([KERNEL_32])], + [KERNEL_ES=64]) +AM_CONDITIONAL([KERNEL_32], [test "x$KERNEL_ES" = x32]) + # Allow a user to pass --with-kernel-dir AC_ARG_WITH([kernel-dir], AS_HELP_STRING([--with-kernel-dir], [specify the root Linux kernel build directory (required)]), AC_SUBST([KERN_DIR], [$withval]), AC_MSG_ERROR([No kernel directory specified. Use --with-kernel-dir])) -KERN_IMAGE=$KERN_DIR/arch/arm64/boot/Image +AS_IF([test "x$KERNEL_ES" = x32], + [KERN_IMAGE=$KERN_DIR/arch/arm/boot/zImage], + [KERN_IMAGE=$KERN_DIR/arch/arm64/boot/Image]) KERN_DTB=$KERN_DIR/arch/arm64/boot/dts/rtsm_ve-aemv8a.dtb # Allow the user to override the default DTB @@ -47,6 +56,10 @@ AC_ARG_ENABLE([psci], AM_CONDITIONAL([PSCI], [test "x$USE_PSCI" = "xyes"]) AS_IF([test "x$USE_PSCI" = "xyes"], [], [USE_PSCI=no]) +AS_IF([test "x$USE_PSCI" != "xyes" -a "x$KERNEL_ES" = "x32"], + [AC_MSG_ERROR([With an AArch32 kernel, boot method must be PSCI.])] +) + # Allow a user to pass --with-cpu-ids C_CPU_IDS="0x0,0x1,0x2,0x3" AC_ARG_WITH(cpu-ids, @@ -102,4 +115,5 @@ echo " Embedded initrd: ${FILESYSTEM:-NONE}" echo " Use PSCI? ${USE_PSCI}" echo " CPU IDs: ${CPU_IDS}" echo " Use GICv3? ${USE_GICV3}" +echo " Kernel execution state: AArch${KERNEL_ES}" echo "" diff --git a/include/psci.h b/include/psci.h index 21ca5ee..df0f647 100644 --- a/include/psci.h +++ b/include/psci.h @@ -10,6 +10,7 @@ #define __PSCI_H #define PSCI_CPU_OFF 0x84000002 +#define PSCI_CPU_ON_32 0x84000003 #define PSCI_CPU_ON_64 0xc4000003 #define PSCI_RET_SUCCESS 0 |