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