aboutsummaryrefslogtreecommitdiff
path: root/bl1/aarch32/bl1_exceptions.S
blob: f2af9ab5b1bc0b00ac762b5a04adaf9782cc0acc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <arch.h>
#include <asm_macros.S>
#include <bl1/bl1.h>
#include <common/bl_common.h>
#include <context.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <smccc_helpers.h>
#include <smccc_macros.S>

	.globl	bl1_aarch32_smc_handler


func bl1_aarch32_smc_handler
	/* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */
	str	lr, [sp, #SMC_CTX_LR_MON]

	/* ------------------------------------------------
	 * SMC in BL1 is handled assuming that the MMU is
	 * turned off by BL2.
	 * ------------------------------------------------
	 */

	/* ----------------------------------------------
	 * Detect if this is a RUN_IMAGE or other SMC.
	 * ----------------------------------------------
	 */
	mov	lr, #BL1_SMC_RUN_IMAGE
	cmp	lr, r0
	bne	smc_handler

	/* ------------------------------------------------
	 * Make sure only Secure world reaches here.
	 * ------------------------------------------------
	 */
	ldcopr  r8, SCR
	tst	r8, #SCR_NS_BIT
	blne	report_exception

	/* ---------------------------------------------------------------------
	 * Pass control to next secure image.
	 * Here it expects r1 to contain the address of a entry_point_info_t
	 * structure describing the BL entrypoint.
	 * ---------------------------------------------------------------------
	 */
	mov	r8, r1
	mov	r0, r1
	bl	bl1_print_next_bl_ep_info

#if SPIN_ON_BL1_EXIT
	bl	print_debug_loop_message
debug_loop:
	b	debug_loop
#endif

	mov	r0, r8
	bl	bl1_plat_prepare_exit

	stcopr	r0, TLBIALL
	dsb	sy
	isb

	/*
	 * Extract PC and SPSR based on struct `entry_point_info_t`
	 * and load it in LR and SPSR registers respectively.
	 */
	ldr	lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
	ldr	r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
	msr	spsr_xc, r1

	/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
	cps	#MODE32_svc
	ldr	lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
	cps	#MODE32_mon

	add	r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
	ldm	r8, {r0, r1, r2, r3}
	eret
endfunc bl1_aarch32_smc_handler

	/* -----------------------------------------------------
	 * Save Secure/Normal world context and jump to
	 * BL1 SMC handler.
	 * -----------------------------------------------------
	 */
func smc_handler
	/* -----------------------------------------------------
	 * Save the GP registers.
	 * -----------------------------------------------------
	 */
	smccc_save_gp_mode_regs

	/*
	 * `sp` still points to `smc_ctx_t`. Save it to a register
	 * and restore the C runtime stack pointer to `sp`.
	 */
	mov	r6, sp
	ldr	sp, [r6, #SMC_CTX_SP_MON]

	ldr	r0, [r6, #SMC_CTX_SCR]
	and	r7, r0, #SCR_NS_BIT		/* flags */

	/* Switch to Secure Mode */
	bic	r0, #SCR_NS_BIT
	stcopr	r0, SCR
	isb

	/* If caller is from Secure world then turn on the MMU */
	tst	r7, #SCR_NS_BIT
	bne	skip_mmu_on

	/* Turn on the MMU */
	mov	r0, #DISABLE_DCACHE
	bl	enable_mmu_svc_mon

	/* Enable the data cache. */
	ldcopr	r9, SCTLR
	orr	r9, r9, #SCTLR_C_BIT
	stcopr	r9, SCTLR
	isb

skip_mmu_on:
	/* Prepare arguments for BL1 SMC wrapper. */
	ldr	r0, [r6, #SMC_CTX_GPREG_R0]	/* smc_fid */
	mov	r1, #0				/* cookie */
	mov	r2, r6				/* handle */
	mov	r3, r7				/* flags */
	bl	bl1_smc_wrapper

	/* Get the smc_context for next BL image */
	bl	smc_get_next_ctx
	mov	r4, r0

	/* Only turn-off MMU if going to secure world */
	ldr	r5, [r4, #SMC_CTX_SCR]
	tst	r5, #SCR_NS_BIT
	bne	skip_mmu_off

	/* Disable the MMU */
	bl	disable_mmu_icache_secure
	stcopr	r0, TLBIALL
	dsb	sy
	isb

skip_mmu_off:
	/* -----------------------------------------------------
	 * Do the transition to next BL image.
	 * -----------------------------------------------------
	 */
	mov	r0, r4
	monitor_exit
endfunc smc_handler