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

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

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.1 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/** @addtogroup main
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Kernel initialization thread.
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
44#include <assert.h>
45#include <main/kinit.h>
46#include <config.h>
47#include <arch.h>
48#include <proc/scheduler.h>
49#include <proc/task.h>
50#include <proc/thread.h>
51#include <proc/program.h>
52#include <panic.h>
53#include <halt.h>
54#include <cpu.h>
55#include <arch/asm.h>
56#include <mm/page.h>
57#include <arch/mm/page.h>
58#include <mm/as.h>
59#include <mm/frame.h>
60#include <mm/km.h>
61#include <print.h>
62#include <log.h>
63#include <mem.h>
64#include <console/console.h>
65#include <interrupt.h>
66#include <console/kconsole.h>
67#include <security/perm.h>
68#include <lib/rd.h>
69#include <ipc/ipc.h>
70#include <str.h>
71#include <sysinfo/stats.h>
72#include <sysinfo/sysinfo.h>
73#include <align.h>
74
75#ifdef CONFIG_SMP
76#include <smp/smp.h>
77#endif /* CONFIG_SMP */
78
79#include <synch/waitq.h>
80#include <synch/spinlock.h>
81#include <synch/workqueue.h>
82#include <synch/rcu.h>
83
84#define ALIVE_CHARS 4
85
86#ifdef CONFIG_KCONSOLE
87static char alive[ALIVE_CHARS] = "-\\|/";
88#endif
89
90#define INIT_PREFIX "init:"
91#define INIT_PREFIX_LEN 5
92
93/** Kernel initialization thread.
94 *
95 * kinit takes care of higher level kernel
96 * initialization (i.e. thread creation,
97 * userspace initialization etc.).
98 *
99 * @param arg Not used.
100 */
101void kinit(void *arg)
102{
103 thread_t *thread;
104
105 /*
106 * Detach kinit as nobody will call thread_join_timeout() on it.
107 */
108 thread_detach(THREAD);
109
110 interrupts_disable();
111
112 /* Start processing RCU callbacks. RCU is fully functional afterwards. */
113 rcu_kinit_init();
114
115 /*
116 * Start processing work queue items. Some may have been queued during boot.
117 */
118 workq_global_worker_init();
119
120#ifdef CONFIG_SMP
121 if (config.cpu_count > 1) {
122 waitq_initialize(&ap_completion_wq);
123
124 /*
125 * Create the kmp thread and wait for its completion.
126 * cpu1 through cpuN-1 will come up consecutively and
127 * not mess together with kcpulb threads.
128 * Just a beautification.
129 */
130 thread = thread_create(kmp, NULL, TASK,
131 THREAD_FLAG_UNCOUNTED, "kmp");
132 if (thread != NULL) {
133 thread_wire(thread, &cpus[0]);
134 thread_ready(thread);
135 } else
136 panic("Unable to create kmp thread.");
137
138 thread_join(thread);
139 thread_detach(thread);
140
141 /*
142 * For each CPU, create its load balancing thread.
143 */
144 unsigned int i;
145
146 for (i = 0; i < config.cpu_count; i++) {
147 thread = thread_create(kcpulb, NULL, TASK,
148 THREAD_FLAG_UNCOUNTED, "kcpulb");
149 if (thread != NULL) {
150 thread_wire(thread, &cpus[i]);
151 thread_ready(thread);
152 } else
153 log(LF_OTHER, LVL_ERROR,
154 "Unable to create kcpulb thread for cpu%u", i);
155 }
156 }
157#endif /* CONFIG_SMP */
158
159 /*
160 * At this point SMP, if present, is configured.
161 */
162 ARCH_OP(post_smp_init);
163
164 /* Start thread computing system load */
165 thread = thread_create(kload, NULL, TASK, THREAD_FLAG_NONE,
166 "kload");
167 if (thread != NULL)
168 thread_ready(thread);
169 else
170 log(LF_OTHER, LVL_ERROR, "Unable to create kload thread");
171
172#ifdef CONFIG_KCONSOLE
173 if (stdin) {
174 /*
175 * Create kernel console.
176 */
177 thread = thread_create(kconsole_thread, NULL, TASK,
178 THREAD_FLAG_NONE, "kconsole");
179 if (thread != NULL)
180 thread_ready(thread);
181 else
182 log(LF_OTHER, LVL_ERROR,
183 "Unable to create kconsole thread");
184 }
185#endif /* CONFIG_KCONSOLE */
186
187 /*
188 * Store the default stack size in sysinfo so that uspace can create
189 * stack with this default size.
190 */
191 sysinfo_set_item_val("default.stack_size", NULL, STACK_SIZE_USER);
192
193 interrupts_enable();
194
195 /*
196 * Create user tasks, load RAM disk images.
197 */
198 size_t i;
199 program_t programs[CONFIG_INIT_TASKS];
200
201 // FIXME: do not propagate arguments through sysinfo
202 // but pass them directly to the tasks
203 for (i = 0; i < init.cnt; i++) {
204 const char *arguments = init.tasks[i].arguments;
205 if (str_length(arguments) == 0)
206 continue;
207 if (str_length(init.tasks[i].name) == 0)
208 continue;
209 size_t arguments_size = str_size(arguments);
210
211 void *arguments_copy = malloc(arguments_size, 0);
212 if (arguments_copy == NULL)
213 continue;
214 memcpy(arguments_copy, arguments, arguments_size);
215
216 char item_name[CONFIG_TASK_NAME_BUFLEN + 15];
217 snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15,
218 "init_args.%s", init.tasks[i].name);
219
220 sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size);
221 }
222
223 for (i = 0; i < init.cnt; i++) {
224 if (init.tasks[i].paddr % FRAME_SIZE) {
225 log(LF_OTHER, LVL_ERROR,
226 "init[%zu]: Address is not frame aligned", i);
227 programs[i].task = NULL;
228 continue;
229 }
230
231 /*
232 * Construct task name from the 'init:' prefix and the
233 * name stored in the init structure (if any).
234 */
235
236 char namebuf[TASK_NAME_BUFLEN];
237
238 const char *name = init.tasks[i].name;
239 if (name[0] == 0)
240 name = "<unknown>";
241
242 static_assert(TASK_NAME_BUFLEN >= INIT_PREFIX_LEN, "");
243 str_cpy(namebuf, TASK_NAME_BUFLEN, INIT_PREFIX);
244 str_cpy(namebuf + INIT_PREFIX_LEN,
245 TASK_NAME_BUFLEN - INIT_PREFIX_LEN, name);
246
247 /*
248 * Create virtual memory mappings for init task images.
249 */
250 uintptr_t page = km_map(init.tasks[i].paddr,
251 init.tasks[i].size,
252 PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
253 assert(page);
254
255 errno_t rc = program_create_from_image((void *) page, namebuf,
256 &programs[i]);
257
258 if (rc == 0) {
259 if (programs[i].task != NULL) {
260 /*
261 * Set permissions to init userspace tasks.
262 */
263 perm_set(programs[i].task,
264 PERM_PERM | PERM_MEM_MANAGER |
265 PERM_IO_MANAGER | PERM_IRQ_REG);
266
267 if (!ipc_phone_0) {
268 ipc_phone_0 = &programs[i].task->answerbox;
269 /*
270 * Hold the first task so that the
271 * ipc_phone_0 remains a valid pointer
272 * even if the first task exits for
273 * whatever reason.
274 */
275 task_hold(programs[i].task);
276 }
277 }
278
279 /*
280 * If programs[i].task == NULL then it is
281 * the program loader and it was registered
282 * successfully.
283 */
284 } else if (i == init.cnt - 1) {
285 /*
286 * Assume the last task is the RAM disk.
287 */
288 init_rd((void *) init.tasks[i].paddr, init.tasks[i].size);
289 } else
290 log(LF_OTHER, LVL_ERROR,
291 "init[%zu]: Init binary load failed "
292 "(error %s, loader status %u)", i,
293 str_error_name(rc), programs[i].loader_status);
294 }
295
296 /*
297 * Run user tasks.
298 */
299 for (i = 0; i < init.cnt; i++) {
300 if (programs[i].task != NULL)
301 program_ready(&programs[i]);
302 }
303
304#ifdef CONFIG_KCONSOLE
305 if (!stdin) {
306 thread_sleep(10);
307 printf("kinit: No stdin\nKernel alive: .");
308
309 unsigned int i = 0;
310 while (true) {
311 printf("\b%c", alive[i % ALIVE_CHARS]);
312 thread_sleep(1);
313 i++;
314 }
315 }
316#endif /* CONFIG_KCONSOLE */
317}
318
319/** @}
320 */
Note: See TracBrowser for help on using the repository browser.