Skip to content

Commit 14985bb

Browse files
fincspelwell
authored andcommitted
armstub7: Major refactoring and size improvements, see details:
- 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 (!)
1 parent 0c39cb5 commit 14985bb

File tree

1 file changed

+130
-109
lines changed

1 file changed

+130
-109
lines changed

armstubs/armstub7.S

Lines changed: 130 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2016 Raspberry Pi (Trading) Ltd.
2+
Copyright (c) 2016-2020 Raspberry Pi (Trading) Ltd.
33
All rights reserved.
44

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

2828
.arch_extension sec
2929
.arch_extension virt
30+
.syntax unified
3031

31-
.section .init
32-
.globl _start
33-
/* the vector table for secure state and HYP mode */
34-
_start:
35-
b jmp_loader /* reset */
36-
#if defined(BCM2711) && (BCM2711 == 1)
37-
osc: .word 54000000
32+
#define MACHINE_ID 3138
33+
34+
#if BCM2711
35+
#define OSC_FREQ 54000000
36+
#define LOCAL_BASE 0xff800000
3837
#else
39-
osc: .word 19200000
38+
#define OSC_FREQ 19200000
39+
#define LOCAL_BASE 0x40000000
4040
#endif
4141

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

53-
movw r0, #0x1da @ Set HYP_MODE | F_BIT | I_BIT | A_BIT
54-
msr spsr_cxfs, r0 @ Set full SPSR
45+
#ifdef GIC
46+
/* Distributor */
47+
#define GIC_DISTB 0x41000
48+
#define GICD_CTLR 0x0
49+
#define GICD_IGROUPR 0x80
50+
#define IT_NR 0x8 /* Number of interrupt enable registers (256 total irqs) */
5551

56-
#if defined(BCM2711) && (BCM2711 == 1)
57-
mov r1, #0x22 @ Set L2 read/write latency to 3
58-
mcr p15, 1, r1, c9, c0, 2 @ Write L2CTLR
52+
/* CPU interface */
53+
#define GIC_CPUB 0x42000
54+
#define GICC_CTRLR 0x0
55+
#define GICC_PMR 0x4
5956
#endif
6057

61-
movs pc, lr @ return to non-secure SVC
62-
63-
value: .word 0x63fff
64-
#define machid 3138
65-
#if defined(BCM2711) && (BCM2711 == 1)
66-
67-
#define PRESCALER_2711 0xff800008
68-
#define MBOX_2711 0xff8000cc
69-
70-
mbox: .word MBOX_2711
71-
GIC_DISTB: .word 0xff841000
58+
#if BCM2710
59+
#define NSACR_VAL 0xc00
7260
#else
73-
mbox: .word 0x400000cc
61+
#define NSACR_VAL 0x60c00
7462
#endif
75-
jmp_loader:
76-
@ Check which proc we are and run proc 0 only
77-
78-
.if !BCM2710
79-
mrc p15, 0, r0, c1, c0, 1 @ Read Auxiliary Control Register
80-
orr r0, r0, #(1<<6) @ SMP
81-
mcr p15, 0, r0, c1, c0, 1 @ Write Auxiliary Control Register
82-
.else
83-
mrrc p15, 1, r0, r1, c15 @ CPU Extended Control Register
84-
orr r0, r0, #(1<<6) @ SMP
85-
and r1, r1, #(~3) @ Set L2 load data prefetch to 0b00 = 16
86-
mcrr p15, 1, r0, r1, c15 @ CPU Extended Control Register
87-
.endif
88-
mrc p15, 0, r0, c1, c0, 0 @ Read System Control Register
89-
/* Cortex A72 manual 4.3.67 says SMP must be set before enabling the cache. */
90-
orr r0, r0, #(1<<12) @ icache enable
91-
mcr p15, 0, r0, c1, c0, 0 @ Write System Control Register
92-
93-
mrc p15, 0, r7, c0, c0, 5 @ Put core number into R7
9463

95-
#ifdef GIC
64+
.section .init
65+
.global _start
9666

97-
#define GIC_CPUB_offset 0x1000
67+
/* Vector table for secure state and HYP mode */
68+
_start:
69+
mrc p15, 0, r6, c0, c0, 5 @ Read MPIDR into r6
70+
blx _main @ Jump to bootstub entrypoint (Thumb-2)
9871

