Remove building with NOCRYPTO option
[minix3.git] / minix / kernel / main.c
blob3198aba7317771fa26463837744aea3bc78c2ee2
1 /* This file contains the main program of MINIX as well as its shutdown code.
2 * The routine main() initializes the system and starts the ball rolling by
3 * setting up the process table, interrupt vectors, and scheduling each task
4 * to run to initialize itself.
5 * The routine shutdown() does the opposite and brings down MINIX.
7 * The entries into this file are:
8 * main: MINIX main program
9 * prepare_shutdown: prepare to take MINIX down
11 #include <string.h>
12 #include <stdlib.h>
13 #include <assert.h>
14 #include <minix/endpoint.h>
15 #include <machine/vmparam.h>
16 #include <minix/u64.h>
17 #include <minix/board.h>
18 #include <sys/reboot.h>
19 #include "clock.h"
20 #include "direct_utils.h"
21 #include "hw_intr.h"
22 #include "arch_proto.h"
24 #ifdef CONFIG_SMP
25 #include "smp.h"
26 #endif
27 #ifdef USE_WATCHDOG
28 #include "watchdog.h"
29 #endif
30 #include "spinlock.h"
32 /* dummy for linking */
33 char *** _penviron;
35 /* Prototype declarations for PRIVATE functions. */
36 static void announce(void);
38 void bsp_finish_booting(void)
40 int i;
41 #if SPROFILE
42 sprofiling = 0; /* we're not profiling until instructed to */
43 #endif /* SPROFILE */
45 cpu_identify();
47 vm_running = 0;
48 krandom.random_sources = RANDOM_SOURCES;
49 krandom.random_elements = RANDOM_ELEMENTS;
51 /* MINIX is now ready. All boot image processes are on the ready queue.
52 * Return to the assembly code to start running the current process.
55 /* it should point somewhere */
56 get_cpulocal_var(bill_ptr) = get_cpulocal_var_ptr(idle_proc);
57 get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc);
58 announce(); /* print MINIX startup banner */
61 * we have access to the cpu local run queue, only now schedule the processes.
62 * We ignore the slots for the former kernel tasks
64 for (i=0; i < NR_BOOT_PROCS - NR_TASKS; i++) {
65 RTS_UNSET(proc_addr(i), RTS_PROC_STOP);
68 * Enable timer interrupts and clock task on the boot CPU. First reset the
69 * CPU accounting values, as the timer initialization (indirectly) uses them.
71 cycles_accounting_init();
73 if (boot_cpu_init_timer(system_hz)) {
74 panic("FATAL : failed to initialize timer interrupts, "
75 "cannot continue without any clock source!");
78 fpu_init();
80 /* Warnings for sanity checks that take time. These warnings are printed
81 * so it's a clear warning no full release should be done with them
82 * enabled.
84 #if DEBUG_SCHED_CHECK
85 FIXME("DEBUG_SCHED_CHECK enabled");
86 #endif
87 #if DEBUG_VMASSERT
88 FIXME("DEBUG_VMASSERT enabled");
89 #endif
90 #if DEBUG_PROC_CHECK
91 FIXME("PROC check enabled");
92 #endif
94 #ifdef CONFIG_SMP
95 cpu_set_flag(bsp_cpu_id, CPU_IS_READY);
96 machine.processors_count = ncpus;
97 machine.bsp_id = bsp_cpu_id;
98 #else
99 machine.processors_count = 1;
100 machine.bsp_id = 0;
101 #endif
104 /* Kernel may no longer use bits of memory as VM will be running soon */
105 kernel_may_alloc = 0;
107 switch_to_user();
108 NOT_REACHABLE;
112 /*===========================================================================*
113 * kmain *
114 *===========================================================================*/
115 void kmain(kinfo_t *local_cbi)
117 /* Start the ball rolling. */
118 struct boot_image *ip; /* boot image pointer */
119 register struct proc *rp; /* process pointer */
120 register int i, j;
121 static int bss_test;
123 /* bss sanity check */
124 assert(bss_test == 0);
125 bss_test = 1;
127 /* save a global copy of the boot parameters */
128 memcpy(&kinfo, local_cbi, sizeof(kinfo));
129 memcpy(&kmess, kinfo.kmess, sizeof(kmess));
131 /* We have done this exercise in pre_init so we expect this code
132 to simply work! */
133 machine.board_id = get_board_id_by_name(env_get(BOARDVARNAME));
134 #ifdef __arm__
135 /* We want to initialize serial before we do any output */
136 arch_ser_init();
137 #endif
138 /* We can talk now */
139 DEBUGBASIC(("MINIX booting\n"));
141 /* Kernel may use bits of main memory before VM is started */
142 kernel_may_alloc = 1;
144 assert(sizeof(kinfo.boot_procs) == sizeof(image));
145 memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs));
147 cstart();
149 BKL_LOCK();
151 DEBUGEXTRA(("main()\n"));
153 /* Clear the process table. Anounce each slot as empty and set up mappings
154 * for proc_addr() and proc_nr() macros. Do the same for the table with
155 * privilege structures for the system processes and the ipc filter pool.
157 proc_init();
158 IPCF_POOL_INIT();
160 if(NR_BOOT_MODULES != kinfo.mbi.mi_mods_count)
161 panic("expecting %d boot processes/modules, found %d",
162 NR_BOOT_MODULES, kinfo.mbi.mi_mods_count);
164 /* Set up proc table entries for processes in boot image. */
165 for (i=0; i < NR_BOOT_PROCS; ++i) {
166 int schedulable_proc;
167 proc_nr_t proc_nr;
168 int ipc_to_m, kcalls;
169 sys_map_t map;
171 ip = &image[i]; /* process' attributes */
172 DEBUGEXTRA(("initializing %s... ", ip->proc_name));
173 rp = proc_addr(ip->proc_nr); /* get process pointer */
174 ip->endpoint = rp->p_endpoint; /* ipc endpoint */
175 rp->p_cpu_time_left = 0;
176 if(i < NR_TASKS) /* name (tasks only) */
177 strlcpy(rp->p_name, ip->proc_name, sizeof(rp->p_name));
179 if(i >= NR_TASKS) {
180 /* Remember this so it can be passed to VM */
181 multiboot_module_t *mb_mod = &kinfo.module_list[i - NR_TASKS];
182 ip->start_addr = mb_mod->mod_start;
183 ip->len = mb_mod->mod_end - mb_mod->mod_start;
186 reset_proc_accounting(rp);
188 /* See if this process is immediately schedulable.
189 * In that case, set its privileges now and allow it to run.
190 * Only kernel tasks and the root system process get to run immediately.
191 * All the other system processes are inhibited from running by the
192 * RTS_NO_PRIV flag. They can only be scheduled once the root system
193 * process has set their privileges.
195 proc_nr = proc_nr(rp);
196 schedulable_proc = (iskerneln(proc_nr) || isrootsysn(proc_nr) ||
197 proc_nr == VM_PROC_NR);
198 if(schedulable_proc) {
199 /* Assign privilege structure. Force a static privilege id. */
200 (void) get_priv(rp, static_priv_id(proc_nr));
202 /* Privileges for kernel tasks. */
203 if(proc_nr == VM_PROC_NR) {
204 priv(rp)->s_flags = VM_F;
205 priv(rp)->s_trap_mask = SRV_T;
206 ipc_to_m = SRV_M;
207 kcalls = SRV_KC;
208 priv(rp)->s_sig_mgr = SELF;
209 rp->p_priority = SRV_Q;
210 rp->p_quantum_size_ms = SRV_QT;
212 else if(iskerneln(proc_nr)) {
213 /* Privilege flags. */
214 priv(rp)->s_flags = (proc_nr == IDLE ? IDL_F : TSK_F);
215 /* Init flags. */
216 priv(rp)->s_init_flags = TSK_I;
217 /* Allowed traps. */
218 priv(rp)->s_trap_mask = (proc_nr == CLOCK
219 || proc_nr == SYSTEM ? CSK_T : TSK_T);
220 ipc_to_m = TSK_M; /* allowed targets */
221 kcalls = TSK_KC; /* allowed kernel calls */
223 /* Privileges for the root system process. */
224 else {
225 assert(isrootsysn(proc_nr));
226 priv(rp)->s_flags= RSYS_F; /* privilege flags */
227 priv(rp)->s_init_flags = SRV_I; /* init flags */
228 priv(rp)->s_trap_mask= SRV_T; /* allowed traps */
229 ipc_to_m = SRV_M; /* allowed targets */
230 kcalls = SRV_KC; /* allowed kernel calls */
231 priv(rp)->s_sig_mgr = SRV_SM; /* signal manager */
232 rp->p_priority = SRV_Q; /* priority queue */
233 rp->p_quantum_size_ms = SRV_QT; /* quantum size */
236 /* Fill in target mask. */
237 memset(&map, 0, sizeof(map));
239 if (ipc_to_m == ALL_M) {
240 for(j = 0; j < NR_SYS_PROCS; j++)
241 set_sys_bit(map, j);
244 fill_sendto_mask(rp, &map);
246 /* Fill in kernel call mask. */
247 for(j = 0; j < SYS_CALL_MASK_SIZE; j++) {
248 priv(rp)->s_k_call_mask[j] = (kcalls == NO_C ? 0 : (~0));
251 else {
252 /* Don't let the process run for now. */
253 RTS_SET(rp, RTS_NO_PRIV | RTS_NO_QUANTUM);
256 /* Arch-specific state initialization. */
257 arch_boot_proc(ip, rp);
259 /* scheduling functions depend on proc_ptr pointing somewhere. */
260 if(!get_cpulocal_var(proc_ptr))
261 get_cpulocal_var(proc_ptr) = rp;
263 /* Process isn't scheduled until VM has set up a pagetable for it. */
264 if(rp->p_nr != VM_PROC_NR && rp->p_nr >= 0) {
265 rp->p_rts_flags |= RTS_VMINHIBIT;
266 rp->p_rts_flags |= RTS_BOOTINHIBIT;
269 rp->p_rts_flags |= RTS_PROC_STOP;
270 rp->p_rts_flags &= ~RTS_SLOT_FREE;
271 DEBUGEXTRA(("done\n"));
274 /* update boot procs info for VM */
275 memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs));
277 #define IPCNAME(n) { \
278 assert((n) >= 0 && (n) <= IPCNO_HIGHEST); \
279 assert(!ipc_call_names[n]); \
280 ipc_call_names[n] = #n; \
283 arch_post_init();
285 IPCNAME(SEND);
286 IPCNAME(RECEIVE);
287 IPCNAME(SENDREC);
288 IPCNAME(NOTIFY);
289 IPCNAME(SENDNB);
290 IPCNAME(SENDA);
292 /* System and processes initialization */
293 memory_init();
294 DEBUGEXTRA(("system_init()... "));
295 system_init();
296 DEBUGEXTRA(("done\n"));
298 /* The bootstrap phase is over, so we can add the physical
299 * memory used for it to the free list.
301 add_memmap(&kinfo, kinfo.bootstrap_start, kinfo.bootstrap_len);
303 #ifdef CONFIG_SMP
304 if (config_no_apic) {
305 DEBUGBASIC(("APIC disabled, disables SMP, using legacy PIC\n"));
306 smp_single_cpu_fallback();
307 } else if (config_no_smp) {
308 DEBUGBASIC(("SMP disabled, using legacy PIC\n"));
309 smp_single_cpu_fallback();
310 } else {
311 smp_init();
313 * if smp_init() returns it means that it failed and we try to finish
314 * single CPU booting
316 bsp_finish_booting();
318 #else
320 * if configured for a single CPU, we are already on the kernel stack which we
321 * are going to use everytime we execute kernel code. We finish booting and we
322 * never return here
324 bsp_finish_booting();
325 #endif
327 NOT_REACHABLE;
330 /*===========================================================================*
331 * announce *
332 *===========================================================================*/
333 static void announce(void)
335 /* Display the MINIX startup banner. */
336 printf("\nMINIX %s. "
337 #ifdef PAE
338 "(PAE) "
339 #endif
340 #ifdef _VCS_REVISION
341 "(" _VCS_REVISION ")\n"
342 #endif
343 "Copyright 2016, Vrije Universiteit, Amsterdam, The Netherlands\n",
344 OS_RELEASE);
345 printf("MINIX is open source software, see http://www.minix3.org\n");
348 /*===========================================================================*
349 * prepare_shutdown *
350 *===========================================================================*/
351 void prepare_shutdown(const int how)
353 /* This function prepares to shutdown MINIX. */
354 static minix_timer_t shutdown_timer;
356 /* Continue after 1 second, to give processes a chance to get scheduled to
357 * do shutdown work. Set a watchog timer to call shutdown(). The timer
358 * argument passes the shutdown status.
360 printf("MINIX will now be shut down ...\n");
361 set_kernel_timer(&shutdown_timer, get_monotonic() + system_hz,
362 minix_shutdown, how);
365 /*===========================================================================*
366 * shutdown *
367 *===========================================================================*/
368 void minix_shutdown(int how)
370 /* This function is called from prepare_shutdown or stop_sequence to bring
371 * down MINIX.
374 #ifdef CONFIG_SMP
376 * FIXME
378 * we will need to stop timers on all cpus if SMP is enabled and put them in
379 * such a state that we can perform the whole boot process once restarted from
380 * monitor again
382 if (ncpus > 1)
383 smp_shutdown_aps();
384 #endif
385 hw_intr_disable_all();
386 stop_local_timer();
388 /* Show shutdown message */
389 direct_cls();
390 if((how & RB_POWERDOWN) == RB_POWERDOWN)
391 direct_print("MINIX has halted and will now power off.\n");
392 else if(how & RB_HALT)
393 direct_print("MINIX has halted. "
394 "It is safe to turn off your computer.\n");
395 else
396 direct_print("MINIX will now reset.\n");
397 arch_shutdown(how);
400 /*===========================================================================*
401 * cstart *
402 *===========================================================================*/
403 void cstart(void)
405 /* Perform system initializations prior to calling main(). Most settings are
406 * determined with help of the environment strings passed by MINIX' loader.
408 register char *value; /* value in key=value pair */
410 /* low-level initialization */
411 prot_init();
413 /* determine verbosity */
414 if ((value = env_get(VERBOSEBOOTVARNAME)))
415 verboseboot = atoi(value);
417 /* Initialize clock variables. */
418 init_clock();
420 /* Get memory parameters. */
421 value = env_get("ac_layout");
422 if(value && atoi(value)) {
423 kinfo.user_sp = (vir_bytes) USR_STACKTOP_COMPACT;
424 kinfo.user_end = (vir_bytes) USR_DATATOP_COMPACT;
427 DEBUGEXTRA(("cstart\n"));
429 /* Record miscellaneous information for user-space servers. */
430 kinfo.nr_procs = NR_PROCS;
431 kinfo.nr_tasks = NR_TASKS;
432 strlcpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
433 strlcpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
435 /* Initialize various user-mapped structures. */
436 memset(&arm_frclock, 0, sizeof(arm_frclock));
438 memset(&kuserinfo, 0, sizeof(kuserinfo));
439 kuserinfo.kui_size = sizeof(kuserinfo);
440 kuserinfo.kui_user_sp = kinfo.user_sp;
442 #ifdef USE_APIC
443 value = env_get("no_apic");
444 if(value)
445 config_no_apic = atoi(value);
446 else
447 config_no_apic = 1;
448 value = env_get("apic_timer_x");
449 if(value)
450 config_apic_timer_x = atoi(value);
451 else
452 config_apic_timer_x = 1;
453 #endif
455 #ifdef USE_WATCHDOG
456 value = env_get("watchdog");
457 if (value)
458 watchdog_enabled = atoi(value);
459 #endif
461 #ifdef CONFIG_SMP
462 if (config_no_apic)
463 config_no_smp = 1;
464 value = env_get("no_smp");
465 if(value)
466 config_no_smp = atoi(value);
467 else
468 config_no_smp = 0;
469 #endif
470 DEBUGEXTRA(("intr_init(0)\n"));
472 intr_init(0);
474 arch_init();
477 /*===========================================================================*
478 * get_value *
479 *===========================================================================*/
481 char *get_value(
482 const char *params, /* boot monitor parameters */
483 const char *name /* key to look up */
486 /* Get environment value - kernel version of getenv to avoid setting up the
487 * usual environment array.
489 register const char *namep;
490 register char *envp;
492 for (envp = (char *) params; *envp != 0;) {
493 for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
495 if (*namep == '\0' && *envp == '=') return(envp + 1);
496 while (*envp++ != 0)
499 return(NULL);
502 /*===========================================================================*
503 * env_get *
504 *===========================================================================*/
505 char *env_get(const char *name)
507 return get_value(kinfo.param_buf, name);
510 void cpu_print_freq(unsigned cpu)
512 u64_t freq;
514 freq = cpu_get_freq(cpu);
515 DEBUGBASIC(("CPU %d freq %lu MHz\n", cpu, (unsigned long)(freq / 1000000)));
518 int is_fpu(void)
520 return get_cpulocal_var(fpu_presence);