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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b60615bd was b60615bd, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Modify kernel malloc()

This new implementation places the allocation size in front of the allocated
object, instead of relying on the slab allocator being able to determine source
slab cache for an object. This should improve scalability and help reduce
complexity of the memory management subsystem (further changes coming).

The drawback is more memory consumed by small malloc() allocations, however that
can be mitigated by switching to an API where the user provides known object
size to deallocation (most users know it either statically or from length they
necessarily remember).

  • Property mode set to 100644
File size: 9.7 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[f761f1eb]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
[e88eb48]29/** @addtogroup kernel_generic
[b45c443]30 * @{
31 */
32
[9179d0a]33/**
[b45c443]34 * @file
[13a638d]35 * @brief Main initialization kernel function for all processors.
[9179d0a]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
[f761f1eb]49#include <arch/asm.h>
[63e27ef]50#include <debug.h>
[d5d2a3f]51#include <context.h>
[bab75df6]52#include <stdio.h>
[02a99d2]53#include <panic.h>
[63e27ef]54#include <assert.h>
[f761f1eb]55#include <config.h>
56#include <time/clock.h>
[b3f8fb7]57#include <time/timeout.h>
[f761f1eb]58#include <proc/scheduler.h>
59#include <proc/thread.h>
60#include <proc/task.h>
61#include <main/kinit.h>
[5fe5f1e]62#include <main/version.h>
[f4338d2]63#include <console/kconsole.h>
[5d67baa]64#include <console/console.h>
[91db0280]65#include <log.h>
[f761f1eb]66#include <cpu.h>
[e0cdb7b6]67#include <align.h>
[aace6624]68#include <interrupt.h>
[b5746a2]69#include <str.h>
[f761f1eb]70#include <mm/frame.h>
71#include <mm/page.h>
[6d7ffa65]72#include <genarch/mm/page_pt.h>
[622f409]73#include <mm/km.h>
[169587a]74#include <mm/tlb.h>
[20d50a1]75#include <mm/as.h>
[4e147a6]76#include <mm/slab.h>
[8d308b9]77#include <mm/reserve.h>
[f761f1eb]78#include <synch/waitq.h>
[d314571]79#include <synch/syswaitq.h>
[393f631]80#include <arch/arch.h>
[f761f1eb]81#include <arch.h>
[f2ffad4]82#include <arch/faddr.h>
[6d9c49a]83#include <ipc/ipc.h>
[93165be]84#include <macros.h>
[2810636]85#include <adt/btree.h>
[5fe5f1e]86#include <smp/smp.h>
[f8ddd17]87#include <ddi/ddi.h>
[4b241f3]88#include <main/main.h>
[13a638d]89#include <ipc/event.h>
[d9fae235]90#include <sysinfo/sysinfo.h>
[9dae191e]91#include <sysinfo/stats.h>
[41deb2a]92#include <lib/ra.h>
[ce732e74]93#include <cap/cap.h>
[5fe5f1e]94
[7c3fb9b]95/*
96 * Ensure [u]int*_t types are of correct size.
[328cc31]97 *
98 * Probably, this is not the best place for such tests
99 * but this file is compiled on all architectures.
100 */
101#define CHECK_INT_TYPE_(signness, size) \
[63e27ef]102 static_assert(sizeof(signness##size##_t) * 8 == size, \
[328cc31]103 #signness #size "_t does not have " #size " bits");
[9e40355e]104
[328cc31]105#define CHECK_INT_TYPE(size) \
[9e40355e]106 CHECK_INT_TYPE_(int, size); \
107 CHECK_INT_TYPE_(uint, size)
[328cc31]108
109CHECK_INT_TYPE(8);
110CHECK_INT_TYPE(16);
111CHECK_INT_TYPE(32);
112CHECK_INT_TYPE(64);
113
[e459f12]114/** Global configuration structure. */
[55896b6]115config_t config = {
116 .identity_configured = false,
[40c8c17]117 .non_identity_configured = false,
118 .physmem_end = 0
[55896b6]119};
[e459f12]120
[3b3faf51]121/** Boot arguments. */
[3bacee1]122char bargs[CONFIG_BOOT_ARGUMENTS_BUFLEN] = { };
[3b3faf51]123
[e459f12]124/** Initial user-space tasks */
125init_t init = {
[6c441cf8]126 .cnt = 0
[e459f12]127};
[5fe5f1e]128
[61e90dd]129/** Boot allocations. */
130ballocs_t ballocs = {
[0b4a67a]131 .base = (uintptr_t) NULL,
[61e90dd]132 .size = 0
133};
134
[f761f1eb]135context_t ctx;
136
[c0855a0]137/** Lowest safe stack virtual address. */
[263bda2]138uintptr_t stack_safe = 0;
[deaa22f]139
[f761f1eb]140/*
141 * These two functions prevent stack from underflowing during the
142 * kernel boot phase when SP is set to the very top of the reserved
143 * space. The stack could get corrupted by a fooled compiler-generated
144 * pop sequence otherwise.
145 */
146static void main_bsp_separated_stack(void);
[263bda2]147
[80d2bdb]148#ifdef CONFIG_SMP
[f761f1eb]149static void main_ap_separated_stack(void);
[80d2bdb]150#endif
[f761f1eb]151
[7f0837c]152/** Main kernel routine for bootstrap CPU.
[673104e]153 *
[7a4202d]154 * The code here still runs on the boot stack, which knows nothing about
155 * preemption counts. Because of that, this function cannot directly call
156 * functions that disable or enable preemption (e.g. spinlock_lock()). The
157 * primary task of this function is to calculate address of a new stack and
158 * switch to it.
[673104e]159 *
[22f7769]160 * Assuming interrupts_disable().
[673104e]161 *
[f761f1eb]162 */
[7a0359b]163NO_TRACE void main_bsp(void)
[f761f1eb]164{
165 config.cpu_count = 1;
166 config.cpu_active = 1;
[a35b458]167
[8a1afd2]168 config.base = (uintptr_t) kernel_load_address;
169
170 config.kernel_size =
171 ALIGN_UP((uintptr_t) kdata_end - config.base, PAGE_SIZE);
[a35b458]172
[95d45482]173 // NOTE: All kernel stacks must be aligned to STACK_SIZE,
174 // see get_stack_base().
[d1da1ff2]175
[d59718e]176 /* Place the stack after the kernel, init and ballocs. */
[d1da1ff2]177 config.stack_base =
178 ALIGN_UP(config.base + config.kernel_size, STACK_SIZE);
[d59718e]179 config.stack_size = STACK_SIZE;
[a35b458]180
[deaa22f]181 /* Avoid placing stack on top of init */
[98000fb]182 size_t i;
[deaa22f]183 for (i = 0; i < init.cnt; i++) {
[d59718e]184 uintptr_t p = init.tasks[i].paddr + init.tasks[i].size;
[d1da1ff2]185 uintptr_t bottom = PA2KA(ALIGN_UP(p, STACK_SIZE));
[d59718e]186
187 if (config.stack_base < bottom)
188 config.stack_base = bottom;
[deaa22f]189 }
[a35b458]190
[61e90dd]191 /* Avoid placing stack on top of boot allocations. */
192 if (ballocs.size) {
[d59718e]193 uintptr_t bottom =
[d1da1ff2]194 ALIGN_UP(ballocs.base + ballocs.size, STACK_SIZE);
[d59718e]195 if (config.stack_base < bottom)
196 config.stack_base = bottom;
[61e90dd]197 }
[a35b458]198
[deaa22f]199 if (config.stack_base < stack_safe)
[d1da1ff2]200 config.stack_base = ALIGN_UP(stack_safe, STACK_SIZE);
[a35b458]201
[be50915]202 context_save(&ctx);
[26aafe8]203 context_set(&ctx, FADDR(main_bsp_separated_stack),
204 config.stack_base, STACK_SIZE);
[be50915]205 context_restore(&ctx);
[f761f1eb]206 /* not reached */
207}
208
[7f0837c]209/** Main kernel routine for bootstrap CPU using new stack.
[673104e]210 *
211 * Second part of main_bsp().
212 *
213 */
[263bda2]214void main_bsp_separated_stack(void)
[fde6429]215{
[7a4202d]216 /* Keep this the first thing. */
[a6e55886]217 current_initialize(CURRENT);
[a35b458]218
[7a4202d]219 version_print();
[a35b458]220
[7e752b2]221 LOG("\nconfig.base=%p config.kernel_size=%zu"
222 "\nconfig.stack_base=%p config.stack_size=%zu",
[1caeb2d]223 (void *) config.base, config.kernel_size,
224 (void *) config.stack_base, config.stack_size);
[a35b458]225
[76fca31]226#ifdef CONFIG_KCONSOLE
[ff3b3197]227 /*
228 * kconsole data structures must be initialized very early
229 * because other subsystems will register their respective
230 * commands.
231 */
[263bda2]232 kconsole_init();
[76fca31]233#endif
[a35b458]234
[ef67bab]235 /*
236 * Exception handler initialization, before architecture
[0132630]237 * starts adding its own handlers
[aace6624]238 */
[263bda2]239 exc_init();
[a35b458]240
[fc1e4f6]241 /*
242 * Memory management subsystems initialization.
[b84aaba]243 */
[36df4109]244 ARCH_OP(pre_mm_init);
[622f409]245 km_identity_init();
[263bda2]246 frame_init();
247 slab_cache_init();
[b60615bd]248 malloc_init();
[dabbe28]249 ra_init();
[263bda2]250 sysinfo_init();
251 btree_init();
252 as_init();
253 page_init();
254 tlb_init();
[622f409]255 km_non_identity_init();
[263bda2]256 ddi_init();
[36df4109]257 ARCH_OP(post_mm_init);
[8d308b9]258 reserve_init();
[36df4109]259 ARCH_OP(pre_smp_init);
[263bda2]260 smp_init();
[a35b458]261
[f8ddd17]262 /* Slab must be initialized after we know the number of processors. */
[263bda2]263 slab_enable_cpucache();
[a35b458]264
[933cadf]265 uint64_t size;
266 const char *size_suffix;
267 bin_order_suffix(zones_total_size(), &size, &size_suffix, false);
268 printf("Detected %u CPU(s), %" PRIu64 " %s free memory\n",
269 config.cpu_count, size, size_suffix);
[a35b458]270
[263bda2]271 cpu_init();
272 calibrate_delay_loop();
[36df4109]273 ARCH_OP(post_cpu_init);
[49e6c6b4]274
[263bda2]275 clock_counter_init();
276 timeout_init();
277 scheduler_init();
[ce732e74]278 caps_init();
[263bda2]279 task_init();
280 thread_init();
[d314571]281 sys_waitq_init();
[3b3faf51]282
283 sysinfo_set_item_data("boot_args", NULL, bargs, str_size(bargs) + 1);
284
[c06eb06]285 if (init.cnt > 0) {
[98000fb]286 size_t i;
[c06eb06]287 for (i = 0; i < init.cnt; i++)
[7e752b2]288 LOG("init[%zu].addr=%p, init[%zu].size=%zu",
[edd7c63c]289 i, (void *) init.tasks[i].paddr, i, init.tasks[i].size);
[c06eb06]290 } else
[ae5aa90]291 printf("No init binaries found.\n");
[a35b458]292
[263bda2]293 ipc_init();
294 event_init();
[6fa9a99d]295 kio_init();
[91db0280]296 log_init();
[263bda2]297 stats_init();
[a35b458]298
[f761f1eb]299 /*
300 * Create kernel task.
301 */
[b84aaba]302 task_t *kernel = task_create(AS_KERNEL, "kernel");
303 if (!kernel)
[f651e80]304 panic("Cannot create kernel task.");
[a35b458]305
[f761f1eb]306 /*
307 * Create the first thread.
308 */
[6eef3c4]309 thread_t *kinit_thread = thread_create(kinit, NULL, kernel,
310 THREAD_FLAG_UNCOUNTED, "kinit");
[b84aaba]311 if (!kinit_thread)
[f651e80]312 panic("Cannot create kinit thread.");
[263bda2]313 thread_ready(kinit_thread);
[a35b458]314
[f761f1eb]315 /*
316 * This call to scheduler() will return to kinit,
317 * starting the thread of kernel threads.
318 */
319 scheduler();
320 /* not reached */
321}
322
[5f85c91]323#ifdef CONFIG_SMP
[263bda2]324
[7f0837c]325/** Main kernel routine for application CPUs.
[673104e]326 *
327 * Executed by application processors, temporary stack
[26678e5]328 * is at ctx.sp which was set during BSP boot.
[5fe5f1e]329 * This function passes control directly to
330 * main_ap_separated_stack().
[673104e]331 *
[22f7769]332 * Assuming interrupts_disable()'d.
[673104e]333 *
[f761f1eb]334 */
335void main_ap(void)
336{
337 /*
338 * Incrementing the active CPU counter will guarantee that the
[26678e5]339 * *_init() functions can find out that they need to
340 * do initialization for AP only.
[f761f1eb]341 */
342 config.cpu_active++;
[a35b458]343
[7ce9284]344 /*
[a6e55886]345 * The CURRENT structure is well defined because ctx.sp is used as stack.
[7ce9284]346 */
[a6e55886]347 current_initialize(CURRENT);
[a35b458]348
[36df4109]349 ARCH_OP(pre_mm_init);
[f761f1eb]350 frame_init();
351 page_init();
[ce031f0]352 tlb_init();
[36df4109]353 ARCH_OP(post_mm_init);
[a35b458]354
[f761f1eb]355 cpu_init();
356 calibrate_delay_loop();
[36df4109]357 ARCH_OP(post_cpu_init);
[a35b458]358
[a6e55886]359 current_copy(CURRENT, (current_t *) CPU->stack);
[a35b458]360
[f761f1eb]361 /*
362 * If we woke kmp up before we left the kernel stack, we could
363 * collide with another CPU coming up. To prevent this, we
364 * switch to this cpu's private stack prior to waking kmp up.
365 */
[b24786a]366 context_save(&CPU->saved_context);
[f8ddd17]367 context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
[26aafe8]368 (uintptr_t) CPU->stack, STACK_SIZE);
[be50915]369 context_restore(&CPU->saved_context);
[f761f1eb]370 /* not reached */
371}
372
[7f0837c]373/** Main kernel routine for application CPUs using new stack.
[673104e]374 *
375 * Second part of main_ap().
376 *
377 */
[f761f1eb]378void main_ap_separated_stack(void)
379{
380 /*
381 * Configure timeouts for this cpu.
382 */
383 timeout_init();
[a35b458]384
[f761f1eb]385 waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST);
386 scheduler();
387 /* not reached */
388}
[263bda2]389
[5f85c91]390#endif /* CONFIG_SMP */
[b45c443]391
[8e3bf3e2]392/** @}
[b45c443]393 */
Note: See TracBrowser for help on using the repository browser.