Skip to content
Permalink
master
Switch branches/tags
Go to file
- The bootstub has been completely rewritten taking advantage of the
  Thumb-2 instruction set, which results in major space gains
- Res0 bits of NSACR are no longer set (supersedes #85)
- CNTVOFF is set to zero, now consistent with armstub8 (supersedes #113)
- SMC instructions are now disabled, now consistent with armstub8
- ACTLR is now configured to allow Non-secure access to several CPU
  configuration registers (CPUACTLR/CPUECTLR/L2CTLR/L2ECTLR/L2ACTLR),
  which makes it possible to e.g. enable Spectre v4 mitigations directly
  in the kernel without needing a separate bootstub variant
  (potentially supersedes #115)

Free space in each affected bootstub after this commit:

  armstub7.bin:        108 bytes
  armstub8-32.bin:     104 bytes
  armstub8-32-gic.bin:  44 bytes (!)
3 contributors

Users who have contributed to this file

@popcornmix @pelwell @fincs
195 lines (166 sloc) 6.41 KB
/*
Copyright (c) 2016-2020 Raspberry Pi (Trading) Ltd.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.arch_extension sec
.arch_extension virt
.syntax unified
#define MACHINE_ID 3138
#if BCM2711
#define OSC_FREQ 54000000
#define LOCAL_BASE 0xff800000
#else
#define OSC_FREQ 19200000
#define LOCAL_BASE 0x40000000
#endif
#define ARML_PRESCALER 0x08
#define ARML_MBOX_CLR03 0xcc
#ifdef GIC
/* Distributor */
#define GIC_DISTB 0x41000
#define GICD_CTLR 0x0
#define GICD_IGROUPR 0x80
#define IT_NR 0x8 /* Number of interrupt enable registers (256 total irqs) */
/* CPU interface */
#define GIC_CPUB 0x42000
#define GICC_CTRLR 0x0
#define GICC_PMR 0x4
#endif
#if BCM2710
#define NSACR_VAL 0xc00
#else
#define NSACR_VAL 0x60c00
#endif
.section .init
.global _start
/* Vector table for secure state and HYP mode */
_start:
mrc p15, 0, r6, c0, c0, 5 @ Read MPIDR into r6
blx _main @ Jump to bootstub entrypoint (Thumb-2)
/*
* Secure monitor handler
* This is executed on a "smc" instruction, we use a "smc #0" to switch
* to non-secure state.
* We only clobber ip (r12) here, so that the caller's r0-r7 remain valid.
*/
_secure_monitor:
#if BCM2710
mcr p15, 0, r1, c1, c0, 1 @ Write ACTLR (Secure)
#endif
mov ip, #0x1b1 @ Set NS, AW, FW, SCD, HVC
mcr p15, 0, ip, c1, c1, 0 @ Write SCR (which sets the NS bit)
mov ip, #0x1fa @ Set HYP_MODE | T_BIT | F_BIT | I_BIT | A_BIT
msr spsr_cxfs, ip @ Set full SPSR
movs pc, lr @ Return to non-secure HYP
/*
* Main bootstub entrypoint (entered in secure SVC mode)
* This code is Thumb-2 in order to save space.
*/
.thumb_func
_main:
movs r0, #0 @ Set r0 to zero (used by code below and also as a kernel argument)
lsls r6, r6, #30 @ Extract processor number field from MPIDR (shifted left by 30)
ldr r7, =LOCAL_BASE @ Load ARM local peripherals base address for later use
#if !BCM2710
mrc p15, 0, r1, c1, c0, 1 @ Read Auxiliary Control Register
orr r1, r1, #(1<<6) @ Enable SMP
mcr p15, 0, r1, c1, c0, 1 @ Write Auxiliary Control Register
#else
mrrc p15, 1, r1, r2, c15 @ CPU Extended Control Register
orr r1, r1, #(1<<6) @ Enable SMP
#if BCM2711
bic r2, r2, #3 @ Set L2 load data prefetch to 0b00 = 16 requests (A72-specific)
#endif
mcrr p15, 1, r1, r2, c15 @ CPU Extended Control Register
#endif
mrc p15, 0, r1, c1, c0, 0 @ Read System Control Register
/* Cortex A72 manual 4.3.67 says SMP must be set before enabling the cache. */
orr r1, r1, #(1<<12) @ Enable icache
mcr p15, 0, r1, c1, c0, 0 @ Write System Control Register
#ifdef GIC
@ Configure the GIC Distributor
add r5, r7, #GIC_DISTB @ Get base address of GIC_DISTB
cbnz r6, 9f @ Skip setting GICD_CTLR if we are not core 0
movs r1, #3
str r1, [r5, #GICD_CTLR] @ Enable group 0 and 1 IRQs from distributor
9:
mov r1, #~0 @ Route all interrupts to group 1
movs r2, #IT_NR
add r5, r5, #GICD_IGROUPR @ Note: GICD_IGROUPR0 is banked for each core so all cores must set it
0: str r1, [r5], #4
subs r2, r2, #1
bne 0b
@ Enable all interrupts coming from group 1 on this core
add r5, r7, #GIC_CPUB @ Get base address of GIC_CPUB
mov r1, #0x1e7
str r1, [r5, #GICC_CTRLR] @ Enable group 1 IRQs from CPU interface
movs r1, #0xff
str r1, [r5, #GICC_PMR] @ Set priority mask
#endif
@ Allow non-secure access to coprocessors
ldr r1, =NSACR_VAL
mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec
@ Initialize the architectural timer
ldr r1, =OSC_FREQ @ osc = 19.2 or 54MHz
mcr p15, 0, r1, c14, c0, 0 @ Write CNTFRQ
#if BCM2711
mov r1, #0x80000000 @ Set ARM_LOCAL_TIMER_PRE_ADD to 1
str r1, [r7, #ARML_PRESCALER]
#endif
movs r1, #1
mcr p15, 0, r1, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0)
@ Initialize exception vectors and switch to non-secure HYP mode
mcr p15, 0, r0, c12, c0, 1 @ Set MVBAR to secure vectors (i.e. zero)
isb
#if BCM2710
movs r1, #0x73 @ Value for ACTLR: enable non-secure access to CPUACTLR/CPUECTLR/L2CTLR/L2ECTLR/L2ACTLR
#endif
smc #0 @ Call into MONITOR mode
mcr p15, 0, r0, c12, c0, 0 @ Write non-secure copy of VBAR
mcrr p15, 4, r0, r0, c14 @ Reset CNTVOFF to zero (must be done now in non-secure HYP mode)
#if BCM2711
movs r1, #0x22 @ Value for L2CTLR: set L2 read/write latency to 3
mcr p15, 1, r1, c9, c0, 2 @ Write L2CTLR
#endif
@ Set kernel entrypoint arguments
mov r1, #MACHINE_ID @ BCM2708 machine id
ldrd r2, r3, atags @ ATAGS and kernel
@ Secondary cores only: synchronize with core 0 using the mailbox
cbz r6, 9f @ Skip this section if we are core 0
lsrs r6, r6, #(30-4) @ Calculate offset to mailbox register (i.e. ARML_MBOX_CLR03 + coreid*0x10)
adds r6, r6, #ARML_MBOX_CLR03
0: wfe
ldr r3, [r7, r6] @ Read message (secondary kernel entrypoint)
cmp r3, #0 @ If zero, there is no message
beq 0b
str r3, [r7, r6] @ Clear mailbox
9:
@ Jump to kernel
bx r3
@ Assembler generated constant pool goes here
.pool
.org 0xf0
.word 0x5afe570b @ magic value to indicate firmware should overwrite atags and kernel
.word 0 @ version
atags: .word 0x0 @ device tree address
kernel: .word 0x0 @ kernel start address