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

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since da13982 was da13982, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 20 months ago

Read symbol table from ELF sections

Instead of the currently broken data generated using genmap.py,
read the ELF symbol table for stack traces and symbol names.
In addition to that, prepare ground for accessing DWARF debug
sections.

Because neither .symtab, nor .debug_* sections are
normally part of the program image, these have to be provided
externally. Instead of the previous way of relinking kernel
to bake in the symbol data, we now only link kernel once
and the extra debug data is loaded as part of the initrd image.

  • Property mode set to 100644
File size: 8.3 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 kernel_generic
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 <stdio.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#include <stdlib.h>
75#include <debug/register.h>
76
77#ifdef CONFIG_SMP
78#include <smp/smp.h>
79#endif /* CONFIG_SMP */
80
81#include <synch/waitq.h>
82#include <synch/spinlock.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 interrupts_disable();
106
107#ifdef CONFIG_SMP
108 if (config.cpu_count > 1) {
109 semaphore_initialize(&ap_completion_semaphore, 0);
110
111 /*
112 * Create the kmp thread and wait for its completion.
113 * cpu1 through cpuN-1 will come up consecutively and
114 * not mess together with kcpulb threads.
115 * Just a beautification.
116 */
117 thread = thread_create(kmp, NULL, TASK,
118 THREAD_FLAG_UNCOUNTED, "kmp");
119 if (!thread)
120 panic("Unable to create kmp thread.");
121
122 thread_wire(thread, &cpus[0]);
123 thread_ready(thread_ref(thread));
124 thread_join(thread);
125 thread_put(thread);
126
127 /*
128 * For each CPU, create its load balancing thread.
129 */
130 unsigned int i;
131
132 for (i = 0; i < config.cpu_count; i++) {
133 thread = thread_create(kcpulb, NULL, TASK,
134 THREAD_FLAG_UNCOUNTED, "kcpulb");
135 if (thread != NULL) {
136 thread_wire(thread, &cpus[i]);
137 thread_ready(thread);
138 } else
139 log(LF_OTHER, LVL_ERROR,
140 "Unable to create kcpulb thread for cpu%u", i);
141 }
142 }
143#endif /* CONFIG_SMP */
144
145 /*
146 * At this point SMP, if present, is configured.
147 */
148 ARCH_OP(post_smp_init);
149
150 /* Start thread computing system load */
151 thread = thread_create(kload, NULL, TASK, THREAD_FLAG_NONE,
152 "kload");
153 if (thread != NULL)
154 thread_ready(thread);
155 else
156 log(LF_OTHER, LVL_ERROR, "Unable to create kload thread");
157
158#ifdef CONFIG_KCONSOLE
159 if (stdin) {
160 /*
161 * Create kernel console.
162 */
163 thread = thread_create(kconsole_thread, NULL, TASK,
164 THREAD_FLAG_NONE, "kconsole");
165 if (thread != NULL)
166 thread_ready(thread);
167 else
168 log(LF_OTHER, LVL_ERROR,
169 "Unable to create kconsole thread");
170 }
171#endif /* CONFIG_KCONSOLE */
172
173 /*
174 * Store the default stack size in sysinfo so that uspace can create
175 * stack with this default size.
176 */
177 sysinfo_set_item_val("default.stack_size", NULL, STACK_SIZE_USER);
178
179 interrupts_enable();
180
181 /*
182 * Create user tasks, load RAM disk images.
183 */
184 size_t i;
185 program_t programs[CONFIG_INIT_TASKS] = { };
186
187 // FIXME: do not propagate arguments through sysinfo
188 // but pass them directly to the tasks
189 for (i = 0; i < init.cnt; i++) {
190 const char *arguments = init.tasks[i].arguments;
191 if (str_length(arguments) == 0)
192 continue;
193 if (str_length(init.tasks[i].name) == 0)
194 continue;
195 size_t arguments_size = str_size(arguments);
196
197 void *arguments_copy = malloc(arguments_size);
198 if (arguments_copy == NULL)
199 continue;
200 memcpy(arguments_copy, arguments, arguments_size);
201
202 char item_name[CONFIG_TASK_NAME_BUFLEN + 15];
203 snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15,
204 "init_args.%s", init.tasks[i].name);
205
206 sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size);
207 }
208
209 for (i = 0; i < init.cnt; i++) {
210 if (init.tasks[i].paddr % FRAME_SIZE) {
211 log(LF_OTHER, LVL_ERROR,
212 "init[%zu]: Address is not frame aligned", i);
213 programs[i].task = NULL;
214 continue;
215 }
216
217 /*
218 * Construct task name from the 'init:' prefix and the
219 * name stored in the init structure (if any).
220 */
221
222 char namebuf[TASK_NAME_BUFLEN];
223
224 const char *name = init.tasks[i].name;
225 if (name[0] == 0)
226 name = "<unknown>";
227
228 static_assert(TASK_NAME_BUFLEN >= INIT_PREFIX_LEN, "");
229 str_cpy(namebuf, TASK_NAME_BUFLEN, INIT_PREFIX);
230 str_cpy(namebuf + INIT_PREFIX_LEN,
231 TASK_NAME_BUFLEN - INIT_PREFIX_LEN, name);
232
233 /*
234 * Create virtual memory mappings for init task images.
235 */
236 uintptr_t page = km_map(init.tasks[i].paddr,
237 init.tasks[i].size, PAGE_SIZE,
238 PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
239 assert(page);
240
241 if (str_cmp(name, "kernel.dbg") == 0) {
242 /*
243 * Not an actual init task, but rather debug sections extracted
244 * from the kernel ELF file and handed to us here so we can use
245 * it for debugging.
246 */
247
248 register_debug_data((void *) page, init.tasks[i].size);
249 programs[i].task = NULL;
250 continue;
251 }
252
253 if (str_cmp(name, "loader") == 0) {
254 /* Register image as the program loader */
255 if (program_loader == NULL) {
256 program_loader = (void *) page;
257 log(LF_OTHER, LVL_NOTE, "Program loader at %p",
258 program_loader);
259 } else {
260 log(LF_OTHER, LVL_ERROR,
261 "init[%zu]: Second binary named \"loader\""
262 " present.", i);
263 }
264
265 programs[i].task = NULL;
266 continue;
267 }
268
269 errno_t rc = program_create_from_image((void *) page, namebuf,
270 &programs[i]);
271
272 if (rc == 0) {
273 assert(programs[i].task != NULL);
274
275 /*
276 * Set permissions to init userspace tasks.
277 */
278 perm_set(programs[i].task,
279 PERM_PERM | PERM_MEM_MANAGER |
280 PERM_IO_MANAGER | PERM_IRQ_REG);
281
282 if (!ipc_box_0) {
283 ipc_box_0 = &programs[i].task->answerbox;
284 /*
285 * Hold the first task so that
286 * ipc_box_0 remains a valid pointer
287 * even if the first task exits for
288 * whatever reason.
289 */
290 task_hold(programs[i].task);
291 }
292
293 } else if (i == init.cnt - 1) {
294 /*
295 * Assume the last task is the RAM disk.
296 */
297 init_rd((void *) init.tasks[i].paddr, init.tasks[i].size);
298 } else {
299 log(LF_OTHER, LVL_ERROR,
300 "init[%zu]: Init binary load failed "
301 "(error %s, loader status %s)", i,
302 str_error_name(rc), str_error_name(programs[i].loader_status));
303 }
304 }
305
306 /*
307 * Run user tasks.
308 */
309 for (i = 0; i < init.cnt; i++) {
310 if (programs[i].task != NULL)
311 program_ready(&programs[i]);
312 }
313
314#ifdef CONFIG_KCONSOLE
315 if (!stdin) {
316 thread_sleep(10);
317 printf("kinit: No stdin\nKernel alive: .");
318
319 unsigned int i = 0;
320 while (true) {
321 printf("\b%c", alive[i % ALIVE_CHARS]);
322 thread_sleep(1);
323 i++;
324 }
325 }
326#endif /* CONFIG_KCONSOLE */
327}
328
329/** @}
330 */
Note: See TracBrowser for help on using the repository browser.