1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Western Digital Corporation or its affiliates.
5  *
6  * Authors:
7  *   Anup Patel <anup.patel@wdc.com>
8  */
9 
10 #include <sbi/riscv_asm.h>
11 #include <sbi/riscv_atomic.h>
12 #include <sbi/riscv_locks.h>
13 #include <sbi/sbi_console.h>
14 #include <sbi/sbi_ecall.h>
15 #include <sbi/sbi_hart.h>
16 #include <sbi/sbi_hartmask.h>
17 #include <sbi/sbi_hsm.h>
18 #include <sbi/sbi_ipi.h>
19 #include <sbi/sbi_platform.h>
20 #include <sbi/sbi_system.h>
21 #include <sbi/sbi_string.h>
22 #include <sbi/sbi_timer.h>
23 #include <sbi/sbi_tlb.h>
24 #include <sbi/sbi_version.h>
25 
26 #define BANNER                                              \
27 	"   ____                    _____ ____ _____\n"     \
28 	"  / __ \\                  / ____|  _ \\_   _|\n"  \
29 	" | |  | |_ __   ___ _ __ | (___ | |_) || |\n"      \
30 	" | |  | | '_ \\ / _ \\ '_ \\ \\___ \\|  _ < | |\n" \
31 	" | |__| | |_) |  __/ | | |____) | |_) || |_\n"     \
32 	"  \\____/| .__/ \\___|_| |_|_____/|____/_____|\n"  \
33 	"        | |\n"                                     \
34 	"        |_|\n\n"
35 
sbi_boot_prints(struct sbi_scratch * scratch,u32 hartid)36 static void sbi_boot_prints(struct sbi_scratch *scratch, u32 hartid)
37 {
38 	int xlen;
39 	char str[128];
40 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
41 
42 #ifdef OPENSBI_VERSION_GIT
43 	sbi_printf("\nOpenSBI %s\n", OPENSBI_VERSION_GIT);
44 #else
45 	sbi_printf("\nOpenSBI v%d.%d\n", OPENSBI_VERSION_MAJOR,
46 		   OPENSBI_VERSION_MINOR);
47 #endif
48 
49 	sbi_printf(BANNER);
50 
51 	/* Determine MISA XLEN and MISA string */
52 	xlen = misa_xlen();
53 	if (xlen < 1) {
54 		sbi_printf("Error %d getting MISA XLEN\n", xlen);
55 		sbi_hart_hang();
56 	}
57 
58 	/* Platform details */
59 	sbi_printf("Platform Name       : %s\n", sbi_platform_name(plat));
60 	sbi_platform_get_features_str(plat, str, sizeof(str));
61 	sbi_printf("Platform Features   : %s\n", str);
62 	sbi_printf("Platform HART Count : %u\n",
63 		   sbi_platform_hart_count(plat));
64 
65 	/* Boot HART details */
66 	sbi_printf("Boot HART ID        : %u\n", hartid);
67 	misa_string(xlen, str, sizeof(str));
68 	sbi_printf("Boot HART ISA       : %s\n", str);
69 	sbi_hart_get_features_str(scratch, str, sizeof(str));
70 	sbi_printf("BOOT HART Features  : %s\n", str);
71 	sbi_printf("BOOT HART PMP Count : %d\n", sbi_hart_pmp_count(scratch));
72 
73 	/* Firmware details */
74 	sbi_printf("Firmware Base       : 0x%lx\n", scratch->fw_start);
75 	sbi_printf("Firmware Size       : %d KB\n",
76 		   (u32)(scratch->fw_size / 1024));
77 
78 	/* Generic details */
79 	sbi_printf("Runtime SBI Version : %d.%d\n",
80 		   sbi_ecall_version_major(), sbi_ecall_version_minor());
81 	sbi_printf("\n");
82 
83 	sbi_hart_delegation_dump(scratch);
84 	sbi_hart_pmp_dump(scratch);
85 }
86 
87 static spinlock_t coldboot_lock = SPIN_LOCK_INITIALIZER;
88 static unsigned long coldboot_done = 0;
89 static struct sbi_hartmask coldboot_wait_hmask = { 0 };
90 
wait_for_coldboot(struct sbi_scratch * scratch,u32 hartid)91 static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
92 {
93 	unsigned long saved_mie, cmip;
94 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
95 
96 	/* Save MIE CSR */
97 	saved_mie = csr_read(CSR_MIE);
98 
99 	/* Set MSIE bit to receive IPI */
100 	csr_set(CSR_MIE, MIP_MSIP);
101 
102 	/* Acquire coldboot lock */
103 	spin_lock(&coldboot_lock);
104 
105 	/* Mark current HART as waiting */
106 	sbi_hartmask_set_hart(hartid, &coldboot_wait_hmask);
107 
108 	/* Wait for coldboot to finish using WFI */
109 	while (!coldboot_done) {
110 		spin_unlock(&coldboot_lock);
111 		do {
112 			wfi();
113 			cmip = csr_read(CSR_MIP);
114 		 } while (!(cmip & MIP_MSIP));
115 		spin_lock(&coldboot_lock);
116 	};
117 
118 	/* Unmark current HART as waiting */
119 	sbi_hartmask_clear_hart(hartid, &coldboot_wait_hmask);
120 
121 	/* Release coldboot lock */
122 	spin_unlock(&coldboot_lock);
123 
124 	/* Restore MIE CSR */
125 	csr_write(CSR_MIE, saved_mie);
126 
127 	/* Clear current HART IPI */
128 	sbi_platform_ipi_clear(plat, hartid);
129 }
130 
wake_coldboot_harts(struct sbi_scratch * scratch,u32 hartid)131 static void wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid)
132 {
133 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
134 
135 	/* Acquire coldboot lock */
136 	spin_lock(&coldboot_lock);
137 
138 	/* Mark coldboot done */
139 	coldboot_done = 1;
140 
141 	/* Send an IPI to all HARTs waiting for coldboot */
142 	for (int i = 0; i <= sbi_scratch_last_hartid(); i++) {
143 		if ((i != hartid) &&
144 		    sbi_hartmask_test_hart(i, &coldboot_wait_hmask))
145 			sbi_platform_ipi_send(plat, i);
146 	}
147 
148 	/* Release coldboot lock */
149 	spin_unlock(&coldboot_lock);
150 }
151 
152 static unsigned long init_count_offset;
153 
init_coldboot(struct sbi_scratch * scratch,u32 hartid)154 static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
155 {
156 	int rc;
157 	unsigned long *init_count;
158 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
159 
160 	/* Note: This has to be first thing in coldboot init sequence */
161 	rc = sbi_scratch_init(scratch);
162 	if (rc)
163 		sbi_hart_hang();
164 
165 	init_count_offset = sbi_scratch_alloc_offset(__SIZEOF_POINTER__,
166 						     "INIT_COUNT");
167 	if (!init_count_offset)
168 		sbi_hart_hang();
169 
170 	rc = sbi_hsm_init(scratch, hartid, TRUE);
171 	if (rc)
172 		sbi_hart_hang();
173 
174 	rc = sbi_platform_early_init(plat, TRUE);
175 	if (rc)
176 		sbi_hart_hang();
177 
178 	rc = sbi_hart_init(scratch, hartid, TRUE);
179 	if (rc)
180 		sbi_hart_hang();
181 
182 	rc = sbi_console_init(scratch);
183 	if (rc)
184 		sbi_hart_hang();
185 
186 	rc = sbi_platform_irqchip_init(plat, TRUE);
187 	if (rc)
188 		sbi_hart_hang();
189 
190 	rc = sbi_ipi_init(scratch, TRUE);
191 	if (rc)
192 		sbi_hart_hang();
193 
194 	rc = sbi_tlb_init(scratch, TRUE);
195 	if (rc)
196 		sbi_hart_hang();
197 
198 	rc = sbi_timer_init(scratch, TRUE);
199 	if (rc)
200 		sbi_hart_hang();
201 
202 	rc = sbi_ecall_init();
203 	if (rc)
204 		sbi_hart_hang();
205 
206 	rc = sbi_platform_final_init(plat, TRUE);
207 	if (rc)
208 		sbi_hart_hang();
209 
210 	if (!(scratch->options & SBI_SCRATCH_NO_BOOT_PRINTS))
211 		sbi_boot_prints(scratch, hartid);
212 
213 	wake_coldboot_harts(scratch, hartid);
214 
215 	init_count = sbi_scratch_offset_ptr(scratch, init_count_offset);
216 	(*init_count)++;
217 
218 	sbi_hsm_prepare_next_jump(scratch, hartid);
219 	sbi_hart_switch_mode(hartid, scratch->next_arg1, scratch->next_addr,
220 			     scratch->next_mode, FALSE);
221 }
222 
init_warmboot(struct sbi_scratch * scratch,u32 hartid)223 static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid)
224 {
225 	int rc;
226 	unsigned long *init_count;
227 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
228 
229 	wait_for_coldboot(scratch, hartid);
230 
231 	if (!init_count_offset)
232 		sbi_hart_hang();
233 
234 	rc = sbi_hsm_init(scratch, hartid, FALSE);
235 	if (rc)
236 		sbi_hart_hang();
237 
238 	rc = sbi_platform_early_init(plat, FALSE);
239 	if (rc)
240 		sbi_hart_hang();
241 
242 	rc = sbi_hart_init(scratch, hartid, FALSE);
243 	if (rc)
244 		sbi_hart_hang();
245 
246 	rc = sbi_platform_irqchip_init(plat, FALSE);
247 	if (rc)
248 		sbi_hart_hang();
249 
250 	rc = sbi_ipi_init(scratch, FALSE);
251 	if (rc)
252 		sbi_hart_hang();
253 
254 	rc = sbi_tlb_init(scratch, FALSE);
255 	if (rc)
256 		sbi_hart_hang();
257 
258 	rc = sbi_timer_init(scratch, FALSE);
259 	if (rc)
260 		sbi_hart_hang();
261 
262 	rc = sbi_platform_final_init(plat, FALSE);
263 	if (rc)
264 		sbi_hart_hang();
265 
266 	init_count = sbi_scratch_offset_ptr(scratch, init_count_offset);
267 	(*init_count)++;
268 
269 	sbi_hsm_prepare_next_jump(scratch, hartid);
270 	sbi_hart_switch_mode(hartid, scratch->next_arg1,
271 			     scratch->next_addr,
272 			     scratch->next_mode, FALSE);
273 }
274 
275 static atomic_t coldboot_lottery = ATOMIC_INITIALIZER(0);
276 
277 /**
278  * Initialize OpenSBI library for current HART and jump to next
279  * booting stage.
280  *
281  * The function expects following:
282  * 1. The 'mscratch' CSR is pointing to sbi_scratch of current HART
283  * 2. Stack pointer (SP) is setup for current HART
284  * 3. Interrupts are disabled in MSTATUS CSR
285  * 4. All interrupts are disabled in MIE CSR
286  *
287  * @param scratch pointer to sbi_scratch of current HART
288  */
sbi_init(struct sbi_scratch * scratch)289 void __noreturn sbi_init(struct sbi_scratch *scratch)
290 {
291 	bool coldboot			= FALSE;
292 	u32 hartid			= current_hartid();
293 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
294 
295 	if ((SBI_HARTMASK_MAX_BITS <= hartid) ||
296 	    sbi_platform_hart_invalid(plat, hartid))
297 		sbi_hart_hang();
298 
299 	if (atomic_xchg(&coldboot_lottery, 1) == 0)
300 		coldboot = TRUE;
301 
302 	if (coldboot)
303 		init_coldboot(scratch, hartid);
304 	else
305 		init_warmboot(scratch, hartid);
306 }
307 
sbi_init_count(u32 hartid)308 unsigned long sbi_init_count(u32 hartid)
309 {
310 	struct sbi_scratch *scratch;
311 	unsigned long *init_count;
312 
313 	if (!init_count_offset)
314 		return 0;
315 
316 	scratch = sbi_hartid_to_scratch(hartid);
317 	if (!scratch)
318 		return 0;
319 
320 	init_count = sbi_scratch_offset_ptr(scratch, init_count_offset);
321 
322 	return *init_count;
323 }
324 
325 /**
326  * Exit OpenSBI library for current HART and stop HART
327  *
328  * The function expects following:
329  * 1. The 'mscratch' CSR is pointing to sbi_scratch of current HART
330  * 2. Stack pointer (SP) is setup for current HART
331  *
332  * @param scratch pointer to sbi_scratch of current HART
333  */
sbi_exit(struct sbi_scratch * scratch)334 void __noreturn sbi_exit(struct sbi_scratch *scratch)
335 {
336 	u32 hartid			= current_hartid();
337 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
338 
339 	if (sbi_platform_hart_invalid(plat, hartid))
340 		sbi_hart_hang();
341 
342 	sbi_platform_early_exit(plat);
343 
344 	sbi_timer_exit(scratch);
345 
346 	sbi_ipi_exit(scratch);
347 
348 	sbi_platform_irqchip_exit(plat);
349 
350 	sbi_platform_final_exit(plat);
351 
352 	sbi_hsm_exit(scratch);
353 }
354