FreeBSD/Linux Kernel Cross Reference
sys/kern/startup.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 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.26 93/05/15 18:55:03 mrt
30 * machparam.h -> machspl.h
31 *
32 * Revision 2.25 93/01/14 17:36:31 danner
33 * Invoke printf_init() for multiP interlock setup.
34 * [92/12/01 af]
35 *
36 * Revision 2.24 92/08/03 17:39:15 jfriedl
37 * removed silly prototypes
38 * [92/08/02 jfriedl]
39 *
40 * Revision 2.23 92/05/21 17:15:47 jfriedl
41 * tried prototypes.
42 * [92/05/20 jfriedl]
43 *
44 * Revision 2.22 92/01/27 16:43:18 rpd
45 * Fixed to finish vm/ipc initialization before calling machine_init.
46 * [92/01/25 rpd]
47 *
48 * Revision 2.21 92/01/14 16:44:57 rpd
49 * Split vm_mem_init into vm_mem_bootstrap and vm_mem_init.
50 * [91/12/29 rpd]
51 *
52 * Revision 2.20 91/09/12 16:38:00 bohman
53 * Changed launch_first_thread() to set active_stacks[] before
54 * starting the first thread.
55 * [91/09/11 17:08:23 bohman]
56 *
57 * Revision 2.19 91/08/28 11:14:37 jsb
58 * Start NORMA ipc and vm systems before user bootstrap.
59 * [91/08/15 08:33:05 jsb]
60 *
61 * Revision 2.18 91/08/03 18:18:59 jsb
62 * Changed NORMA specific startup again.
63 * [91/07/24 22:32:51 jsb]
64 *
65 * Revision 2.17 91/07/31 17:48:00 dbg
66 * Remove interrupt_stack_alloc - not all multiprocessors use it.
67 *
68 * Revised scheduling state machine.
69 * [91/07/30 17:05:11 dbg]
70 *
71 * Revision 2.16 91/06/17 15:47:15 jsb
72 * Renamed NORMA conditionals.
73 * [91/06/17 10:51:38 jsb]
74 *
75 * Revision 2.15 91/06/06 17:07:27 jsb
76 * Changed NORMA_IPC specific startup.
77 * [91/05/14 09:19:55 jsb]
78 *
79 * Revision 2.14 91/05/18 14:33:30 rpd
80 * Added argument to kernel_thread.
81 * [91/04/03 rpd]
82 *
83 * Revision 2.13 91/05/14 16:47:00 mrt
84 * Correcting copyright
85 *
86 * Revision 2.12 91/03/16 14:51:45 rpd
87 * Updated for new kmem_alloc interface.
88 * [91/03/03 rpd]
89 * Removed thread_swappable.
90 * [91/01/18 rpd]
91 *
92 * Revision 2.11 91/02/05 17:29:18 mrt
93 * Changed to new Mach copyright
94 * [91/02/01 16:17:40 mrt]
95 *
96 * Revision 2.10 91/01/08 15:17:00 rpd
97 * Swapin the startup thread and idle threads.
98 * [90/11/20 rpd]
99 *
100 * Removed swapout_thread.
101 * [90/11/11 rpd]
102 *
103 * Revision 2.9 90/10/12 18:07:34 rpd
104 * Fixed call to thread_bind in start_kernel_threads.
105 * Fix from Philippe Bernadat.
106 * [90/10/10 rpd]
107 *
108 * Revision 2.8 90/09/28 16:55:37 jsb
109 * Added NORMA_IPC support.
110 * [90/09/28 14:05:00 jsb]
111 *
112 * Revision 2.7 90/09/09 14:32:47 rpd
113 * Fixed setup_main to call pset_sys_init.
114 * [90/08/30 rpd]
115 *
116 * Revision 2.6 90/08/27 22:03:40 dbg
117 * Pass processor argument to choose_thread.
118 * Rename cpu_start to cpu_launch_first_thread to avoid conflict
119 * with processor code.
120 * [90/07/17 dbg]
121 *
122 * Revision 2.5 90/06/02 14:56:12 rpd
123 * Start sched_thread. On multiprocessors, start action_thread
124 * instead of shutdown_thread.
125 * [90/04/28 rpd]
126 * Updated to new scheduling technology.
127 * [90/03/26 22:19:00 rpd]
128 *
129 * Revision 2.4 90/01/11 11:44:11 dbg
130 * If multiprocessor, start shutdown thread. If uniprocessor,
131 * don't allocate interrupt stacks.
132 * [89/12/19 dbg]
133 *
134 * Add call to start other CPUs if multiprocessor.
135 * [89/12/01 dbg]
136 *
137 * Revision 2.3 89/09/08 11:26:32 dbg
138 * Move kalloc initialization to vm_init.
139 * [89/09/06 dbg]
140 *
141 * Move bootstrap initialization to kern/bootstrap.c. Initialize
142 * device service here.
143 * [89/08/02 dbg]
144 *
145 * Initialize kalloc package.
146 * [89/07/11 dbg]
147 *
148 * Revision 2.2 89/08/05 16:07:22 rwd
149 * Call mappable_time_init.
150 * [89/08/04 18:31:35 rwd]
151 *
152 * 23-May-89 David Golub (dbg) at Carnegie-Mellon University
153 * Thread creation must be done by a running thread;
154 * thread_setrun (called by thread_resume & kernel_thread) may look
155 * at current thread.
156 *
157 * 19-May-89 David Golub (dbg) at Carnegie-Mellon University
158 * Don't export first_task and first_thread; they don't last very
159 * long.
160 *
161 * 15-Aug-88 David Golub (dbg) at Carnegie-Mellon University
162 * Initial threads are now part of the kernel task, not first-task.
163 * Create the bootstrap task as a kernel task.
164 *
165 * 8-Aug-88 David Golub (dbg) at Carnegie-Mellon University
166 * Modified for stand-alone MACH kernel.
167 *
168 * 1-Jul-88 David Golub (dbg) at Carnegie-Mellon University
169 * Created.
170 *
171 */
172
173 /*
174 * Mach kernel startup.
175 */
176
177
178 #include <xpr_debug.h>
179 #include <cpus.h>
180 #include <mach_host.h>
181 #include <norma_ipc.h>
182 #include <norma_vm.h>
183
184 #include <mach/boolean.h>
185 #include <mach/machine.h>
186 #include <mach/task_special_ports.h>
187 #include <mach/vm_param.h>
188 #include <ipc/ipc_init.h>
189 #include <kern/cpu_number.h>
190 #include <kern/processor.h>
191 #include <kern/sched_prim.h>
192 #include <kern/task.h>
193 #include <kern/thread.h>
194 #include <kern/thread_swap.h>
195 #include <kern/time_out.h>
196 #include <kern/timer.h>
197 #include <kern/zalloc.h>
198 #include <vm/vm_kern.h>
199 #include <vm/vm_map.h>
200 #include <vm/vm_object.h>
201 #include <vm/vm_page.h>
202 #include <machine/machspl.h>
203 #include <machine/pmap.h>
204 #include <sys/version.h>
205
206
207
208 extern void vm_mem_init();
209 extern void vm_mem_bootstrap();
210 extern void init_timeout();
211 extern void machine_init();
212
213 extern void idle_thread();
214 extern void vm_pageout();
215 extern void reaper_thread();
216 extern void swapin_thread();
217 extern void sched_thread();
218
219 extern void bootstrap_create();
220 extern void device_service_create();
221
222 void cpu_launch_first_thread(); /* forward */
223 void start_kernel_threads(); /* forward */
224
225 #if NCPUS > 1
226 extern void start_other_cpus();
227 extern void action_thread();
228 #endif NCPUS > 1
229
230 /*
231 * Running in virtual memory, on the interrupt stack.
232 * Does not return. Dispatches initial thread.
233 *
234 * Assumes that master_cpu is set.
235 */
236 void setup_main()
237 {
238 thread_t startup_thread;
239
240 panic_init();
241 printf_init();
242
243 sched_init();
244 vm_mem_bootstrap();
245 ipc_bootstrap();
246 vm_mem_init();
247 ipc_init();
248
249 /*
250 * As soon as the virtual memory system is up, we record
251 * that this CPU is using the kernel pmap.
252 */
253 PMAP_ACTIVATE_KERNEL(master_cpu);
254
255 init_timers();
256 init_timeout();
257
258 #if XPR_DEBUG
259 xprbootstrap();
260 #endif XPR_DEBUG
261
262 timestamp_init();
263
264 mapable_time_init();
265
266 machine_init();
267
268 machine_info.max_cpus = NCPUS;
269 machine_info.memory_size = mem_size;
270 machine_info.avail_cpus = 0;
271 machine_info.major_version = KERNEL_MAJOR_VERSION;
272 machine_info.minor_version = KERNEL_MINOR_VERSION;
273
274 /*
275 * Initialize the IPC, task, and thread subsystems.
276 */
277 task_init();
278 thread_init();
279 swapper_init();
280 #if MACH_HOST
281 pset_sys_init();
282 #endif MACH_HOST
283
284 /*
285 * Kick off the time-out driven routines by calling
286 * them the first time.
287 */
288 recompute_priorities();
289 compute_mach_factor();
290
291 /*
292 * Create a kernel thread to start the other kernel
293 * threads. Thread_resume (from kernel_thread) calls
294 * thread_setrun, which may look at current thread;
295 * we must avoid this, since there is no current thread.
296 */
297
298 /*
299 * Create the thread, and point it at the routine.
300 */
301 (void) thread_create(kernel_task, &startup_thread);
302 thread_start(startup_thread, start_kernel_threads);
303
304 /*
305 * Give it a kernel stack.
306 */
307 thread_doswapin(startup_thread);
308
309 /*
310 * Pretend it is already running, and resume it.
311 * Since it looks as if it is running, thread_resume
312 * will not try to put it on the run queues.
313 *
314 * We can do all of this without locking, because nothing
315 * else is running yet.
316 */
317 startup_thread->state |= TH_RUN;
318 (void) thread_resume(startup_thread);
319
320 /*
321 * Start the thread.
322 */
323 cpu_launch_first_thread(startup_thread);
324 /*NOTREACHED*/
325 }
326
327 /*
328 * Now running in a thread. Create the rest of the kernel threads
329 * and the bootstrap task.
330 */
331 void start_kernel_threads()
332 {
333 register int i;
334
335 /*
336 * Create the idle threads and the other
337 * service threads.
338 */
339 for (i = 0; i < NCPUS; i++) {
340 if (machine_slot[i].is_cpu) {
341 thread_t th;
342
343 (void) thread_create(kernel_task, &th);
344 thread_bind(th, cpu_to_processor(i));
345 thread_start(th, idle_thread);
346 thread_doswapin(th);
347 (void) thread_resume(th);
348 }
349 }
350
351 (void) kernel_thread(kernel_task, reaper_thread, (char *) 0);
352 (void) kernel_thread(kernel_task, swapin_thread, (char *) 0);
353 (void) kernel_thread(kernel_task, sched_thread, (char *) 0);
354
355 #if NCPUS > 1
356 /*
357 * Create the shutdown thread.
358 */
359 (void) kernel_thread(kernel_task, action_thread, (char *) 0);
360
361 /*
362 * Allow other CPUs to run.
363 */
364 start_other_cpus();
365 #endif NCPUS > 1
366
367 /*
368 * Create the device service.
369 */
370 device_service_create();
371
372 /*
373 * Initialize NORMA ipc system.
374 */
375 #if NORMA_IPC
376 norma_ipc_init();
377 #endif NORMA_IPC
378
379 /*
380 * Initialize NORMA vm system.
381 */
382 #if NORMA_VM
383 norma_vm_init();
384 #endif NORMA_VM
385
386 /*
387 * Start the user bootstrap.
388 */
389 bootstrap_create();
390
391 #if XPR_DEBUG
392 xprinit(); /* XXX */
393 #endif XPR_DEBUG
394
395 /*
396 * Become the pageout daemon.
397 */
398 (void) spl0();
399 vm_pageout();
400 /*NOTREACHED*/
401 }
402
403 #if NCPUS > 1
404
405 extern void slave_machine_init();
406
407 void slave_main()
408 {
409 slave_machine_init();
410
411 cpu_launch_first_thread(THREAD_NULL);
412 }
413 #endif NCPUS > 1
414
415 /*
416 * Start up the first thread on a CPU.
417 * First thread is specified for the master CPU.
418 */
419 void cpu_launch_first_thread(th)
420 register thread_t th;
421 {
422 register int mycpu;
423
424 mycpu = cpu_number();
425
426 cpu_up(mycpu);
427
428 start_timer(&kernel_timer[mycpu]);
429
430 /*
431 * Block all interrupts for choose_thread.
432 */
433 (void) splhigh();
434
435 if (th == THREAD_NULL)
436 th = choose_thread(cpu_to_processor(mycpu));
437 if (th == THREAD_NULL)
438 panic("cpu_launch_first_thread");
439
440 startrtclock(); /* needs an active thread */
441 PMAP_ACTIVATE_KERNEL(mycpu);
442
443 active_threads[mycpu] = th;
444 active_stacks[mycpu] = th->kernel_stack;
445 thread_lock(th);
446 th->state &= ~TH_UNINT;
447 thread_unlock(th);
448 timer_switch(&th->system_timer);
449
450 PMAP_ACTIVATE_USER(vm_map_pmap(th->task->map), th, mycpu);
451
452 load_context(th);
453 /*NOTREACHED*/
454 }
Cache object: 5f2e2f8cf82f9257b3c95cb92892638f
|