1/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <arch.h>
7#include <asm_macros.S>
8#include <rmm_el3_ifc.h>
9#include <sizes.h>
10#include <smc.h>
11#include <xlat_tables.h>
12
13#define RMM_STACK_SIZE		(SZ_4K * RMM_NUM_PAGES_PER_STACK)
14
15.globl rmm_entry
16
17/*
18 * Initialize essential R-EL2 sysregs and C runtime environment
19 */
20.macro rmm_el2_init_env _vector, _is_cold_boot_flag, _warm_boot
21
22	/*
23	 * Stash arguments from previous boot stage
24	 */
25	mov	x20, x0
26	mov	x21, x1
27	mov	x22, x2
28	mov	x23, x3
29
30	mov_imm	x1, SCTLR_EL2_INIT
31	msr	sctlr_el2, x1
32
33	mov_imm	x2, HCR_EL2_INIT
34	msr	hcr_el2, x2
35
36	mov_imm	x3, CPTR_EL2_INIT
37	msr	cptr_el2, x3
38
39	mov_imm	x4, ICC_SRE_EL2_INIT
40	msr	ICC_SRE_EL2, x4
41
42	isb
43
44	ldr	x1, \_is_cold_boot_flag
45	cbz	x1, 1f
46
47	/*
48	 * As PIE is enabled, fixup the Global Descriptor Table only
49	 * once during cold boot. This is needed before accessing any
50	 * symbol addresses.
51	 */
52	bl	fixup_gdt_reloc
53
54	/* Cold and warm boot need to go through this path */
551:
56	/* Early validate and init CPU Id */
57	mov	x0, x20
58	bl	rmm_el3_ifc_validate_cpuid
59
60	/* Setup stack on this CPU. X0 already contains the CPU Id */
61	bl	rmm_get_my_stack
62	mov	sp, x0
63
64	/*
65	 * Setup exception vectors
66	 */
67	adrp	x3, \_vector
68	add	x3, x3, :lo12:\_vector
69	msr	vbar_el2, x3
70	isb
71
72	/*
73	 * Find out whether this is a cold or warm boot
74	 */
75	ldr	x1, \_is_cold_boot_flag
76	cbnz	x1, 2f
77
78	/*
79	 * Restore arguments in preparation for the warm boot path
80	 */
81	mov	x0, x20
82	mov	x1, x21
83	mov	x2, x22
84	mov	x3, x23
85	b	\_warm_boot
86
872:
88	/*
89	 * Update cold boot flag to indicate cold boot is done
90	 */
91	adr	x2, \_is_cold_boot_flag
92	str	xzr, [x2]
93
94	/*
95	 * Initialize BSS section
96	 */
97	adrp	x0, bss_start
98	add	x0, x0, :lo12:bss_start
99	adrp	x1, bss_end
100	add	x1, x1, :lo12:bss_end
101	sub	x2, x1, x0
102	mov	x1, xzr
103	bl	memset
104
105	/*
106	 * Restore args received from previous BL image
107	 */
108	mov	x0, x20
109	mov	x1, x21
110	mov	x2, x22
111	mov	x3, x23
112.endm
113
114/*
115 * This is the main entry for both Primary and secondary PEs.
116 */
117func rmm_entry
118
119	rmm_el2_init_env el2_vectors, cold_boot_flag, skip_to_warmboot
120
121	/*
122	 * Initialize platform specific peripherals like UART and
123	 * xlat tables.
124	 */
125	bl	plat_setup
126	bl	xlat_enable_mmu_el2
127
128	bl	rmm_main
129	b	smc_ret
130
131skip_to_warmboot:
132	/*
133	 * Carry on with the rest of the RMM warmboot path
134	 */
135	bl	plat_warmboot_setup
136	bl	xlat_enable_mmu_el2
137
138	bl	rmm_warmboot_main
139smc_ret:
140	mov_imm	x0, SMC_RMM_BOOT_COMPLETE
141	mov_imm	x1, E_RMM_BOOT_SUCCESS
142	smc	#0
143
144	/* Jump to the SMC handler post-init */
145	b	rmm_handler
146
147	/*
148	 * Flag to mark if it is a cold boot.
149	 * 1: cold boot, 0: warmboot.
150	 */
151.align 3
152cold_boot_flag:
153	.dword		1
154endfunc rmm_entry
155
156/*
157 * Return the stack for a given PE index in x0
158 * stack-start				     stack_end
159 *       o--sz---o....o--sz---o--sz---o--sz---o
160 *       ^\_____/^....^\_____/^\_____/^\_____/^
161 * id = (MAX_CPU-1)      2       1       0
162 * Arg : x0 - CPU position
163 * sz: RMM_STACK_SIZE bytes.
164 */
165func rmm_get_my_stack
166#ifndef NDEBUG
167	cmp	x0, #MAX_CPUS
168	ASM_ASSERT lo
169#endif
170	adrp	x1, stack_end
171	add	x1, x1, :lo12:stack_end
172	mov	x2, #(RMM_STACK_SIZE)	/* stack size per CPU */
173	umsubl	x0, w0, w2, x1
174	ret
175endfunc rmm_get_my_stack
176