WIP-mmap-page-at-0
[akaros.git] / kern / src / init.c
1 /* See COPYRIGHT for copyright information. */
2
3 #ifdef CONFIG_BSD_ON_CORE0
4 #error "Yeah, it's not possible to build ROS with BSD on Core 0, sorry......"
5 #else
6
7 #include <arch/arch.h>
8 #include <arch/topology.h>
9 #include <arch/console.h>
10 #include <multiboot.h>
11 #include <stab.h>
12 #include <smp.h>
13
14 #include <time.h>
15 #include <atomic.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <assert.h>
19 #include <monitor.h>
20 #include <pmap.h>
21 #include <process.h>
22 #include <trap.h>
23 #include <syscall.h>
24 #include <kclock.h>
25 #include <manager.h>
26 #include <testing.h>
27 #include <kmalloc.h>
28 #include <hashtable.h>
29 #include <radix.h>
30 #include <mm.h>
31 #include <frontend.h>
32 #include <ex_table.h>
33 #include <percpu.h>
34
35 #include <arch/init.h>
36 #include <bitmask.h>
37 #include <slab.h>
38 #include <kfs.h>
39 #include <vfs.h>
40 #include <devfs.h>
41 #include <blockdev.h>
42 #include <ext2fs.h>
43 #include <kthread.h>
44 #include <console.h>
45 #include <linker_func.h>
46 #include <ip.h>
47 #include <acpi.h>
48 #include <coreboot_tables.h>
49
50 #define MAX_BOOT_CMDLINE_SIZE 4096
51
52 #define ASSIGN_PTRVAL(prm, top, val)                    \
53         do {                                                                            \
54                 if (prm && (prm < top)) {                               \
55                         *prm = val;                                                     \
56                         prm++;                                                          \
57                 }                                                                               \
58         } while (0)
59
60 int booting = 1;
61 struct proc_global_info __proc_global_info;
62 struct sysinfo_t sysinfo;
63 static char boot_cmdline[MAX_BOOT_CMDLINE_SIZE];
64
65 static void run_linker_funcs(void);
66 static int run_init_script(void);
67
68 const char *get_boot_option(const char *base, const char *option, char *param,
69                                                         size_t max_param)
70 {
71         size_t optlen = strlen(option);
72         char *ptop = param + max_param - 1;
73         const char *opt, *arg;
74
75         if (!base)
76                 base = boot_cmdline;
77         for (;;) {
78                 opt = strstr(base, option);
79                 if (!opt)
80                         return NULL;
81                 if (((opt == base) || (opt[-1] == ' ')) &&
82                         ((opt[optlen] == 0) || (opt[optlen] == '=') ||
83                          (opt[optlen] == ' ')))
84                         break;
85                 base = opt + optlen;
86         }
87         arg = opt + optlen;
88         if (*arg == '=') {
89                 arg++;
90                 if (*arg == '\'') {
91                         arg++;
92                         for (; *arg; arg++) {
93                                 if (*arg == '\\')
94                                         arg++;
95                                 else if (*arg == '\'')
96                                         break;
97                                 ASSIGN_PTRVAL(param, ptop, *arg);
98                         }
99                 } else {
100                         for (; *arg && (*arg != ' '); arg++)
101                                 ASSIGN_PTRVAL(param, ptop, *arg);
102                 }
103         }
104         ASSIGN_PTRVAL(param, ptop, 0);
105
106         return arg;
107 }
108
109 static void extract_multiboot_cmdline(struct multiboot_info *mbi)
110 {
111         if (mbi && (mbi->flags & MULTIBOOT_INFO_CMDLINE) && mbi->cmdline) {
112                 const char *cmdln = (const char *) KADDR(mbi->cmdline);
113
114                 /* We need to copy the command line in a permanent buffer, since the
115                  * multiboot memory where it is currently residing will be part of the
116                  * free boot memory later on in the boot process.
117                  */
118                 strlcpy(boot_cmdline, cmdln, sizeof(boot_cmdline));
119         }
120 }
121
122 struct page *mmap_zero_pg;
123
124 // XXX if we want to do anything else, we'll need to put it in a section that is
125 // linked to be at virtual address 0.
126 //              could have this get turned on, then be in all new processes addr space
127 //void xme() {} __attribute__ ((section ("mmap-zero")));
128 void xme()
129 {
130         breakpoint();
131 }
132
133 void kernel_init(multiboot_info_t *mboot_info)
134 {
135         extern char __start_bss[], __stop_bss[];
136
137         memset(__start_bss, 0, __stop_bss - __start_bss);
138         /* mboot_info is a physical address.  while some arches currently have the
139          * lower memory mapped, everyone should have it mapped at kernbase by now.
140          * also, it might be in 'free' memory, so once we start dynamically using
141          * memory, we may clobber it. */
142         multiboot_kaddr = (struct multiboot_info*)((physaddr_t)mboot_info
143                                                + KERNBASE);
144         extract_multiboot_cmdline(multiboot_kaddr);
145
146         cons_init();
147         print_cpuinfo();
148
149         printk("Boot Command Line: '%s'\n", boot_cmdline);
150
151         exception_table_init();
152         cache_init();                                   // Determine systems's cache properties
153         pmem_init(multiboot_kaddr);
154         kmem_cache_init();              // Sets up slab allocator
155         kmalloc_init();
156         hashtable_init();
157         radix_init();
158         cache_color_alloc_init();       // Inits data structs
159         colored_page_alloc_init();      // Allocates colors for agnostic processes
160         acpiinit();
161         topology_init();
162         percpu_init();
163         kthread_init();                                 /* might need to tweak when this happens */
164         vmr_init();
165         file_init();
166         page_check();
167         idt_init();
168         kernel_msg_init();
169         timer_init();
170         vfs_init();
171         devfs_init();
172         time_init();
173         kb_buf_init(&cons_buf);
174         arch_init();
175         block_init();
176         enable_irq();
177         run_linker_funcs();
178         /* reset/init devtab after linker funcs 3 and 4.  these run NIC and medium
179          * pre-inits, which need to happen before devether. */
180         devtabreset();
181         devtabinit();
182
183
184
185         int ret;
186         ret = kpage_alloc(&mmap_zero_pg);
187         assert(!ret);
188
189         printk("got paddr %p, ref %d\n", page2pa(mmap_zero_pg),
190                kref_refcnt(&mmap_zero_pg->pg_kref));
191         ret = map_vmap_segment(0, page2pa(mmap_zero_pg), 1, PTE_KERN_RW);
192         assert(!ret);
193         memcpy(0, (void*)xme, PGSIZE);
194         printk("ref %d\n", kref_refcnt(&mmap_zero_pg->pg_kref));
195
196
197
198
199 #ifdef CONFIG_EXT2FS
200         mount_fs(&ext2_fs_type, "/dev/ramdisk", "/mnt", 0);
201 #endif /* CONFIG_EXT2FS */
202 #ifdef CONFIG_ETH_AUDIO
203         eth_audio_init();
204 #endif /* CONFIG_ETH_AUDIO */
205         get_coreboot_info(&sysinfo);
206         booting = 0;
207
208 #ifdef CONFIG_RUN_INIT_SCRIPT
209         if (run_init_script()) {
210                 printk("Configured to run init script, but no script specified!\n");
211                 manager();
212         }
213 #else
214         manager();
215 #endif
216 }
217
218 #ifdef CONFIG_RUN_INIT_SCRIPT
219 static int run_init_script(void)
220 {
221         /* If we have an init script path specified */
222         if (strlen(CONFIG_INIT_SCRIPT_PATH_AND_ARGS) != 0) {
223                 int vargs = 0;
224                 char *sptr = &CONFIG_INIT_SCRIPT_PATH_AND_ARGS[0];
225
226                 /* Figure out how many arguments there are, by finding the spaces */
227                 /* TODO: consider rewriting this stuff with parsecmd */
228                 while (*sptr != '\0') {
229                         if (*(sptr++) != ' ') {
230                                 vargs++;
231                                 while ((*sptr != ' ') && (*sptr != '\0'))
232                                         sptr++;
233                         }
234                 }
235
236                 /* Initialize l_argv with its first three arguments, but allocate space
237                  * for all arguments as calculated above */
238                 int static_args = 2;
239                 int total_args = vargs + static_args;
240                 char *l_argv[total_args];
241                 l_argv[0] = "/bin/bash";
242                 l_argv[1] = "bash";
243
244                 /* Initialize l_argv with the rest of the arguments */
245                 int i = static_args;
246                 sptr = &CONFIG_INIT_SCRIPT_PATH_AND_ARGS[0];
247                 while (*sptr != '\0') {
248                         if (*sptr != ' ') {
249                                 l_argv[i++] = sptr;
250                                 while ((*sptr != ' ') && (*sptr != '\0'))
251                                         sptr++;
252                                 if (*sptr == '\0')
253                                         break;
254                                 *sptr = '\0';
255                         }
256                         sptr++;
257                 }
258
259                 /* Run the script with its arguments */
260                 mon_bin_run(total_args, l_argv, NULL);
261         }
262         return -1;
263 }
264 #endif
265
266 /*
267  * Panic is called on unresolvable fatal errors.
268  * It prints "panic: mesg", and then enters the kernel monitor.
269  */
270 void _panic(const char *file, int line, const char *fmt,...)
271 {
272         va_list ap;
273         struct per_cpu_info *pcpui;
274         /* We're panicing, possibly in a place that can't handle the lock checker */
275         pcpui = &per_cpu_info[core_id_early()];
276         pcpui->__lock_checking_enabled--;
277         va_start(ap, fmt);
278         printk("kernel panic at %s:%d, from core %d: ", file, line,
279                core_id_early());
280         vcprintf(fmt, ap);
281         cprintf("\n");
282         va_end(ap);
283
284 dead:
285         monitor(NULL);
286         /* We could consider turning the lock checker back on here, but things are
287          * probably a mess anyways, and with it on we would probably lock up right
288          * away when we idle. */
289         //pcpui->__lock_checking_enabled++;
290         smp_idle();
291 }
292
293 /* like panic, but don't */
294 void _warn(const char *file, int line, const char *fmt,...)
295 {
296         va_list ap;
297
298         va_start(ap, fmt);
299         printk("kernel warning at %s:%d, from core %d: ", file, line,
300                core_id_early());
301         vcprintf(fmt, ap);
302         cprintf("\n");
303         va_end(ap);
304 }
305
306 static void run_links(linker_func_t *linkstart, linker_func_t *linkend)
307 {
308         /* Unlike with devtab, our linker sections for the function pointers are
309          * 8 byte aligned (4 on 32 bit) (done by the linker/compiler), so we don't
310          * have to worry about that.  */
311         printd("linkstart %p, linkend %p\n", linkstart, linkend);
312         for (int i = 0; &linkstart[i] < linkend; i++) {
313                 printd("i %d, linkfunc %p\n", i, linkstart[i]);
314                 linkstart[i]();
315         }
316 }
317
318 static void run_linker_funcs(void)
319 {
320         run_links(__linkerfunc1start, __linkerfunc1end);
321         run_links(__linkerfunc2start, __linkerfunc2end);
322         run_links(__linkerfunc3start, __linkerfunc3end);
323         run_links(__linkerfunc4start, __linkerfunc4end);
324 }
325
326 /* You need to reference PROVIDE symbols somewhere, or they won't be included.
327  * Only really a problem for debugging. */
328 void debug_linker_tables(void)
329 {
330         extern struct dev __devtabstart[];
331         extern struct dev __devtabend[];
332         printk("devtab %p %p\nlink1 %p %p\nlink2 %p %p\nlink3 %p %p\nlink4 %p %p\n",
333                __devtabstart,
334                __devtabend,
335                    __linkerfunc1start,
336                    __linkerfunc1end,
337                    __linkerfunc2start,
338                    __linkerfunc2end,
339                    __linkerfunc3start,
340                    __linkerfunc3end,
341                    __linkerfunc4start,
342                    __linkerfunc4end);
343 }
344
345 #endif //Everything For Free