source: mainline/generic/src/main/main.c@ d9cf9d5f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d9cf9d5f was 9179d0a, checked in by Jakub Jermar <jakub@…>, 20 years ago

Add some @file doxygen comments and improve already existing comments.

  • Property mode set to 100644
File size: 8.0 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/**
30 * @file main.c
31 * @brief Main initialization kernel function for all processors.
32 *
33 * During kernel boot, all processors, after architecture dependent
34 * initialization, start executing code found in this file. After
35 * bringing up all subsystems, control is passed to scheduler().
36 *
37 * The bootstrap processor starts executing main_bsp() while
38 * the application processors start executing main_ap().
39 *
40 * @see scheduler()
41 * @see main_bsp()
42 * @see main_ap()
43 */
44
45#include <arch/asm.h>
46#include <context.h>
47#include <print.h>
48#include <panic.h>
49#include <debug.h>
50#include <config.h>
51#include <time/clock.h>
52#include <proc/scheduler.h>
53#include <proc/thread.h>
54#include <proc/task.h>
55#include <main/kinit.h>
56#include <main/version.h>
57#include <console/kconsole.h>
58#include <cpu.h>
59#include <align.h>
60#include <interrupt.h>
61#include <arch/mm/memory_init.h>
62#include <mm/frame.h>
63#include <mm/page.h>
64#include <genarch/mm/page_pt.h>
65#include <mm/tlb.h>
66#include <mm/as.h>
67#include <mm/slab.h>
68#include <synch/waitq.h>
69#include <synch/futex.h>
70#include <arch/arch.h>
71#include <arch.h>
72#include <arch/faddr.h>
73#include <typedefs.h>
74#include <ipc/ipc.h>
75#include <macros.h>
76#include <adt/btree.h>
77
78#ifdef CONFIG_SMP
79#include <arch/smp/apic.h>
80#include <arch/smp/mps.h>
81#endif /* CONFIG_SMP */
82#include <smp/smp.h>
83
84config_t config; /**< Global configuration structure. */
85init_t init = {0}; /**< Initial user-space tasks */
86
87context_t ctx;
88
89/**
90 * These 'hardcoded' variables will be intialized by
91 * the linker or the low level assembler code with
92 * appropriate sizes and addresses.
93 */
94__address hardcoded_load_address = 0;
95size_t hardcoded_ktext_size = 0;
96size_t hardcoded_kdata_size = 0;
97
98void main_bsp(void);
99void main_ap(void);
100
101/*
102 * These two functions prevent stack from underflowing during the
103 * kernel boot phase when SP is set to the very top of the reserved
104 * space. The stack could get corrupted by a fooled compiler-generated
105 * pop sequence otherwise.
106 */
107static void main_bsp_separated_stack(void);
108#ifdef CONFIG_SMP
109static void main_ap_separated_stack(void);
110#endif
111
112#define CONFIG_STACK_SIZE ((1<<STACK_FRAMES)*STACK_SIZE)
113
114/** Main kernel routine for bootstrap CPU.
115 *
116 * Initializes the kernel by bootstrap CPU.
117 * This function passes control directly to
118 * main_bsp_separated_stack().
119 *
120 * Assuming interrupts_disable().
121 *
122 */
123void main_bsp(void)
124{
125 __address stackaddr;
126
127 config.cpu_count = 1;
128 config.cpu_active = 1;
129
130 config.base = hardcoded_load_address;
131 config.memory_size = get_memory_size();
132
133 config.kernel_size = ALIGN_UP(hardcoded_ktext_size + hardcoded_kdata_size, PAGE_SIZE);
134 stackaddr = config.base + config.kernel_size;
135
136 /* Avoid placing kernel on top of init */
137 count_t i;
138 bool overlap = false;
139 for (i = 0; i < init.cnt; i++)
140 if (PA_overlaps(stackaddr, CONFIG_STACK_SIZE, init.tasks[i].addr, init.tasks[i].size)) {
141 stackaddr = ALIGN_UP(init.tasks[i].addr + init.tasks[i].size, CONFIG_STACK_SIZE);
142 init.tasks[i].size = ALIGN_UP(init.tasks[i].size, CONFIG_STACK_SIZE) + CONFIG_STACK_SIZE;
143 overlap = true;
144 }
145
146 if (!overlap)
147 config.kernel_size += CONFIG_STACK_SIZE;
148
149 context_save(&ctx);
150 context_set(&ctx, FADDR(main_bsp_separated_stack), stackaddr, THREAD_STACK_SIZE);
151 context_restore(&ctx);
152 /* not reached */
153}
154
155
156/** Main kernel routine for bootstrap CPU using new stack.
157 *
158 * Second part of main_bsp().
159 *
160 */
161void main_bsp_separated_stack(void)
162{
163 task_t *k;
164 thread_t *t;
165 count_t i;
166
167 the_initialize(THE);
168
169 /*
170 * kconsole data structures must be initialized very early
171 * because other subsystems will register their respective
172 * commands.
173 */
174 kconsole_init();
175
176 /*
177 * Exception handler initialization, before architecture
178 * starts adding its own handlers
179 */
180 exc_init();
181
182 /*
183 * Memory management subsystems initialization.
184 */
185 arch_pre_mm_init();
186 frame_init(); /* Initialize at least 1 memory segment big enough for slab to work */
187 slab_cache_init();
188 btree_init();
189 as_init();
190 page_init();
191 tlb_init();
192 arch_post_mm_init();
193
194 version_print();
195 printf("%.*p: hardcoded_ktext_size=%zdK, hardcoded_kdata_size=%zdK\n", sizeof(__address) * 2, config.base, hardcoded_ktext_size / 1024, hardcoded_kdata_size / 1024);
196
197 arch_pre_smp_init();
198 smp_init();
199
200 slab_enable_cpucache(); /* Slab must be initialized AFTER we know the number of processors */
201
202 printf("config.memory_size=%zdM\n", config.memory_size/(1024*1024));
203 printf("config.cpu_count=%zd\n", config.cpu_count);
204 cpu_init();
205
206 calibrate_delay_loop();
207 timeout_init();
208 scheduler_init();
209 task_init();
210 thread_init();
211 futex_init();
212
213 for (i = 0; i < init.cnt; i++)
214 printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i, sizeof(__address)*2, init.tasks[i].addr, i, init.tasks[i].size);
215
216 ipc_init();
217
218 /*
219 * Create kernel task.
220 */
221 k = task_create(AS_KERNEL, "KERNEL");
222 if (!k)
223 panic("can't create kernel task\n");
224
225 /*
226 * Create the first thread.
227 */
228 t = thread_create(kinit, NULL, k, 0, "kinit");
229 if (!t)
230 panic("can't create kinit thread\n");
231 thread_ready(t);
232
233 /*
234 * This call to scheduler() will return to kinit,
235 * starting the thread of kernel threads.
236 */
237 scheduler();
238 /* not reached */
239}
240
241
242#ifdef CONFIG_SMP
243/** Main kernel routine for application CPUs.
244 *
245 * Executed by application processors, temporary stack
246 * is at ctx.sp which was set during BP boot.
247 * This function passes control directly to
248 * main_ap_separated_stack().
249 *
250 * Assuming interrupts_disable()'d.
251 *
252 */
253void main_ap(void)
254{
255 /*
256 * Incrementing the active CPU counter will guarantee that the
257 * pm_init() will not attempt to build GDT and IDT tables again.
258 * Neither frame_init() will do the complete thing. Neither cpu_init()
259 * will do.
260 */
261 config.cpu_active++;
262
263 /*
264 * The THE structure is well defined because ctx.sp is used as stack.
265 */
266 the_initialize(THE);
267
268 arch_pre_mm_init();
269 frame_init();
270 page_init();
271 tlb_init();
272 arch_post_mm_init();
273
274 cpu_init();
275
276 calibrate_delay_loop();
277
278 l_apic_init();
279 l_apic_debug();
280
281 the_copy(THE, (the_t *) CPU->stack);
282
283 /*
284 * If we woke kmp up before we left the kernel stack, we could
285 * collide with another CPU coming up. To prevent this, we
286 * switch to this cpu's private stack prior to waking kmp up.
287 */
288 context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), (__address) CPU->stack, CPU_STACK_SIZE);
289 context_restore(&CPU->saved_context);
290 /* not reached */
291}
292
293
294/** Main kernel routine for application CPUs using new stack.
295 *
296 * Second part of main_ap().
297 *
298 */
299void main_ap_separated_stack(void)
300{
301 /*
302 * Configure timeouts for this cpu.
303 */
304 timeout_init();
305
306 waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST);
307 scheduler();
308 /* not reached */
309}
310#endif /* CONFIG_SMP */
Note: See TracBrowser for help on using the repository browser.