source: mainline/kernel/generic/src/main/kinit.c@ 08e103d4

Last change on this file since 08e103d4 was 08e103d4, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use clearer naming for string length functions

This and the following commit change the names of functions, as well as
their documentation, to use unambiguous terms "bytes" and "code points"
instead of ambiguous terms "size", "length", and "characters".

  • Property mode set to 100644
File size: 8.1 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
[2f57690]35 * @brief Kernel initialization thread.
[9179d0a]36 *
37 * This file contains kinit kernel thread which carries out
38 * high level system initialization.
39 *
40 * This file is responsible for finishing SMP configuration
41 * and creation of userspace init tasks.
42 */
43
[63e27ef]44#include <assert.h>
[f761f1eb]45#include <main/kinit.h>
[2677758]46#include <config.h>
47#include <arch.h>
[f761f1eb]48#include <proc/scheduler.h>
49#include <proc/task.h>
50#include <proc/thread.h>
[c98e6ee]51#include <proc/program.h>
[f761f1eb]52#include <panic.h>
[b2e121a]53#include <halt.h>
[f761f1eb]54#include <cpu.h>
55#include <arch/asm.h>
56#include <mm/page.h>
57#include <arch/mm/page.h>
[20d50a1]58#include <mm/as.h>
[ff3b3197]59#include <mm/frame.h>
[32817cc]60#include <mm/km.h>
[bab75df6]61#include <stdio.h>
[b2fa1204]62#include <log.h>
[44a7ee5]63#include <mem.h>
[ff3b3197]64#include <console/console.h>
[aace6624]65#include <interrupt.h>
[f4338d2]66#include <console/kconsole.h>
[719a208]67#include <security/perm.h>
[d4b5542]68#include <lib/rd.h>
[b3f8fb7]69#include <ipc/ipc.h>
[19f857a]70#include <str.h>
[9dae191e]71#include <sysinfo/stats.h>
[c8cbd39]72#include <sysinfo/sysinfo.h>
[32817cc]73#include <align.h>
[aafed15]74#include <stdlib.h>
[f761f1eb]75
[5f85c91]76#ifdef CONFIG_SMP
[26678e5]77#include <smp/smp.h>
[5f85c91]78#endif /* CONFIG_SMP */
[f761f1eb]79
80#include <synch/waitq.h>
81#include <synch/spinlock.h>
82
[c19a4169]83#define ALIVE_CHARS 4
84
[753d851]85#ifdef CONFIG_KCONSOLE
[c19a4169]86static char alive[ALIVE_CHARS] = "-\\|/";
[753d851]87#endif
[c19a4169]88
[da581872]89#define INIT_PREFIX "init:"
90#define INIT_PREFIX_LEN 5
[20f1597]91
[880de6e]92/** Kernel initialization thread.
93 *
94 * kinit takes care of higher level kernel
95 * initialization (i.e. thread creation,
96 * userspace initialization etc.).
97 *
98 * @param arg Not used.
99 */
[f761f1eb]100void kinit(void *arg)
101{
[76fca31]102 thread_t *thread;
[a35b458]103
[2cb5e64]104 /*
105 * Detach kinit as nobody will call thread_join_timeout() on it.
106 */
107 thread_detach(THREAD);
[8a64e81e]108
[22f7769]109 interrupts_disable();
[a35b458]110
[2f57690]111#ifdef CONFIG_SMP
[f761f1eb]112 if (config.cpu_count > 1) {
[26678e5]113 waitq_initialize(&ap_completion_wq);
[a35b458]114
[f761f1eb]115 /*
116 * Create the kmp thread and wait for its completion.
117 * cpu1 through cpuN-1 will come up consecutively and
[169c408]118 * not mess together with kcpulb threads.
[f761f1eb]119 * Just a beautification.
120 */
[6eef3c4]121 thread = thread_create(kmp, NULL, TASK,
122 THREAD_FLAG_UNCOUNTED, "kmp");
[abf6c01]123 if (!thread)
[f651e80]124 panic("Unable to create kmp thread.");
[a35b458]125
[abf6c01]126 thread_wire(thread, &cpus[0]);
127 thread_ready(thread);
[76fca31]128 thread_join(thread);
129 thread_detach(thread);
[a35b458]130
[76cec1e]131 /*
[f761f1eb]132 * For each CPU, create its load balancing thread.
133 */
[7e752b2]134 unsigned int i;
[a35b458]135
[f761f1eb]136 for (i = 0; i < config.cpu_count; i++) {
[6eef3c4]137 thread = thread_create(kcpulb, NULL, TASK,
138 THREAD_FLAG_UNCOUNTED, "kcpulb");
[76fca31]139 if (thread != NULL) {
[6eef3c4]140 thread_wire(thread, &cpus[i]);
[76fca31]141 thread_ready(thread);
[8e3bf3e2]142 } else
[b2fa1204]143 log(LF_OTHER, LVL_ERROR,
144 "Unable to create kcpulb thread for cpu%u", i);
[f761f1eb]145 }
146 }
[5f85c91]147#endif /* CONFIG_SMP */
[a35b458]148
[a83a802]149 /*
150 * At this point SMP, if present, is configured.
151 */
[36df4109]152 ARCH_OP(post_smp_init);
[a35b458]153
[9dae191e]154 /* Start thread computing system load */
[6eef3c4]155 thread = thread_create(kload, NULL, TASK, THREAD_FLAG_NONE,
156 "kload");
[9dae191e]157 if (thread != NULL)
158 thread_ready(thread);
159 else
[b2fa1204]160 log(LF_OTHER, LVL_ERROR, "Unable to create kload thread");
[a35b458]161
[76fca31]162#ifdef CONFIG_KCONSOLE
163 if (stdin) {
164 /*
165 * Create kernel console.
166 */
[6eef3c4]167 thread = thread_create(kconsole_thread, NULL, TASK,
168 THREAD_FLAG_NONE, "kconsole");
[76fca31]169 if (thread != NULL)
170 thread_ready(thread);
171 else
[b2fa1204]172 log(LF_OTHER, LVL_ERROR,
173 "Unable to create kconsole thread");
[76fca31]174 }
175#endif /* CONFIG_KCONSOLE */
[a35b458]176
[0aae87a6]177 /*
178 * Store the default stack size in sysinfo so that uspace can create
179 * stack with this default size.
180 */
[67b152e]181 sysinfo_set_item_val("default.stack_size", NULL, STACK_SIZE_USER);
[a35b458]182
[22f7769]183 interrupts_enable();
[a35b458]184
[49eec93]185 /*
186 * Create user tasks, load RAM disk images.
187 */
[98000fb]188 size_t i;
[c98e6ee]189 program_t programs[CONFIG_INIT_TASKS];
[a35b458]190
[c8cbd39]191 // FIXME: do not propagate arguments through sysinfo
192 // but pass them directly to the tasks
193 for (i = 0; i < init.cnt; i++) {
194 const char *arguments = init.tasks[i].arguments;
[08e103d4]195 if (str_code_points(arguments) == 0)
[c8cbd39]196 continue;
[08e103d4]197 if (str_code_points(init.tasks[i].name) == 0)
[c8cbd39]198 continue;
[08e103d4]199 size_t arguments_size = str_bytes(arguments);
[c8cbd39]200
[11b285d]201 void *arguments_copy = malloc(arguments_size);
[c8cbd39]202 if (arguments_copy == NULL)
203 continue;
204 memcpy(arguments_copy, arguments, arguments_size);
205
206 char item_name[CONFIG_TASK_NAME_BUFLEN + 15];
207 snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15,
208 "init_args.%s", init.tasks[i].name);
209
210 sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size);
211 }
212
[b6b576c]213 for (i = 0; i < init.cnt; i++) {
[32817cc]214 if (init.tasks[i].paddr % FRAME_SIZE) {
[b2fa1204]215 log(LF_OTHER, LVL_ERROR,
216 "init[%zu]: Address is not frame aligned", i);
[2319df3]217 programs[i].task = NULL;
[228b135]218 continue;
219 }
[a35b458]220
[20f1597]221 /*
[da581872]222 * Construct task name from the 'init:' prefix and the
[20f1597]223 * name stored in the init structure (if any).
224 */
[a35b458]225
[2f57690]226 char namebuf[TASK_NAME_BUFLEN];
[a35b458]227
[a000878c]228 const char *name = init.tasks[i].name;
[b60c582]229 if (name[0] == 0)
[2f57690]230 name = "<unknown>";
[a35b458]231
[63e27ef]232 static_assert(TASK_NAME_BUFLEN >= INIT_PREFIX_LEN, "");
[f4b1535]233 str_cpy(namebuf, TASK_NAME_BUFLEN, INIT_PREFIX);
234 str_cpy(namebuf + INIT_PREFIX_LEN,
235 TASK_NAME_BUFLEN - INIT_PREFIX_LEN, name);
[a35b458]236
[32817cc]237 /*
238 * Create virtual memory mappings for init task images.
239 */
[221c9ec]240 uintptr_t page = km_map(init.tasks[i].paddr,
[6bf5b8c]241 init.tasks[i].size, PAGE_SIZE,
[221c9ec]242 PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
[63e27ef]243 assert(page);
[a35b458]244
[57d44dd]245 if (str_cmp(name, "loader") == 0) {
246 /* Register image as the program loader */
247 if (program_loader == NULL) {
248 program_loader = (void *) page;
249 log(LF_OTHER, LVL_NOTE, "Program loader at %p",
250 program_loader);
251 } else {
252 log(LF_OTHER, LVL_ERROR,
253 "init[%zu]: Second binary named \"loader\""
254 " present.", i);
255 }
[1cac875]256
257 programs[i].task = NULL;
[57d44dd]258 continue;
259 }
260
[b7fd2a0]261 errno_t rc = program_create_from_image((void *) page, namebuf,
[32817cc]262 &programs[i]);
[a35b458]263
[fb48a0e]264 if (rc == 0) {
[57d44dd]265 assert(programs[i].task != NULL);
266
267 /*
268 * Set permissions to init userspace tasks.
269 */
270 perm_set(programs[i].task,
271 PERM_PERM | PERM_MEM_MANAGER |
272 PERM_IO_MANAGER | PERM_IRQ_REG);
273
274 if (!ipc_box_0) {
275 ipc_box_0 = &programs[i].task->answerbox;
[fb48a0e]276 /*
[57d44dd]277 * Hold the first task so that
278 * ipc_box_0 remains a valid pointer
279 * even if the first task exits for
280 * whatever reason.
[fb48a0e]281 */
[57d44dd]282 task_hold(programs[i].task);
[fb48a0e]283 }
[a35b458]284
[fb48a0e]285 } else if (i == init.cnt - 1) {
286 /*
287 * Assume the last task is the RAM disk.
288 */
[221c9ec]289 init_rd((void *) init.tasks[i].paddr, init.tasks[i].size);
[57d44dd]290 } else {
[b2fa1204]291 log(LF_OTHER, LVL_ERROR,
292 "init[%zu]: Init binary load failed "
[62ca560]293 "(error %s, loader status %u)", i,
294 str_error_name(rc), programs[i].loader_status);
[57d44dd]295 }
[49eec93]296 }
[a35b458]297
[49eec93]298 /*
[566f4cfb]299 * Run user tasks.
[49eec93]300 */
301 for (i = 0; i < init.cnt; i++) {
[566f4cfb]302 if (programs[i].task != NULL)
[c98e6ee]303 program_ready(&programs[i]);
[44c259c]304 }
[a35b458]305
[76fca31]306#ifdef CONFIG_KCONSOLE
[ff3b3197]307 if (!stdin) {
[c19a4169]308 thread_sleep(10);
[eddf924]309 printf("kinit: No stdin\nKernel alive: .");
[a35b458]310
[c19a4169]311 unsigned int i = 0;
312 while (true) {
313 printf("\b%c", alive[i % ALIVE_CHARS]);
[ff3b3197]314 thread_sleep(1);
[76fca31]315 i++;
[ff3b3197]316 }
[f761f1eb]317 }
[76fca31]318#endif /* CONFIG_KCONSOLE */
[f761f1eb]319}
[b45c443]320
[8e3bf3e2]321/** @}
[b45c443]322 */
Note: See TracBrowser for help on using the repository browser.