xref: /arm-trusted-firmware/include/arch/aarch32/smccc_macros.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu#ifndef SMCCC_MACROS_S
7*91f16700Schasinglulu#define SMCCC_MACROS_S
8*91f16700Schasinglulu
9*91f16700Schasinglulu#include <arch.h>
10*91f16700Schasinglulu
11*91f16700Schasinglulu/*
12*91f16700Schasinglulu * Macro to save the General purpose registers (r0 - r12), the banked
13*91f16700Schasinglulu * spsr, lr, sp registers and the `scr` register to the SMC context on entry
14*91f16700Schasinglulu * due a SMC call. The `lr` of the current mode (monitor) is expected to be
15*91f16700Schasinglulu * already saved. The `sp` must point to the `smc_ctx_t` to save to.
16*91f16700Schasinglulu * Additionally, also save the 'pmcr' register as this is updated whilst
17*91f16700Schasinglulu * executing in the secure world.
18*91f16700Schasinglulu */
19*91f16700Schasinglulu	.macro smccc_save_gp_mode_regs
20*91f16700Schasinglulu	/* Save r0 - r12 in the SMC context */
21*91f16700Schasinglulu	stm	sp, {r0-r12}
22*91f16700Schasinglulu	mov	r0, sp
23*91f16700Schasinglulu	add	r0, r0, #SMC_CTX_SP_USR
24*91f16700Schasinglulu
25*91f16700Schasinglulu#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
26*91f16700Schasinglulu	/* Must be in secure state to restore Monitor mode */
27*91f16700Schasinglulu	ldcopr	r4, SCR
28*91f16700Schasinglulu	bic	r2, r4, #SCR_NS_BIT
29*91f16700Schasinglulu	stcopr	r2, SCR
30*91f16700Schasinglulu	isb
31*91f16700Schasinglulu
32*91f16700Schasinglulu	cps	#MODE32_sys
33*91f16700Schasinglulu	stm	r0!, {sp, lr}
34*91f16700Schasinglulu
35*91f16700Schasinglulu	cps	#MODE32_irq
36*91f16700Schasinglulu	mrs	r2, spsr
37*91f16700Schasinglulu	stm	r0!, {r2, sp, lr}
38*91f16700Schasinglulu
39*91f16700Schasinglulu	cps	#MODE32_fiq
40*91f16700Schasinglulu	mrs	r2, spsr
41*91f16700Schasinglulu	stm	r0!, {r2, sp, lr}
42*91f16700Schasinglulu
43*91f16700Schasinglulu	cps	#MODE32_svc
44*91f16700Schasinglulu	mrs	r2, spsr
45*91f16700Schasinglulu	stm	r0!, {r2, sp, lr}
46*91f16700Schasinglulu
47*91f16700Schasinglulu	cps	#MODE32_abt
48*91f16700Schasinglulu	mrs	r2, spsr
49*91f16700Schasinglulu	stm	r0!, {r2, sp, lr}
50*91f16700Schasinglulu
51*91f16700Schasinglulu	cps	#MODE32_und
52*91f16700Schasinglulu	mrs	r2, spsr
53*91f16700Schasinglulu	stm	r0!, {r2, sp, lr}
54*91f16700Schasinglulu
55*91f16700Schasinglulu	/* lr_mon is already saved by caller */
56*91f16700Schasinglulu	cps	#MODE32_mon
57*91f16700Schasinglulu	mrs	r2, spsr
58*91f16700Schasinglulu	stm	r0!, {r2}
59*91f16700Schasinglulu
60*91f16700Schasinglulu	stcopr	r4, SCR
61*91f16700Schasinglulu#else
62*91f16700Schasinglulu	/* Save the banked registers including the current SPSR and LR */
63*91f16700Schasinglulu	mrs	r4, sp_usr
64*91f16700Schasinglulu	mrs	r5, lr_usr
65*91f16700Schasinglulu	mrs	r6, spsr_irq
66*91f16700Schasinglulu	mrs	r7, sp_irq
67*91f16700Schasinglulu	mrs	r8, lr_irq
68*91f16700Schasinglulu	mrs	r9, spsr_fiq
69*91f16700Schasinglulu	mrs	r10, sp_fiq
70*91f16700Schasinglulu	mrs	r11, lr_fiq
71*91f16700Schasinglulu	mrs	r12, spsr_svc
72*91f16700Schasinglulu	stm	r0!, {r4-r12}
73*91f16700Schasinglulu
74*91f16700Schasinglulu	mrs	r4, sp_svc
75*91f16700Schasinglulu	mrs	r5, lr_svc
76*91f16700Schasinglulu	mrs	r6, spsr_abt
77*91f16700Schasinglulu	mrs	r7, sp_abt
78*91f16700Schasinglulu	mrs	r8, lr_abt
79*91f16700Schasinglulu	mrs	r9, spsr_und
80*91f16700Schasinglulu	mrs	r10, sp_und
81*91f16700Schasinglulu	mrs	r11, lr_und
82*91f16700Schasinglulu	mrs	r12, spsr
83*91f16700Schasinglulu	stm	r0!, {r4-r12}
84*91f16700Schasinglulu	/* lr_mon is already saved by caller */
85*91f16700Schasinglulu
86*91f16700Schasinglulu	ldcopr	r4, SCR
87*91f16700Schasinglulu
88*91f16700Schasinglulu#if ARM_ARCH_MAJOR > 7
89*91f16700Schasinglulu	/*
90*91f16700Schasinglulu	 * Check if earlier initialization of SDCR.SCCD to 1
91*91f16700Schasinglulu	 * failed, meaning that ARMv8-PMU is not implemented,
92*91f16700Schasinglulu	 * cycle counting is not disabled and PMCR should be
93*91f16700Schasinglulu	 * saved in Non-secure context.
94*91f16700Schasinglulu	 */
95*91f16700Schasinglulu	ldcopr	r5, SDCR
96*91f16700Schasinglulu	tst	r5, #SDCR_SCCD_BIT
97*91f16700Schasinglulu	bne	1f
98*91f16700Schasinglulu#endif
99*91f16700Schasinglulu	/* Secure Cycle Counter is not disabled */
100*91f16700Schasinglulu#endif
101*91f16700Schasinglulu	ldcopr	r5, PMCR
102*91f16700Schasinglulu
103*91f16700Schasinglulu	/* Check caller's security state */
104*91f16700Schasinglulu	tst	r4, #SCR_NS_BIT
105*91f16700Schasinglulu	beq	2f
106*91f16700Schasinglulu
107*91f16700Schasinglulu	/* Save PMCR if called from Non-secure state */
108*91f16700Schasinglulu	str	r5, [sp, #SMC_CTX_PMCR]
109*91f16700Schasinglulu
110*91f16700Schasinglulu	/* Disable cycle counter when event counting is prohibited */
111*91f16700Schasinglulu2:	orr	r5, r5, #PMCR_DP_BIT
112*91f16700Schasinglulu	stcopr	r5, PMCR
113*91f16700Schasinglulu	isb
114*91f16700Schasinglulu1:	str	r4, [sp, #SMC_CTX_SCR]
115*91f16700Schasinglulu	.endm
116*91f16700Schasinglulu
117*91f16700Schasinglulu/*
118*91f16700Schasinglulu * Macro to restore the `smc_ctx_t`, which includes the General purpose
119*91f16700Schasinglulu * registers and banked mode registers, and exit from the monitor mode.
120*91f16700Schasinglulu * r0 must point to the `smc_ctx_t` to restore from.
121*91f16700Schasinglulu */
122*91f16700Schasinglulu	.macro monitor_exit
123*91f16700Schasinglulu	/*
124*91f16700Schasinglulu	 * Save the current sp and restore the smc context
125*91f16700Schasinglulu	 * pointer to sp which will be used for handling the
126*91f16700Schasinglulu	 * next SMC.
127*91f16700Schasinglulu	 */
128*91f16700Schasinglulu	str	sp, [r0, #SMC_CTX_SP_MON]
129*91f16700Schasinglulu	mov	sp, r0
130*91f16700Schasinglulu
131*91f16700Schasinglulu	/*
132*91f16700Schasinglulu	 * Restore SCR first so that we access the right banked register
133*91f16700Schasinglulu	 * when the other mode registers are restored.
134*91f16700Schasinglulu	 */
135*91f16700Schasinglulu	ldr	r1, [r0, #SMC_CTX_SCR]
136*91f16700Schasinglulu	stcopr	r1, SCR
137*91f16700Schasinglulu	isb
138*91f16700Schasinglulu
139*91f16700Schasinglulu	/*
140*91f16700Schasinglulu	 * Restore PMCR when returning to Non-secure state
141*91f16700Schasinglulu	 */
142*91f16700Schasinglulu	tst	r1, #SCR_NS_BIT
143*91f16700Schasinglulu	beq	2f
144*91f16700Schasinglulu
145*91f16700Schasinglulu	/*
146*91f16700Schasinglulu	 * Back to Non-secure state
147*91f16700Schasinglulu	 */
148*91f16700Schasinglulu#if ARM_ARCH_MAJOR > 7
149*91f16700Schasinglulu	/*
150*91f16700Schasinglulu	 * Check if earlier initialization SDCR.SCCD to 1
151*91f16700Schasinglulu	 * failed, meaning that ARMv8-PMU is not implemented and
152*91f16700Schasinglulu	 * PMCR should be restored from Non-secure context.
153*91f16700Schasinglulu	 */
154*91f16700Schasinglulu	ldcopr	r1, SDCR
155*91f16700Schasinglulu	tst	r1, #SDCR_SCCD_BIT
156*91f16700Schasinglulu	bne	2f
157*91f16700Schasinglulu#endif
158*91f16700Schasinglulu	/*
159*91f16700Schasinglulu	 * Restore the PMCR register.
160*91f16700Schasinglulu	 */
161*91f16700Schasinglulu	ldr	r1, [r0, #SMC_CTX_PMCR]
162*91f16700Schasinglulu	stcopr	r1, PMCR
163*91f16700Schasinglulu2:
164*91f16700Schasinglulu	/* Restore the banked registers including the current SPSR */
165*91f16700Schasinglulu	add	r1, r0, #SMC_CTX_SP_USR
166*91f16700Schasinglulu
167*91f16700Schasinglulu#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
168*91f16700Schasinglulu	/* Must be in secure state to restore Monitor mode */
169*91f16700Schasinglulu	ldcopr	r4, SCR
170*91f16700Schasinglulu	bic	r2, r4, #SCR_NS_BIT
171*91f16700Schasinglulu	stcopr	r2, SCR
172*91f16700Schasinglulu	isb
173*91f16700Schasinglulu
174*91f16700Schasinglulu	cps	#MODE32_sys
175*91f16700Schasinglulu	ldm	r1!, {sp, lr}
176*91f16700Schasinglulu
177*91f16700Schasinglulu	cps	#MODE32_irq
178*91f16700Schasinglulu	ldm	r1!, {r2, sp, lr}
179*91f16700Schasinglulu	msr	spsr_fsxc, r2
180*91f16700Schasinglulu
181*91f16700Schasinglulu	cps	#MODE32_fiq
182*91f16700Schasinglulu	ldm	r1!, {r2, sp, lr}
183*91f16700Schasinglulu	msr	spsr_fsxc, r2
184*91f16700Schasinglulu
185*91f16700Schasinglulu	cps	#MODE32_svc
186*91f16700Schasinglulu	ldm	r1!, {r2, sp, lr}
187*91f16700Schasinglulu	msr	spsr_fsxc, r2
188*91f16700Schasinglulu
189*91f16700Schasinglulu	cps	#MODE32_abt
190*91f16700Schasinglulu	ldm	r1!, {r2, sp, lr}
191*91f16700Schasinglulu	msr	spsr_fsxc, r2
192*91f16700Schasinglulu
193*91f16700Schasinglulu	cps	#MODE32_und
194*91f16700Schasinglulu	ldm	r1!, {r2, sp, lr}
195*91f16700Schasinglulu	msr	spsr_fsxc, r2
196*91f16700Schasinglulu
197*91f16700Schasinglulu	cps	#MODE32_mon
198*91f16700Schasinglulu	ldm	r1!, {r2}
199*91f16700Schasinglulu	msr	spsr_fsxc, r2
200*91f16700Schasinglulu
201*91f16700Schasinglulu	stcopr	r4, SCR
202*91f16700Schasinglulu	isb
203*91f16700Schasinglulu#else
204*91f16700Schasinglulu	ldm	r1!, {r4-r12}
205*91f16700Schasinglulu	msr	sp_usr, r4
206*91f16700Schasinglulu	msr	lr_usr, r5
207*91f16700Schasinglulu	msr	spsr_irq, r6
208*91f16700Schasinglulu	msr	sp_irq, r7
209*91f16700Schasinglulu	msr	lr_irq, r8
210*91f16700Schasinglulu	msr	spsr_fiq, r9
211*91f16700Schasinglulu	msr	sp_fiq, r10
212*91f16700Schasinglulu	msr	lr_fiq, r11
213*91f16700Schasinglulu	msr	spsr_svc, r12
214*91f16700Schasinglulu
215*91f16700Schasinglulu	ldm	r1!, {r4-r12}
216*91f16700Schasinglulu	msr	sp_svc, r4
217*91f16700Schasinglulu	msr	lr_svc, r5
218*91f16700Schasinglulu	msr	spsr_abt, r6
219*91f16700Schasinglulu	msr	sp_abt, r7
220*91f16700Schasinglulu	msr	lr_abt, r8
221*91f16700Schasinglulu	msr	spsr_und, r9
222*91f16700Schasinglulu	msr	sp_und, r10
223*91f16700Schasinglulu	msr	lr_und, r11
224*91f16700Schasinglulu	/*
225*91f16700Schasinglulu	 * Use the `_fsxc` suffix explicitly to instruct the assembler
226*91f16700Schasinglulu	 * to update all the 32 bits of SPSR. Else, by default, the
227*91f16700Schasinglulu	 * assembler assumes `_fc` suffix which only modifies
228*91f16700Schasinglulu	 * f->[31:24] and c->[7:0] bits of SPSR.
229*91f16700Schasinglulu	 */
230*91f16700Schasinglulu	msr	spsr_fsxc, r12
231*91f16700Schasinglulu#endif
232*91f16700Schasinglulu
233*91f16700Schasinglulu	/* Restore the LR */
234*91f16700Schasinglulu	ldr	lr, [r0, #SMC_CTX_LR_MON]
235*91f16700Schasinglulu
236*91f16700Schasinglulu	/* Restore the rest of the general purpose registers */
237*91f16700Schasinglulu	ldm	r0, {r0-r12}
238*91f16700Schasinglulu	exception_return
239*91f16700Schasinglulu	.endm
240*91f16700Schasinglulu
241*91f16700Schasinglulu#endif /* SMCCC_MACROS_S */
242