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