source: mainline/kernel/generic/src/main/main.c@ 88be3a0b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 88be3a0b was 8d308b9, checked in by Jakub Jermar <jakub@…>, 14 years ago

Start tracking reservable memory after zones are created and possibly
merged. The initial amount of reservable memory is the number of free
frames at the time of call to reserve_init().

  • Property mode set to 100644
File size: 8.8 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 <main/kinit.h>
61#include <main/version.h>
62#include <console/kconsole.h>
63#include <console/console.h>
64#include <cpu.h>
65#include <align.h>
66#include <interrupt.h>
67#include <mm/frame.h>
68#include <mm/page.h>
69#include <genarch/mm/page_pt.h>
70#include <mm/tlb.h>
71#include <mm/as.h>
72#include <mm/slab.h>
73#include <mm/reserve.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 = (uintptr_t) 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 */
133NO_TRACE void 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=%zu"
186 "\nconfig.stack_base=%p config.stack_size=%zu",
187 (void *) config.base, config.kernel_size,
188 (void *) config.stack_base, 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 arch_post_mm_init();
220 reserve_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 uint64_t size;
228 const char *size_suffix;
229 bin_order_suffix(zones_total_size(), &size, &size_suffix, false);
230 printf("Detected %u CPU(s), %" PRIu64 " %s free memory\n",
231 config.cpu_count, size, size_suffix);
232
233 cpu_init();
234
235 calibrate_delay_loop();
236 clock_counter_init();
237 timeout_init();
238 scheduler_init();
239 task_init();
240 thread_init();
241 futex_init();
242
243 if (init.cnt > 0) {
244 size_t i;
245 for (i = 0; i < init.cnt; i++)
246 LOG("init[%zu].addr=%p, init[%zu].size=%zu",
247 i, (void *) init.tasks[i].addr, i, init.tasks[i].size);
248 } else
249 printf("No init binaries found.\n");
250
251 ipc_init();
252 event_init();
253 klog_init();
254 stats_init();
255
256 /*
257 * Create kernel task.
258 */
259 task_t *kernel = task_create(AS_KERNEL, "kernel");
260 if (!kernel)
261 panic("Cannot create kernel task.");
262
263 /*
264 * Create the first thread.
265 */
266 thread_t *kinit_thread
267 = thread_create(kinit, NULL, kernel, 0, "kinit", true);
268 if (!kinit_thread)
269 panic("Cannot create kinit thread.");
270 thread_ready(kinit_thread);
271
272 /*
273 * This call to scheduler() will return to kinit,
274 * starting the thread of kernel threads.
275 */
276 scheduler();
277 /* not reached */
278}
279
280#ifdef CONFIG_SMP
281
282/** Main kernel routine for application CPUs.
283 *
284 * Executed by application processors, temporary stack
285 * is at ctx.sp which was set during BSP boot.
286 * This function passes control directly to
287 * main_ap_separated_stack().
288 *
289 * Assuming interrupts_disable()'d.
290 *
291 */
292void main_ap(void)
293{
294 /*
295 * Incrementing the active CPU counter will guarantee that the
296 * *_init() functions can find out that they need to
297 * do initialization for AP only.
298 */
299 config.cpu_active++;
300
301 /*
302 * The THE structure is well defined because ctx.sp is used as stack.
303 */
304 the_initialize(THE);
305
306 arch_pre_mm_init();
307 frame_init();
308 page_init();
309 tlb_init();
310 arch_post_mm_init();
311
312 cpu_init();
313 calibrate_delay_loop();
314 arch_post_cpu_init();
315
316 the_copy(THE, (the_t *) CPU->stack);
317
318 /*
319 * If we woke kmp up before we left the kernel stack, we could
320 * collide with another CPU coming up. To prevent this, we
321 * switch to this cpu's private stack prior to waking kmp up.
322 */
323 context_save(&CPU->saved_context);
324 context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
325 (uintptr_t) CPU->stack, CPU_STACK_SIZE);
326 context_restore(&CPU->saved_context);
327 /* not reached */
328}
329
330/** Main kernel routine for application CPUs using new stack.
331 *
332 * Second part of main_ap().
333 *
334 */
335void main_ap_separated_stack(void)
336{
337 /*
338 * Configure timeouts for this cpu.
339 */
340 timeout_init();
341
342 waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST);
343 scheduler();
344 /* not reached */
345}
346
347#endif /* CONFIG_SMP */
348
349/** @}
350 */
Note: See TracBrowser for help on using the repository browser.