]> xenbits.xensource.com Git - people/julieng/boot-wrapper-aarch64.git/commitdiff
Add AArch32 to the boot-wrapper
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Fri, 4 Dec 2015 12:43:20 +0000 (12:43 +0000)
committerMark Rutland <mark.rutland@arm.com>
Wed, 15 Jun 2016 09:27:35 +0000 (10:27 +0100)
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>
13 files changed:
Makefile.am
arch/aarch32/boot.S [new file with mode: 0644]
arch/aarch32/common.S [new file with mode: 0644]
arch/aarch32/include/asm/cpu.h [new file with mode: 0644]
arch/aarch32/include/asm/gic-v3.h [new file with mode: 0644]
arch/aarch32/include/asm/io.h [new file with mode: 0644]
arch/aarch32/psci.S [new file with mode: 0644]
arch/aarch32/stack.S [new file with mode: 0644]
arch/aarch32/utils.S [new file with mode: 0644]
configure.ac
include/linkage.h [new file with mode: 0644]
model.lds.S
platform.c

index 5cc7d0b176394ce94f4f81b9dace2af29f15f78b..692d2cc71d3fe373f593c5f85800ab9bd65ae15f 100644 (file)
@@ -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 (file)
index 0000000..2a85ad5
--- /dev/null
@@ -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 (file)
index 0000000..6b11e62
--- /dev/null
@@ -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 (file)
index 0000000..878be67
--- /dev/null
@@ -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 (file)
index 0000000..ec9a327
--- /dev/null
@@ -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 (file)
index 0000000..4f37272
--- /dev/null
@@ -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 (file)
index 0000000..78dca96
--- /dev/null
@@ -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 (file)
index 0000000..59f3f52
--- /dev/null
@@ -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 (file)
index 0000000..53d8747
--- /dev/null
@@ -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
index bc35515cd1b3d966b497e5d739107bbdbb0420c4..ab8f5b33c14742d182b0feef8a5508192c80d75e 100644 (file)
@@ -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 (file)
index 0000000..844a811
--- /dev/null
@@ -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
index f1902e1d213dc950255546da88f77afed3bc133f..51c568499dfff23cf7bc47e2810eb3b35e5bfd30 100644 (file)
@@ -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)
index 16b15bc7fcdf09afb8193c399add2651151de6f7..a528a550a29b849f3bd1cb9c3993534616e0eb46 100644 (file)
@@ -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