32,7 → 32,7 |
|
/** |
* @file |
* @brief Main initialization kernel function for all processors. |
* @brief Main initialization kernel function for all processors. |
* |
* During kernel boot, all processors, after architecture dependent |
* initialization, start executing code found in this file. After |
57,11 → 57,9 |
#include <proc/scheduler.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/tasklet.h> |
#include <main/kinit.h> |
#include <main/version.h> |
#include <console/kconsole.h> |
#include <console/console.h> |
#include <cpu.h> |
#include <align.h> |
#include <interrupt.h> |
79,10 → 77,9 |
#include <ipc/ipc.h> |
#include <macros.h> |
#include <adt/btree.h> |
#include <console/klog.h> |
#include <smp/smp.h> |
#include <ddi/ddi.h> |
#include <main/main.h> |
#include <ipc/event.h> |
|
/** Global configuration structure. */ |
config_t config; |
89,7 → 86,7 |
|
/** Initial user-space tasks */ |
init_t init = { |
.cnt = 0 |
0 |
}; |
|
/** Boot allocations. */ |
105,15 → 102,17 |
* the linker or the low level assembler code with |
* appropriate sizes and addresses. |
*/ |
uintptr_t hardcoded_load_address = 0; /**< Virtual address of where the kernel |
* is loaded. */ |
size_t hardcoded_ktext_size = 0; /**< Size of the kernel code in bytes. |
*/ |
size_t hardcoded_kdata_size = 0; /**< Size of the kernel data in bytes. |
*/ |
uintptr_t stack_safe = 0; /**< Lowest safe stack virtual address. |
*/ |
|
/** Virtual address of where the kernel is loaded. */ |
uintptr_t hardcoded_load_address = 0; |
/** Size of the kernel code in bytes. */ |
size_t hardcoded_ktext_size = 0; |
/** Size of the kernel data in bytes. */ |
size_t hardcoded_kdata_size = 0; |
/** Lowest safe stack virtual address. */ |
uintptr_t stack_safe = 0; |
void main_bsp(void); |
void main_ap(void); |
|
/* |
* These two functions prevent stack from underflowing during the |
130,11 → 129,9 |
|
/** Main kernel routine for bootstrap CPU. |
* |
* The code here still runs on the boot stack, which knows nothing about |
* preemption counts. Because of that, this function cannot directly call |
* functions that disable or enable preemption (e.g. spinlock_lock()). The |
* primary task of this function is to calculate address of a new stack and |
* switch to it. |
* Initializes the kernel by bootstrap CPU. |
* This function passes control directly to |
* main_bsp_separated_stack(). |
* |
* Assuming interrupts_disable(). |
* |
153,7 → 150,7 |
config.stack_base = config.base + config.kernel_size; |
|
/* Avoid placing stack on top of init */ |
size_t i; |
count_t i; |
for (i = 0; i < init.cnt; i++) { |
if (PA_overlaps(config.stack_base, config.stack_size, |
init.tasks[i].addr, init.tasks[i].size)) |
187,93 → 184,89 |
*/ |
void main_bsp_separated_stack(void) |
{ |
/* Keep this the first thing. */ |
task_t *k; |
thread_t *t; |
count_t i; |
|
the_initialize(THE); |
|
version_print(); |
|
LOG("\nconfig.base=%#" PRIp " config.kernel_size=%" PRIs |
"\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs, |
config.base, config.kernel_size, config.stack_base, |
config.stack_size); |
|
#ifdef CONFIG_KCONSOLE |
|
/* |
* kconsole data structures must be initialized very early |
* because other subsystems will register their respective |
* commands. |
*/ |
LOG_EXEC(kconsole_init()); |
#endif |
kconsole_init(); |
|
/* |
* Exception handler initialization, before architecture |
* starts adding its own handlers |
*/ |
LOG_EXEC(exc_init()); |
|
exc_init(); |
|
/* |
* Memory management subsystems initialization. |
*/ |
LOG_EXEC(arch_pre_mm_init()); |
LOG_EXEC(frame_init()); |
|
*/ |
arch_pre_mm_init(); |
frame_init(); |
/* Initialize at least 1 memory segment big enough for slab to work. */ |
LOG_EXEC(slab_cache_init()); |
LOG_EXEC(btree_init()); |
LOG_EXEC(as_init()); |
LOG_EXEC(page_init()); |
LOG_EXEC(tlb_init()); |
LOG_EXEC(ddi_init()); |
LOG_EXEC(tasklet_init()); |
LOG_EXEC(arch_post_mm_init()); |
LOG_EXEC(arch_pre_smp_init()); |
LOG_EXEC(smp_init()); |
slab_cache_init(); |
btree_init(); |
as_init(); |
page_init(); |
tlb_init(); |
ddi_init(); |
arch_post_mm_init(); |
|
version_print(); |
printf("kernel: %.*p hardcoded_ktext_size=%zd KB, " |
"hardcoded_kdata_size=%zd KB\n", sizeof(uintptr_t) * 2, |
config.base, SIZE2KB(hardcoded_ktext_size), |
SIZE2KB(hardcoded_kdata_size)); |
printf("stack: %.*p size=%zd KB\n", sizeof(uintptr_t) * 2, |
config.stack_base, SIZE2KB(config.stack_size)); |
|
arch_pre_smp_init(); |
smp_init(); |
/* Slab must be initialized after we know the number of processors. */ |
LOG_EXEC(slab_enable_cpucache()); |
slab_enable_cpucache(); |
|
printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n", |
config.cpu_count, SIZE2MB(zone_total_size())); |
printf("Detected %zu CPU(s), %llu MB free memory\n", |
config.cpu_count, SIZE2MB(zone_total_size())); |
cpu_init(); |
|
LOG_EXEC(cpu_init()); |
calibrate_delay_loop(); |
clock_counter_init(); |
timeout_init(); |
scheduler_init(); |
task_init(); |
thread_init(); |
futex_init(); |
klog_init(); |
|
LOG_EXEC(calibrate_delay_loop()); |
LOG_EXEC(clock_counter_init()); |
LOG_EXEC(timeout_init()); |
LOG_EXEC(scheduler_init()); |
LOG_EXEC(task_init()); |
LOG_EXEC(thread_init()); |
LOG_EXEC(futex_init()); |
|
if (init.cnt > 0) { |
size_t i; |
for (i = 0; i < init.cnt; i++) |
LOG("init[%" PRIs "].addr=%#" PRIp ", init[%" PRIs |
"].size=%#" PRIs, i, init.tasks[i].addr, i, |
printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i, |
sizeof(uintptr_t) * 2, init.tasks[i].addr, i, |
init.tasks[i].size); |
} else |
printf("No init binaries found.\n"); |
printf("No init binaries found\n"); |
|
LOG_EXEC(ipc_init()); |
LOG_EXEC(event_init()); |
LOG_EXEC(klog_init()); |
|
ipc_init(); |
|
/* |
* Create kernel task. |
*/ |
task_t *kernel = task_create(AS_KERNEL, "kernel"); |
if (!kernel) |
panic("Cannot create kernel task."); |
k = task_create(AS_KERNEL, "kernel"); |
if (!k) |
panic("can't create kernel task\n"); |
|
/* |
* Create the first thread. |
*/ |
thread_t *kinit_thread |
= thread_create(kinit, NULL, kernel, 0, "kinit", true); |
if (!kinit_thread) |
panic("Cannot create kinit thread."); |
LOG_EXEC(thread_ready(kinit_thread)); |
t = thread_create(kinit, NULL, k, 0, "kinit", true); |
if (!t) |
panic("can't create kinit thread\n"); |
thread_ready(t); |
|
/* |
* This call to scheduler() will return to kinit, |
326,7 → 319,6 |
* collide with another CPU coming up. To prevent this, we |
* switch to this cpu's private stack prior to waking kmp up. |
*/ |
context_save(&CPU->saved_context); |
context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), |
(uintptr_t) CPU->stack, CPU_STACK_SIZE); |
context_restore(&CPU->saved_context); |