source: mainline/kernel/generic/src/main/main.c@ e2ea4ab1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e2ea4ab1 was da52547, checked in by Martin Decky <martin@…>, 15 years ago

add early_putchar() which can be used to do early kernel console output for debugging purposes
(the availability of this feature depends on each platform and specific configuration, currently it works only on ia32/amd64 with EGA and no framebuffer)
instrument more kernel functions
mark some functions as no_instrument (context_restore(), overlaps(), main_bsp())

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup main
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Main initialization kernel function for all processors.
36 *
37 * During kernel boot, all processors, after architecture dependent
38 * initialization, start executing code found in this file. After
39 * bringing up all subsystems, control is passed to scheduler().
40 *
41 * The bootstrap processor starts executing main_bsp() while
42 * the application processors start executing main_ap().
43 *
44 * @see scheduler()
45 * @see main_bsp()
46 * @see main_ap()
47 */
48
49#include <arch/asm.h>
50#include <context.h>
51#include <print.h>
52#include <panic.h>
53#include <debug.h>
54#include <config.h>
55#include <time/clock.h>
56#include <time/timeout.h>
57#include <proc/scheduler.h>
58#include <proc/thread.h>
59#include <proc/task.h>
60#include <proc/tasklet.h>
61#include <main/kinit.h>
62#include <main/version.h>
63#include <console/kconsole.h>
64#include <console/console.h>
65#include <cpu.h>
66#include <align.h>
67#include <interrupt.h>
68#include <mm/frame.h>
69#include <mm/page.h>
70#include <genarch/mm/page_pt.h>
71#include <mm/tlb.h>
72#include <mm/as.h>
73#include <mm/slab.h>
74#include <synch/waitq.h>
75#include <synch/futex.h>
76#include <arch/arch.h>
77#include <arch.h>
78#include <arch/faddr.h>
79#include <ipc/ipc.h>
80#include <macros.h>
81#include <adt/btree.h>
82#include <smp/smp.h>
83#include <ddi/ddi.h>
84#include <main/main.h>
85#include <ipc/event.h>
86#include <sysinfo/sysinfo.h>
87#include <sysinfo/stats.h>
88
89/** Global configuration structure. */
90config_t config;
91
92/** Initial user-space tasks */
93init_t init = {
94 .cnt = 0
95};
96
97/** Boot allocations. */
98ballocs_t ballocs = {
99 .base = NULL,
100 .size = 0
101};
102
103context_t ctx;
104
105/** Lowest safe stack virtual address. */
106uintptr_t stack_safe = 0;
107
108/*
109 * These two functions prevent stack from underflowing during the
110 * kernel boot phase when SP is set to the very top of the reserved
111 * space. The stack could get corrupted by a fooled compiler-generated
112 * pop sequence otherwise.
113 */
114static void main_bsp_separated_stack(void);
115
116#ifdef CONFIG_SMP
117static void main_ap_separated_stack(void);
118#endif
119
120#define CONFIG_STACK_SIZE ((1 << STACK_FRAMES) * STACK_SIZE)
121
122/** Main kernel routine for bootstrap CPU.
123 *
124 * The code here still runs on the boot stack, which knows nothing about
125 * preemption counts. Because of that, this function cannot directly call
126 * functions that disable or enable preemption (e.g. spinlock_lock()). The
127 * primary task of this function is to calculate address of a new stack and
128 * switch to it.
129 *
130 * Assuming interrupts_disable().
131 *
132 */
133void __attribute__((no_instrument_function)) main_bsp(void)
134{
135 config.cpu_count = 1;
136 config.cpu_active = 1;
137
138 config.base = hardcoded_load_address;
139 config.kernel_size = ALIGN_UP(hardcoded_ktext_size +
140 hardcoded_kdata_size, PAGE_SIZE);
141 config.stack_size = CONFIG_STACK_SIZE;
142
143 /* Initialy the stack is placed just after the kernel */
144 config.stack_base = config.base + config.kernel_size;
145
146 /* Avoid placing stack on top of init */
147 size_t i;
148 for (i = 0; i < init.cnt; i++) {
149 if (PA_overlaps(config.stack_base, config.stack_size,
150 init.tasks[i].addr, init.tasks[i].size))
151 config.stack_base = ALIGN_UP(init.tasks[i].addr +
152 init.tasks[i].size, config.stack_size);
153 }
154
155 /* Avoid placing stack on top of boot allocations. */
156 if (ballocs.size) {
157 if (PA_overlaps(config.stack_base, config.stack_size,
158 ballocs.base, ballocs.size))
159 config.stack_base = ALIGN_UP(ballocs.base +
160 ballocs.size, PAGE_SIZE);
161 }
162
163 if (config.stack_base < stack_safe)
164 config.stack_base = ALIGN_UP(stack_safe, PAGE_SIZE);
165
166 context_save(&ctx);
167 context_set(&ctx, FADDR(main_bsp_separated_stack), config.stack_base,
168 THREAD_STACK_SIZE);
169 context_restore(&ctx);
170 /* not reached */
171}
172
173/** Main kernel routine for bootstrap CPU using new stack.
174 *
175 * Second part of main_bsp().
176 *
177 */
178void main_bsp_separated_stack(void)
179{
180 /* Keep this the first thing. */
181 the_initialize(THE);
182
183 version_print();
184
185 LOG("\nconfig.base=%p config.kernel_size=%" PRIs
186 "\nconfig.stack_base=%p config.stack_size=%" PRIs,
187 config.base, config.kernel_size, config.stack_base,
188 config.stack_size);
189
190#ifdef CONFIG_KCONSOLE
191 /*
192 * kconsole data structures must be initialized very early
193 * because other subsystems will register their respective
194 * commands.
195 */
196 kconsole_init();
197#endif
198
199 /*
200 * Exception handler initialization, before architecture
201 * starts adding its own handlers
202 */
203 exc_init();
204
205 /*
206 * Memory management subsystems initialization.
207 */
208 arch_pre_mm_init();
209 frame_init();
210
211 /* Initialize at least 1 memory segment big enough for slab to work. */
212 slab_cache_init();
213 sysinfo_init();
214 btree_init();
215 as_init();
216 page_init();
217 tlb_init();
218 ddi_init();
219 tasklet_init();
220 arch_post_mm_init();
221 arch_pre_smp_init();
222 smp_init();
223
224 /* Slab must be initialized after we know the number of processors. */
225 slab_enable_cpucache();
226
227 printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n",
228 config.cpu_count, SIZE2MB(zones_total_size()));
229
230 cpu_init();
231
232 calibrate_delay_loop();
233 clock_counter_init();
234 timeout_init();
235 scheduler_init();
236 task_init();
237 thread_init();
238 futex_init();
239
240 if (init.cnt > 0) {
241 size_t i;
242 for (i = 0; i < init.cnt; i++)
243 LOG("init[%" PRIs "].addr=%p, init[%" PRIs
244 "].size=%" PRIs, i, init.tasks[i].addr, i,
245 init.tasks[i].size);
246 } else
247 printf("No init binaries found.\n");
248
249 ipc_init();
250 event_init();
251 klog_init();
252 stats_init();
253
254 /*
255 * Create kernel task.
256 */
257 task_t *kernel = task_create(AS_KERNEL, "kernel");
258 if (!kernel)
259 panic("Cannot create kernel task.");
260
261 /*
262 * Create the first thread.
263 */
264 thread_t *kinit_thread
265 = thread_create(kinit, NULL, kernel, 0, "kinit", true);
266 if (!kinit_thread)
267 panic("Cannot create kinit thread.");
268 thread_ready(kinit_thread);
269
270 /*
271 * This call to scheduler() will return to kinit,
272 * starting the thread of kernel threads.
273 */
274 scheduler();
275 /* not reached */
276}
277
278#ifdef CONFIG_SMP
279
280/** Main kernel routine for application CPUs.
281 *
282 * Executed by application processors, temporary stack
283 * is at ctx.sp which was set during BSP boot.
284 * This function passes control directly to
285 * main_ap_separated_stack().
286 *
287 * Assuming interrupts_disable()'d.
288 *
289 */
290void main_ap(void)
291{
292 /*
293 * Incrementing the active CPU counter will guarantee that the
294 * *_init() functions can find out that they need to
295 * do initialization for AP only.
296 */
297 config.cpu_active++;
298
299 /*
300 * The THE structure is well defined because ctx.sp is used as stack.
301 */
302 the_initialize(THE);
303
304 arch_pre_mm_init();
305 frame_init();
306 page_init();
307 tlb_init();
308 arch_post_mm_init();
309
310 cpu_init();
311 calibrate_delay_loop();
312 arch_post_cpu_init();
313
314 the_copy(THE, (the_t *) CPU->stack);
315
316 /*
317 * If we woke kmp up before we left the kernel stack, we could
318 * collide with another CPU coming up. To prevent this, we
319 * switch to this cpu's private stack prior to waking kmp up.
320 */
321 context_save(&CPU->saved_context);
322 context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
323 (uintptr_t) CPU->stack, CPU_STACK_SIZE);
324 context_restore(&CPU->saved_context);
325 /* not reached */
326}
327
328/** Main kernel routine for application CPUs using new stack.
329 *
330 * Second part of main_ap().
331 *
332 */
333void main_ap_separated_stack(void)
334{
335 /*
336 * Configure timeouts for this cpu.
337 */
338 timeout_init();
339
340 waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST);
341 scheduler();
342 /* not reached */
343}
344
345#endif /* CONFIG_SMP */
346
347/** @}
348 */
Note: See TracBrowser for help on using the repository browser.