aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>2015-09-22 10:42:15 +0100
committerMark Rutland <mark.rutland@arm.com>2016-06-15 10:27:35 +0100
commit259bef910fee48a927e4700e9e82f99e94962098 (patch)
tree480a6ea46677c13399639827bd781435a7b2be1f
parentc311db0c5821f72604bfdaf40c6cbb0b672017c1 (diff)
downloadboot-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.am18
-rw-r--r--arch/aarch64/boot.S12
-rw-r--r--arch/aarch64/include/asm/cpu.h11
-rw-r--r--arch/aarch64/psci.S6
-rw-r--r--boot_common.c4
-rw-r--r--configure.ac16
-rw-r--r--include/psci.h1
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