99-
#define GICC_CTRLR 0x0
100-
#define GICC_PMR 0x4
101-
#define IT_NR 0x8 @ Number of interrupt enable registers (256 total irqs)
102-
#define GICD_CTRLR 0x0
103-
#define GICD_IGROUPR 0x80
72+
/*
73+
* Secure monitor handler
74+
* This is executed on a "smc" instruction, we use a "smc #0" to switch
75+
* to non-secure state.
76+
* We only clobber ip (r12) here, so that the caller's r0-r7 remain valid.
77+
*/
78+
_secure_monitor:
79+
#if BCM2710
80+
mcr p15, 0, r1, c1, c0, 1 @ Write ACTLR (Secure)
81+
#endif
82+
mov ip, #0x1b1 @ Set NS, AW, FW, SCD, HVC
83+
mcr p15, 0, ip, c1, c1, 0 @ Write SCR (which sets the NS bit)
84+
mov ip, #0x1fa @ Set HYP_MODE | T_BIT | F_BIT | I_BIT | A_BIT
85+
msr spsr_cxfs, ip @ Set full SPSR
86+
movs pc, lr @ Return to non-secure HYP
10487

105-
setup_gic: @ Called from secure mode - set all interrupts to group 1 and enable.
106-
ldr r2, GIC_DISTB
88+
/*
89+
* Main bootstub entrypoint (entered in secure SVC mode)
90+
* This code is Thumb-2 in order to save space.
91+
*/
92+
.thumb_func
93+
_main:
94+
movs r0, #0 @ Set r0 to zero (used by code below and also as a kernel argument)
95+
lsls r6, r6, #30 @ Extract processor number field from MPIDR (shifted left by 30)
96+
ldr r7, =LOCAL_BASE @ Load ARM local peripherals base address for later use
97+
98+
#if !BCM2710
99+
mrc p15, 0, r1, c1, c0, 1 @ Read Auxiliary Control Register
100+
orr r1, r1, #(1<<6) @ Enable SMP
101+
mcr p15, 0, r1, c1, c0, 1 @ Write Auxiliary Control Register
102+
#else
103+
mrrc p15, 1, r1, r2, c15 @ CPU Extended Control Register
104+
orr r1, r1, #(1<<6) @ Enable SMP
105+
#if BCM2711
106+
bic r2, r2, #3 @ Set L2 load data prefetch to 0b00 = 16 requests (A72-specific)
107+
#endif
108+
mcrr p15, 1, r1, r2, c15 @ CPU Extended Control Register
109+
#endif
107110

108-
ands r7,r7, #3 @ primary core
111+
mrc p15, 0, r1, c1, c0, 0 @ Read System Control Register
112+
/* Cortex A72 manual 4.3.67 says SMP must be set before enabling the cache. */
113+
orr r1, r1, #(1<<12) @ Enable icache
114+
mcr p15, 0, r1, c1, c0, 0 @ Write System Control Register
109115

