1433d6423SLionel Sambuc /* This file contains the main program of MINIX as well as its shutdown code.
2433d6423SLionel Sambuc * The routine main() initializes the system and starts the ball rolling by
3433d6423SLionel Sambuc * setting up the process table, interrupt vectors, and scheduling each task
4433d6423SLionel Sambuc * to run to initialize itself.
5433d6423SLionel Sambuc * The routine shutdown() does the opposite and brings down MINIX.
6433d6423SLionel Sambuc *
7433d6423SLionel Sambuc * The entries into this file are:
8433d6423SLionel Sambuc * main: MINIX main program
9433d6423SLionel Sambuc * prepare_shutdown: prepare to take MINIX down
10433d6423SLionel Sambuc */
11433d6423SLionel Sambuc #include <string.h>
12433d6423SLionel Sambuc #include <stdlib.h>
13433d6423SLionel Sambuc #include <assert.h>
14433d6423SLionel Sambuc #include <minix/endpoint.h>
15433d6423SLionel Sambuc #include <machine/vmparam.h>
16433d6423SLionel Sambuc #include <minix/u64.h>
17433d6423SLionel Sambuc #include <minix/board.h>
18433d6423SLionel Sambuc #include <sys/reboot.h>
19433d6423SLionel Sambuc #include "clock.h"
20433d6423SLionel Sambuc #include "direct_utils.h"
21433d6423SLionel Sambuc #include "hw_intr.h"
22433d6423SLionel Sambuc #include "arch_proto.h"
23433d6423SLionel Sambuc
24433d6423SLionel Sambuc #ifdef CONFIG_SMP
25433d6423SLionel Sambuc #include "smp.h"
26433d6423SLionel Sambuc #endif
27433d6423SLionel Sambuc #ifdef USE_WATCHDOG
28433d6423SLionel Sambuc #include "watchdog.h"
29433d6423SLionel Sambuc #endif
30433d6423SLionel Sambuc #include "spinlock.h"
31433d6423SLionel Sambuc
32433d6423SLionel Sambuc /* dummy for linking */
33433d6423SLionel Sambuc char *** _penviron;
34433d6423SLionel Sambuc
35433d6423SLionel Sambuc /* Prototype declarations for PRIVATE functions. */
36433d6423SLionel Sambuc static void announce(void);
37433d6423SLionel Sambuc
bsp_finish_booting(void)38433d6423SLionel Sambuc void bsp_finish_booting(void)
39433d6423SLionel Sambuc {
40433d6423SLionel Sambuc int i;
41433d6423SLionel Sambuc #if SPROFILE
42433d6423SLionel Sambuc sprofiling = 0; /* we're not profiling until instructed to */
43433d6423SLionel Sambuc #endif /* SPROFILE */
44433d6423SLionel Sambuc
45433d6423SLionel Sambuc cpu_identify();
46433d6423SLionel Sambuc
47433d6423SLionel Sambuc vm_running = 0;
48433d6423SLionel Sambuc krandom.random_sources = RANDOM_SOURCES;
49433d6423SLionel Sambuc krandom.random_elements = RANDOM_ELEMENTS;
50433d6423SLionel Sambuc
51433d6423SLionel Sambuc /* MINIX is now ready. All boot image processes are on the ready queue.
52433d6423SLionel Sambuc * Return to the assembly code to start running the current process.
53433d6423SLionel Sambuc */
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc /* it should point somewhere */
56433d6423SLionel Sambuc get_cpulocal_var(bill_ptr) = get_cpulocal_var_ptr(idle_proc);
57433d6423SLionel Sambuc get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc);
58433d6423SLionel Sambuc announce(); /* print MINIX startup banner */
59433d6423SLionel Sambuc
60433d6423SLionel Sambuc /*
61433d6423SLionel Sambuc * we have access to the cpu local run queue, only now schedule the processes.
62433d6423SLionel Sambuc * We ignore the slots for the former kernel tasks
63433d6423SLionel Sambuc */
64433d6423SLionel Sambuc for (i=0; i < NR_BOOT_PROCS - NR_TASKS; i++) {
65433d6423SLionel Sambuc RTS_UNSET(proc_addr(i), RTS_PROC_STOP);
66433d6423SLionel Sambuc }
67433d6423SLionel Sambuc /*
68366d18b2SDavid van Moolenbroek * Enable timer interrupts and clock task on the boot CPU. First reset the
69366d18b2SDavid van Moolenbroek * CPU accounting values, as the timer initialization (indirectly) uses them.
70433d6423SLionel Sambuc */
71366d18b2SDavid van Moolenbroek cycles_accounting_init();
72366d18b2SDavid van Moolenbroek
73433d6423SLionel Sambuc if (boot_cpu_init_timer(system_hz)) {
74433d6423SLionel Sambuc panic("FATAL : failed to initialize timer interrupts, "
75433d6423SLionel Sambuc "cannot continue without any clock source!");
76433d6423SLionel Sambuc }
77433d6423SLionel Sambuc
78433d6423SLionel Sambuc fpu_init();
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc /* Warnings for sanity checks that take time. These warnings are printed
81433d6423SLionel Sambuc * so it's a clear warning no full release should be done with them
82433d6423SLionel Sambuc * enabled.
83433d6423SLionel Sambuc */
84433d6423SLionel Sambuc #if DEBUG_SCHED_CHECK
85433d6423SLionel Sambuc FIXME("DEBUG_SCHED_CHECK enabled");
86433d6423SLionel Sambuc #endif
87433d6423SLionel Sambuc #if DEBUG_VMASSERT
88433d6423SLionel Sambuc FIXME("DEBUG_VMASSERT enabled");
89433d6423SLionel Sambuc #endif
90433d6423SLionel Sambuc #if DEBUG_PROC_CHECK
91433d6423SLionel Sambuc FIXME("PROC check enabled");
92433d6423SLionel Sambuc #endif
93433d6423SLionel Sambuc
94433d6423SLionel Sambuc #ifdef CONFIG_SMP
95433d6423SLionel Sambuc cpu_set_flag(bsp_cpu_id, CPU_IS_READY);
96433d6423SLionel Sambuc machine.processors_count = ncpus;
97433d6423SLionel Sambuc machine.bsp_id = bsp_cpu_id;
98433d6423SLionel Sambuc #else
99433d6423SLionel Sambuc machine.processors_count = 1;
100433d6423SLionel Sambuc machine.bsp_id = 0;
101433d6423SLionel Sambuc #endif
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc /* Kernel may no longer use bits of memory as VM will be running soon */
105433d6423SLionel Sambuc kernel_may_alloc = 0;
106433d6423SLionel Sambuc
107433d6423SLionel Sambuc switch_to_user();
108433d6423SLionel Sambuc NOT_REACHABLE;
109433d6423SLionel Sambuc }
110433d6423SLionel Sambuc
111433d6423SLionel Sambuc
112433d6423SLionel Sambuc /*===========================================================================*
113433d6423SLionel Sambuc * kmain *
114433d6423SLionel Sambuc *===========================================================================*/
kmain(kinfo_t * local_cbi)115433d6423SLionel Sambuc void kmain(kinfo_t *local_cbi)
116433d6423SLionel Sambuc {
117433d6423SLionel Sambuc /* Start the ball rolling. */
118433d6423SLionel Sambuc struct boot_image *ip; /* boot image pointer */
119433d6423SLionel Sambuc register struct proc *rp; /* process pointer */
120433d6423SLionel Sambuc register int i, j;
121433d6423SLionel Sambuc static int bss_test;
122433d6423SLionel Sambuc
123433d6423SLionel Sambuc /* bss sanity check */
124433d6423SLionel Sambuc assert(bss_test == 0);
125433d6423SLionel Sambuc bss_test = 1;
126433d6423SLionel Sambuc
127433d6423SLionel Sambuc /* save a global copy of the boot parameters */
128433d6423SLionel Sambuc memcpy(&kinfo, local_cbi, sizeof(kinfo));
129433d6423SLionel Sambuc memcpy(&kmess, kinfo.kmess, sizeof(kmess));
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc /* We have done this exercise in pre_init so we expect this code
132433d6423SLionel Sambuc to simply work! */
133433d6423SLionel Sambuc machine.board_id = get_board_id_by_name(env_get(BOARDVARNAME));
134433d6423SLionel Sambuc #ifdef __arm__
135433d6423SLionel Sambuc /* We want to initialize serial before we do any output */
136433d6423SLionel Sambuc arch_ser_init();
137433d6423SLionel Sambuc #endif
138433d6423SLionel Sambuc /* We can talk now */
139da9af514SLionel Sambuc DEBUGBASIC(("MINIX booting\n"));
140433d6423SLionel Sambuc
141433d6423SLionel Sambuc /* Kernel may use bits of main memory before VM is started */
142433d6423SLionel Sambuc kernel_may_alloc = 1;
143433d6423SLionel Sambuc
144433d6423SLionel Sambuc assert(sizeof(kinfo.boot_procs) == sizeof(image));
145433d6423SLionel Sambuc memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs));
146433d6423SLionel Sambuc
147433d6423SLionel Sambuc cstart();
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc BKL_LOCK();
150433d6423SLionel Sambuc
151433d6423SLionel Sambuc DEBUGEXTRA(("main()\n"));
152433d6423SLionel Sambuc
153c8a9900bSCristiano Giuffrida /* Clear the process table. Anounce each slot as empty and set up mappings
154c8a9900bSCristiano Giuffrida * for proc_addr() and proc_nr() macros. Do the same for the table with
155c8a9900bSCristiano Giuffrida * privilege structures for the system processes and the ipc filter pool.
156c8a9900bSCristiano Giuffrida */
157433d6423SLionel Sambuc proc_init();
158c8a9900bSCristiano Giuffrida IPCF_POOL_INIT();
159433d6423SLionel Sambuc
160433d6423SLionel Sambuc if(NR_BOOT_MODULES != kinfo.mbi.mi_mods_count)
161433d6423SLionel Sambuc panic("expecting %d boot processes/modules, found %d",
162433d6423SLionel Sambuc NR_BOOT_MODULES, kinfo.mbi.mi_mods_count);
163433d6423SLionel Sambuc
164433d6423SLionel Sambuc /* Set up proc table entries for processes in boot image. */
165433d6423SLionel Sambuc for (i=0; i < NR_BOOT_PROCS; ++i) {
166433d6423SLionel Sambuc int schedulable_proc;
167433d6423SLionel Sambuc proc_nr_t proc_nr;
168433d6423SLionel Sambuc int ipc_to_m, kcalls;
169433d6423SLionel Sambuc sys_map_t map;
170433d6423SLionel Sambuc
171433d6423SLionel Sambuc ip = &image[i]; /* process' attributes */
172433d6423SLionel Sambuc DEBUGEXTRA(("initializing %s... ", ip->proc_name));
173433d6423SLionel Sambuc rp = proc_addr(ip->proc_nr); /* get process pointer */
174433d6423SLionel Sambuc ip->endpoint = rp->p_endpoint; /* ipc endpoint */
175433d6423SLionel Sambuc rp->p_cpu_time_left = 0;
176433d6423SLionel Sambuc if(i < NR_TASKS) /* name (tasks only) */
177433d6423SLionel Sambuc strlcpy(rp->p_name, ip->proc_name, sizeof(rp->p_name));
178433d6423SLionel Sambuc
179433d6423SLionel Sambuc if(i >= NR_TASKS) {
180433d6423SLionel Sambuc /* Remember this so it can be passed to VM */
181433d6423SLionel Sambuc multiboot_module_t *mb_mod = &kinfo.module_list[i - NR_TASKS];
182433d6423SLionel Sambuc ip->start_addr = mb_mod->mod_start;
183433d6423SLionel Sambuc ip->len = mb_mod->mod_end - mb_mod->mod_start;
184433d6423SLionel Sambuc }
185433d6423SLionel Sambuc
186433d6423SLionel Sambuc reset_proc_accounting(rp);
187433d6423SLionel Sambuc
188433d6423SLionel Sambuc /* See if this process is immediately schedulable.
189433d6423SLionel Sambuc * In that case, set its privileges now and allow it to run.
190433d6423SLionel Sambuc * Only kernel tasks and the root system process get to run immediately.
191433d6423SLionel Sambuc * All the other system processes are inhibited from running by the
192433d6423SLionel Sambuc * RTS_NO_PRIV flag. They can only be scheduled once the root system
193433d6423SLionel Sambuc * process has set their privileges.
194433d6423SLionel Sambuc */
195433d6423SLionel Sambuc proc_nr = proc_nr(rp);
196433d6423SLionel Sambuc schedulable_proc = (iskerneln(proc_nr) || isrootsysn(proc_nr) ||
197433d6423SLionel Sambuc proc_nr == VM_PROC_NR);
198433d6423SLionel Sambuc if(schedulable_proc) {
199433d6423SLionel Sambuc /* Assign privilege structure. Force a static privilege id. */
200433d6423SLionel Sambuc (void) get_priv(rp, static_priv_id(proc_nr));
201433d6423SLionel Sambuc
202433d6423SLionel Sambuc /* Privileges for kernel tasks. */
203433d6423SLionel Sambuc if(proc_nr == VM_PROC_NR) {
204433d6423SLionel Sambuc priv(rp)->s_flags = VM_F;
205433d6423SLionel Sambuc priv(rp)->s_trap_mask = SRV_T;
206433d6423SLionel Sambuc ipc_to_m = SRV_M;
207433d6423SLionel Sambuc kcalls = SRV_KC;
208433d6423SLionel Sambuc priv(rp)->s_sig_mgr = SELF;
209433d6423SLionel Sambuc rp->p_priority = SRV_Q;
210433d6423SLionel Sambuc rp->p_quantum_size_ms = SRV_QT;
211433d6423SLionel Sambuc }
212433d6423SLionel Sambuc else if(iskerneln(proc_nr)) {
213433d6423SLionel Sambuc /* Privilege flags. */
214433d6423SLionel Sambuc priv(rp)->s_flags = (proc_nr == IDLE ? IDL_F : TSK_F);
21576bf77a2SCristiano Giuffrida /* Init flags. */
21676bf77a2SCristiano Giuffrida priv(rp)->s_init_flags = TSK_I;
217433d6423SLionel Sambuc /* Allowed traps. */
218433d6423SLionel Sambuc priv(rp)->s_trap_mask = (proc_nr == CLOCK
219433d6423SLionel Sambuc || proc_nr == SYSTEM ? CSK_T : TSK_T);
220433d6423SLionel Sambuc ipc_to_m = TSK_M; /* allowed targets */
221433d6423SLionel Sambuc kcalls = TSK_KC; /* allowed kernel calls */
222433d6423SLionel Sambuc }
223433d6423SLionel Sambuc /* Privileges for the root system process. */
224433d6423SLionel Sambuc else {
225433d6423SLionel Sambuc assert(isrootsysn(proc_nr));
226433d6423SLionel Sambuc priv(rp)->s_flags= RSYS_F; /* privilege flags */
22776bf77a2SCristiano Giuffrida priv(rp)->s_init_flags = SRV_I; /* init flags */
228433d6423SLionel Sambuc priv(rp)->s_trap_mask= SRV_T; /* allowed traps */
229433d6423SLionel Sambuc ipc_to_m = SRV_M; /* allowed targets */
230433d6423SLionel Sambuc kcalls = SRV_KC; /* allowed kernel calls */
231433d6423SLionel Sambuc priv(rp)->s_sig_mgr = SRV_SM; /* signal manager */
232433d6423SLionel Sambuc rp->p_priority = SRV_Q; /* priority queue */
233433d6423SLionel Sambuc rp->p_quantum_size_ms = SRV_QT; /* quantum size */
234433d6423SLionel Sambuc }
235433d6423SLionel Sambuc
236433d6423SLionel Sambuc /* Fill in target mask. */
237433d6423SLionel Sambuc memset(&map, 0, sizeof(map));
238433d6423SLionel Sambuc
239433d6423SLionel Sambuc if (ipc_to_m == ALL_M) {
240433d6423SLionel Sambuc for(j = 0; j < NR_SYS_PROCS; j++)
241433d6423SLionel Sambuc set_sys_bit(map, j);
242433d6423SLionel Sambuc }
243433d6423SLionel Sambuc
244433d6423SLionel Sambuc fill_sendto_mask(rp, &map);
245433d6423SLionel Sambuc
246433d6423SLionel Sambuc /* Fill in kernel call mask. */
247433d6423SLionel Sambuc for(j = 0; j < SYS_CALL_MASK_SIZE; j++) {
248433d6423SLionel Sambuc priv(rp)->s_k_call_mask[j] = (kcalls == NO_C ? 0 : (~0));
249433d6423SLionel Sambuc }
250433d6423SLionel Sambuc }
251433d6423SLionel Sambuc else {
252433d6423SLionel Sambuc /* Don't let the process run for now. */
253433d6423SLionel Sambuc RTS_SET(rp, RTS_NO_PRIV | RTS_NO_QUANTUM);
254433d6423SLionel Sambuc }
255433d6423SLionel Sambuc
256433d6423SLionel Sambuc /* Arch-specific state initialization. */
257433d6423SLionel Sambuc arch_boot_proc(ip, rp);
258433d6423SLionel Sambuc
259433d6423SLionel Sambuc /* scheduling functions depend on proc_ptr pointing somewhere. */
260433d6423SLionel Sambuc if(!get_cpulocal_var(proc_ptr))
261433d6423SLionel Sambuc get_cpulocal_var(proc_ptr) = rp;
262433d6423SLionel Sambuc
263433d6423SLionel Sambuc /* Process isn't scheduled until VM has set up a pagetable for it. */
264433d6423SLionel Sambuc if(rp->p_nr != VM_PROC_NR && rp->p_nr >= 0) {
265433d6423SLionel Sambuc rp->p_rts_flags |= RTS_VMINHIBIT;
266433d6423SLionel Sambuc rp->p_rts_flags |= RTS_BOOTINHIBIT;
267433d6423SLionel Sambuc }
268433d6423SLionel Sambuc
269433d6423SLionel Sambuc rp->p_rts_flags |= RTS_PROC_STOP;
270433d6423SLionel Sambuc rp->p_rts_flags &= ~RTS_SLOT_FREE;
271433d6423SLionel Sambuc DEBUGEXTRA(("done\n"));
272433d6423SLionel Sambuc }
273433d6423SLionel Sambuc
274433d6423SLionel Sambuc /* update boot procs info for VM */
275433d6423SLionel Sambuc memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs));
276433d6423SLionel Sambuc
277433d6423SLionel Sambuc #define IPCNAME(n) { \
278433d6423SLionel Sambuc assert((n) >= 0 && (n) <= IPCNO_HIGHEST); \
279433d6423SLionel Sambuc assert(!ipc_call_names[n]); \
280433d6423SLionel Sambuc ipc_call_names[n] = #n; \
281433d6423SLionel Sambuc }
282433d6423SLionel Sambuc
283433d6423SLionel Sambuc arch_post_init();
284433d6423SLionel Sambuc
285433d6423SLionel Sambuc IPCNAME(SEND);
286433d6423SLionel Sambuc IPCNAME(RECEIVE);
287433d6423SLionel Sambuc IPCNAME(SENDREC);
288433d6423SLionel Sambuc IPCNAME(NOTIFY);
289433d6423SLionel Sambuc IPCNAME(SENDNB);
290433d6423SLionel Sambuc IPCNAME(SENDA);
291433d6423SLionel Sambuc
292433d6423SLionel Sambuc /* System and processes initialization */
293433d6423SLionel Sambuc memory_init();
294433d6423SLionel Sambuc DEBUGEXTRA(("system_init()... "));
295433d6423SLionel Sambuc system_init();
296433d6423SLionel Sambuc DEBUGEXTRA(("done\n"));
297433d6423SLionel Sambuc
298433d6423SLionel Sambuc /* The bootstrap phase is over, so we can add the physical
299433d6423SLionel Sambuc * memory used for it to the free list.
300433d6423SLionel Sambuc */
301433d6423SLionel Sambuc add_memmap(&kinfo, kinfo.bootstrap_start, kinfo.bootstrap_len);
302433d6423SLionel Sambuc
303433d6423SLionel Sambuc #ifdef CONFIG_SMP
304433d6423SLionel Sambuc if (config_no_apic) {
305da9af514SLionel Sambuc DEBUGBASIC(("APIC disabled, disables SMP, using legacy PIC\n"));
306433d6423SLionel Sambuc smp_single_cpu_fallback();
307433d6423SLionel Sambuc } else if (config_no_smp) {
308da9af514SLionel Sambuc DEBUGBASIC(("SMP disabled, using legacy PIC\n"));
309433d6423SLionel Sambuc smp_single_cpu_fallback();
310433d6423SLionel Sambuc } else {
311433d6423SLionel Sambuc smp_init();
312433d6423SLionel Sambuc /*
313433d6423SLionel Sambuc * if smp_init() returns it means that it failed and we try to finish
314433d6423SLionel Sambuc * single CPU booting
315433d6423SLionel Sambuc */
316433d6423SLionel Sambuc bsp_finish_booting();
317433d6423SLionel Sambuc }
318433d6423SLionel Sambuc #else
319433d6423SLionel Sambuc /*
320433d6423SLionel Sambuc * if configured for a single CPU, we are already on the kernel stack which we
321433d6423SLionel Sambuc * are going to use everytime we execute kernel code. We finish booting and we
322433d6423SLionel Sambuc * never return here
323433d6423SLionel Sambuc */
324433d6423SLionel Sambuc bsp_finish_booting();
325433d6423SLionel Sambuc #endif
326433d6423SLionel Sambuc
327433d6423SLionel Sambuc NOT_REACHABLE;
328433d6423SLionel Sambuc }
329433d6423SLionel Sambuc
330433d6423SLionel Sambuc /*===========================================================================*
331433d6423SLionel Sambuc * announce *
332433d6423SLionel Sambuc *===========================================================================*/
announce(void)333433d6423SLionel Sambuc static void announce(void)
334433d6423SLionel Sambuc {
335433d6423SLionel Sambuc /* Display the MINIX startup banner. */
336433d6423SLionel Sambuc printf("\nMINIX %s. "
337bf609e10Srlfnb #ifdef PAE
338bf609e10Srlfnb "(PAE) "
339bf609e10Srlfnb #endif
340433d6423SLionel Sambuc #ifdef _VCS_REVISION
341433d6423SLionel Sambuc "(" _VCS_REVISION ")\n"
342433d6423SLionel Sambuc #endif
3434cb315c4SJacob Adams "Copyright 2016, Vrije Universiteit, Amsterdam, The Netherlands\n",
344433d6423SLionel Sambuc OS_RELEASE);
345433d6423SLionel Sambuc printf("MINIX is open source software, see http://www.minix3.org\n");
346433d6423SLionel Sambuc }
347433d6423SLionel Sambuc
348433d6423SLionel Sambuc /*===========================================================================*
349433d6423SLionel Sambuc * prepare_shutdown *
350433d6423SLionel Sambuc *===========================================================================*/
prepare_shutdown(const int how)351433d6423SLionel Sambuc void prepare_shutdown(const int how)
352433d6423SLionel Sambuc {
353433d6423SLionel Sambuc /* This function prepares to shutdown MINIX. */
354433d6423SLionel Sambuc static minix_timer_t shutdown_timer;
355433d6423SLionel Sambuc
356433d6423SLionel Sambuc /* Continue after 1 second, to give processes a chance to get scheduled to
357433d6423SLionel Sambuc * do shutdown work. Set a watchog timer to call shutdown(). The timer
358433d6423SLionel Sambuc * argument passes the shutdown status.
359433d6423SLionel Sambuc */
360433d6423SLionel Sambuc printf("MINIX will now be shut down ...\n");
361*cfd712b4SDavid van Moolenbroek set_kernel_timer(&shutdown_timer, get_monotonic() + system_hz,
362*cfd712b4SDavid van Moolenbroek minix_shutdown, how);
363433d6423SLionel Sambuc }
364433d6423SLionel Sambuc
365433d6423SLionel Sambuc /*===========================================================================*
366433d6423SLionel Sambuc * shutdown *
367433d6423SLionel Sambuc *===========================================================================*/
minix_shutdown(int how)368*cfd712b4SDavid van Moolenbroek void minix_shutdown(int how)
369433d6423SLionel Sambuc {
370433d6423SLionel Sambuc /* This function is called from prepare_shutdown or stop_sequence to bring
371433d6423SLionel Sambuc * down MINIX.
372433d6423SLionel Sambuc */
373433d6423SLionel Sambuc
374433d6423SLionel Sambuc #ifdef CONFIG_SMP
375433d6423SLionel Sambuc /*
376433d6423SLionel Sambuc * FIXME
377433d6423SLionel Sambuc *
378433d6423SLionel Sambuc * we will need to stop timers on all cpus if SMP is enabled and put them in
379433d6423SLionel Sambuc * such a state that we can perform the whole boot process once restarted from
380433d6423SLionel Sambuc * monitor again
381433d6423SLionel Sambuc */
382433d6423SLionel Sambuc if (ncpus > 1)
383433d6423SLionel Sambuc smp_shutdown_aps();
384433d6423SLionel Sambuc #endif
385433d6423SLionel Sambuc hw_intr_disable_all();
386433d6423SLionel Sambuc stop_local_timer();
387433d6423SLionel Sambuc
388433d6423SLionel Sambuc /* Show shutdown message */
389433d6423SLionel Sambuc direct_cls();
390433d6423SLionel Sambuc if((how & RB_POWERDOWN) == RB_POWERDOWN)
391433d6423SLionel Sambuc direct_print("MINIX has halted and will now power off.\n");
392433d6423SLionel Sambuc else if(how & RB_HALT)
393433d6423SLionel Sambuc direct_print("MINIX has halted. "
394433d6423SLionel Sambuc "It is safe to turn off your computer.\n");
395433d6423SLionel Sambuc else
396433d6423SLionel Sambuc direct_print("MINIX will now reset.\n");
397433d6423SLionel Sambuc arch_shutdown(how);
398433d6423SLionel Sambuc }
399433d6423SLionel Sambuc
400433d6423SLionel Sambuc /*===========================================================================*
401433d6423SLionel Sambuc * cstart *
402433d6423SLionel Sambuc *===========================================================================*/
cstart(void)4036077d1adSDr. Florian Grätz void cstart(void)
404433d6423SLionel Sambuc {
405433d6423SLionel Sambuc /* Perform system initializations prior to calling main(). Most settings are
406433d6423SLionel Sambuc * determined with help of the environment strings passed by MINIX' loader.
407433d6423SLionel Sambuc */
408433d6423SLionel Sambuc register char *value; /* value in key=value pair */
409433d6423SLionel Sambuc
410433d6423SLionel Sambuc /* low-level initialization */
411433d6423SLionel Sambuc prot_init();
412433d6423SLionel Sambuc
413433d6423SLionel Sambuc /* determine verbosity */
414433d6423SLionel Sambuc if ((value = env_get(VERBOSEBOOTVARNAME)))
415433d6423SLionel Sambuc verboseboot = atoi(value);
416433d6423SLionel Sambuc
417d91f738bSDavid van Moolenbroek /* Initialize clock variables. */
418d91f738bSDavid van Moolenbroek init_clock();
419433d6423SLionel Sambuc
42053398d73SCristiano Giuffrida /* Get memory parameters. */
42153398d73SCristiano Giuffrida value = env_get("ac_layout");
42253398d73SCristiano Giuffrida if(value && atoi(value)) {
42353398d73SCristiano Giuffrida kinfo.user_sp = (vir_bytes) USR_STACKTOP_COMPACT;
42453398d73SCristiano Giuffrida kinfo.user_end = (vir_bytes) USR_DATATOP_COMPACT;
42553398d73SCristiano Giuffrida }
42653398d73SCristiano Giuffrida
427433d6423SLionel Sambuc DEBUGEXTRA(("cstart\n"));
428433d6423SLionel Sambuc
429433d6423SLionel Sambuc /* Record miscellaneous information for user-space servers. */
430433d6423SLionel Sambuc kinfo.nr_procs = NR_PROCS;
431433d6423SLionel Sambuc kinfo.nr_tasks = NR_TASKS;
432433d6423SLionel Sambuc strlcpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
433433d6423SLionel Sambuc strlcpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
434433d6423SLionel Sambuc
43526f5c8f8SDavid van Moolenbroek /* Initialize various user-mapped structures. */
43626f5c8f8SDavid van Moolenbroek memset(&arm_frclock, 0, sizeof(arm_frclock));
43726f5c8f8SDavid van Moolenbroek
43820054ae9SDavid van Moolenbroek memset(&kuserinfo, 0, sizeof(kuserinfo));
43920054ae9SDavid van Moolenbroek kuserinfo.kui_size = sizeof(kuserinfo);
44020054ae9SDavid van Moolenbroek kuserinfo.kui_user_sp = kinfo.user_sp;
44120054ae9SDavid van Moolenbroek
442433d6423SLionel Sambuc #ifdef USE_APIC
443433d6423SLionel Sambuc value = env_get("no_apic");
444433d6423SLionel Sambuc if(value)
445433d6423SLionel Sambuc config_no_apic = atoi(value);
446433d6423SLionel Sambuc else
447433d6423SLionel Sambuc config_no_apic = 1;
448433d6423SLionel Sambuc value = env_get("apic_timer_x");
449433d6423SLionel Sambuc if(value)
450433d6423SLionel Sambuc config_apic_timer_x = atoi(value);
451433d6423SLionel Sambuc else
452433d6423SLionel Sambuc config_apic_timer_x = 1;
453433d6423SLionel Sambuc #endif
454433d6423SLionel Sambuc
455433d6423SLionel Sambuc #ifdef USE_WATCHDOG
456433d6423SLionel Sambuc value = env_get("watchdog");
457433d6423SLionel Sambuc if (value)
458433d6423SLionel Sambuc watchdog_enabled = atoi(value);
459433d6423SLionel Sambuc #endif
460433d6423SLionel Sambuc
461433d6423SLionel Sambuc #ifdef CONFIG_SMP
462433d6423SLionel Sambuc if (config_no_apic)
463433d6423SLionel Sambuc config_no_smp = 1;
464433d6423SLionel Sambuc value = env_get("no_smp");
465433d6423SLionel Sambuc if(value)
466433d6423SLionel Sambuc config_no_smp = atoi(value);
467433d6423SLionel Sambuc else
468433d6423SLionel Sambuc config_no_smp = 0;
469433d6423SLionel Sambuc #endif
470433d6423SLionel Sambuc DEBUGEXTRA(("intr_init(0)\n"));
471433d6423SLionel Sambuc
472433d6423SLionel Sambuc intr_init(0);
473433d6423SLionel Sambuc
474433d6423SLionel Sambuc arch_init();
475433d6423SLionel Sambuc }
476433d6423SLionel Sambuc
477433d6423SLionel Sambuc /*===========================================================================*
478433d6423SLionel Sambuc * get_value *
479433d6423SLionel Sambuc *===========================================================================*/
480433d6423SLionel Sambuc
get_value(const char * params,const char * name)481433d6423SLionel Sambuc char *get_value(
482433d6423SLionel Sambuc const char *params, /* boot monitor parameters */
483433d6423SLionel Sambuc const char *name /* key to look up */
484433d6423SLionel Sambuc )
485433d6423SLionel Sambuc {
486433d6423SLionel Sambuc /* Get environment value - kernel version of getenv to avoid setting up the
487433d6423SLionel Sambuc * usual environment array.
488433d6423SLionel Sambuc */
489433d6423SLionel Sambuc register const char *namep;
490433d6423SLionel Sambuc register char *envp;
491433d6423SLionel Sambuc
492433d6423SLionel Sambuc for (envp = (char *) params; *envp != 0;) {
493433d6423SLionel Sambuc for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
494433d6423SLionel Sambuc ;
495433d6423SLionel Sambuc if (*namep == '\0' && *envp == '=') return(envp + 1);
496433d6423SLionel Sambuc while (*envp++ != 0)
497433d6423SLionel Sambuc ;
498433d6423SLionel Sambuc }
499433d6423SLionel Sambuc return(NULL);
500433d6423SLionel Sambuc }
501433d6423SLionel Sambuc
502433d6423SLionel Sambuc /*===========================================================================*
503433d6423SLionel Sambuc * env_get *
504433d6423SLionel Sambuc *===========================================================================*/
env_get(const char * name)505433d6423SLionel Sambuc char *env_get(const char *name)
506433d6423SLionel Sambuc {
507433d6423SLionel Sambuc return get_value(kinfo.param_buf, name);
508433d6423SLionel Sambuc }
509433d6423SLionel Sambuc
cpu_print_freq(unsigned cpu)510433d6423SLionel Sambuc void cpu_print_freq(unsigned cpu)
511433d6423SLionel Sambuc {
512433d6423SLionel Sambuc u64_t freq;
513433d6423SLionel Sambuc
514433d6423SLionel Sambuc freq = cpu_get_freq(cpu);
515da9af514SLionel Sambuc DEBUGBASIC(("CPU %d freq %lu MHz\n", cpu, (unsigned long)(freq / 1000000)));
516433d6423SLionel Sambuc }
517433d6423SLionel Sambuc
is_fpu(void)518433d6423SLionel Sambuc int is_fpu(void)
519433d6423SLionel Sambuc {
520433d6423SLionel Sambuc return get_cpulocal_var(fpu_presence);
521433d6423SLionel Sambuc }
522433d6423SLionel Sambuc
523