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 #include <string.h>
8 
9 #include <bootmem.h>
10 #include <idle.h>
11 #include <object.h>
12 #include <panic.h>
13 #include <refcount.h>
14 #include <thread.h>
15 #include <thread_init.h>
16 
17 #include "event_handlers.h"
18 #include "thread_arch.h"
19 
20 extern void
21 thread_switch_boot_thread(thread_t *new_thread);
22 
23 // Thread size is the size of the whole thread TLS area to be allocated,
24 // which is larger than 'struct thread'
25 extern const size_t thread_size;
26 extern const size_t thread_align;
27 
28 void
thread_standard_handle_boot_runtime_first_init(void)29 thread_standard_handle_boot_runtime_first_init(void)
30 {
31 	void_ptr_result_t ret;
32 	thread_t	 *idle_thread;
33 
34 	// Allocate boot CPU idle thread and TLS out of bootmem.
35 	ret = bootmem_allocate(thread_size, thread_align);
36 	if (ret.e != OK) {
37 		panic("unable to allocate boot idle thread");
38 	}
39 
40 	// For now, we just zero-initialise the thread and TLS data and init the
41 	// reference count. The real setup will be done in the idle module after
42 	// partitions and allocators are working.
43 	idle_thread = (thread_t *)ret.r;
44 
45 	assert(thread_size >= sizeof(*idle_thread));
46 	errno_t err_mem = memset_s(idle_thread, thread_size, 0, thread_size);
47 	if (err_mem != 0) {
48 		panic("Error in memset_s operation!");
49 	}
50 	refcount_init(&idle_thread->header.refcount);
51 
52 	// This must be the last operation in boot_runtime_first_init.
53 	thread_switch_boot_thread(idle_thread);
54 }
55 
56 void
thread_standard_handle_boot_runtime_warm_init(thread_t * idle_thread)57 thread_standard_handle_boot_runtime_warm_init(thread_t *idle_thread)
58 {
59 	// This must be the last operation in boot_runtime_warm_init.
60 	thread_switch_boot_thread(idle_thread);
61 }
62 
63 noreturn void
thread_boot_set_idle(void)64 thread_boot_set_idle(void)
65 {
66 	thread_t *thread = thread_get_self();
67 	assert(thread == idle_thread());
68 
69 	thread_arch_set_thread(thread);
70 }
71