X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0b4e3aa066abc0728aacb4bbeb86f53f9737156e..378393581903b274cb7a4d18e0d978071a6b592d:/osfmk/kern/startup.c diff --git a/osfmk/kern/startup.c b/osfmk/kern/startup.c index b3a5b0094..65f9d00f8 100644 --- a/osfmk/kern/startup.c +++ b/osfmk/kern/startup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -57,13 +57,12 @@ #include #include #include -#include #include #include -#include #include #include +#include #include #include #include @@ -71,18 +70,18 @@ #include #include #include -#include +#include #include #include #include -#include #include #include #include #include -#include #include #include +#include +#include #include #include #include @@ -90,33 +89,30 @@ #include #include #include -#include +#include +#include #ifdef __ppc__ #include #include +#include #endif -/* Externs XXX */ -extern void rtclock_reset(void); +static void kernel_bootstrap_thread(void); -/* Forwards */ -void cpu_launch_first_thread( - thread_t thread); -void start_kernel_threads(void); -void swapin_thread(); +static void load_context( + thread_t thread); /* * Running in virtual memory, on the interrupt stack. - * Does not return. Dispatches initial thread. - * - * Assumes that master_cpu is set. */ void -setup_main(void) +kernel_bootstrap(void) { - thread_t startup_thread; + kern_return_t result; + thread_t thread; + lck_mod_init(); sched_init(); vm_mem_bootstrap(); ipc_bootstrap(); @@ -129,126 +125,71 @@ setup_main(void) */ PMAP_ACTIVATE_KERNEL(master_cpu); -#ifdef __ppc__ mapping_free_prime(); /* Load up with temporary mapping blocks */ -#endif machine_init(); kmod_init(); clock_init(); - init_timers(); - timer_call_initialize(); - - machine_info.max_cpus = NCPUS; machine_info.memory_size = mem_size; - machine_info.avail_cpus = 0; - machine_info.major_version = KERNEL_MAJOR_VERSION; - machine_info.minor_version = KERNEL_MINOR_VERSION; + machine_info.max_mem = max_mem; + machine_info.major_version = version_major; + machine_info.minor_version = version_minor; /* * Initialize the IPC, task, and thread subsystems. */ ledger_init(); task_init(); - act_init(); thread_init(); - subsystem_init(); - - /* - * Initialize the Event Trace Analysis Package. - * Dynamic Phase: 2 of 2 - */ - etap_init_phase2(); /* - * Create a kernel thread to start the other kernel - * threads. Thread_resume (from kernel_thread) calls - * thread_setrun, which may look at current thread; - * we must avoid this, since there is no current thread. + * Create a kernel thread to execute the kernel bootstrap. */ - startup_thread = kernel_thread_with_priority( - kernel_task, MAXPRI_KERNEL, - start_kernel_threads, TRUE, FALSE); - - /* - * Pretend it is already running, and resume it. - * Since it looks as if it is running, thread_resume - * will not try to put it on the run queues. - * - * We can do all of this without locking, because nothing - * else is running yet. - */ - startup_thread->state = TH_RUN; - (void) thread_resume(startup_thread->top_act); - /* - * Start the thread. - */ - cpu_launch_first_thread(startup_thread); + result = kernel_thread_create((thread_continue_t)kernel_bootstrap_thread, NULL, MAXPRI_KERNEL, &thread); + if (result != KERN_SUCCESS) + panic("kernel_bootstrap"); + + thread->state = TH_RUN; + thread_deallocate(thread); + + load_context(thread); /*NOTREACHED*/ - panic("cpu_launch_first_thread returns!"); } /* - * Now running in a thread. Create the rest of the kernel threads - * and the bootstrap task. + * Now running in a thread. Kick off other services, + * invoke user bootstrap, enter pageout loop. */ -void -start_kernel_threads(void) +static void +kernel_bootstrap_thread(void) { - register int i; - - thread_bind(current_thread(), cpu_to_processor(cpu_number())); - - /* - * Create the idle threads and the other - * service threads. - */ - for (i = 0; i < NCPUS; i++) { - processor_t processor = cpu_to_processor(i); - thread_t thread; - spl_t s; - - thread = kernel_thread_with_priority( - kernel_task, MAXPRI_KERNEL, - idle_thread, TRUE, FALSE); - s = splsched(); - thread_lock(thread); - thread_bind_locked(thread, processor); - processor->idle_thread = thread; - thread->ref_count++; - thread->state |= TH_IDLE; - thread_go_locked(thread, THREAD_AWAKENED); - thread_unlock(thread); - splx(s); - } + processor_t processor = current_processor(); + thread_t self = current_thread(); /* - * Initialize the stack swapin mechanism. + * Create the idle processor thread. */ - swapin_init(); + idle_thread_create(processor); /* - * Initialize the periodic scheduler mechanism. + * N.B. Do not stick anything else + * before this point. + * + * Start up the scheduler services. */ - sched_tick_init(); + sched_startup(); /* - * Initialize the thread callout mechanism. + * Remain on current processor as + * additional processors come online. */ - thread_call_initialize(); + thread_bind(self, processor); /* - * Invoke some black magic. + * Kick off memory mapping adjustments. */ -#if __ppc__ mapping_adjust(); -#endif - - /* - * Initialize the thread reaper mechanism. - */ - thread_reaper(); /* * Create the clock service. @@ -260,110 +201,142 @@ start_kernel_threads(void) */ device_service_create(); - shared_file_boot_time_init(); + shared_file_boot_time_init(ENV_DEFAULT_ROOT, cpu_type()); #ifdef IOKIT { PE_init_iokit(); } #endif + + (void) spllo(); /* Allow interruptions */ + + /* + * Fill in the comm area (mapped into every task address space.) + */ + commpage_populate(); /* * Start the user bootstrap. */ - - (void) spllo(); /* Allow interruptions */ - #ifdef MACH_BSD { - extern void bsd_init(void); bsd_init(); } #endif - thread_bind(current_thread(), PROCESSOR_NULL); +#if __ppc__ + serial_keyboard_init(); /* Start serial keyboard if wanted */ +#endif + + thread_bind(self, PROCESSOR_NULL); /* * Become the pageout daemon. */ - vm_pageout(); /*NOTREACHED*/ } +/* + * slave_main: + * + * Load the first thread to start a processor. + */ void slave_main(void) { - processor_t myprocessor = current_processor(); + processor_t processor = current_processor(); thread_t thread; - thread = myprocessor->next_thread; - myprocessor->next_thread = THREAD_NULL; - if (thread == THREAD_NULL) { - thread = machine_wake_thread; - machine_wake_thread = THREAD_NULL; - thread_bind(thread, myprocessor); + /* + * Use the idle processor thread if there + * is no dedicated start up thread. + */ + if (processor->next_thread == THREAD_NULL) { + thread = processor->idle_thread; + thread->continuation = (thread_continue_t)processor_start_thread; + thread->parameter = NULL; } - cpu_launch_first_thread(thread); + else { + thread = processor->next_thread; + processor->next_thread = THREAD_NULL; + } + + load_context(thread); /*NOTREACHED*/ - panic("slave_main"); } /* - * Now running in a thread context + * processor_start_thread: + * + * First thread to execute on a started processor. + * + * Called at splsched. */ void -start_cpu_thread(void) +processor_start_thread(void) { - processor_t processor; - - processor = cpu_to_processor(cpu_number()); + processor_t processor = current_processor(); + thread_t self = current_thread(); slave_machine_init(); - if (processor->processor_self == IP_NULL) { - ipc_processor_init(processor); - ipc_processor_enable(processor); - } + /* + * If running the idle processor thread, + * reenter the idle loop, else terminate. + */ + if (self == processor->idle_thread) + thread_block((thread_continue_t)idle_thread); - (void) thread_terminate(current_act()); + thread_terminate(self); + /*NOTREACHED*/ } /* - * Start up the first thread on a CPU. + * load_context: + * + * Start the first thread on a processor. */ -void -cpu_launch_first_thread( +static void +load_context( thread_t thread) { - register int mycpu = cpu_number(); + processor_t processor = current_processor(); - /* initialize preemption disabled */ - cpu_data[mycpu].preemption_level = 1; + machine_set_current_thread(thread); + processor_up(processor); - cpu_up(mycpu); - start_timer(&kernel_timer[mycpu]); - clock_get_uptime(&cpu_to_processor(mycpu)->last_dispatch); + PMAP_ACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num)); - if (thread == THREAD_NULL) { - thread = cpu_to_processor(mycpu)->idle_thread; - if (thread == THREAD_NULL) - panic("cpu_launch_first_thread"); + /* + * Acquire a stack if none attached. The panic + * should never occur since the thread is expected + * to have reserved stack. + */ + if (!thread->kernel_stack) { + if (!stack_alloc_try(thread)) + panic("load_context"); } - rtclock_reset(); /* start realtime clock ticking */ - PMAP_ACTIVATE_KERNEL(mycpu); + /* + * The idle processor threads are not counted as + * running for load calculations. + */ + if (!(thread->state & TH_IDLE)) + pset_run_incr(thread->processor_set); - thread_machine_set_current(thread); - thread_lock(thread); - thread->state &= ~TH_UNINT; - _mk_sp_thread_begin(thread); - thread_unlock(thread); - timer_switch(&thread->system_timer); + processor->active_thread = thread; + processor->current_pri = thread->sched_pri; + processor->deadline = UINT64_MAX; + thread->last_processor = processor; - PMAP_ACTIVATE_USER(thread->top_act, mycpu); + processor->last_dispatch = mach_absolute_time(); + timer_switch((uint32_t)processor->last_dispatch, + &PROCESSOR_DATA(processor, offline_timer)); - /* preemption enabled by load_context */ - load_context(thread); + PMAP_ACTIVATE_USER(thread, PROCESSOR_DATA(processor, slot_num)); + + machine_load_context(thread); /*NOTREACHED*/ }