blob: 95ce9387b83e972414b6de2d5711a9f40fe097df [file] [log] [blame]
Andre Przywarae776fd22013-09-19 18:06:40 +02001/*
Andre Przywara8de142c2013-09-19 18:06:45 +02002 * code for switching cores into non-secure state and into HYP mode
Andre Przywarae776fd22013-09-19 18:06:40 +02003 *
4 * Copyright (c) 2013 Andre Przywara <andre.przywara@linaro.org>
5 *
Andre Przywara6b216452013-10-07 10:56:51 +02006 * SPDX-License-Identifier: GPL-2.0+
Andre Przywarae776fd22013-09-19 18:06:40 +02007 */
8
9#include <config.h>
Andre Przywaradd5e8da2013-09-19 18:06:41 +020010#include <linux/linkage.h>
11#include <asm/gic.h>
12#include <asm/armv7.h>
Marc Zyngier855ca662014-07-12 14:24:03 +010013#include <asm/proc-armv/ptrace.h>
Andre Przywaradd5e8da2013-09-19 18:06:41 +020014
15.arch_extension sec
Andre Przywara8de142c2013-09-19 18:06:45 +020016.arch_extension virt
Andre Przywarae776fd22013-09-19 18:06:40 +020017
Marc Zyngier855ca662014-07-12 14:24:03 +010018 .pushsection ._secure.text, "ax"
19
Masahiro Yamada92bd4ac2013-10-07 11:46:56 +090020 .align 5
Andre Przywara8de142c2013-09-19 18:06:45 +020021/* the vector table for secure state and HYP mode */
Andre Przywarae776fd22013-09-19 18:06:40 +020022_monitor_vectors:
23 .word 0 /* reset */
24 .word 0 /* undef */
25 adr pc, _secure_monitor
26 .word 0
27 .word 0
Marc Zyngier855ca662014-07-12 14:24:03 +010028 .word 0
Andre Przywarae776fd22013-09-19 18:06:40 +020029 .word 0
30 .word 0
Andre Przywarae776fd22013-09-19 18:06:40 +020031
Marc Zyngier855ca662014-07-12 14:24:03 +010032.macro is_cpu_virt_capable tmp
33 mrc p15, 0, \tmp, c0, c1, 1 @ read ID_PFR1
34 and \tmp, \tmp, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
35 cmp \tmp, #(1 << CPUID_ARM_VIRT_SHIFT)
36.endm
37
Andre Przywarae776fd22013-09-19 18:06:40 +020038/*
39 * secure monitor handler
Bin Meng75574052016-02-05 19:30:11 -080040 * U-Boot calls this "software interrupt" in start.S
Andre Przywarae776fd22013-09-19 18:06:40 +020041 * This is executed on a "smc" instruction, we use a "smc #0" to switch
42 * to non-secure state.
Marc Zyngier855ca662014-07-12 14:24:03 +010043 * r0, r1, r2: passed to the callee
44 * ip: target PC
Andre Przywarae776fd22013-09-19 18:06:40 +020045 */
Andre Przywarae776fd22013-09-19 18:06:40 +020046_secure_monitor:
Marc Zyngier03a12012014-07-12 14:24:05 +010047#ifdef CONFIG_ARMV7_PSCI
48 ldr r5, =_psci_vectors @ Switch to the next monitor
49 mcr p15, 0, r5, c12, c0, 1
50 isb
51
Chen-Yu Tsai70617c72016-06-19 12:38:31 +080052 @ Obtain a secure stack
53 bl psci_stack_setup
54
55 @ Configure the PSCI backend
56 push {r0, r1, r2, ip}
Marc Zyngier03a12012014-07-12 14:24:05 +010057 bl psci_arch_init
Chen-Yu Tsai70617c72016-06-19 12:38:31 +080058 pop {r0, r1, r2, ip}
Marc Zyngier03a12012014-07-12 14:24:05 +010059#endif
60
Ian Campbell363e4242015-09-29 10:27:09 +010061#ifdef CONFIG_ARM_ERRATA_773022
62 mrc p15, 0, r5, c1, c0, 1
63 orr r5, r5, #(1 << 1)
64 mcr p15, 0, r5, c1, c0, 1
65 isb
66#endif
67
68#ifdef CONFIG_ARM_ERRATA_774769
69 mrc p15, 0, r5, c1, c0, 1
70 orr r5, r5, #(1 << 25)
71 mcr p15, 0, r5, c1, c0, 1
72 isb
73#endif
74
Marc Zyngier855ca662014-07-12 14:24:03 +010075 mrc p15, 0, r5, c1, c1, 0 @ read SCR
Marc Zyngier03a12012014-07-12 14:24:05 +010076 bic r5, r5, #0x4a @ clear IRQ, EA, nET bits
Marc Zyngier855ca662014-07-12 14:24:03 +010077 orr r5, r5, #0x31 @ enable NS, AW, FW bits
Marc Zyngier03a12012014-07-12 14:24:05 +010078 @ FIQ preserved for secure mode
Marc Zyngier855ca662014-07-12 14:24:03 +010079 mov r6, #SVC_MODE @ default mode is SVC
80 is_cpu_virt_capable r4
Marc Zyngier4cd832b2014-07-12 14:24:00 +010081#ifdef CONFIG_ARMV7_VIRT
Marc Zyngier855ca662014-07-12 14:24:03 +010082 orreq r5, r5, #0x100 @ allow HVC instruction
83 moveq r6, #HYP_MODE @ Enter the kernel as HYP
Andre Przywara8de142c2013-09-19 18:06:45 +020084#endif
85
Marc Zyngier855ca662014-07-12 14:24:03 +010086 mcr p15, 0, r5, c1, c1, 0 @ write SCR (with NS bit set)
Marc Zyngiere9195772014-07-12 14:23:59 +010087 isb
Andre Przywarae776fd22013-09-19 18:06:40 +020088
Marc Zyngier4cd832b2014-07-12 14:24:00 +010089 bne 1f
Andre Przywara8de142c2013-09-19 18:06:45 +020090
Marc Zyngier4cd832b2014-07-12 14:24:00 +010091 @ Reset CNTVOFF to 0 before leaving monitor mode
Marc Zyngier855ca662014-07-12 14:24:03 +010092 mrc p15, 0, r4, c0, c1, 1 @ read ID_PFR1
93 ands r4, r4, #CPUID_ARM_GENTIMER_MASK @ test arch timer bits
94 movne r4, #0
95 mcrrne p15, 4, r4, r4, c14 @ Reset CNTVOFF to zero
Marc Zyngier4cd832b2014-07-12 14:24:00 +0100961:
Marc Zyngier855ca662014-07-12 14:24:03 +010097 mov lr, ip
98 mov ip, #(F_BIT | I_BIT | A_BIT) @ Set A, I and F
99 tst lr, #1 @ Check for Thumb PC
100 orrne ip, ip, #T_BIT @ Set T if Thumb
101 orr ip, ip, r6 @ Slot target mode in
102 msr spsr_cxfs, ip @ Set full SPSR
103 movs pc, lr @ ERET to non-secure
104
105ENTRY(_do_nonsec_entry)
106 mov ip, r0
107 mov r0, r1
108 mov r1, r2
109 mov r2, r3
110 smc #0
111ENDPROC(_do_nonsec_entry)
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200112
Marc Zyngier855ca662014-07-12 14:24:03 +0100113.macro get_cbar_addr addr
114#ifdef CONFIG_ARM_GIC_BASE_ADDRESS
115 ldr \addr, =CONFIG_ARM_GIC_BASE_ADDRESS
116#else
117 mrc p15, 4, \addr, c15, c0, 0 @ read CBAR
118 bfc \addr, #0, #15 @ clear reserved bits
119#endif
120.endm
121
122.macro get_gicd_addr addr
123 get_cbar_addr \addr
124 add \addr, \addr, #GIC_DIST_OFFSET @ GIC dist i/f offset
125.endm
Andre Przywara8de142c2013-09-19 18:06:45 +0200126
Marc Zyngier855ca662014-07-12 14:24:03 +0100127.macro get_gicc_addr addr, tmp
128 get_cbar_addr \addr
129 is_cpu_virt_capable \tmp
130 movne \tmp, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9
131 moveq \tmp, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7
132 add \addr, \addr, \tmp
133.endm
134
135#ifndef CONFIG_ARMV7_PSCI
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200136/*
Andre Przywaradbbe1962013-09-19 18:06:44 +0200137 * Secondary CPUs start here and call the code for the core specific parts
138 * of the non-secure and HYP mode transition. The GIC distributor specific
139 * code has already been executed by a C function before.
140 * Then they go back to wfi and wait to be woken up by the kernel again.
141 */
142ENTRY(_smp_pen)
Marc Zyngier855ca662014-07-12 14:24:03 +0100143 cpsid i
144 cpsid f
Andre Przywaradbbe1962013-09-19 18:06:44 +0200145
146 bl _nonsec_init
Andre Przywaradbbe1962013-09-19 18:06:44 +0200147
148 adr r0, _smp_pen @ do not use this address again
149 b smp_waitloop @ wait for IPIs, board specific
150ENDPROC(_smp_pen)
Marc Zyngier855ca662014-07-12 14:24:03 +0100151#endif
Andre Przywaradbbe1962013-09-19 18:06:44 +0200152
153/*
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200154 * Switch a core to non-secure state.
155 *
156 * 1. initialize the GIC per-core interface
157 * 2. allow coprocessor access in non-secure modes
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200158 *
159 * Called from smp_pen by secondary cores and directly by the BSP.
160 * Do not assume that the stack is available and only use registers
161 * r0-r3 and r12.
162 *
163 * PERIPHBASE is used to get the GIC address. This could be 40 bits long,
164 * though, but we check this in C before calling this function.
165 */
166ENTRY(_nonsec_init)
Marc Zyngier855ca662014-07-12 14:24:03 +0100167 get_gicd_addr r3
168
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200169 mvn r1, #0 @ all bits to 1
170 str r1, [r3, #GICD_IGROUPRn] @ allow private interrupts
171
Marc Zyngier855ca662014-07-12 14:24:03 +0100172 get_gicc_addr r3, r1
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200173
Marc Zyngier855ca662014-07-12 14:24:03 +0100174 mov r1, #3 @ Enable both groups
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200175 str r1, [r3, #GICC_CTLR] @ and clear all other bits
176 mov r1, #0xff
177 str r1, [r3, #GICC_PMR] @ set priority mask register
178
Marc Zyngier855ca662014-07-12 14:24:03 +0100179 mrc p15, 0, r0, c1, c1, 2
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200180 movw r1, #0x3fff
Marc Zyngier855ca662014-07-12 14:24:03 +0100181 movt r1, #0x0004
182 orr r0, r0, r1
183 mcr p15, 0, r0, c1, c1, 2 @ NSACR = all copros to non-sec
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200184
185/* The CNTFRQ register of the generic timer needs to be
186 * programmed in secure state. Some primary bootloaders / firmware
187 * omit this, so if the frequency is provided in the configuration,
188 * we do this here instead.
189 * But first check if we have the generic timer.
190 */
Xiubo Li20a23ae2014-11-21 17:40:55 +0800191#ifdef CONFIG_TIMER_CLK_FREQ
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200192 mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
193 and r0, r0, #CPUID_ARM_GENTIMER_MASK @ mask arch timer bits
194 cmp r0, #(1 << CPUID_ARM_GENTIMER_SHIFT)
Xiubo Li20a23ae2014-11-21 17:40:55 +0800195 ldreq r1, =CONFIG_TIMER_CLK_FREQ
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200196 mcreq p15, 0, r1, c14, c0, 0 @ write CNTFRQ
197#endif
198
199 adr r1, _monitor_vectors
200 mcr p15, 0, r1, c12, c0, 1 @ set MVBAR to secure vectors
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200201 isb
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200202
203 mov r0, r3 @ return GICC address
Andre Przywaradd5e8da2013-09-19 18:06:41 +0200204 bx lr
205ENDPROC(_nonsec_init)
Andre Przywaradbbe1962013-09-19 18:06:44 +0200206
207#ifdef CONFIG_SMP_PEN_ADDR
208/* void __weak smp_waitloop(unsigned previous_address); */
209ENTRY(smp_waitloop)
210 wfi
211 ldr r1, =CONFIG_SMP_PEN_ADDR @ load start address
212 ldr r1, [r1]
Xiubo Li9d946422014-11-21 17:40:54 +0800213#ifdef CONFIG_PEN_ADDR_BIG_ENDIAN
214 rev r1, r1
215#endif
Andre Przywaradbbe1962013-09-19 18:06:44 +0200216 cmp r0, r1 @ make sure we dont execute this code
217 beq smp_waitloop @ again (due to a spurious wakeup)
Marc Zyngier855ca662014-07-12 14:24:03 +0100218 mov r0, r1
219 b _do_nonsec_entry
Andre Przywaradbbe1962013-09-19 18:06:44 +0200220ENDPROC(smp_waitloop)
221.weak smp_waitloop
222#endif
Andre Przywara8de142c2013-09-19 18:06:45 +0200223
Marc Zyngier855ca662014-07-12 14:24:03 +0100224 .popsection