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