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