]> xenbits.xensource.com Git - people/julieng/boot-wrapper-aarch64.git/commitdiff
Add support for 32-bit kernel
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Tue, 22 Sep 2015 09:42:15 +0000 (10:42 +0100)
committerMark Rutland <mark.rutland@arm.com>
Wed, 15 Jun 2016 09:27:35 +0000 (10:27 +0100)
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>
Makefile.am
arch/aarch64/boot.S
arch/aarch64/include/asm/cpu.h
arch/aarch64/psci.S
boot_common.c
configure.ac
include/psci.h

index af0d7a6d72e96d1f7db94f9e9e754ae7c46f166b..0e2b92a0215478f99412a612b27b2b5d7a3873a4 100644 (file)
@@ -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
 
index 1602807b717c8adef9215e41de19d8b11b81bf59..ceeee764e7aca57f2e10e3e410a6e767c27b398e 100644 (file)
@@ -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
index eb3d8d713bf9d511aa3f5a4a1774e8e641f0f1a0..66726efc06ff23ab43cfec51fc2a7973b87d335e 100644 (file)
 #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__
 
index 5f7e2d77feb9707a21c7040dbc7f85ba25407658..01ebe7db3995b0ec3b85af765eca869ea59200ed 100644 (file)
@@ -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
 
index daf319814d0036372380bfbbf043d4bb4ce1db59..4947fe3c25409281d91ffc73d49e46cca4ac3405 100644 (file)
@@ -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);
 
index 929da13e68870d7709ab28cf12607a514868dc1b..bc35515cd1b3d966b497e5d739107bbdbb0420c4 100644 (file)
@@ -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 ""
index 21ca5ee981aeb2f5acce66b3308f018f32e46311..df0f6470b0c844f0363b317c666f8d834f4dac9a 100644 (file)
@@ -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