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