diff options
author | Jean-Philippe Brucker <jean-philippe.brucker@arm.com> | 2015-12-04 12:43:20 +0000 |
---|---|---|
committer | Mark Rutland <mark.rutland@arm.com> | 2016-06-15 10:27:35 +0100 |
commit | e3fe71d0a592064adf1bfde81193b23df03c3469 (patch) | |
tree | 617f12b38d2b94c0b9b15db0238b0849552614f5 | |
parent | 5933e49b6f45fa18dd1e32d14372bb60837ff954 (diff) | |
download | boot-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.am | 6 | ||||
-rw-r--r-- | arch/aarch32/boot.S | 120 | ||||
-rw-r--r-- | arch/aarch32/common.S | 17 | ||||
-rw-r--r-- | arch/aarch32/include/asm/cpu.h | 99 | ||||
-rw-r--r-- | arch/aarch32/include/asm/gic-v3.h | 29 | ||||
-rw-r--r-- | arch/aarch32/include/asm/io.h | 31 | ||||
-rw-r--r-- | arch/aarch32/psci.S | 75 | ||||
-rw-r--r-- | arch/aarch32/stack.S | 32 | ||||
-rw-r--r-- | arch/aarch32/utils.S | 46 | ||||
-rw-r--r-- | configure.ac | 19 | ||||
-rw-r--r-- | include/linkage.h | 22 | ||||
-rw-r--r-- | model.lds.S | 5 | ||||
-rw-r--r-- | platform.c | 2 |
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) @@ -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 |