FreeBSD/Linux Kernel Cross Reference
sys/kern/startup.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990,1989,1988 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: startup.c,v $
29 * Revision 2.27 93/11/17 17:24:45 dbg
30 * Remove ancient timestamp facility.
31 * [93/06/18 dbg]
32 *
33 * Remove call to mapable_time_init.
34 * [93/06/07 dbg]
35 *
36 * Break up thread lock.
37 * [93/05/26 dbg]
38 *
39 * Declare continuations as returning 'no_return'.
40 * Call idle_thread_create to build idle threads.
41 * Call kernel_reply_kmsg_init.
42 * Initialize system clock after finding devices, since we now
43 * probe for the clock.
44 * Changes for selectable scheduler policies.
45 * [93/05/21 dbg]
46 *
47 * Revision 2.26 93/05/15 18:55:03 mrt
48 * machparam.h -> machspl.h
49 *
50 * Revision 2.25 93/01/14 17:36:31 danner
51 * Invoke printf_init() for multiP interlock setup.
52 * [92/12/01 af]
53 *
54 * Revision 2.24 92/08/03 17:39:15 jfriedl
55 * removed silly prototypes
56 * [92/08/02 jfriedl]
57 *
58 * Revision 2.23 92/05/21 17:15:47 jfriedl
59 * tried prototypes.
60 * [92/05/20 jfriedl]
61 *
62 * Revision 2.22 92/01/27 16:43:18 rpd
63 * Fixed to finish vm/ipc initialization before calling machine_init.
64 * [92/01/25 rpd]
65 *
66 * Revision 2.21 92/01/14 16:44:57 rpd
67 * Split vm_mem_init into vm_mem_bootstrap and vm_mem_init.
68 * [91/12/29 rpd]
69 *
70 * Revision 2.20 91/09/12 16:38:00 bohman
71 * Changed launch_first_thread() to set active_stacks[] before
72 * starting the first thread.
73 * [91/09/11 17:08:23 bohman]
74 *
75 * Revision 2.19 91/08/28 11:14:37 jsb
76 * Start NORMA ipc and vm systems before user bootstrap.
77 * [91/08/15 08:33:05 jsb]
78 *
79 * Revision 2.18 91/08/03 18:18:59 jsb
80 * Changed NORMA specific startup again.
81 * [91/07/24 22:32:51 jsb]
82 *
83 * Revision 2.17 91/07/31 17:48:00 dbg
84 * Remove interrupt_stack_alloc - not all multiprocessors use it.
85 *
86 * Revised scheduling state machine.
87 * [91/07/30 17:05:11 dbg]
88 *
89 * Revision 2.16 91/06/17 15:47:15 jsb
90 * Renamed NORMA conditionals.
91 * [91/06/17 10:51:38 jsb]
92 *
93 * Revision 2.15 91/06/06 17:07:27 jsb
94 * Changed NORMA_IPC specific startup.
95 * [91/05/14 09:19:55 jsb]
96 *
97 * Revision 2.14 91/05/18 14:33:30 rpd
98 * Added argument to kernel_thread.
99 * [91/04/03 rpd]
100 *
101 * Revision 2.13 91/05/14 16:47:00 mrt
102 * Correcting copyright
103 *
104 * Revision 2.12 91/03/16 14:51:45 rpd
105 * Updated for new kmem_alloc interface.
106 * [91/03/03 rpd]
107 * Removed thread_swappable.
108 * [91/01/18 rpd]
109 *
110 * Revision 2.11 91/02/05 17:29:18 mrt
111 * Changed to new Mach copyright
112 * [91/02/01 16:17:40 mrt]
113 *
114 * Revision 2.10 91/01/08 15:17:00 rpd
115 * Swapin the startup thread and idle threads.
116 * [90/11/20 rpd]
117 *
118 * Removed swapout_thread.
119 * [90/11/11 rpd]
120 *
121 * Revision 2.9 90/10/12 18:07:34 rpd
122 * Fixed call to thread_bind in start_kernel_threads.
123 * Fix from Philippe Bernadat.
124 * [90/10/10 rpd]
125 *
126 * Revision 2.8 90/09/28 16:55:37 jsb
127 * Added NORMA_IPC support.
128 * [90/09/28 14:05:00 jsb]
129 *
130 * Revision 2.7 90/09/09 14:32:47 rpd
131 * Fixed setup_main to call pset_sys_init.
132 * [90/08/30 rpd]
133 *
134 * Revision 2.6 90/08/27 22:03:40 dbg
135 * Pass processor argument to choose_thread.
136 * Rename cpu_start to cpu_launch_first_thread to avoid conflict
137 * with processor code.
138 * [90/07/17 dbg]
139 *
140 * Revision 2.5 90/06/02 14:56:12 rpd
141 * Start sched_thread. On multiprocessors, start action_thread
142 * instead of shutdown_thread.
143 * [90/04/28 rpd]
144 * Updated to new scheduling technology.
145 * [90/03/26 22:19:00 rpd]
146 *
147 * Revision 2.4 90/01/11 11:44:11 dbg
148 * If multiprocessor, start shutdown thread. If uniprocessor,
149 * don't allocate interrupt stacks.
150 * [89/12/19 dbg]
151 *
152 * Add call to start other CPUs if multiprocessor.
153 * [89/12/01 dbg]
154 *
155 * Revision 2.3 89/09/08 11:26:32 dbg
156 * Move kalloc initialization to vm_init.
157 * [89/09/06 dbg]
158 *
159 * Move bootstrap initialization to kern/bootstrap.c. Initialize
160 * device service here.
161 * [89/08/02 dbg]
162 *
163 * Initialize kalloc package.
164 * [89/07/11 dbg]
165 *
166 * Revision 2.2 89/08/05 16:07:22 rwd
167 * Call mappable_time_init.
168 * [89/08/04 18:31:35 rwd]
169 *
170 * 23-May-89 David Golub (dbg) at Carnegie-Mellon University
171 * Thread creation must be done by a running thread;
172 * thread_setrun (called by thread_resume & kernel_thread) may look
173 * at current thread.
174 *
175 * 19-May-89 David Golub (dbg) at Carnegie-Mellon University
176 * Don't export first_task and first_thread; they don't last very
177 * long.
178 *
179 * 15-Aug-88 David Golub (dbg) at Carnegie-Mellon University
180 * Initial threads are now part of the kernel task, not first-task.
181 * Create the bootstrap task as a kernel task.
182 *
183 * 8-Aug-88 David Golub (dbg) at Carnegie-Mellon University
184 * Modified for stand-alone MACH kernel.
185 *
186 * 1-Jul-88 David Golub (dbg) at Carnegie-Mellon University
187 * Created.
188 *
189 */
190
191 /*
192 * Mach kernel startup.
193 */
194
195
196 #include <xpr_debug.h>
197 #include <cpus.h>
198 #include <mach_host.h>
199 #include <norma_ipc.h>
200 #include <norma_vm.h>
201
202 #include <mach/boolean.h>
203 #include <mach/machine.h>
204 #include <mach/task_special_ports.h>
205 #include <mach/vm_param.h>
206
207 #include <ipc/ipc_init.h>
208
209 #include <kern/clock.h>
210 #include <kern/cpu_number.h>
211 #include <kern/kern_io.h>
212 #include <kern/kern_kmsg.h>
213 #include <kern/mach_timer.h>
214 #include <kern/machine.h>
215 #include <kern/processor.h>
216 #include <kern/sched.h>
217 #include <kern/sched_prim.h>
218 #include <kern/task.h>
219 #include <kern/thread.h>
220 #include <kern/thread_swap.h>
221 #include <kern/time_out.h>
222 #include <kern/timer.h>
223 #include <kern/xpr.h>
224 #include <kern/zalloc.h>
225
226 #include <sched_policy/standard.h>
227
228 #include <vm/vm_kern.h>
229 #include <vm/vm_map.h>
230 #include <vm/vm_object.h>
231 #include <vm/vm_page.h>
232 #include <machine/machspl.h>
233 #include <machine/pmap.h>
234 #include <sys/version.h>
235
236
237 /*
238 * Initialization routines in various subsystems.
239 */
240
241 extern void vm_mem_init(void);
242 extern void vm_mem_bootstrap(void);
243
244 extern no_return idle_thread(void);
245 extern no_return vm_pageout(void);
246 extern no_return reaper_thread(void);
247 extern no_return swapin_thread(void);
248
249 extern void bootstrap_create(void);
250 extern void device_service_create(void);
251 extern void idle_thread_create(processor_t);
252
253 no_return cpu_launch_first_thread(thread_t); /* forward */
254 no_return start_kernel_threads(void); /* forward */
255
256 extern no_return load_context(thread_t);
257
258 /*
259 * Running in virtual memory, on the interrupt stack.
260 * Does not return. Dispatches initial thread.
261 *
262 * Assumes that master_cpu is set.
263 */
264 no_return setup_main(void)
265 {
266 thread_t startup_thread;
267
268 /*
269 * Allow printing and panics
270 */
271 printf_init();
272 panic_init();
273
274 /*
275 * Get VM running as soon as possible
276 */
277 vm_mem_bootstrap(); /* can do 'zinit' now */
278
279 /*
280 * Initialize the low-level scheduling packages
281 */
282 sched_init();
283 ast_init();
284 #if NCPUS > 1
285 action_thread_init(); /* action queue */
286 #endif
287
288 /*
289 * Initialize packages that need VM and zones
290 */
291 sched_policy_init(); /* set up scheduling policies */
292 pset_sys_bootstrap(); /* first pset: needs scheduling
293 policies and quanta */
294 ipc_bootstrap(); /* IPC system */
295
296 /*
297 * Initialize packages that need IPC ports
298 */
299 vm_mem_init(); /* rest of VM - needs IPC */
300 ipc_init(); /* rest of IPC - needs full VM */
301 kernel_reply_kmsg_init(); /* kernel reply messages */
302
303 /*
304 * As soon as the virtual memory system is up, we record
305 * that this CPU is using the kernel pmap.
306 */
307 PMAP_ACTIVATE_KERNEL(master_cpu);
308
309 /*
310 * Set up all of the timers
311 */
312 init_timers(); /* internal timers */
313 mach_timer_init(); /* user-visible timers */
314
315 #if XPR_DEBUG
316 xprbootstrap();
317 #endif /* XPR_DEBUG */
318
319 /*
320 * Call machine-dependent initialization.
321 * This configures devices, among other things.
322 */
323 machine_init();
324
325 machine_info.max_cpus = NCPUS;
326 machine_info.memory_size = mem_size;
327 machine_info.avail_cpus = 0;
328 machine_info.major_version = KERNEL_MAJOR_VERSION;
329 machine_info.minor_version = KERNEL_MINOR_VERSION;
330
331 /*
332 * Initialize the task, thread, and processor set subsystems.
333 */
334 task_init();
335 thread_init();
336 swapper_init();
337 #if MACH_HOST
338 pset_sys_init();
339 #endif /* MACH_HOST */
340
341 /*
342 * Initialize the periodic scheduling calculations.
343 */
344 init_sched_calculations();
345
346 /*
347 * Create a kernel thread to start the other kernel
348 * threads. Thread_resume (from kernel_thread) calls
349 * thread_setrun, which may look at current thread;
350 * we must avoid this, since there is no current thread.
351 */
352
353 /*
354 * Enable the fixed priority policy on the default
355 * processor set.
356 */
357 (void) processor_set_policy_add(&default_pset, POLICY_FIXEDPRI,
358 0, 0);
359
360 /*
361 * Set fixed-priority as the default for the
362 * kernel task.
363 */
364 {
365 struct policy_param_fixedpri param;
366
367 param.priority = FP_BASEPRI_SYSTEM;
368 param.no_preempt = TRUE;
369
370 (void) task_set_default_policy(kernel_task, &default_pset,
371 POLICY_FIXEDPRI,
372 (policy_param_t)¶m,
373 POLICY_PARAM_FIXEDPRI_COUNT,
374 FALSE);
375 }
376
377 /*
378 * Create the thread, and point it at the routine.
379 */
380 (void) thread_create(kernel_task, &startup_thread);
381 thread_start(startup_thread, start_kernel_threads);
382
383 /*
384 * Give it a kernel stack.
385 */
386 thread_doswapin(startup_thread);
387
388 /*
389 * Pretend it is already running, and resume it.
390 * Since it looks as if it is running, thread_resume
391 * will not try to put it on the run queues.
392 *
393 * We can do all of this without locking, because nothing
394 * else is running yet.
395 */
396 startup_thread->state |= TH_RUN;
397 (void) thread_resume(startup_thread);
398
399 /*
400 * Start the thread.
401 */
402 cpu_launch_first_thread(startup_thread);
403 /*NOTREACHED*/
404 }
405
406 /*
407 * Now running in a thread. Create the rest of the kernel threads
408 * and the bootstrap task.
409 */
410 no_return start_kernel_threads(void)
411 {
412 register int i;
413
414 /*
415 * Create the idle threads and the other
416 * service threads.
417 */
418 for (i = 0; i < NCPUS; i++) {
419 if (machine_slot[i].is_cpu) {
420 idle_thread_create(cpu_to_processor(i));
421 }
422 }
423
424 (void) kernel_thread(kernel_task, reaper_thread, (char *) 0);
425 (void) kernel_thread(kernel_task, swapin_thread, (char *) 0);
426
427 #if NCPUS > 1
428 /*
429 * Create the shutdown thread.
430 */
431 (void) kernel_thread(kernel_task, action_thread, (char *) 0);
432
433 /*
434 * Allow other CPUs to run.
435 */
436 start_other_cpus();
437 #endif /* NCPUS > 1 */
438
439 /*
440 * Create the device service.
441 */
442 device_service_create();
443
444 /*
445 * Initialize NORMA ipc system.
446 */
447 #if NORMA_IPC
448 norma_ipc_init();
449 #endif /* NORMA_IPC */
450
451 /*
452 * Initialize NORMA vm system.
453 */
454 #if NORMA_VM
455 norma_vm_init();
456 #endif /* NORMA_VM */
457
458 /*
459 * Start the user bootstrap.
460 */
461 bootstrap_create();
462
463 #if XPR_DEBUG
464 xprinit(); /* XXX */
465 #endif /* XPR_DEBUG */
466
467 /*
468 * Become the pageout daemon.
469 */
470 (void) spl0();
471 vm_pageout();
472 /*NOTREACHED*/
473 }
474
475 #if NCPUS > 1
476
477 /*
478 * Do system initialization for other processors.
479 */
480 no_return slave_main(void)
481 {
482 /*
483 * Do machine_specific initialization.
484 */
485 slave_machine_init();
486
487 /*
488 * Run the processor`s idle thread first.
489 */
490 cpu_launch_first_thread(current_processor()->idle_thread);
491 }
492 #endif /* NCPUS > 1 */
493
494 /*
495 * Start up the first thread on a CPU.
496 * First thread is supplied.
497 */
498 no_return cpu_launch_first_thread(
499 register thread_t th)
500 {
501 register int mycpu;
502
503 mycpu = cpu_number();
504
505 cpu_up(mycpu);
506
507 start_timer(&kernel_timer[mycpu]);
508
509 (void) splhigh();
510
511 enable_clock_interrupts(); /* needs an active thread */
512 PMAP_ACTIVATE_KERNEL(mycpu);
513
514 active_threads[mycpu] = th;
515 active_stacks[mycpu] = th->kernel_stack;
516 thread_sched_lock(th);
517 th->state &= ~TH_UNINT;
518 thread_sched_unlock(th);
519 timer_switch(&th->system_timer);
520
521 PMAP_ACTIVATE_USER(vm_map_pmap(th->task->map), th, mycpu);
522
523 load_context(th);
524 /*NOTREACHED*/
525 }
Cache object: 31d3cf70ddacc838e9337da07e46ff5d
|