Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2010-2014 Wind River Systems, Inc.
3 : : *
4 : : * SPDX-License-Identifier: Apache-2.0
5 : : */
6 : :
7 : : /**
8 : : * @file
9 : : * @brief Kernel initialization module
10 : : *
11 : : * This module contains routines that are used to initialize the kernel.
12 : : */
13 : :
14 : : #include <zephyr.h>
15 : : #include <offsets_short.h>
16 : : #include <kernel.h>
17 : : #include <sys/printk.h>
18 : : #include <debug/stack.h>
19 : : #include <random/rand32.h>
20 : : #include <linker/sections.h>
21 : : #include <toolchain.h>
22 : : #include <kernel_structs.h>
23 : : #include <device.h>
24 : : #include <init.h>
25 : : #include <linker/linker-defs.h>
26 : : #include <ksched.h>
27 : : #include <string.h>
28 : : #include <sys/dlist.h>
29 : : #include <kernel_internal.h>
30 : : #include <drivers/entropy.h>
31 : : #include <logging/log_ctrl.h>
32 : : #include <tracing/tracing.h>
33 : : #include <stdbool.h>
34 : : #include <debug/gcov.h>
35 : : #include <kswap.h>
36 : : #include <timing/timing.h>
37 : : #include <logging/log.h>
38 : : LOG_MODULE_REGISTER(os, CONFIG_KERNEL_LOG_LEVEL);
39 : :
40 : : /* the only struct z_kernel instance */
41 : : struct z_kernel _kernel;
42 : :
43 : : /* init/main and idle threads */
44 : : K_THREAD_PINNED_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
45 : : struct k_thread z_main_thread;
46 : :
47 : : #ifdef CONFIG_MULTITHREADING
48 : : __pinned_bss
49 : : struct k_thread z_idle_threads[CONFIG_MP_NUM_CPUS];
50 : :
51 : : static K_KERNEL_PINNED_STACK_ARRAY_DEFINE(z_idle_stacks,
52 : : CONFIG_MP_NUM_CPUS,
53 : : CONFIG_IDLE_STACK_SIZE);
54 : : #endif /* CONFIG_MULTITHREADING */
55 : :
56 : : /*
57 : : * storage space for the interrupt stack
58 : : *
59 : : * Note: This area is used as the system stack during kernel initialization,
60 : : * since the kernel hasn't yet set up its own stack areas. The dual purposing
61 : : * of this area is safe since interrupts are disabled until the kernel context
62 : : * switches to the init thread.
63 : : */
64 : : K_KERNEL_PINNED_STACK_ARRAY_DEFINE(z_interrupt_stacks,
65 : : CONFIG_MP_NUM_CPUS,
66 : : CONFIG_ISR_STACK_SIZE);
67 : :
68 : : extern void idle(void *unused1, void *unused2, void *unused3);
69 : :
70 : :
71 : : /* LCOV_EXCL_START
72 : : *
73 : : * This code is called so early in the boot process that code coverage
74 : : * doesn't work properly. In addition, not all arches call this code,
75 : : * some like x86 do this with optimized assembly
76 : : */
77 : :
78 : : /**
79 : : * @brief equivalent of memset() for early boot usage
80 : : *
81 : : * Architectures that can't safely use the regular (optimized) memset very
82 : : * early during boot because e.g. hardware isn't yet sufficiently initialized
83 : : * may override this with their own safe implementation.
84 : : */
85 : : __boot_func
86 : : void __weak z_early_memset(void *dst, int c, size_t n)
87 : : {
88 : : (void) memset(dst, c, n);
89 : : }
90 : :
91 : : /**
92 : : * @brief equivalent of memcpy() for early boot usage
93 : : *
94 : : * Architectures that can't safely use the regular (optimized) memcpy very
95 : : * early during boot because e.g. hardware isn't yet sufficiently initialized
96 : : * may override this with their own safe implementation.
97 : : */
98 : : __boot_func
99 : : void __weak z_early_memcpy(void *dst, const void *src, size_t n)
100 : : {
101 : : (void) memcpy(dst, src, n);
102 : : }
103 : :
104 : : /**
105 : : * @brief Clear BSS
106 : : *
107 : : * This routine clears the BSS region, so all bytes are 0.
108 : : */
109 : : __boot_func
110 : : void z_bss_zero(void)
111 : : {
112 : : z_early_memset(__bss_start, 0, __bss_end - __bss_start);
113 : : #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay)
114 : : z_early_memset(&__ccm_bss_start, 0,
115 : : (uintptr_t) &__ccm_bss_end
116 : : - (uintptr_t) &__ccm_bss_start);
117 : : #endif
118 : : #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)
119 : : z_early_memset(&__dtcm_bss_start, 0,
120 : : (uintptr_t) &__dtcm_bss_end
121 : : - (uintptr_t) &__dtcm_bss_start);
122 : : #endif
123 : : #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay)
124 : : z_early_memset(&__ocm_bss_start, 0,
125 : : (uintptr_t) &__ocm_bss_end
126 : : - (uintptr_t) &__ocm_bss_start);
127 : : #endif
128 : : #ifdef CONFIG_CODE_DATA_RELOCATION
129 : : extern void bss_zeroing_relocation(void);
130 : :
131 : : bss_zeroing_relocation();
132 : : #endif /* CONFIG_CODE_DATA_RELOCATION */
133 : : #ifdef CONFIG_COVERAGE_GCOV
134 : : z_early_memset(&__gcov_bss_start, 0,
135 : : ((uintptr_t) &__gcov_bss_end - (uintptr_t) &__gcov_bss_start));
136 : : #endif
137 : : }
138 : :
139 : : #ifdef CONFIG_LINKER_USE_BOOT_SECTION
140 : : /**
141 : : * @brief Clear BSS within the bot region
142 : : *
143 : : * This routine clears the BSS within the boot region.
144 : : * This is separate from z_bss_zero() as boot region may
145 : : * contain symbols required for the boot process before
146 : : * paging is initialized.
147 : : */
148 : : __boot_func
149 : : void z_bss_zero_boot(void)
150 : : {
151 : : z_early_memset(&lnkr_boot_bss_start, 0,
152 : : (uintptr_t)&lnkr_boot_bss_end
153 : : - (uintptr_t)&lnkr_boot_bss_start);
154 : : }
155 : : #endif /* CONFIG_LINKER_USE_BOOT_SECTION */
156 : :
157 : : #ifdef CONFIG_LINKER_USE_PINNED_SECTION
158 : : /**
159 : : * @brief Clear BSS within the pinned region
160 : : *
161 : : * This routine clears the BSS within the pinned region.
162 : : * This is separate from z_bss_zero() as pinned region may
163 : : * contain symbols required for the boot process before
164 : : * paging is initialized.
165 : : */
166 : : #ifdef CONFIG_LINKER_USE_BOOT_SECTION
167 : : __boot_func
168 : : #else
169 : : __pinned_func
170 : : #endif
171 : : void z_bss_zero_pinned(void)
172 : : {
173 : : z_early_memset(&lnkr_pinned_bss_start, 0,
174 : : (uintptr_t)&lnkr_pinned_bss_end
175 : : - (uintptr_t)&lnkr_pinned_bss_start);
176 : : }
177 : : #endif /* CONFIG_LINKER_USE_PINNED_SECTION */
178 : :
179 : : #ifdef CONFIG_STACK_CANARIES
180 : : extern volatile uintptr_t __stack_chk_guard;
181 : : #endif /* CONFIG_STACK_CANARIES */
182 : :
183 : : /* LCOV_EXCL_STOP */
184 : :
185 : : __pinned_bss
186 : : bool z_sys_post_kernel;
187 : :
188 : : extern void boot_banner(void);
189 : :
190 : : /**
191 : : * @brief Mainline for kernel's background thread
192 : : *
193 : : * This routine completes kernel initialization by invoking the remaining
194 : : * init functions, then invokes application's main() routine.
195 : : */
196 : : __boot_func
197 : 1 : static void bg_thread_main(void *unused1, void *unused2, void *unused3)
198 : : {
199 : : ARG_UNUSED(unused1);
200 : : ARG_UNUSED(unused2);
201 : : ARG_UNUSED(unused3);
202 : :
203 : : #ifdef CONFIG_MMU
204 : : /* Invoked here such that backing store or eviction algorithms may
205 : : * initialize kernel objects, and that all POST_KERNEL and later tasks
206 : : * may perform memory management tasks (except for z_phys_map() which
207 : : * is allowed at any time)
208 : : */
209 : : z_mem_manage_init();
210 : : #endif /* CONFIG_MMU */
211 : 1 : z_sys_post_kernel = true;
212 : :
213 : 1 : z_sys_init_run_level(_SYS_INIT_LEVEL_POST_KERNEL);
214 : : #if CONFIG_STACK_POINTER_RANDOM
215 : : z_stack_adjust_initialized = 1;
216 : : #endif
217 : 1 : boot_banner();
218 : :
219 : : #if defined(CONFIG_CPLUSPLUS) && !defined(CONFIG_ARCH_POSIX)
220 : : void z_cpp_init_static(void);
221 : 1 : z_cpp_init_static();
222 : : #endif
223 : :
224 : : /* Final init level before app starts */
225 : 1 : z_sys_init_run_level(_SYS_INIT_LEVEL_APPLICATION);
226 : :
227 : 1 : z_init_static_threads();
228 : :
229 : : #ifdef CONFIG_KERNEL_COHERENCE
230 : : __ASSERT_NO_MSG(arch_mem_coherent(&_kernel));
231 : : #endif
232 : :
233 : : #ifdef CONFIG_SMP
234 : : if (!IS_ENABLED(CONFIG_SMP_BOOT_DELAY)) {
235 : : z_smp_init();
236 : : }
237 : : z_sys_init_run_level(_SYS_INIT_LEVEL_SMP);
238 : : #endif
239 : :
240 : : #ifdef CONFIG_MMU
241 : : z_mem_manage_boot_finish();
242 : : #endif /* CONFIG_MMU */
243 : :
244 : : extern void main(void);
245 : :
246 : 1 : main();
247 : :
248 : : /* Mark nonessential since main() has no more work to do */
249 : 1 : z_main_thread.base.user_options &= ~K_ESSENTIAL;
250 : :
251 : : #ifdef CONFIG_COVERAGE_DUMP
252 : : /* Dump coverage data once the main() has exited. */
253 : 1 : gcov_coverage_dump();
254 : : #endif
255 : : } /* LCOV_EXCL_LINE ... because we just dumped final coverage data */
256 : :
257 : : #if defined(CONFIG_MULTITHREADING)
258 : : __boot_func
259 : 1 : static void init_idle_thread(int i)
260 : : {
261 : 1 : struct k_thread *thread = &z_idle_threads[i];
262 : 1 : k_thread_stack_t *stack = z_idle_stacks[i];
263 : :
264 : : #ifdef CONFIG_THREAD_NAME
265 : :
266 : : #if CONFIG_MP_NUM_CPUS > 1
267 : : char tname[8];
268 : : snprintk(tname, 8, "idle %02d", i);
269 : : #else
270 : 1 : char *tname = "idle";
271 : : #endif
272 : :
273 : : #else
274 : : char *tname = NULL;
275 : : #endif /* CONFIG_THREAD_NAME */
276 : :
277 : 1 : z_setup_new_thread(thread, stack,
278 : 1 : CONFIG_IDLE_STACK_SIZE, idle, &_kernel.cpus[i],
279 : : NULL, NULL, K_IDLE_PRIO, K_ESSENTIAL,
280 : : tname);
281 : 1 : z_mark_thread_as_started(thread);
282 : :
283 : : #ifdef CONFIG_SMP
284 : : thread->base.is_idle = 1U;
285 : : #endif
286 : 1 : }
287 : :
288 : 1 : void z_init_cpu(int id)
289 : : {
290 : 1 : init_idle_thread(id);
291 : 1 : _kernel.cpus[id].idle_thread = &z_idle_threads[id];
292 : 1 : _kernel.cpus[id].id = id;
293 : 1 : _kernel.cpus[id].irq_stack =
294 : 1 : (Z_KERNEL_STACK_BUFFER(z_interrupt_stacks[id]) +
295 : : K_KERNEL_STACK_SIZEOF(z_interrupt_stacks[id]));
296 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
297 : : _kernel.cpus[id].usage.track_usage =
298 : : CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE;
299 : : #endif
300 : 1 : }
301 : :
302 : : /**
303 : : *
304 : : * @brief Initializes kernel data structures
305 : : *
306 : : * This routine initializes various kernel data structures, including
307 : : * the init and idle threads and any architecture-specific initialization.
308 : : *
309 : : * Note that all fields of "_kernel" are set to zero on entry, which may
310 : : * be all the initialization many of them require.
311 : : *
312 : : * @return initial stack pointer for the main thread
313 : : */
314 : : __boot_func
315 : 1 : static char *prepare_multithreading(void)
316 : : {
317 : : char *stack_ptr;
318 : :
319 : : /* _kernel.ready_q is all zeroes */
320 : 1 : z_sched_init();
321 : :
322 : : #ifndef CONFIG_SMP
323 : : /*
324 : : * prime the cache with the main thread since:
325 : : *
326 : : * - the cache can never be NULL
327 : : * - the main thread will be the one to run first
328 : : * - no other thread is initialized yet and thus their priority fields
329 : : * contain garbage, which would prevent the cache loading algorithm
330 : : * to work as intended
331 : : */
332 : 1 : _kernel.ready_q.cache = &z_main_thread;
333 : : #endif
334 : 1 : stack_ptr = z_setup_new_thread(&z_main_thread, z_main_stack,
335 : : CONFIG_MAIN_STACK_SIZE, bg_thread_main,
336 : : NULL, NULL, NULL,
337 : : CONFIG_MAIN_THREAD_PRIORITY,
338 : : K_ESSENTIAL, "main");
339 : 1 : z_mark_thread_as_started(&z_main_thread);
340 : 1 : z_ready_thread(&z_main_thread);
341 : :
342 : 1 : z_init_cpu(0);
343 : :
344 : 1 : return stack_ptr;
345 : : }
346 : :
347 : : __boot_func
348 : 1 : static FUNC_NORETURN void switch_to_main_thread(char *stack_ptr)
349 : : {
350 : : #ifdef CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN
351 : 1 : arch_switch_to_main_thread(&z_main_thread, stack_ptr, bg_thread_main);
352 : : #else
353 : : ARG_UNUSED(stack_ptr);
354 : : /*
355 : : * Context switch to main task (entry function is _main()): the
356 : : * current fake thread is not on a wait queue or ready queue, so it
357 : : * will never be rescheduled in.
358 : : */
359 : : z_swap_unlocked();
360 : : #endif
361 : : CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
362 : : }
363 : : #endif /* CONFIG_MULTITHREADING */
364 : :
365 : : #if defined(CONFIG_ENTROPY_HAS_DRIVER) || defined(CONFIG_TEST_RANDOM_GENERATOR)
366 : : __boot_func
367 : : void z_early_boot_rand_get(uint8_t *buf, size_t length)
368 : : {
369 : : #ifdef CONFIG_ENTROPY_HAS_DRIVER
370 : : const struct device *entropy = DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy));
371 : : int rc;
372 : :
373 : : if (!device_is_ready(entropy)) {
374 : : goto sys_rand_fallback;
375 : : }
376 : :
377 : : /* Try to see if driver provides an ISR-specific API */
378 : : rc = entropy_get_entropy_isr(entropy, buf, length, ENTROPY_BUSYWAIT);
379 : : if (rc == -ENOTSUP) {
380 : : /* Driver does not provide an ISR-specific API, assume it can
381 : : * be called from ISR context
382 : : */
383 : : rc = entropy_get_entropy(entropy, buf, length);
384 : : }
385 : :
386 : : if (rc >= 0) {
387 : : return;
388 : : }
389 : :
390 : : /* Fall through to fallback */
391 : :
392 : : sys_rand_fallback:
393 : : #endif
394 : :
395 : : /* FIXME: this assumes sys_rand32_get() won't use any synchronization
396 : : * primitive, like semaphores or mutexes. It's too early in the boot
397 : : * process to use any of them. Ideally, only the path where entropy
398 : : * devices are available should be built, this is only a fallback for
399 : : * those devices without a HWRNG entropy driver.
400 : : */
401 : : sys_rand_get(buf, length);
402 : : }
403 : : /* defined(CONFIG_ENTROPY_HAS_DRIVER) || defined(CONFIG_TEST_RANDOM_GENERATOR) */
404 : : #endif
405 : :
406 : : /**
407 : : *
408 : : * @brief Initialize kernel
409 : : *
410 : : * This routine is invoked when the system is ready to run C code. The
411 : : * processor must be running in 32-bit mode, and the BSS must have been
412 : : * cleared/zeroed.
413 : : *
414 : : * @return Does not return
415 : : */
416 : : __boot_func
417 : 1 : FUNC_NORETURN void z_cstart(void)
418 : : {
419 : : /* gcov hook needed to get the coverage report.*/
420 : 1 : gcov_static_init();
421 : :
422 : : /* perform any architecture-specific initialization */
423 : 1 : arch_kernel_init();
424 : :
425 : : LOG_CORE_INIT();
426 : :
427 : : #if defined(CONFIG_MULTITHREADING)
428 : : /* Note: The z_ready_thread() call in prepare_multithreading() requires
429 : : * a dummy thread even if CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN=y
430 : : */
431 : : struct k_thread dummy_thread;
432 : :
433 : 1 : z_dummy_thread_init(&dummy_thread);
434 : : #endif
435 : : /* do any necessary initialization of static devices */
436 : 1 : z_device_state_init();
437 : :
438 : : /* perform basic hardware initialization */
439 : 1 : z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_1);
440 : 1 : z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_2);
441 : :
442 : : #ifdef CONFIG_STACK_CANARIES
443 : : uintptr_t stack_guard;
444 : :
445 : : z_early_boot_rand_get((uint8_t *)&stack_guard, sizeof(stack_guard));
446 : : __stack_chk_guard = stack_guard;
447 : : __stack_chk_guard <<= 8;
448 : : #endif /* CONFIG_STACK_CANARIES */
449 : :
450 : : #ifdef CONFIG_TIMING_FUNCTIONS_NEED_AT_BOOT
451 : : timing_init();
452 : : timing_start();
453 : : #endif
454 : :
455 : : #ifdef CONFIG_MULTITHREADING
456 : 1 : switch_to_main_thread(prepare_multithreading());
457 : : #else
458 : : #ifdef ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING
459 : : /* Custom ARCH-specific routine to switch to main()
460 : : * in the case of no multi-threading.
461 : : */
462 : : ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING(bg_thread_main,
463 : : NULL, NULL, NULL);
464 : : #else
465 : : bg_thread_main(NULL, NULL, NULL);
466 : :
467 : : /* LCOV_EXCL_START
468 : : * We've already dumped coverage data at this point.
469 : : */
470 : : irq_lock();
471 : : while (true) {
472 : : }
473 : : /* LCOV_EXCL_STOP */
474 : : #endif
475 : : #endif /* CONFIG_MULTITHREADING */
476 : :
477 : : /*
478 : : * Compiler can't tell that the above routines won't return and issues
479 : : * a warning unless we explicitly tell it that control never gets this
480 : : * far.
481 : : */
482 : :
483 : : CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
484 : : }
|