aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>2015-12-04 12:43:20 +0000
committerMark Rutland <mark.rutland@arm.com>2016-06-15 10:27:35 +0100
commite3fe71d0a592064adf1bfde81193b23df03c3469 (patch)
tree617f12b38d2b94c0b9b15db0238b0849552614f5
parent5933e49b6f45fa18dd1e32d14372bb60837ff954 (diff)
downloadboot-wrapper-aarch64-e3fe71d0a592064adf1bfde81193b23df03c3469.tar.gz
Add AArch32 to the boot-wrapper
This patch allows to build a 32-bit boot-wrapper, and create a complete linux-system.axf for models that start in AArch32. Most of the code is a simple translation of the AArch64 side. We add an --aarch32-bw argument to ./configure, and bump the version to 0.2, to welcome this new architecture. Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
-rw-r--r--Makefile.am6
-rw-r--r--arch/aarch32/boot.S120
-rw-r--r--arch/aarch32/common.S17
-rw-r--r--arch/aarch32/include/asm/cpu.h99
-rw-r--r--arch/aarch32/include/asm/gic-v3.h29
-rw-r--r--arch/aarch32/include/asm/io.h31
-rw-r--r--arch/aarch32/psci.S75
-rw-r--r--arch/aarch32/stack.S32
-rw-r--r--arch/aarch32/utils.S46
-rw-r--r--configure.ac19
-rw-r--r--include/linkage.h22
-rw-r--r--model.lds.S5
-rw-r--r--platform.c2
13 files changed, 494 insertions, 9 deletions
diff --git a/Makefile.am b/Makefile.am
index 5cc7d0b..692d2cc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,8 +32,14 @@ PSCI_CPU_OFF := 0x84000002
OFILES =
+if BOOTWRAPPER_32
+CPPFLAGS += -DBOOTWRAPPER_32
+CFLAGS += -marm -mno-unaligned-access
+ARCH_SRC := arch/aarch32/
+else
CFLAGS += -mgeneral-regs-only -mstrict-align
ARCH_SRC := arch/aarch64/
+endif
if PSCI
BOOTMETHOD := psci.o
diff --git a/arch/aarch32/boot.S b/arch/aarch32/boot.S
new file mode 100644
index 0000000..2a85ad5
--- /dev/null
+++ b/arch/aarch32/boot.S
@@ -0,0 +1,120 @@
+/*
+ * arch/aarch32/boot.S - simple register setup code for stand-alone Linux booting
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+#include <cpu.h>
+#include <linkage.h>
+
+#include "common.S"
+
+ .arch_extension sec
+ .arch_extension virt
+
+ .section .init
+ENTRY(_start)
+ /* Stack initialisation */
+ cpuid r0, r1
+ bl find_logical_id
+ cmp r0, #MPIDR_INVALID
+ beq _spin_dead
+
+ bl setup_stack
+
+ mrs r0, cpsr
+ and r0, #PSR_MODE_MASK
+
+ cmp r0, #PSR_HYP
+ bne _switch_monitor
+
+ mov r0, #1
+ ldr r1, =flag_no_el3
+ str r0, [r1]
+ b start_no_el3
+
+_switch_monitor:
+ ldr r0, =boot_vectors
+ bl setup_vector
+ smc #0
+
+_monitor:
+ /* Move the stack to Monitor mode*/
+ mrs sp, sp_svc
+
+ /* Setup secure registers and devices */
+ mov r0, #1 @ Non-secure lower level
+ orr r0, #(1 << 8) @ HVC enable
+ mcr p15, 0, r0, c1, c1, 0 @ SCR
+
+ mov r0, #(1 << 10 | 1 << 11) @ Enable NS access to CPACR
+ mcr p15, 0, r0, c1, c1, 2 @ NSACR
+
+ ldr r0, =CNTFRQ
+ mcr p15, 0, r0, c14, c0, 0 @ CNTFRQ
+
+ bl gic_secure_init
+
+ /* Initialise boot method */
+ b start_el3
+
+_spin_dead:
+ b .
+
+ .text
+
+ /*
+ * r0: kernel address
+ * r1-r3, sp[0]: kernel arguments
+ */
+ENTRY(jump_kernel)
+ sub sp, #4 @ Ignore fourth argument
+ push {r0 - r3}
+ mov r5, sp
+
+ ldr r0, =HSCTLR_RESET
+ mcr p15, 4, r0, c1, c0, 0 @ HSCTLR
+
+ ldr r0, =SCTLR_RESET
+ mcr p15, 0, r0, c1, c0, 0 @ SCTLR
+
+ /* Reset our stack pointer */
+ cpuid r0, r1
+ bl find_logical_id
+ bl setup_stack
+
+ ldr lr, [r5], #4
+ ldm r5, {r0 - r2}
+
+ ldr r4, =flag_no_el3
+ ldr r4, [r4]
+ cmp r4, #1
+ bxeq lr @ no EL3
+
+ ldr r4, =SPSR_KERNEL
+ /* Return in thumb2 mode when bit 0 of address is 1 */
+ tst lr, #1
+ orrne r4, #PSR_T
+
+ msr spsr_cxf, r4
+ movs pc, lr
+
+ .section .vectors
+ .align 6
+boot_vectors:
+ b .
+ b .
+ b _monitor
+ b .
+ b .
+ b .
+ b .
+ b .
+
+ .section .data
+ .align 2
+flag_no_el3:
+ .long 0
diff --git a/arch/aarch32/common.S b/arch/aarch32/common.S
new file mode 100644
index 0000000..6b11e62
--- /dev/null
+++ b/arch/aarch32/common.S
@@ -0,0 +1,17 @@
+/*
+ * arch/aarch32/common.S - common definitions useful for boot code
+ *
+ * Copyright (C) 2013 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+#include <asm/cpu.h>
+
+ /* Returns mpidr in \dest, clobbers \tmp and flags */
+ .macro cpuid dest, tmp
+ mrc p15, 0, \dest, c0, c0, 5 @ MPIDR
+ ldr \tmp, =MPIDR_ID_BITS
+ ands \dest, \dest, \tmp
+ .endm
diff --git a/arch/aarch32/include/asm/cpu.h b/arch/aarch32/include/asm/cpu.h
new file mode 100644
index 0000000..878be67
--- /dev/null
+++ b/arch/aarch32/include/asm/cpu.h
@@ -0,0 +1,99 @@
+/*
+ * arch/aarch32/include/asm/cpu.h
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+#ifndef __ASM_AARCH32_CPU_H
+#define __ASM_AARCH32_CPU_H
+
+#define MPIDR_ID_BITS 0x00ffffff
+#define MPIDR_INVALID (-1)
+
+/* Only RES1 bits and CP15 barriers for the kernel */
+#define HSCTLR_RESET (3 << 28 | 3 << 22 | 1 << 18 | 1 << 16 | 1 << 11 | 3 << 4)
+#define SCTLR_RESET (3 << 22 | 1 << 11 | 1 << 5 | 3 << 4)
+
+#define PSR_SVC 0x13
+#define PSR_HYP 0x1a
+#define PSR_MON 0x16
+#define PSR_MODE_MASK 0x1f
+
+#define PSR_T (1 << 5)
+#define PSR_F (1 << 6)
+#define PSR_I (1 << 7)
+#define PSR_A (1 << 8)
+
+
+#define SPSR_KERNEL (PSR_A | PSR_I | PSR_F | PSR_HYP)
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+#ifdef __ARM_ARCH_8A__
+#define sevl() asm volatile ("sevl" : : : "memory")
+#else
+/* sevl doesn't exist on ARMv7. Send event globally */
+#define sevl() asm volatile ("sev" : : : "memory")
+#endif
+
+static inline unsigned long read_mpidr(void)
+{
+ unsigned long mpidr;
+
+ asm volatile ("mrc p15, 0, %0, c0, c0, 5\n" : "=r" (mpidr));
+ return mpidr & MPIDR_ID_BITS;
+}
+
+static inline uint32_t read_id_pfr1(void)
+{
+ uint32_t val;
+
+ asm volatile ("mrc p15, 0, %0, c0, c1, 1\n" : "=r" (val));
+ return val;
+}
+
+static inline uint32_t read_clidr(void)
+{
+ uint32_t val;
+
+ asm volatile ("mrc p15, 1, %0, c0, c0, 1" : "=r" (val));
+ return val;
+}
+
+static inline uint32_t read_ccsidr(void)
+{
+ uint32_t val;
+
+ asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (val));
+ return val;
+}
+
+static inline void write_csselr(uint32_t val)
+{
+ asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (val));
+}
+
+static inline void dccisw(uint32_t val)
+{
+ asm volatile ("mcr p15, 0, %0, c7, c14, 2" : : "r" (val));
+}
+
+static inline void iciallu(void)
+{
+ uint32_t val = 0;
+
+ asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (val));
+}
+
+static inline int has_gicv3_sysreg(void)
+{
+ return !!((read_id_pfr1() >> 28) & 0xf);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/aarch32/include/asm/gic-v3.h b/arch/aarch32/include/asm/gic-v3.h
new file mode 100644
index 0000000..ec9a327
--- /dev/null
+++ b/arch/aarch32/include/asm/gic-v3.h
@@ -0,0 +1,29 @@
+/*
+ * arch/aarch32/include/asm/gic-v3.h
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+#ifndef __ASM_AARCH32_GICV3_H
+#define __ASM_AARCH32_GICV3_H
+
+static inline uint32_t gic_read_icc_sre(void)
+{
+ uint32_t val;
+ asm volatile ("mrc p15, 6, %0, c12, c12, 5" : "=r" (val));
+ return val;
+}
+
+static inline void gic_write_icc_sre(uint32_t val)
+{
+ asm volatile ("mcr p15, 6, %0, c12, c12, 5" : : "r" (val));
+}
+
+static inline void gic_write_icc_ctlr(uint32_t val)
+{
+ asm volatile ("mcr p15, 6, %0, c12, c12, 4" : : "r" (val));
+}
+
+#endif
diff --git a/arch/aarch32/include/asm/io.h b/arch/aarch32/include/asm/io.h
new file mode 100644
index 0000000..4f37272
--- /dev/null
+++ b/arch/aarch32/include/asm/io.h
@@ -0,0 +1,31 @@
+/*
+ * arch/aarch32/include/asm/io.h
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+#ifndef __ASM_AARCH32_IO_H
+#define __ASM_AARCH32_IO_H
+
+#include <stdint.h>
+
+#ifndef __ASSEMBLY__
+
+static inline void raw_writel(uint32_t val, void *addr)
+{
+ asm volatile ("str %0, [%1]\n" : : "r" (val), "r" (addr));
+}
+
+static inline uint32_t raw_readl(void *addr)
+{
+ uint32_t val;
+
+ asm volatile ("ldr %0, [%1]\n" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/aarch32/psci.S b/arch/aarch32/psci.S
new file mode 100644
index 0000000..78dca96
--- /dev/null
+++ b/arch/aarch32/psci.S
@@ -0,0 +1,75 @@
+/*
+ * arch/aarch32/psci.S - basic PSCI implementation
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+#include <cpu.h>
+#include <linkage.h>
+#include <psci.h>
+
+#include "common.S"
+
+ .section .vectors
+ .align 6
+smc_vectors:
+ b err_exception @ Reset
+ b err_exception @ Undef
+ b handle_smc @ SMC
+ b err_exception @ Prefetch abort
+ b err_exception @ Data abort
+ b . @ Unused
+ b err_exception @ IRQ
+ b err_exception @ FIQ
+
+ .text
+err_exception:
+ b .
+
+handle_smc:
+ @ Follow the SMC32 calling convention: preserve r4 - r14
+ push {r4 - r12, lr}
+
+ ldr r4, =PSCI_CPU_ON_32
+ cmp r4, r0
+ ldr r4, =psci_cpu_on
+ beq do_psci_call
+
+ ldr r4, =PSCI_CPU_OFF
+ cmp r4, r0
+ ldr r4, =psci_cpu_off
+ beq do_psci_call
+
+ adr r4, psci_invalid
+
+do_psci_call:
+ mov r0, r1
+ mov r1, r2
+ mov r2, r3
+
+ blx r4
+
+ pop {r4 - r12, lr}
+ movs pc, lr
+
+psci_invalid:
+ mov r0, #PSCI_RET_NOT_SUPPORTED
+ bx lr
+
+ENTRY(start_el3)
+ ldr r0, =smc_vectors
+ blx setup_vector
+ /* pass through */
+
+ENTRY(start_no_el3)
+ /*
+ * For no-el3, we assume that firmware launched the boot-wrapper in
+ * non-secure EL2 or EL1. We assume it has its own PSCI implementation
+ * sitting at EL3, and that this path is only taken by primary CPU.
+ */
+ cpuid r0, r1
+ blx find_logical_id
+ b psci_first_spin
diff --git a/arch/aarch32/stack.S b/arch/aarch32/stack.S
new file mode 100644
index 0000000..59f3f52
--- /dev/null
+++ b/arch/aarch32/stack.S
@@ -0,0 +1,32 @@
+/*
+ * arch/aarch32/stack.S - stack handling
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+ .globl setup_stack
+ .globl stack_top
+ .globl stack_bottom
+
+ .text
+ /*
+ * Setup initial stack pointer
+ * r0: logical CPU ID
+ * Clobbers r1 and r2
+ */
+setup_stack:
+ mov r1, #STACK_SIZE
+ ldr r2, =stack_top
+ mls sp, r0, r1, r2
+ bx lr
+
+ .section .stack
+ .align 2
+stack_bottom:
+ .irp cpu, CPU_IDS
+ .space STACK_SIZE
+ .endr
+stack_top:
diff --git a/arch/aarch32/utils.S b/arch/aarch32/utils.S
new file mode 100644
index 0000000..53d8747
--- /dev/null
+++ b/arch/aarch32/utils.S
@@ -0,0 +1,46 @@
+/*
+ * arch/aarch32/utils.S - basic utilities
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+#include <cpu.h>
+#include <linkage.h>
+
+ .text
+
+/*
+ * Takes masked MPIDR in r0, returns logical ID in r0.
+ * Z flag is set when CPU is primary; cleared otherwise.
+ * Returns MPIDR_INVALID for unknown MPIDRs
+ * Clobbers r1, r2, r3.
+ */
+ENTRY(find_logical_id)
+ ldr r2, =id_table
+ mov r1, #0
+1: mov r3, #NR_CPUS
+
+ cmp r1, r3
+ bgt 3f
+ ldr r3, [r2, r1, lsl #2]
+ cmp r3, r0
+ beq 2f
+ add r1, r1, #1
+ b 1b
+
+2: movs r0, r1
+ bx lr
+3: mov r0, #MPIDR_INVALID
+ bx lr
+
+/*
+ * Setup EL3 vectors.
+ * r0: vector address
+ */
+ENTRY(setup_vector)
+ mcr p15, 0, r0, c12, c0, 1 @ MVBAR
+ isb
+ bx lr
diff --git a/configure.ac b/configure.ac
index bc35515..ab8f5b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,17 +5,15 @@
# Use of this source code is governed by a BSD-style license that can
# be found in the LICENSE.txt file.
-AC_INIT([aarch64-boot-wrapper], [v0.1])
-
-# Ensure that we're using an AArch64 compiler
-AC_CANONICAL_SYSTEM
-
-if test "x$host_cpu" != "xaarch64"; then
- AC_MSG_ERROR([The boot-wrapper can only be used with an AArch64 compiler.])
-fi
+AC_INIT([boot-wrapper], [v0.2])
AM_INIT_AUTOMAKE([foreign])
+AC_ARG_ENABLE([aarch32-bw],
+ AS_HELP_STRING([--enable-aarch32-bw], [build a 32-bit boot-wrapper]),
+ [BOOTWRAPPER_ES=32], [BOOTWRAPPER_ES=64])
+AM_CONDITIONAL([BOOTWRAPPER_32], [test "x$BOOTWRAPPER_ES" = "x32"])
+
AC_ARG_ENABLE([aarch32-kernel],
AC_HELP_STRING([--enable-aarch32-kernel],
[start kernel in AArch32 instead of AArch64]),
@@ -23,6 +21,10 @@ AC_ARG_ENABLE([aarch32-kernel],
[KERNEL_ES=64])
AM_CONDITIONAL([KERNEL_32], [test "x$KERNEL_ES" = x32])
+AS_IF([test "x$BOOTWRAPPER_ES" = x32 -a "x$KERNEL_ES" != x32],
+ [AC_MSG_ERROR([a 32-bit boot-wrapper cannot launch a 64-bit kernel])]
+)
+
# 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)]),
@@ -115,5 +117,6 @@ echo " Embedded initrd: ${FILESYSTEM:-NONE}"
echo " Use PSCI? ${USE_PSCI}"
echo " CPU IDs: ${CPU_IDS}"
echo " Use GICv3? ${USE_GICV3}"
+echo " Boot-wrapper execution state: AArch${BOOTWRAPPER_ES}"
echo " Kernel execution state: AArch${KERNEL_ES}"
echo ""
diff --git a/include/linkage.h b/include/linkage.h
new file mode 100644
index 0000000..844a811
--- /dev/null
+++ b/include/linkage.h
@@ -0,0 +1,22 @@
+/*
+ * include/linkage.h
+ *
+ * Copyright (C) 2015 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+
+#ifndef __LINKAGE_H
+#define __LINKAGE_H
+
+#ifdef __ASSEMBLY__
+
+#define ENTRY(name) \
+ .globl name; \
+ .type name, %function; \
+ name:
+
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/model.lds.S b/model.lds.S
index f1902e1..51c5684 100644
--- a/model.lds.S
+++ b/model.lds.S
@@ -7,8 +7,13 @@
* found in the LICENSE.txt file.
*/
+#ifdef BOOTWRAPPER_32
+OUTPUT_FORMAT("elf32-littlearm")
+OUTPUT_ARCH(arm)
+#else
OUTPUT_FORMAT("elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
+#endif
TARGET(binary)
INPUT(KERNEL)
diff --git a/platform.c b/platform.c
index 16b15bc..a528a55 100644
--- a/platform.c
+++ b/platform.c
@@ -57,7 +57,7 @@ void init_platform(void)
/* Enable the UART, TXen and RXen */
raw_writel(0x301, PL011(UARTCR));
- print_string("Boot-wrapper v0.1\r\n\r\n");
+ print_string("Boot-wrapper v0.2\r\n\r\n");
/*
* CLCD output site MB