blob: 36b5a318d7d7ad7c08a64e0a84a97ce0378e41d9 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2013-2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24/*
25 * Main entry point to the OS. Initializes modules in order and creates
26 * the default thread.
27 */
28#include <compiler.h>
29#include <debug.h>
30#include <string.h>
31#include <app.h>
32#include <arch.h>
33#include <platform.h>
34#include <target.h>
35#include <lib/heap.h>
36#include <kernel/mutex.h>
37#include <kernel/novm.h>
38#include <kernel/thread.h>
39#include <lk/init.h>
40#include <lk/main.h>
41
42/* saved boot arguments from whoever loaded the system */
43ulong lk_boot_args[4];
44
45extern void (*__ctor_list[])(void);
46extern void (*__ctor_end[])(void);
47extern int __bss_start;
48extern int _end;
49
50#if WITH_SMP
51static thread_t *secondary_bootstrap_threads[SMP_MAX_CPUS - 1];
52static uint secondary_bootstrap_thread_count;
53#endif
54
55static int bootstrap2(void *arg);
56
57extern void kernel_init(void);
58
59static void call_constructors(void)
60{
61 void (**ctor)(void);
62
63 for (ctor = __ctor_list; ctor != __ctor_end; ctor++)
64 (*ctor)();
65}
66
67/* called from arch code */
68void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3)
69{
70 // save the boot args
71 lk_boot_args[0] = arg0;
72 lk_boot_args[1] = arg1;
73 lk_boot_args[2] = arg2;
74 lk_boot_args[3] = arg3;
75
76 // get us into some sort of thread context
77 thread_init_early();
78
79 // early arch stuff
80 lk_primary_cpu_init_level(LK_INIT_LEVEL_EARLIEST, LK_INIT_LEVEL_ARCH_EARLY - 1);
81 arch_early_init();
82
83 // do any super early platform initialization
84 lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH_EARLY, LK_INIT_LEVEL_PLATFORM_EARLY - 1);
85 platform_early_init();
86
87 // do any super early target initialization
88 lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM_EARLY, LK_INIT_LEVEL_TARGET_EARLY - 1);
89 target_early_init();
90
91#if WITH_SMP
92 dprintf(INFO, "\nwelcome to lk/MP\n\n");
93#else
94 dprintf(INFO, "\nwelcome to lk\n\n");
95#endif
96 dprintf(INFO, "boot args 0x%lx 0x%lx 0x%lx 0x%lx\n",
97 lk_boot_args[0], lk_boot_args[1], lk_boot_args[2], lk_boot_args[3]);
98
99 // bring up the kernel heap
100 lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET_EARLY, LK_INIT_LEVEL_HEAP - 1);
101 dprintf(SPEW, "initializing heap\n");
102 heap_init();
103
104 // deal with any static constructors
105 dprintf(SPEW, "calling constructors\n");
106 call_constructors();
107
108 // initialize the kernel
109 lk_primary_cpu_init_level(LK_INIT_LEVEL_HEAP, LK_INIT_LEVEL_KERNEL - 1);
110 kernel_init();
111
112 lk_primary_cpu_init_level(LK_INIT_LEVEL_KERNEL, LK_INIT_LEVEL_THREADING - 1);
113
114 // create a thread to complete system initialization
115 dprintf(SPEW, "creating bootstrap completion thread\n");
116 thread_t *t = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
117 thread_set_pinned_cpu(t, 0);
118 thread_detach(t);
119 thread_resume(t);
120
121 // become the idle thread and enable interrupts to start the scheduler
122 thread_become_idle();
123}
124
125static int bootstrap2(void *arg)
126{
127 dprintf(SPEW, "top of bootstrap2()\n");
128
129 lk_primary_cpu_init_level(LK_INIT_LEVEL_THREADING, LK_INIT_LEVEL_ARCH - 1);
130 arch_init();
131
132 // initialize the rest of the platform
133 dprintf(SPEW, "initializing platform\n");
134 lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH, LK_INIT_LEVEL_PLATFORM - 1);
135 platform_init();
136
137 // initialize the target
138 dprintf(SPEW, "initializing target\n");
139 lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM, LK_INIT_LEVEL_TARGET - 1);
140 target_init();
141
142 dprintf(SPEW, "calling apps_init()\n");
143 lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET, LK_INIT_LEVEL_APPS - 1);
144 apps_init();
145
146 lk_primary_cpu_init_level(LK_INIT_LEVEL_APPS, LK_INIT_LEVEL_LAST);
147
148 return 0;
149}
150
151#if WITH_SMP
152void lk_secondary_cpu_entry(void)
153{
154 uint cpu = arch_curr_cpu_num();
155
156 if (cpu > secondary_bootstrap_thread_count) {
157 dprintf(CRITICAL, "Invalid secondary cpu num %d, SMP_MAX_CPUS %d, secondary_bootstrap_thread_count %d\n",
158 cpu, SMP_MAX_CPUS, secondary_bootstrap_thread_count);
159 return;
160 }
161
162 thread_secondary_cpu_init_early();
163 thread_resume(secondary_bootstrap_threads[cpu - 1]);
164
165 dprintf(SPEW, "entering scheduler on cpu %d\n", cpu);
166 thread_secondary_cpu_entry();
167}
168
169static int secondary_cpu_bootstrap2(void *arg)
170{
171 /* secondary cpu initialize from threading level up. 0 to threading was handled in arch */
172 lk_init_level(LK_INIT_FLAG_SECONDARY_CPUS, LK_INIT_LEVEL_THREADING, LK_INIT_LEVEL_LAST);
173
174 return 0;
175}
176
177void lk_init_secondary_cpus(uint secondary_cpu_count)
178{
179 if (secondary_cpu_count >= SMP_MAX_CPUS) {
180 dprintf(CRITICAL, "Invalid secondary_cpu_count %d, SMP_MAX_CPUS %d\n",
181 secondary_cpu_count, SMP_MAX_CPUS);
182 secondary_cpu_count = SMP_MAX_CPUS - 1;
183 }
184 for (uint i = 0; i < secondary_cpu_count; i++) {
185 dprintf(SPEW, "creating bootstrap completion thread for cpu %d\n", i + 1);
186 thread_t *t = thread_create("secondarybootstrap2",
187 &secondary_cpu_bootstrap2, NULL,
188 DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
189 t->pinned_cpu = i + 1;
190 thread_detach(t);
191 secondary_bootstrap_threads[i] = t;
192 }
193 secondary_bootstrap_thread_count = secondary_cpu_count;
194}
195#endif