Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

armstub7: Major refactoring and size improvements #117

Merged
merged 2 commits into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 130 additions & 109 deletions armstubs/armstub7.S
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2016 Raspberry Pi (Trading) Ltd.
Copyright (c) 2016-2020 Raspberry Pi (Trading) Ltd.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -27,146 +27,167 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

.arch_extension sec
.arch_extension virt
.syntax unified

.section .init
.globl _start
/* the vector table for secure state and HYP mode */
_start:
b jmp_loader /* reset */
#if defined(BCM2711) && (BCM2711 == 1)
osc: .word 54000000
#define MACHINE_ID 3138

#if BCM2711
#define OSC_FREQ 54000000
#define LOCAL_BASE 0xff800000
#else
osc: .word 19200000
#define OSC_FREQ 19200000
#define LOCAL_BASE 0x40000000
#endif

/*
* secure monitor handler
* U-boot calls this "software interrupt" in start.S
* This is executed on a "smc" instruction, we use a "smc #0" to switch
* to non-secure state.
* We use only r0 and r1 here, due to constraints in the caller.
*/
_secure_monitor:
movw r1, #0x131 @ set NS, AW, FW, HVC
mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set)
#define ARML_PRESCALER 0x08
#define ARML_MBOX_CLR03 0xcc

movw r0, #0x1da @ Set HYP_MODE | F_BIT | I_BIT | A_BIT
msr spsr_cxfs, r0 @ Set full SPSR
#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) */

#if defined(BCM2711) && (BCM2711 == 1)
mov r1, #0x22 @ Set L2 read/write latency to 3
mcr p15, 1, r1, c9, c0, 2 @ Write L2CTLR
/* CPU interface */
#define GIC_CPUB 0x42000
#define GICC_CTRLR 0x0
#define GICC_PMR 0x4
#endif

movs pc, lr @ return to non-secure SVC

value: .word 0x63fff
#define machid 3138
#if defined(BCM2711) && (BCM2711 == 1)

#define PRESCALER_2711 0xff800008
#define MBOX_2711 0xff8000cc

mbox: .word MBOX_2711
GIC_DISTB: .word 0xff841000
#if BCM2710
#define NSACR_VAL 0xc00
#else
mbox: .word 0x400000cc
#define NSACR_VAL 0x60c00
#endif
jmp_loader:
@ Check which proc we are and run proc 0 only

.if !BCM2710
mrc p15, 0, r0, c1, c0, 1 @ Read Auxiliary Control Register
orr r0, r0, #(1<<6) @ SMP
mcr p15, 0, r0, c1, c0, 1 @ Write Auxiliary Control Register
.else
mrrc p15, 1, r0, r1, c15 @ CPU Extended Control Register
orr r0, r0, #(1<<6) @ SMP
and r1, r1, #(~3) @ Set L2 load data prefetch to 0b00 = 16
mcrr p15, 1, r0, r1, c15 @ CPU Extended Control Register
.endif
mrc p15, 0, r0, c1, c0, 0 @ Read System Control Register
/* Cortex A72 manual 4.3.67 says SMP must be set before enabling the cache. */
orr r0, r0, #(1<<12) @ icache enable
mcr p15, 0, r0, c1, c0, 0 @ Write System Control Register

mrc p15, 0, r7, c0, c0, 5 @ Put core number into R7

#ifdef GIC
.section .init
.global _start

#define GIC_CPUB_offset 0x1000
/* 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)

#define GICC_CTRLR 0x0
#define GICC_PMR 0x4
#define IT_NR 0x8 @ Number of interrupt enable registers (256 total irqs)
#define GICD_CTRLR 0x0
#define GICD_IGROUPR 0x80
/*
* 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

setup_gic: @ Called from secure mode - set all interrupts to group 1 and enable.
ldr r2, GIC_DISTB
/*
* 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

ands r7,r7, #3 @ primary core
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

movne r0, #3 @ Enable group 0 and 1 IRQs from distributor
strne r0, [r2, #GICD_CTRLR]
#ifdef GIC

mov r0, #~0
mov r1, #~0 @ group 1 all the things
strd r0, r1, [r2,#(GICD_IGROUPR)]! @ update to bring the CPU registers within range
strd r0, r1, [r2,#8]
strd r0, r1, [r2,#16]
strd r0, r1, [r2,#24]
@ 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

movw r1, #0x1e7
str r1, [r2, #(GIC_CPUB_offset - GICD_IGROUPR) ]! @ Enable group 1 IRQs from CPU interface
@ 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

movw r1, #0xff
str r1, [r2, #GICC_PMR] @ priority mask
movs r1, #0xff
str r1, [r5, #GICC_PMR] @ Set priority mask

#endif

mov r0, #1
mcr p15, 0, r0, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0)

@ set to non-sec
ldr r1, value @ value = 0x63fff
@ Allow non-secure access to coprocessors
ldr r1, =NSACR_VAL
mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec
@ timer frequency
ldr r1, osc @ osc = 19.2 / 54MHz
mcr p15, 0, r1, c14, c0, 0 @ write CNTFRQ
#if defined(BCM2711) && (BCM2711 == 1)

@ 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
ldr r2, mbox
str r1, [r2, #(PRESCALER_2711 - MBOX_2711)]
str r1, [r7, #ARML_PRESCALER]
#endif
movs r1, #1
mcr p15, 0, r1, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0)

adr ip, _start
mcr p15, 0, ip, c12, c0, 1 @ set MVBAR to secure vectors

@ 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
smc #0 @ call into MONITOR mode

mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR

ldrd r2,r3, atags @ ATAGS and kernel

ands r7,r7, #3 @ primary core
beq 9f
#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)

ldr r5, mbox @ mbox
#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

1:
wfe
ldr r3, [r5, r7, lsl #4]
cmp r3, #0 @ magic
beq 1b
@ clear mailbox
str r3, [r5, r7, lsl #4]
@ 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:
mov r0, #0
movw r1, #machid @ BCM2708 machine id

@ 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
Expand Down
7 changes: 7 additions & 0 deletions armstubs/armstub8.S
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
#define SCR_VAL \
(SCR_RW | SCR_HCE | SCR_SMD | SCR_RES1_5 | SCR_RES1_4 | SCR_NS)

#define ACTLR_VAL \
(BIT(0) | BIT(1) | BIT(4) | BIT(5) | BIT(6))

#define CPUECTLR_EL1 S3_1_C15_C2_1
#define CPUECTLR_EL1_SMPEN BIT(6)

Expand Down Expand Up @@ -120,6 +123,10 @@ _start:
mov x0, #SCR_VAL
msr SCR_EL3, x0

/* Set up ACTLR */
mov x0, #ACTLR_VAL
msr ACTLR_EL3, x0

/* Set SMPEN */
mov x0, #CPUECTLR_EL1_SMPEN
msr CPUECTLR_EL1, x0
Expand Down