110-
movne r0, #3 @ Enable group 0 and 1 IRQs from distributor
111-
strne r0, [r2, #GICD_CTRLR]
116+
#ifdef GIC
112117

113-
mov r0, #~0
114-
mov r1, #~0 @ group 1 all the things
115-
strd r0, r1, [r2,#(GICD_IGROUPR)]! @ update to bring the CPU registers within range
116-
strd r0, r1, [r2,#8]
117-
strd r0, r1, [r2,#16]
118-
strd r0, r1, [r2,#24]
118+
@ Configure the GIC Distributor
119+
add r5, r7, #GIC_DISTB @ Get base address of GIC_DISTB
120+
cbnz r6, 9f @ Skip setting GICD_CTLR if we are not core 0
121+
movs r1, #3
122+
str r1, [r5, #GICD_CTLR] @ Enable group 0 and 1 IRQs from distributor
123+
9:
124+
mov r1, #~0 @ Route all interrupts to group 1
125+
movs r2, #IT_NR
126+
add r5, r5, #GICD_IGROUPR @ Note: GICD_IGROUPR0 is banked for each core so all cores must set it
127+
0: str r1, [r5], #4
128+
subs r2, r2, #1
129+
bne 0b
119130

120-
movw r1, #0x1e7
121-
str r1, [r2, #(GIC_CPUB_offset - GICD_IGROUPR) ]! @ Enable group 1 IRQs from CPU interface
131+
@ Enable all interrupts coming from group 1 on this core
132+
add r5, r7, #GIC_CPUB @ Get base address of GIC_CPUB
133+
mov r1, #0x1e7
134+
str r1, [r5, #GICC_CTRLR] @ Enable group 1 IRQs from CPU interface
122135

123-
movw r1, #0xff
124-
str r1, [r2, #GICC_PMR] @ priority mask
136+
movs r1, #0xff
137+
str r1, [r5, #GICC_PMR] @ Set priority mask
125138

126139
#endif
127140

128-
mov r0, #1
129-
mcr p15, 0, r0, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0)
130-
131-
@ set to non-sec
132-
ldr r1, value @ value = 0x63fff
141+
@ Allow non-secure access to coprocessors
142+
ldr r1, =NSACR_VAL
133143
mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec
134-
@ timer frequency
135-
ldr r1, osc @ osc = 19.2 / 54MHz
136-
mcr p15, 0, r1, c14, c0, 0 @ write CNTFRQ
137-
#if defined(BCM2711) && (BCM2711 == 1)
144+
145+
@ Initialize the architectural timer
146+
ldr r1, =OSC_FREQ @ osc = 19.2 or 54MHz
147+
mcr p15, 0, r1, c14, c0, 0 @ Write CNTFRQ
148+
#if BCM2711
138149
mov r1, #0x80000000 @ Set ARM_LOCAL_TIMER_PRE_ADD to 1
139-
ldr r2, mbox
140-
str r1, [r2, #(PRESCALER_2711 - MBOX_2711)]
150+
str r1, [r7, #ARML_PRESCALER]
141151
#endif
152+
movs r1, #1
153+
mcr p15, 0, r1, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0)
142154

143-
adr ip, _start
144-
mcr p15, 0, ip, c12, c0, 1 @ set MVBAR to secure vectors
145-
155+
@ Initialize exception vectors and switch to non-secure HYP mode
156+
mcr p15, 0, r0, c12, c0, 1 @ Set MVBAR to secure vectors (i.e. zero)
146157
isb
147-
smc #0 @ call into MONITOR mode
148-
149-
mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR
150-
151-
ldrd r2,r3, atags @ ATAGS and kernel
152-
153-
ands r7,r7, #3 @ primary core
154-
beq 9f
158+
#if BCM2710
159+
movs r1, #0x73 @ Value for ACTLR: enable non-secure access to CPUACTLR/CPUECTLR/L2CTLR/L2ECTLR/L2ACTLR
160+
#endif
161+
smc #0 @ Call into MONITOR mode
162+
mcr p15, 0, r0, c12, c0, 0 @ Write non-secure copy of VBAR
163+
mcrr p15, 4, r0, r0, c14 @ Reset CNTVOFF to zero (must be done now in non-secure HYP mode)
155164

156-
ldr r5, mbox @ mbox
165+
#if BCM2711
166+
movs r1, #0x22 @ Value for L2CTLR: set L2 read/write latency to 3
167+
mcr p15, 1, r1, c9, c0, 2 @ Write L2CTLR
168+
#endif
157169

158-
1:
159-
wfe
160-
ldr r3, [r5, r7, lsl #4]
161-
cmp r3, #0 @ magic
162-
beq 1b
163-
@ clear mailbox
164-
str r3, [r5, r7, lsl #4]
170+
@ Set kernel entrypoint arguments
171+
mov r1, #MACHINE_ID @ BCM2708 machine id
172+
ldrd r2, r3, atags @ ATAGS and kernel
173+
174+
@ Secondary cores only: synchronize with core 0 using the mailbox
175+
cbz r6, 9f @ Skip this section if we are core 0
176+
lsrs r6, r6, #(30-4) @ Calculate offset to mailbox register (i.e. ARML_MBOX_CLR03 + coreid*0x10)
177+
adds r6, r6, #ARML_MBOX_CLR03
178+
0: wfe
179+
ldr r3, [r7, r6] @ Read message (secondary kernel entrypoint)
180+
cmp r3, #0 @ If zero, there is no message
181+
beq 0b
182+
str r3, [r7, r6] @ Clear mailbox
165183
9:
166-
mov r0, #0
167-
movw r1, #machid @ BCM2708 machine id
184+
185+
@ Jump to kernel
168186
bx r3
169187

188+
@ Assembler generated constant pool goes here
189+
.pool
190+
170191
.org 0xf0
171192
.word 0x5afe570b @ magic value to indicate firmware should overwrite atags and kernel
172193
.word 0 @ version

0 commit comments

Comments
 (0)