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
boot_primary_init_intc(void)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
boot_secondary_init_intc(void)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
boot_primary_init_intc(void)82 void boot_primary_init_intc(void)
83 {
84 hfic_init();
85 }
86 #endif
87
plat_console_init(void)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
read_console(void)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
get_console_notif_vm_id(void)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
console_itr_cb(struct itr_handler * hdl __unused)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
atomic_console_notif(struct notif_driver * ndrv __unused,enum notif_event ev,uint16_t vm_id)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
yielding_console_notif(struct notif_driver * ndrv __unused,enum notif_event ev)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
init_console_itr(void)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
claim_console(void)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
init_tzc400(void)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)
release_secondary_early_hpen(size_t pos)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
psci_cpu_on(uint32_t core_id,uint32_t entry,uint32_t context_id)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)
init_callout_service(void)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