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