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