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
18 #include <minix/com.h>
19 #include <minix/endpoint.h>
20 #include <machine/vmparam.h>
21 #include <minix/u64.h>
22 #include <minix/type.h>
25 #include "arch_proto.h"
35 /* dummy for linking */
38 /* Prototype declarations for PRIVATE functions. */
39 static void announce(void);
41 void bsp_finish_booting(void)
45 sprofiling
= 0; /* we're not profiling until instructed to */
47 cprof_procs_no
= 0; /* init nr of hash table slots used */
52 krandom
.random_sources
= RANDOM_SOURCES
;
53 krandom
.random_elements
= RANDOM_ELEMENTS
;
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.
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 */
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
68 for (i
=0; i
< NR_BOOT_PROCS
- NR_TASKS
; i
++) {
69 RTS_UNSET(proc_addr(i
), RTS_PROC_STOP
);
72 * enable timer interrupts and clock task on the boot CPU
74 if (boot_cpu_init_timer(system_hz
)) {
75 panic("FATAL : failed to initialize timer interrupts, "
76 "cannot continue without any clock source!");
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
86 FIXME("DEBUG_SCHED_CHECK enabled");
89 FIXME("DEBUG_VMASSERT enabled");
92 FIXME("PROC check enabled");
95 DEBUGEXTRA(("cycles_accounting_init()... "));
96 cycles_accounting_init();
97 DEBUGEXTRA(("done\n"));
100 cpu_set_flag(bsp_cpu_id
, CPU_IS_READY
);
101 machine
.processors_count
= ncpus
;
102 machine
.bsp_id
= bsp_cpu_id
;
104 machine
.processors_count
= 1;
108 /* Kernel may no longer use bits of memory as VM will be running soon */
109 kernel_may_alloc
= 0;
115 /*===========================================================================*
117 *===========================================================================*/
118 void kmain(kinfo_t
*local_cbi
)
120 /* Start the ball rolling. */
121 struct boot_image
*ip
; /* boot image pointer */
122 register struct proc
*rp
; /* process pointer */
125 /* save a global copy of the boot parameters */
126 memcpy(&kinfo
, local_cbi
, sizeof(kinfo
));
127 memcpy(&kmess
, kinfo
.kmess
, sizeof(kmess
));
129 /* We can talk now */
130 printf("MINIX booting\n");
132 /* Kernel may use bits of main memory before VM is started */
133 kernel_may_alloc
= 1;
135 assert(sizeof(kinfo
.boot_procs
) == sizeof(image
));
136 memcpy(kinfo
.boot_procs
, image
, sizeof(kinfo
.boot_procs
));
142 DEBUGEXTRA(("main()\n"));
146 if(NR_BOOT_MODULES
!= kinfo
.mbi
.mods_count
)
147 panic("expecting %d boot processes/modules, found %d",
148 NR_BOOT_MODULES
, kinfo
.mbi
.mods_count
);
150 /* Set up proc table entries for processes in boot image. */
151 for (i
=0; i
< NR_BOOT_PROCS
; ++i
) {
152 int schedulable_proc
;
154 int ipc_to_m
, kcalls
;
157 ip
= &image
[i
]; /* process' attributes */
158 DEBUGEXTRA(("initializing %s... ", ip
->proc_name
));
159 rp
= proc_addr(ip
->proc_nr
); /* get process pointer */
160 ip
->endpoint
= rp
->p_endpoint
; /* ipc endpoint */
161 make_zero64(rp
->p_cpu_time_left
);
162 if(i
< NR_TASKS
) /* name (tasks only) */
163 strlcpy(rp
->p_name
, ip
->proc_name
, sizeof(rp
->p_name
));
166 /* Remember this so it can be passed to VM */
167 multiboot_module_t
*mb_mod
= &kinfo
.module_list
[i
- NR_TASKS
];
168 ip
->start_addr
= mb_mod
->mod_start
;
169 ip
->len
= mb_mod
->mod_end
- mb_mod
->mod_start
;
172 reset_proc_accounting(rp
);
174 /* See if this process is immediately schedulable.
175 * In that case, set its privileges now and allow it to run.
176 * Only kernel tasks and the root system process get to run immediately.
177 * All the other system processes are inhibited from running by the
178 * RTS_NO_PRIV flag. They can only be scheduled once the root system
179 * process has set their privileges.
181 proc_nr
= proc_nr(rp
);
182 schedulable_proc
= (iskerneln(proc_nr
) || isrootsysn(proc_nr
) ||
183 proc_nr
== VM_PROC_NR
);
184 if(schedulable_proc
) {
185 /* Assign privilege structure. Force a static privilege id. */
186 (void) get_priv(rp
, static_priv_id(proc_nr
));
188 /* Priviliges for kernel tasks. */
189 if(proc_nr
== VM_PROC_NR
) {
190 priv(rp
)->s_flags
= VM_F
;
191 priv(rp
)->s_trap_mask
= SRV_T
;
194 priv(rp
)->s_sig_mgr
= SELF
;
195 rp
->p_priority
= SRV_Q
;
196 rp
->p_quantum_size_ms
= SRV_QT
;
198 else if(iskerneln(proc_nr
)) {
199 /* Privilege flags. */
200 priv(rp
)->s_flags
= (proc_nr
== IDLE
? IDL_F
: TSK_F
);
202 priv(rp
)->s_trap_mask
= (proc_nr
== CLOCK
203 || proc_nr
== SYSTEM
? CSK_T
: TSK_T
);
204 ipc_to_m
= TSK_M
; /* allowed targets */
205 kcalls
= TSK_KC
; /* allowed kernel calls */
207 /* Priviliges for the root system process. */
209 assert(isrootsysn(proc_nr
));
210 priv(rp
)->s_flags
= RSYS_F
; /* privilege flags */
211 priv(rp
)->s_trap_mask
= SRV_T
; /* allowed traps */
212 ipc_to_m
= SRV_M
; /* allowed targets */
213 kcalls
= SRV_KC
; /* allowed kernel calls */
214 priv(rp
)->s_sig_mgr
= SRV_SM
; /* signal manager */
215 rp
->p_priority
= SRV_Q
; /* priority queue */
216 rp
->p_quantum_size_ms
= SRV_QT
; /* quantum size */
219 /* Fill in target mask. */
220 memset(&map
, 0, sizeof(map
));
222 if (ipc_to_m
== ALL_M
) {
223 for(j
= 0; j
< NR_SYS_PROCS
; j
++)
227 fill_sendto_mask(rp
, &map
);
229 /* Fill in kernel call mask. */
230 for(j
= 0; j
< SYS_CALL_MASK_SIZE
; j
++) {
231 priv(rp
)->s_k_call_mask
[j
] = (kcalls
== NO_C
? 0 : (~0));
235 /* Don't let the process run for now. */
236 RTS_SET(rp
, RTS_NO_PRIV
| RTS_NO_QUANTUM
);
239 /* Arch-specific state initialization. */
240 arch_boot_proc(ip
, rp
);
242 /* scheduling functions depend on proc_ptr pointing somewhere. */
243 if(!get_cpulocal_var(proc_ptr
))
244 get_cpulocal_var(proc_ptr
) = rp
;
246 /* Process isn't scheduled until VM has set up a pagetable for it. */
247 if(rp
->p_nr
!= VM_PROC_NR
&& rp
->p_nr
>= 0) {
248 rp
->p_rts_flags
|= RTS_VMINHIBIT
;
249 rp
->p_rts_flags
|= RTS_BOOTINHIBIT
;
252 rp
->p_rts_flags
|= RTS_PROC_STOP
;
253 rp
->p_rts_flags
&= ~RTS_SLOT_FREE
;
254 DEBUGEXTRA(("done\n"));
257 /* update boot procs info for VM */
258 memcpy(kinfo
.boot_procs
, image
, sizeof(kinfo
.boot_procs
));
260 #define IPCNAME(n) { \
261 assert((n) >= 0 && (n) <= IPCNO_HIGHEST); \
262 assert(!ipc_call_names[n]); \
263 ipc_call_names[n] = #n; \
275 /* System and processes initialization */
277 DEBUGEXTRA(("system_init()... "));
279 DEBUGEXTRA(("done\n"));
281 /* The bootstrap phase is over, so we can add the physical
282 * memory used for it to the free list.
284 add_memmap(&kinfo
, kinfo
.bootstrap_start
, kinfo
.bootstrap_len
);
287 if (config_no_apic
) {
288 BOOT_VERBOSE(printf("APIC disabled, disables SMP, using legacy PIC\n"));
289 smp_single_cpu_fallback();
290 } else if (config_no_smp
) {
291 BOOT_VERBOSE(printf("SMP disabled, using legacy PIC\n"));
292 smp_single_cpu_fallback();
296 * if smp_init() returns it means that it failed and we try to finish
299 bsp_finish_booting();
303 * if configured for a single CPU, we are already on the kernel stack which we
304 * are going to use everytime we execute kernel code. We finish booting and we
307 bsp_finish_booting();
313 /*===========================================================================*
315 *===========================================================================*/
316 static void announce(void)
318 /* Display the MINIX startup banner. */
319 printf("\nMINIX %s.%s. "
321 "(" _VCS_REVISION
")\n"
323 "Copyright 2012, Vrije Universiteit, Amsterdam, The Netherlands\n",
324 OS_RELEASE
, OS_VERSION
);
325 printf("MINIX is open source software, see http://www.minix3.org\n");
328 /*===========================================================================*
330 *===========================================================================*/
331 void prepare_shutdown(const int how
)
333 /* This function prepares to shutdown MINIX. */
334 static timer_t shutdown_timer
;
336 /* Continue after 1 second, to give processes a chance to get scheduled to
337 * do shutdown work. Set a watchog timer to call shutdown(). The timer
338 * argument passes the shutdown status.
340 printf("MINIX will now be shut down ...\n");
341 tmr_arg(&shutdown_timer
)->ta_int
= how
;
342 set_timer(&shutdown_timer
, get_uptime() + system_hz
, minix_shutdown
);
345 /*===========================================================================*
347 *===========================================================================*/
348 void minix_shutdown(timer_t
*tp
)
350 /* This function is called from prepare_shutdown or stop_sequence to bring
351 * down MINIX. How to shutdown is in the argument: RBT_HALT (return to the
352 * monitor), RBT_RESET (hard reset).
358 * we will need to stop timers on all cpus if SMP is enabled and put them in
359 * such a state that we can perform the whole boot process once restarted from
365 hw_intr_disable_all();
367 arch_shutdown(tp
? tmr_arg(tp
)->ta_int
: RBT_PANIC
);
370 /*===========================================================================*
372 *===========================================================================*/
375 /* Perform system initializations prior to calling main(). Most settings are
376 * determined with help of the environment strings passed by MINIX' loader.
378 register char *value
; /* value in key=value pair */
381 /* low-level initialization */
384 /* determine verbosity */
385 if ((value
= env_get(VERBOSEBOOTVARNAME
)))
386 verboseboot
= atoi(value
);
388 /* Get clock tick frequency. */
389 value
= env_get("hz");
391 system_hz
= atoi(value
);
392 if(!value
|| system_hz
< 2 || system_hz
> 50000) /* sanity check */
393 system_hz
= DEFAULT_HZ
;
395 DEBUGEXTRA(("cstart\n"));
397 /* Record miscellaneous information for user-space servers. */
398 kinfo
.nr_procs
= NR_PROCS
;
399 kinfo
.nr_tasks
= NR_TASKS
;
400 strlcpy(kinfo
.release
, OS_RELEASE
, sizeof(kinfo
.release
));
401 strlcpy(kinfo
.version
, OS_VERSION
, sizeof(kinfo
.version
));
403 /* Load average data initialization. */
404 kloadinfo
.proc_last_slot
= 0;
405 for(h
= 0; h
< _LOAD_HISTORY
; h
++)
406 kloadinfo
.proc_load_history
[h
] = 0;
409 value
= env_get("no_apic");
411 config_no_apic
= atoi(value
);
414 value
= env_get("apic_timer_x");
416 config_apic_timer_x
= atoi(value
);
418 config_apic_timer_x
= 1;
422 value
= env_get("watchdog");
424 watchdog_enabled
= atoi(value
);
430 value
= env_get("no_smp");
432 config_no_smp
= atoi(value
);
436 DEBUGEXTRA(("intr_init(0)\n"));
443 /*===========================================================================*
445 *===========================================================================*/
448 const char *params
, /* boot monitor parameters */
449 const char *name
/* key to look up */
452 /* Get environment value - kernel version of getenv to avoid setting up the
453 * usual environment array.
455 register const char *namep
;
458 for (envp
= (char *) params
; *envp
!= 0;) {
459 for (namep
= name
; *namep
!= 0 && *namep
== *envp
; namep
++, envp
++)
461 if (*namep
== '\0' && *envp
== '=') return(envp
+ 1);
468 /*===========================================================================*
470 *===========================================================================*/
471 char *env_get(const char *name
)
473 return get_value(kinfo
.param_buf
, name
);
476 void cpu_print_freq(unsigned cpu
)
480 freq
= cpu_get_freq(cpu
);
481 printf("CPU %d freq %lu MHz\n", cpu
, div64u(freq
, 1000000));
486 return get_cpulocal_var(fpu_presence
);