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