]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/startup.c
xnu-792.6.76.tar.gz
[apple/xnu.git] / osfmk / kern / startup.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_COPYRIGHT@
24 */
25 /*
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50 /*
51 */
52
53 /*
54 * Mach kernel startup.
55 */
56
57 #include <debug.h>
58 #include <xpr_debug.h>
59 #include <mach_kdp.h>
60 #include <mach_host.h>
61 #include <norma_vm.h>
62
63 #include <mach/boolean.h>
64 #include <mach/machine.h>
65 #include <mach/thread_act.h>
66 #include <mach/task_special_ports.h>
67 #include <mach/vm_param.h>
68 #include <ipc/ipc_init.h>
69 #include <kern/assert.h>
70 #include <kern/misc_protos.h>
71 #include <kern/clock.h>
72 #include <kern/cpu_number.h>
73 #include <kern/ledger.h>
74 #include <kern/machine.h>
75 #include <kern/processor.h>
76 #include <kern/sched_prim.h>
77 #include <kern/startup.h>
78 #include <kern/task.h>
79 #include <kern/thread.h>
80 #include <kern/timer.h>
81 #include <kern/xpr.h>
82 #include <kern/zalloc.h>
83 #include <kern/locks.h>
84 #include <vm/vm_shared_memory_server.h>
85 #include <vm/vm_kern.h>
86 #include <vm/vm_init.h>
87 #include <vm/vm_map.h>
88 #include <vm/vm_object.h>
89 #include <vm/vm_page.h>
90 #include <vm/vm_pageout.h>
91 #include <machine/pmap.h>
92 #include <machine/commpage.h>
93 #include <libkern/version.h>
94
95 #ifdef __ppc__
96 #include <ppc/Firmware.h>
97 #include <ppc/mappings.h>
98 #include <ppc/serial_io.h>
99 #endif
100
101 static void kernel_bootstrap_thread(void);
102
103 static void load_context(
104 thread_t thread);
105
106 /*
107 * Running in virtual memory, on the interrupt stack.
108 */
109 void
110 kernel_bootstrap(void)
111 {
112 kern_return_t result;
113 thread_t thread;
114
115 lck_mod_init();
116 sched_init();
117 vm_mem_bootstrap();
118 ipc_bootstrap();
119 vm_mem_init();
120 ipc_init();
121
122 /*
123 * As soon as the virtual memory system is up, we record
124 * that this CPU is using the kernel pmap.
125 */
126 PMAP_ACTIVATE_KERNEL(master_cpu);
127
128 mapping_free_prime(); /* Load up with temporary mapping blocks */
129
130 machine_init();
131 kmod_init();
132 clock_init();
133
134 machine_info.memory_size = mem_size;
135 machine_info.max_mem = max_mem;
136 machine_info.major_version = version_major;
137 machine_info.minor_version = version_minor;
138
139 /*
140 * Initialize the IPC, task, and thread subsystems.
141 */
142 ledger_init();
143 task_init();
144 thread_init();
145
146 /*
147 * Create a kernel thread to execute the kernel bootstrap.
148 */
149 result = kernel_thread_create((thread_continue_t)kernel_bootstrap_thread, NULL, MAXPRI_KERNEL, &thread);
150 if (result != KERN_SUCCESS)
151 panic("kernel_bootstrap");
152
153 thread->state = TH_RUN;
154 thread_deallocate(thread);
155
156 load_context(thread);
157 /*NOTREACHED*/
158 }
159
160 /*
161 * Now running in a thread. Kick off other services,
162 * invoke user bootstrap, enter pageout loop.
163 */
164 static void
165 kernel_bootstrap_thread(void)
166 {
167 processor_t processor = current_processor();
168 thread_t self = current_thread();
169
170 /*
171 * Create the idle processor thread.
172 */
173 idle_thread_create(processor);
174
175 /*
176 * N.B. Do not stick anything else
177 * before this point.
178 *
179 * Start up the scheduler services.
180 */
181 sched_startup();
182
183 /*
184 * Remain on current processor as
185 * additional processors come online.
186 */
187 thread_bind(self, processor);
188
189 /*
190 * Kick off memory mapping adjustments.
191 */
192 mapping_adjust();
193
194 /*
195 * Create the clock service.
196 */
197 clock_service_create();
198
199 /*
200 * Create the device service.
201 */
202 device_service_create();
203
204 shared_file_boot_time_init(ENV_DEFAULT_ROOT, cpu_type());
205
206 #ifdef IOKIT
207 {
208 PE_init_iokit();
209 }
210 #endif
211
212 (void) spllo(); /* Allow interruptions */
213
214 /*
215 * Fill in the comm area (mapped into every task address space.)
216 */
217 commpage_populate();
218
219 /*
220 * Start the user bootstrap.
221 */
222 #ifdef MACH_BSD
223 {
224 bsd_init();
225 }
226 #endif
227
228 #if __ppc__
229 serial_keyboard_init(); /* Start serial keyboard if wanted */
230 #endif
231
232 thread_bind(self, PROCESSOR_NULL);
233
234 /*
235 * Become the pageout daemon.
236 */
237 vm_pageout();
238 /*NOTREACHED*/
239 }
240
241 /*
242 * slave_main:
243 *
244 * Load the first thread to start a processor.
245 */
246 void
247 slave_main(void)
248 {
249 processor_t processor = current_processor();
250 thread_t thread;
251
252 /*
253 * Use the idle processor thread if there
254 * is no dedicated start up thread.
255 */
256 if (processor->next_thread == THREAD_NULL) {
257 thread = processor->idle_thread;
258 thread->continuation = (thread_continue_t)processor_start_thread;
259 thread->parameter = NULL;
260 }
261 else {
262 thread = processor->next_thread;
263 processor->next_thread = THREAD_NULL;
264 }
265
266 load_context(thread);
267 /*NOTREACHED*/
268 }
269
270 /*
271 * processor_start_thread:
272 *
273 * First thread to execute on a started processor.
274 *
275 * Called at splsched.
276 */
277 void
278 processor_start_thread(void)
279 {
280 processor_t processor = current_processor();
281 thread_t self = current_thread();
282
283 slave_machine_init();
284
285 /*
286 * If running the idle processor thread,
287 * reenter the idle loop, else terminate.
288 */
289 if (self == processor->idle_thread)
290 thread_block((thread_continue_t)idle_thread);
291
292 thread_terminate(self);
293 /*NOTREACHED*/
294 }
295
296 /*
297 * load_context:
298 *
299 * Start the first thread on a processor.
300 */
301 static void
302 load_context(
303 thread_t thread)
304 {
305 processor_t processor = current_processor();
306
307 machine_set_current_thread(thread);
308 processor_up(processor);
309
310 PMAP_ACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num));
311
312 /*
313 * Acquire a stack if none attached. The panic
314 * should never occur since the thread is expected
315 * to have reserved stack.
316 */
317 if (!thread->kernel_stack) {
318 if (!stack_alloc_try(thread))
319 panic("load_context");
320 }
321
322 /*
323 * The idle processor threads are not counted as
324 * running for load calculations.
325 */
326 if (!(thread->state & TH_IDLE))
327 pset_run_incr(thread->processor_set);
328
329 processor->active_thread = thread;
330 processor->current_pri = thread->sched_pri;
331 processor->deadline = UINT64_MAX;
332 thread->last_processor = processor;
333
334 processor->last_dispatch = mach_absolute_time();
335 timer_switch((uint32_t)processor->last_dispatch,
336 &PROCESSOR_DATA(processor, offline_timer));
337
338 PMAP_ACTIVATE_USER(thread, PROCESSOR_DATA(processor, slot_num));
339
340 machine_load_context(thread);
341 /*NOTREACHED*/
342 }