main.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2004 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00049 #include <arch/asm.h>
00050 #include <context.h>
00051 #include <print.h>
00052 #include <panic.h>
00053 #include <debug.h>
00054 #include <config.h>
00055 #include <time/clock.h>
00056 #include <proc/scheduler.h>
00057 #include <proc/thread.h>
00058 #include <proc/task.h>
00059 #include <main/kinit.h>
00060 #include <main/version.h>
00061 #include <console/kconsole.h>
00062 #include <cpu.h>
00063 #include <align.h>
00064 #include <interrupt.h>
00065 #include <arch/mm/memory_init.h>
00066 #include <mm/frame.h>
00067 #include <mm/page.h>
00068 #include <genarch/mm/page_pt.h>
00069 #include <mm/tlb.h>
00070 #include <mm/as.h>
00071 #include <mm/slab.h>
00072 #include <synch/waitq.h>
00073 #include <synch/futex.h>
00074 #include <arch/arch.h>
00075 #include <arch.h>
00076 #include <arch/faddr.h>
00077 #include <typedefs.h>
00078 #include <ipc/ipc.h>
00079 #include <macros.h>
00080 #include <adt/btree.h>
00081 #include <console/klog.h>
00082 
00083 #ifdef CONFIG_SMP
00084 #include <arch/smp/apic.h>
00085 #include <arch/smp/mps.h>
00086 #endif /* CONFIG_SMP */
00087 #include <smp/smp.h>
00088 
00090 config_t config = {
00091         .mm_initialized = false
00092 };
00093 
00095 init_t init = {
00096         0
00097 };
00098 
00099 context_t ctx;
00100 
00106 __address hardcoded_load_address = 0;
00107 size_t hardcoded_ktext_size = 0;
00108 size_t hardcoded_kdata_size = 0;
00109 
00110 void main_bsp(void);
00111 void main_ap(void);
00112 
00113 /*
00114  * These two functions prevent stack from underflowing during the
00115  * kernel boot phase when SP is set to the very top of the reserved
00116  * space. The stack could get corrupted by a fooled compiler-generated
00117  * pop sequence otherwise.
00118  */
00119 static void main_bsp_separated_stack(void);
00120 #ifdef CONFIG_SMP
00121 static void main_ap_separated_stack(void);
00122 #endif
00123 
00124 #define CONFIG_STACK_SIZE       ((1<<STACK_FRAMES)*STACK_SIZE)
00125 
00135 void main_bsp(void)
00136 {
00137         __address stackaddr;
00138 
00139         config.cpu_count = 1;
00140         config.cpu_active = 1;
00141         
00142         config.base = hardcoded_load_address;
00143         config.memory_size = get_memory_size();
00144         
00145         config.kernel_size = ALIGN_UP(hardcoded_ktext_size + hardcoded_kdata_size, PAGE_SIZE);
00146         stackaddr = config.base + config.kernel_size;
00147         
00148         /* Avoid placing kernel on top of init */
00149         count_t i;
00150         bool overlap = false;
00151         for (i = 0; i < init.cnt; i++)
00152                 if (PA_overlaps(stackaddr, CONFIG_STACK_SIZE, init.tasks[i].addr, init.tasks[i].size)) {
00153                         stackaddr = ALIGN_UP(init.tasks[i].addr + init.tasks[i].size, CONFIG_STACK_SIZE);
00154                         init.tasks[i].size = ALIGN_UP(init.tasks[i].size, CONFIG_STACK_SIZE) + CONFIG_STACK_SIZE;
00155                         overlap = true;
00156                 }
00157         
00158         if (!overlap)
00159                 config.kernel_size += CONFIG_STACK_SIZE;
00160         
00161         context_save(&ctx);
00162         context_set(&ctx, FADDR(main_bsp_separated_stack), stackaddr, THREAD_STACK_SIZE);
00163         context_restore(&ctx);
00164         /* not reached */
00165 }
00166 
00167 
00173 void main_bsp_separated_stack(void) 
00174 {
00175         task_t *k;
00176         thread_t *t;
00177         count_t i;
00178         
00179         the_initialize(THE);
00180 
00181         /*
00182          * kconsole data structures must be initialized very early
00183          * because other subsystems will register their respective
00184          * commands.
00185          */
00186         kconsole_init();
00187         
00188         /*
00189          * Exception handler initialization, before architecture
00190          * starts adding its own handlers
00191          */
00192         exc_init();
00193 
00194         /*
00195          * Memory management subsystems initialization.
00196          */     
00197         arch_pre_mm_init();
00198         frame_init();           /* Initialize at least 1 memory segment big enough for slab to work */
00199         slab_cache_init();
00200         btree_init();
00201         as_init();
00202         page_init();
00203         tlb_init();
00204         config.mm_initialized = true;
00205         arch_post_mm_init();
00206 
00207         version_print();
00208         printf("%.*p: hardcoded_ktext_size=%zdK, hardcoded_kdata_size=%zdK\n", sizeof(__address) * 2, config.base, hardcoded_ktext_size >> 10, hardcoded_kdata_size >> 10);
00209 
00210         arch_pre_smp_init();
00211         smp_init();
00212         
00213         slab_enable_cpucache(); /* Slab must be initialized AFTER we know the number of processors */
00214 
00215         printf("config.memory_size=%zdM\n", config.memory_size >> 20);
00216         printf("config.cpu_count=%zd\n", config.cpu_count);
00217         cpu_init();
00218         
00219         calibrate_delay_loop();
00220         clock_counter_init();
00221         timeout_init();
00222         scheduler_init();
00223         task_init();
00224         thread_init();
00225         futex_init();
00226         klog_init();
00227         
00228         for (i = 0; i < init.cnt; i++)
00229                 printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i, sizeof(__address) * 2, init.tasks[i].addr, i, init.tasks[i].size);
00230         
00231         ipc_init();
00232 
00233         /*
00234          * Create kernel task.
00235          */
00236         k = task_create(AS_KERNEL, "KERNEL");
00237         if (!k)
00238                 panic("can't create kernel task\n");
00239         
00240         /*
00241          * Create the first thread.
00242          */
00243         t = thread_create(kinit, NULL, k, 0, "kinit");
00244         if (!t)
00245                 panic("can't create kinit thread\n");
00246         thread_ready(t);
00247         
00248         /*
00249          * This call to scheduler() will return to kinit,
00250          * starting the thread of kernel threads.
00251          */
00252         scheduler();
00253         /* not reached */
00254 }
00255 
00256 
00257 #ifdef CONFIG_SMP
00258 
00268 void main_ap(void)
00269 {
00270         /*
00271          * Incrementing the active CPU counter will guarantee that the
00272          * pm_init() will not attempt to build GDT and IDT tables again.
00273          * Neither frame_init() will do the complete thing. Neither cpu_init()
00274          * will do.
00275          */
00276         config.cpu_active++;
00277 
00278         /*
00279          * The THE structure is well defined because ctx.sp is used as stack.
00280          */
00281         the_initialize(THE);
00282         
00283         arch_pre_mm_init();
00284         frame_init();
00285         page_init();
00286         tlb_init();
00287         arch_post_mm_init();
00288         
00289         cpu_init();
00290         
00291         calibrate_delay_loop();
00292 
00293         l_apic_init();
00294         l_apic_debug();
00295 
00296         the_copy(THE, (the_t *) CPU->stack);
00297 
00298         /*
00299          * If we woke kmp up before we left the kernel stack, we could
00300          * collide with another CPU coming up. To prevent this, we
00301          * switch to this cpu's private stack prior to waking kmp up.
00302          */
00303         context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), (__address) CPU->stack, CPU_STACK_SIZE);
00304         context_restore(&CPU->saved_context);
00305         /* not reached */
00306 }
00307 
00308 
00314 void main_ap_separated_stack(void)
00315 {
00316         /*
00317          * Configure timeouts for this cpu.
00318          */
00319         timeout_init();
00320 
00321         waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST);
00322         scheduler();
00323         /* not reached */
00324 }
00325 #endif /* CONFIG_SMP */
00326 

Generated on Sun Jun 18 16:26:58 2006 for HelenOS Kernel (amd64) by  doxygen 1.4.6