1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #include <assert.h>
6 #include <hyptypes.h>
7 
8 #include <hypversion.h>
9 
10 #include <boot.h>
11 #include <compiler.h>
12 #include <log.h>
13 #include <memdb.h>
14 #include <prng.h>
15 #include <qcbor.h>
16 #include <thread_init.h>
17 #include <trace.h>
18 #include <util.h>
19 
20 #include <events/boot.h>
21 
22 #include "boot_init.h"
23 #include "event_handlers.h"
24 
25 #define STR(x)	#x
26 #define XSTR(x) STR(x)
27 
28 const char hypervisor_version[] = XSTR(HYP_CONF_STR) "-" XSTR(HYP_GIT_VERSION)
29 #if defined(QUALITY)
30 	" " XSTR(QUALITY)
31 #endif
32 	;
33 const char hypervisor_build_date[] = HYP_BUILD_DATE;
34 
35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Wreserved-identifier"
37 extern uintptr_t	 __stack_chk_guard;
38 uintptr_t __stack_chk_guard __attribute__((used, visibility("hidden")));
39 #pragma clang diagnostic pop
40 
41 noreturn void
boot_cold_init(cpu_index_t cpu)42 boot_cold_init(cpu_index_t cpu) LOCK_IMPL
43 {
44 	// Set the stack canary, either globally, or for the init thread if the
45 	// canary is thread-local. Note that we can't do this in an event
46 	// handler because that might trigger a stack check failure if the event
47 	// handler is not inlined (e.g. in debug builds).
48 	uint64_result_t guard_r = prng_get64();
49 	assert(guard_r.e == OK);
50 	__stack_chk_guard = (uintptr_t)guard_r.r;
51 
52 	// We can't trace/log early because the CPU index and preemption count
53 	// in the thread are still uninitialized.
54 
55 	trigger_boot_cpu_early_init_event();
56 	trigger_boot_cold_init_event(cpu);
57 	trigger_boot_cpu_cold_init_event(cpu);
58 
59 	// It's safe to log now.
60 	TRACE_AND_LOG(ERROR, WARN, "Hypervisor cold boot, version: {:s} ({:s})",
61 		      (register_t)hypervisor_version,
62 		      (register_t)hypervisor_build_date);
63 
64 	TRACE(DEBUG, INFO, "boot_cpu_warm_init");
65 	trigger_boot_cpu_warm_init_event();
66 	TRACE(DEBUG, INFO, "boot_hypervisor_start");
67 	trigger_boot_hypervisor_start_event();
68 	TRACE(DEBUG, INFO, "boot_cpu_start");
69 	trigger_boot_cpu_start_event();
70 	TRACE(DEBUG, INFO, "entering idle");
71 	thread_boot_set_idle();
72 }
73 
74 #if defined(VERBOSE) && VERBOSE
75 #define STACK_GUARD_BYTE 0xb8
76 #define STACK_GUARD_SIZE 256U
77 #include <string.h>
78 
79 #include <panic.h>
80 
81 extern char aarch64_boot_stack[];
82 #endif
83 
84 void
boot_handle_boot_cold_init(void)85 boot_handle_boot_cold_init(void)
86 {
87 #if defined(VERBOSE) && VERBOSE
88 	// Add a red-zone to the boot stack
89 	errno_t err_mem = memset_s(aarch64_boot_stack, STACK_GUARD_SIZE,
90 				   STACK_GUARD_BYTE, STACK_GUARD_SIZE);
91 	if (err_mem != 0) {
92 		panic("Error in memset_s operation!");
93 	}
94 #endif
95 }
96 
97 void
boot_handle_idle_start(void)98 boot_handle_idle_start(void)
99 {
100 #if defined(VERBOSE) && VERBOSE
101 	char *stack_bottom = (char *)aarch64_boot_stack;
102 	// Check red-zone in the boot stack
103 	for (index_t i = 0; i < STACK_GUARD_SIZE; i++) {
104 		if (stack_bottom[i] != (char)STACK_GUARD_BYTE) {
105 			panic("boot stack overflow!");
106 		}
107 	}
108 #endif
109 }
110 
111 noreturn void
boot_secondary_init(cpu_index_t cpu)112 boot_secondary_init(cpu_index_t cpu) LOCK_IMPL
113 {
114 	// We can't trace/log early because the CPU index and preemption count
115 	// in the thread are still uninitialized
116 
117 	trigger_boot_cpu_early_init_event();
118 	trigger_boot_cpu_cold_init_event(cpu);
119 
120 	// It's safe to log now.
121 	TRACE_AND_LOG(INFO, WARN, "secondary cpu ({:d}) cold boot",
122 		      (register_t)cpu);
123 
124 	trigger_boot_cpu_warm_init_event();
125 	trigger_boot_cpu_start_event();
126 
127 	TRACE_LOCAL(DEBUG, INFO, "cpu cold boot complete");
128 	thread_boot_set_idle();
129 }
130 
131 // Warm (second or later) power-on of any CPU.
132 noreturn void
boot_warm_init(void)133 boot_warm_init(void) LOCK_IMPL
134 {
135 	trigger_boot_cpu_early_init_event();
136 	TRACE_LOCAL(INFO, INFO, "cpu warm boot start");
137 	trigger_boot_cpu_warm_init_event();
138 	trigger_boot_cpu_start_event();
139 	TRACE_LOCAL(DEBUG, INFO, "cpu warm boot complete");
140 	thread_boot_set_idle();
141 }
142 
143 static error_t
boot_do_memdb_walk(paddr_t base,size_t size,void * arg)144 boot_do_memdb_walk(paddr_t base, size_t size, void *arg)
145 {
146 	qcbor_enc_ctxt_t *qcbor_enc_ctxt = (qcbor_enc_ctxt_t *)arg;
147 
148 	if ((size == 0U) && (util_add_overflows(base, size - 1U))) {
149 		return ERROR_ARGUMENT_SIZE;
150 	}
151 
152 	QCBOREncode_OpenArray(qcbor_enc_ctxt);
153 
154 	QCBOREncode_AddUInt64(qcbor_enc_ctxt, base);
155 	QCBOREncode_AddUInt64(qcbor_enc_ctxt, size);
156 
157 	QCBOREncode_CloseArray(qcbor_enc_ctxt);
158 
159 	return OK;
160 }
161 
162 error_t
boot_add_free_range(uintptr_t object,memdb_type_t type,qcbor_enc_ctxt_t * qcbor_enc_ctxt)163 boot_add_free_range(uintptr_t object, memdb_type_t type,
164 		    qcbor_enc_ctxt_t *qcbor_enc_ctxt)
165 {
166 	error_t ret;
167 
168 	QCBOREncode_OpenArrayInMap(qcbor_enc_ctxt, "free_ranges");
169 
170 	ret = memdb_walk(object, type, boot_do_memdb_walk,
171 			 (void *)qcbor_enc_ctxt);
172 
173 	QCBOREncode_CloseArray(qcbor_enc_ctxt);
174 
175 	return ret;
176 }
177 
178 void
boot_start_hypervisor_handover(void)179 boot_start_hypervisor_handover(void)
180 {
181 	trigger_boot_hypervisor_handover_event();
182 }
183