xref: /optee_os/core/arch/arm/plat-vexpress/main.c (revision 6945b3687b22d876c658817a8d6b57e1d449846c)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2016-2023, Linaro Limited
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  */
6 
7 #include <arm.h>
8 #include <config.h>
9 #include <console.h>
10 #include <drivers/gic.h>
11 #include <drivers/hfic.h>
12 #include <drivers/pl011.h>
13 #include <drivers/tzc400.h>
14 #include <initcall.h>
15 #include <keep.h>
16 #include <kernel/boot.h>
17 #include <kernel/interrupt.h>
18 #include <kernel/misc.h>
19 #include <kernel/notif.h>
20 #include <kernel/panic.h>
21 #include <kernel/spinlock.h>
22 #include <kernel/thread_spmc.h>
23 #include <kernel/timer.h>
24 #include <kernel/virtualization.h>
25 #include <mm/core_memprot.h>
26 #include <mm/core_mmu.h>
27 #include <platform_config.h>
28 #include <sm/psci.h>
29 #include <stdint.h>
30 #include <trace.h>
31 
32 static struct pl011_data console_data __nex_bss;
33 static uint16_t console_notif_vm_id __nex_bss;
34 static uint16_t console_notif_backup_vm_id __nex_bss;
35 
36 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
37 #if defined(PLATFORM_FLAVOR_fvp)
38 register_phys_mem(MEM_AREA_RAM_SEC, TZCDRAM_BASE, TZCDRAM_SIZE);
39 #endif
40 #if defined(PLATFORM_FLAVOR_qemu_virt)
41 register_phys_mem_pgdir(MEM_AREA_IO_SEC, SECRAM_BASE, SECRAM_COHERENT_SIZE);
42 #endif
43 #ifdef DRAM0_BASE
44 register_ddr(DRAM0_BASE, DRAM0_SIZE);
45 #endif
46 #ifdef DRAM1_BASE
47 register_ddr(DRAM1_BASE, DRAM1_SIZE);
48 #endif
49 
50 #ifdef CFG_GIC
51 register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE);
52 register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
53 #ifdef GIC_REDIST_BASE
54 register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_REDIST_BASE, GIC_REDIST_SIZE);
55 #endif
56 
57 void boot_primary_init_intc(void)
58 {
59 #ifdef GIC_REDIST_BASE
60 	gic_init_v3(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET,
61 		    GIC_REDIST_BASE);
62 #else
63 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
64 #endif
65 	if (IS_ENABLED(CFG_CORE_SEL1_SPMC) &&
66 	    IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) {
67 		size_t it = CFG_CORE_ASYNC_NOTIF_GIC_INTID;
68 
69 		if (it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX)
70 			gic_init_donate_sgi_to_ns(it);
71 		thread_spmc_set_async_notif_intid(it);
72 	}
73 }
74 
75 void boot_secondary_init_intc(void)
76 {
77 	gic_init_per_cpu();
78 }
79 #endif /*CFG_GIC*/
80 
81 #ifdef CFG_CORE_HAFNIUM_INTC
82 void boot_primary_init_intc(void)
83 {
84 	hfic_init();
85 }
86 #endif
87 
88 void plat_console_init(void)
89 {
90 	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
91 		   CONSOLE_BAUDRATE);
92 	register_serial_console(&console_data.chip);
93 }
94 
95 #if (defined(CFG_GIC) || defined(CFG_CORE_HAFNIUM_INTC)) && \
96 	defined(IT_CONSOLE_UART) && \
97 	!(defined(CFG_WITH_ARM_TRUSTED_FW) && defined(CFG_ARM_GICV2)) && \
98 	!defined(CFG_SEMIHOSTING_CONSOLE) && \
99 	!defined(CFG_FFA_CONSOLE)
100 /*
101  * This cannot be enabled with TF-A and GICv3 because TF-A then need to
102  * assign the interrupt number of the UART to OP-TEE (S-EL1). Currently
103  * there's no way of TF-A to know which interrupts that OP-TEE will serve.
104  * If TF-A doesn't assign the interrupt we're enabling below to OP-TEE it
105  * will hang in EL3 since the interrupt will just be delivered again and
106  * again.
107  */
108 
109 static void read_console(void)
110 {
111 	struct serial_chip *cons = &console_data.chip;
112 
113 	if (!cons->ops->getchar || !cons->ops->have_rx_data)
114 		return;
115 
116 	while (cons->ops->have_rx_data(cons)) {
117 		int ch __maybe_unused = cons->ops->getchar(cons);
118 
119 		DMSG("got 0x%x", ch);
120 	}
121 }
122 
123 static uint16_t get_console_notif_vm_id(void)
124 {
125 	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
126 		return console_notif_vm_id;
127 	return 0;
128 }
129 
130 static enum itr_return console_itr_cb(struct itr_handler *hdl __unused)
131 {
132 	if (notif_async_is_started(get_console_notif_vm_id())) {
133 		/*
134 		 * Asynchronous notifications are enabled, lets read from
135 		 * uart in the bottom half instead.
136 		 */
137 		console_data.chip.ops->rx_intr_disable(&console_data.chip);
138 		notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF,
139 				 get_console_notif_vm_id());
140 	} else {
141 		read_console();
142 	}
143 	return ITRR_HANDLED;
144 }
145 
146 static struct itr_handler console_itr __nex_data = {
147 	.it = IT_CONSOLE_UART,
148 	.flags = ITRF_TRIGGER_LEVEL,
149 	.handler = console_itr_cb,
150 };
151 DECLARE_KEEP_PAGER(console_itr);
152 
153 static void atomic_console_notif(struct notif_driver *ndrv __unused,
154 				 enum notif_event ev, uint16_t vm_id)
155 {
156 	switch (ev) {
157 	case NOTIF_EVENT_STARTED:
158 		DMSG("Asynchronous notifications started, event %d (vm %#"PRIx16")",
159 		     (int)ev, vm_id);
160 		break;
161 	case NOTIF_EVENT_SHUTDOWN:
162 		DMSG("Shutting down partition, event %d (vm %#"PRIx16")",
163 		     (int)ev, vm_id);
164 		if (vm_id == console_notif_backup_vm_id)
165 			console_notif_backup_vm_id = 0;
166 		if (vm_id == console_notif_vm_id)
167 			console_notif_vm_id = console_notif_backup_vm_id;
168 		break;
169 	default:
170 		EMSG("Unknown event %d", (int)ev);
171 	}
172 }
173 DECLARE_KEEP_PAGER(atomic_console_notif);
174 
175 static void yielding_console_notif(struct notif_driver *ndrv __unused,
176 				   enum notif_event ev)
177 {
178 	switch (ev) {
179 	case NOTIF_EVENT_DO_BOTTOM_HALF:
180 		if (IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
181 		    console_notif_vm_id != virt_get_current_guest_id())
182 			break;
183 		read_console();
184 		console_data.chip.ops->rx_intr_enable(&console_data.chip);
185 		break;
186 	case NOTIF_EVENT_STOPPED:
187 		DMSG("Asynchronous notifications stopped");
188 		console_data.chip.ops->rx_intr_enable(&console_data.chip);
189 		break;
190 	default:
191 		EMSG("Unknown event %d", (int)ev);
192 	}
193 }
194 
195 static unsigned int console_notif_lock __nex_bss __maybe_unused;
196 static struct notif_driver console_notif __nex_data = {
197 	.atomic_cb = atomic_console_notif,
198 	.yielding_cb = yielding_console_notif,
199 };
200 
201 static TEE_Result init_console_itr(void)
202 {
203 	TEE_Result res = TEE_ERROR_GENERIC;
204 	bool have_itr_ctrl = console_data.chip.ops->rx_intr_enable &&
205 			     console_data.chip.ops->rx_intr_disable;
206 
207 	res = interrupt_add_handler_with_chip(interrupt_get_main_chip(),
208 					      &console_itr);
209 	if (res)
210 		return res;
211 
212 	interrupt_enable(console_itr.chip, console_itr.it);
213 
214 	if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF) && have_itr_ctrl)
215 		notif_register_driver(&console_notif);
216 	return TEE_SUCCESS;
217 }
218 nex_driver_init(init_console_itr);
219 
220 #ifdef CFG_NS_VIRTUALIZATION
221 static TEE_Result claim_console(void)
222 {
223 	uint32_t state = cpu_spin_lock_xsave(&console_notif_lock);
224 
225 	console_notif_vm_id = virt_get_current_guest_id();
226 	if (!console_notif_backup_vm_id)
227 		console_notif_backup_vm_id = console_notif_vm_id;
228 
229 	cpu_spin_unlock_xrestore(&console_notif_lock, state);
230 
231 	return TEE_SUCCESS;
232 }
233 driver_init(claim_console);
234 #endif
235 #endif
236 
237 #ifdef CFG_TZC400
238 register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC400_BASE, TZC400_REG_SIZE);
239 
240 static TEE_Result init_tzc400(void)
241 {
242 	void *va;
243 
244 	DMSG("Initializing TZC400");
245 
246 	va = phys_to_virt(TZC400_BASE, MEM_AREA_IO_SEC, TZC400_REG_SIZE);
247 	if (!va) {
248 		EMSG("TZC400 not mapped");
249 		panic();
250 	}
251 
252 	tzc_init((vaddr_t)va);
253 	tzc_dump_state();
254 
255 	return TEE_SUCCESS;
256 }
257 
258 service_init(init_tzc400);
259 #endif /*CFG_TZC400*/
260 
261 #if defined(PLATFORM_FLAVOR_qemu_virt)
262 static void release_secondary_early_hpen(size_t pos)
263 {
264 	struct mailbox {
265 		uint64_t ep;
266 		uint64_t hpen[];
267 	} *mailbox;
268 
269 	if (cpu_mmu_enabled())
270 		mailbox = phys_to_virt(SECRAM_BASE, MEM_AREA_IO_SEC,
271 				       SECRAM_COHERENT_SIZE);
272 	else
273 		mailbox = (void *)SECRAM_BASE;
274 
275 	if (!mailbox)
276 		panic();
277 
278 	mailbox->ep = TEE_LOAD_ADDR;
279 	dsb_ishst();
280 	mailbox->hpen[pos] = 1;
281 	dsb_ishst();
282 	sev();
283 }
284 
285 int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id)
286 {
287 	size_t pos = get_core_pos_mpidr(core_id);
288 	static bool core_is_released[CFG_TEE_CORE_NB_CORE];
289 
290 	if (!pos || pos >= CFG_TEE_CORE_NB_CORE)
291 		return PSCI_RET_INVALID_PARAMETERS;
292 
293 	DMSG("core pos: %zu: ns_entry %#" PRIx32, pos, entry);
294 
295 	if (core_is_released[pos]) {
296 		EMSG("core %zu already released", pos);
297 		return PSCI_RET_DENIED;
298 	}
299 	core_is_released[pos] = true;
300 
301 	boot_set_core_ns_entry(pos, entry, context_id);
302 	release_secondary_early_hpen(pos);
303 
304 	return PSCI_RET_SUCCESS;
305 }
306 #endif /*PLATFORM_FLAVOR_qemu_virt*/
307 
308 #if defined(CFG_CALLOUT) && defined(IT_SEC_PHY_TIMER)
309 static TEE_Result init_callout_service(void)
310 {
311 	timer_init_callout_service(interrupt_get_main_chip(), IT_SEC_PHY_TIMER);
312 
313 	return TEE_SUCCESS;
314 }
315 
316 nex_early_init(init_callout_service);
317 #endif
318