|
|
1.1 root 1: /*
2: * Copyright (c) 2000 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 [email protected]
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 <cpus.h>
61: #include <mach_host.h>
62: #include <norma_vm.h>
63: #include <etap.h>
64:
65: #include <mach/boolean.h>
66: #include <mach/machine.h>
67: #include <mach/task_special_ports.h>
68: #include <mach/vm_param.h>
69: #include <ipc/ipc_init.h>
70: #include <kern/assert.h>
71: #include <kern/misc_protos.h>
72: #include <kern/clock.h>
73: #include <kern/cpu_number.h>
74: #include <kern/etap_macros.h>
75: #include <kern/machine.h>
76: #include <kern/processor.h>
77: #include <kern/sched_prim.h>
78: #include <kern/sf.h>
79: #include <kern/startup.h>
80: #include <kern/task.h>
81: #include <kern/thread.h>
82: #include <kern/timer.h>
83: #include <kern/xpr.h>
84: #include <kern/zalloc.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 <sys/version.h>
93:
94: vm_offset_t shared_file_text_region;
95: vm_offset_t shared_file_data_region;
96:
97: #ifdef __ppc__
98: #include <ppc/Firmware.h>
99: #include <ppc/mappings.h>
100: #include <ppc/miscserv.h>
101: #endif
102:
103: /* Externs XXX */
104: extern void rtclock_reset(void);
105:
106: /* Forwards */
107: void cpu_launch_first_thread(
108: thread_t thread);
109: void start_kernel_threads(void);
110: void swapin_thread();
111:
112: ipc_port_t shared_text_region_handle;
113: ipc_port_t shared_data_region_handle;
114: vm_offset_t shared_file_mapping_array;
115:
116: /*
117: * Running in virtual memory, on the interrupt stack.
118: * Does not return. Dispatches initial thread.
119: *
120: * Assumes that master_cpu is set.
121: */
122: void
123: setup_main(void)
124: {
125: mk_sp_attribute_struct_t startup_thread_attributes;
126: thread_t startup_thread;
127:
128: printf_init();
129: panic_init();
130:
131: sched_init();
132: vm_mem_bootstrap();
133: ipc_bootstrap();
134: vm_mem_init();
135: ipc_init();
136: pager_mux_hash_init();
137:
138: /*
139: * As soon as the virtual memory system is up, we record
140: * that this CPU is using the kernel pmap.
141: */
142: PMAP_ACTIVATE_KERNEL(master_cpu);
143:
144: #ifdef __ppc__
145: mapping_free_prime(); /* Load up with temporary mapping blocks */
146: #endif
147:
148: machine_init();
149: kmod_init();
150: clock_init();
151:
152: init_timers();
153:
154: machine_info.max_cpus = NCPUS;
155: machine_info.memory_size = mem_size;
156: machine_info.avail_cpus = 0;
157: machine_info.major_version = KERNEL_MAJOR_VERSION;
158: machine_info.minor_version = KERNEL_MINOR_VERSION;
159:
160: /*
161: * Initialize the IPC, task, and thread subsystems.
162: */
163: ledger_init();
164: swapper_init();
165: task_init();
166: act_init();
167: thread_init();
168: subsystem_init();
169: #if MACH_HOST
170: pset_sys_init();
171: #endif /* MACH_HOST */
172:
173: /*
174: * Initialize the Event Trace Analysis Package.
175: * Dynamic Phase: 2 of 2
176: */
177: etap_init_phase2();
178:
179: /*
180: * Create a kernel thread to start the other kernel
181: * threads. Thread_resume (from kernel_thread) calls
182: * thread_setrun, which may look at current thread;
183: * we must avoid this, since there is no current thread.
184: */
185: startup_thread_attributes.policy_id = POLICY_FIFO;
186: startup_thread_attributes.priority =
187: startup_thread_attributes.max_priority = BASEPRI_KERNEL;
188: startup_thread_attributes.sched_data =
189: startup_thread_attributes.unconsumed_quantum = 0;
190:
191: /*
192: * Create the thread, and point it at the routine.
193: */
194: startup_thread = kernel_thread_with_attributes(kernel_task,
195: (sp_attributes_t)&startup_thread_attributes,
196: start_kernel_threads, FALSE);
197:
198: /*
199: * Pretend it is already running, and resume it.
200: * Since it looks as if it is running, thread_resume
201: * will not try to put it on the run queues.
202: *
203: * We can do all of this without locking, because nothing
204: * else is running yet.
205: */
206: startup_thread->state |= TH_RUN;
207: (void) thread_resume(startup_thread->top_act);
208: /*
209: * Start the thread.
210: */
211: cpu_launch_first_thread(startup_thread);
212: /*NOTREACHED*/
213: panic("cpu_launch_first_thread returns!");
214: }
215:
216: /*
217: * Now running in a thread. Create the rest of the kernel threads
218: * and the bootstrap task.
219: */
220: void
221: start_kernel_threads(void)
222: {
223: mk_sp_attribute_struct_t idle_thread_attributes;
224: register int i;
225: long shared_text_region_size;
226: long shared_data_region_size;
227:
228: thread_bind(current_thread(), cpu_to_processor(cpu_number()));
229: /*
230: * Create the idle threads and the other
231: * service threads.
232: */
233: idle_thread_attributes.policy_id = POLICY_FIFO;
234: idle_thread_attributes.priority =
235: idle_thread_attributes.max_priority = BASEPRI_KERNEL;
236: idle_thread_attributes.sched_data =
237: idle_thread_attributes.unconsumed_quantum = 0;
238:
239: for (i = 0; i < NCPUS; i++) {
240: if (1 /*machine_slot[i].is_cpu*/) {
241: processor_t processor = cpu_to_processor(i);
242: thread_t thread;
243: sched_policy_t *policy;
244: sf_return_t sfr;
245: spl_t s;
246:
247: thread = kernel_thread_with_attributes(kernel_task,
248: (sp_attributes_t)&idle_thread_attributes,
249: idle_thread, FALSE);
250: s = splsched();
251: thread_lock(thread);
252: thread_bind_locked(thread, processor);
253: processor->idle_thread = thread;
254: /*(void) thread_resume(thread->top_act);*/
255: thread->state |= TH_RUN;
256:
257: /* get pointer to scheduling policy "object" */
258: policy = &sched_policy[thread->policy];
259:
260: sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
261: assert(sfr == SF_SUCCESS);
262: thread_unlock(thread);
263: splx(s);
264: }
265: }
266:
267: /*
268: * Initialize the thread callout mechanism.
269: */
270: thread_call_initialize();
271:
272: /*
273: * Invoke some black magic.
274: */
275: #if __ppc__
276: mapping_adjust();
277: #endif
278:
279: /*
280: * Invoke the thread reaper mechanism.
281: */
282: thread_reaper();
283:
284: /*
285: * Start the stack swapin thread
286: */
287: kernel_thread(kernel_task,swapin_thread);
288:
289: /*
290: * Invoke the periodic scheduler mechanism.
291: */
292: recompute_priorities();
293:
294: /*
295: * Create the clock service.
296: */
297: clock_service_create();
298:
299: /*
300: * Create the device service.
301: */
302: device_service_create();
303:
304: shared_text_region_size = 0x10000000;
305: shared_data_region_size = 0x10000000;
306: shared_file_init(&shared_text_region_handle,
307: shared_text_region_size, &shared_data_region_handle,
308: shared_data_region_size, &shared_file_mapping_array);
309:
310: #ifdef IOKIT
311: {
312: PE_init_iokit();
313: }
314: #endif
315:
316: /*
317: * Start the user bootstrap.
318: */
319:
320: (void) spllo(); /* Allow interruptions */
321:
322: #ifdef MACH_BSD
323: {
324: extern void bsd_init(void);
325: bsd_init();
326: }
327: #endif
328:
329: /*
330: * Invoke the processor action mechanism.
331: */
332: processor_action();
333:
334: thread_bind(current_thread(), PROCESSOR_NULL);
335:
336: /*
337: * Become the pageout daemon.
338: */
339:
340: vm_pageout();
341: /*NOTREACHED*/
342: }
343:
344: void
345: slave_main(void)
346: {
347: thread_t startup_thread;
348:
349: startup_thread = cpu_to_processor(cpu_number())->next_thread;
350: rem_runq(startup_thread);
351: cpu_launch_first_thread(startup_thread);
352: /*NOTREACHED*/
353: panic("cpu_launch_first_thread returns!");
354: }
355:
356: /*
357: * Now running in a thread context
358: */
359: void
360: start_cpu_thread(void)
361: {
362: processor_t processor;
363:
364: processor = cpu_to_processor(cpu_number());
365:
366: slave_machine_init();
367:
368: if (processor->processor_self == IP_NULL) {
369: ipc_processor_init(processor);
370: ipc_processor_enable(processor);
371: }
372:
373: printf("start_cpu_thread done on cpu %x\n", cpu_number());
374:
375: /* TODO: Mark this processor ready to dispatch threads */
376:
377: thread_terminate_self();
378: }
379:
380: /*
381: * Start up the first thread on a CPU.
382: * First thread is specified for the master CPU.
383: */
384: void
385: cpu_launch_first_thread(
386: thread_t thread)
387: {
388: register int mycpu = cpu_number();
389:
390: cpu_up(mycpu);
391: start_timer(&kernel_timer[mycpu]);
392:
393: if (thread == THREAD_NULL) {
394: thread = cpu_to_processor(mycpu)->idle_thread;
395: if (thread == THREAD_NULL || !rem_runq(thread))
396: panic("cpu_launch_first_thread");
397: }
398:
399: rtclock_reset(); /* start realtime clock ticking */
400: PMAP_ACTIVATE_KERNEL(mycpu);
401:
402: thread_machine_set_current(thread);
403: thread_lock(thread);
404: thread->state &= ~TH_UNINT;
405: thread_unlock(thread);
406: timer_switch(&thread->system_timer);
407:
408: PMAP_ACTIVATE_USER(thread->top_act, mycpu);
409:
410: assert(mycpu == cpu_number());
411:
412: /* The following is necessary to keep things balanced */
413: disable_preemption();
414:
415: load_context(thread);
416: /*NOTREACHED*/
417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.