|
|
1.1 root 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 [email protected]
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: * Mach kernel startup.
28: */
29:
30:
31: #include <xpr_debug.h>
32: #include <cpus.h>
33: #include <mach_host.h>
34: #include <norma_ipc.h>
35: #include <norma_vm.h>
36:
37: #include <mach/boolean.h>
38: #include <mach/machine.h>
39: #include <mach/task_special_ports.h>
40: #include <mach/vm_param.h>
41: #include <ipc/ipc_init.h>
42: #include <kern/cpu_number.h>
43: #include <kern/processor.h>
44: #include <kern/sched_prim.h>
45: #include <kern/task.h>
46: #include <kern/thread.h>
47: #include <kern/thread_swap.h>
48: #include <kern/time_out.h>
49: #include <kern/timer.h>
50: #include <kern/zalloc.h>
51: #include <vm/vm_kern.h>
52: #include <vm/vm_map.h>
53: #include <vm/vm_object.h>
54: #include <vm/vm_page.h>
55: #include <machine/machspl.h>
56: #include <machine/pmap.h>
57: #include <mach/version.h>
58:
59:
60:
61: extern void vm_mem_init();
62: extern void vm_mem_bootstrap();
63: extern void init_timeout();
64: extern void machine_init();
65:
66: extern void idle_thread();
67: extern void vm_pageout();
68: extern void reaper_thread();
69: extern void swapin_thread();
70: extern void sched_thread();
71:
72: extern void bootstrap_create();
73: extern void device_service_create();
74:
75: void cpu_launch_first_thread(); /* forward */
76: void start_kernel_threads(); /* forward */
77:
78: #if NCPUS > 1
79: extern void start_other_cpus();
80: extern void action_thread();
81: #endif NCPUS > 1
82:
83: /* XX */
84: extern vm_offset_t phys_first_addr, phys_last_addr;
85:
86: /*
87: * Running in virtual memory, on the interrupt stack.
88: * Does not return. Dispatches initial thread.
89: *
90: * Assumes that master_cpu is set.
91: */
92: void setup_main()
93: {
94: thread_t startup_thread;
95:
96: panic_init();
97: printf_init();
98:
99: sched_init();
100: vm_mem_bootstrap();
101: ipc_bootstrap();
102: vm_mem_init();
103: ipc_init();
104:
105: /*
106: * As soon as the virtual memory system is up, we record
107: * that this CPU is using the kernel pmap.
108: */
109: PMAP_ACTIVATE_KERNEL(master_cpu);
110:
111: init_timers();
112: init_timeout();
113:
114: #if XPR_DEBUG
115: xprbootstrap();
116: #endif XPR_DEBUG
117:
118: timestamp_init();
119:
120: mapable_time_init();
121:
122: machine_init();
123:
124: machine_info.max_cpus = NCPUS;
125: machine_info.memory_size = phys_last_addr - phys_first_addr; /* XXX mem_size */
126: machine_info.avail_cpus = 0;
127: machine_info.major_version = KERNEL_MAJOR_VERSION;
128: machine_info.minor_version = KERNEL_MINOR_VERSION;
129:
130: /*
131: * Initialize the IPC, task, and thread subsystems.
132: */
133: task_init();
134: thread_init();
135: swapper_init();
136: #if MACH_HOST
137: pset_sys_init();
138: #endif MACH_HOST
139:
140: /*
141: * Kick off the time-out driven routines by calling
142: * them the first time.
143: */
144: recompute_priorities();
145: compute_mach_factor();
146:
147: /*
148: * Create a kernel thread to start the other kernel
149: * threads. Thread_resume (from kernel_thread) calls
150: * thread_setrun, which may look at current thread;
151: * we must avoid this, since there is no current thread.
152: */
153:
154: /*
155: * Create the thread, and point it at the routine.
156: */
157: (void) thread_create(kernel_task, &startup_thread);
158: thread_start(startup_thread, start_kernel_threads);
159:
160: /*
161: * Give it a kernel stack.
162: */
163: thread_doswapin(startup_thread);
164:
165: /*
166: * Pretend it is already running, and resume it.
167: * Since it looks as if it is running, thread_resume
168: * will not try to put it on the run queues.
169: *
170: * We can do all of this without locking, because nothing
171: * else is running yet.
172: */
173: startup_thread->state |= TH_RUN;
174: (void) thread_resume(startup_thread);
175:
176: /*
177: * Start the thread.
178: */
179: cpu_launch_first_thread(startup_thread);
180: /*NOTREACHED*/
181: }
182:
183: /*
184: * Now running in a thread. Create the rest of the kernel threads
185: * and the bootstrap task.
186: */
187: void start_kernel_threads()
188: {
189: register int i;
190:
191: /*
192: * Create the idle threads and the other
193: * service threads.
194: */
195: for (i = 0; i < NCPUS; i++) {
196: if (machine_slot[i].is_cpu) {
197: thread_t th;
198:
199: (void) thread_create(kernel_task, &th);
200: thread_bind(th, cpu_to_processor(i));
201: thread_start(th, idle_thread);
202: thread_doswapin(th);
203: (void) thread_resume(th);
204: }
205: }
206:
207: (void) kernel_thread(kernel_task, reaper_thread, (char *) 0);
208: (void) kernel_thread(kernel_task, swapin_thread, (char *) 0);
209: (void) kernel_thread(kernel_task, sched_thread, (char *) 0);
210:
211: #if NCPUS > 1
212: /*
213: * Create the shutdown thread.
214: */
215: (void) kernel_thread(kernel_task, action_thread, (char *) 0);
216:
217: /*
218: * Allow other CPUs to run.
219: */
220: start_other_cpus();
221: #endif NCPUS > 1
222:
223: /*
224: * Create the device service.
225: */
226: device_service_create();
227:
228: /*
229: * Initialize NORMA ipc system.
230: */
231: #if NORMA_IPC
232: norma_ipc_init();
233: #endif NORMA_IPC
234:
235: /*
236: * Initialize NORMA vm system.
237: */
238: #if NORMA_VM
239: norma_vm_init();
240: #endif NORMA_VM
241:
242: /*
243: * Start the user bootstrap.
244: */
245: bootstrap_create();
246:
247: #if XPR_DEBUG
248: xprinit(); /* XXX */
249: #endif XPR_DEBUG
250:
251: /*
252: * Become the pageout daemon.
253: */
254: (void) spl0();
255: vm_pageout();
256: /*NOTREACHED*/
257: }
258:
259: #if NCPUS > 1
260: void slave_main()
261: {
262: cpu_launch_first_thread(THREAD_NULL);
263: }
264: #endif NCPUS > 1
265:
266: /*
267: * Start up the first thread on a CPU.
268: * First thread is specified for the master CPU.
269: */
270: void cpu_launch_first_thread(th)
271: register thread_t th;
272: {
273: register int mycpu;
274:
275: mycpu = cpu_number();
276:
277: cpu_up(mycpu);
278:
279: start_timer(&kernel_timer[mycpu]);
280:
281: /*
282: * Block all interrupts for choose_thread.
283: */
284: (void) splhigh();
285:
286: if (th == THREAD_NULL)
287: th = choose_thread(cpu_to_processor(mycpu));
288: if (th == THREAD_NULL)
289: panic("cpu_launch_first_thread");
290:
291: startrtclock(); /* needs an active thread */
292: PMAP_ACTIVATE_KERNEL(mycpu);
293:
294: active_threads[mycpu] = th;
295: active_stacks[mycpu] = th->kernel_stack;
296: thread_lock(th);
297: th->state &= ~TH_UNINT;
298: thread_unlock(th);
299: timer_switch(&th->system_timer);
300:
301: PMAP_ACTIVATE_USER(vm_map_pmap(th->task->map), th, mycpu);
302:
303: load_context(th);
304: /*NOTREACHED*/
305: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.