Mac OS X Internals: A Systems Approach
5.9. Slave Processors
Before we discuss user-level startup, let us look at the ppc_init_cpu() [osfmk/ppc/ppc_init.c] function. Recall from Figure 52 that at boot time, a slave processor calls ppc_init_cpu() instead of ppc_init(). The execution journey of a slave processor is much shorter than that of the master processor. Figure 522 shows the execution path of ppc_init_cpu(). Figure 522. Slave processor initialization
ppc_init_cpu() clears the SleepState bit in the cpu_flags field of the processor's per_proc_info structure. On 64-bit hardware, ppc_init_cpu() checks whether the wcte global variable is set to 0; if so, it disables the noncacheable unit's store gather timer through an SCOM command. The value of the wcte variable can be set through the wcte boot argument (see Table 412). Next, ppc_init_cpu() calls cpu_init() [osfmk/ppc/cpu.c], which we came across earlier in this chapter. cpu_init() restores the Timebase Register from values saved in the CPU's per_proc_info structure. It also sets the values of some fields in the per_proc_info structure. Finally, ppc_init_cpu() calls slave_main() [osfmk/kern/startup.c], which never returns. Recall how the kernel_bootstrap() function, while running on the master processor, arrangedthrough load_context()for kernel_bootstrap_thread() to start executing. Similarly, slave_main() arranges for processor_start_thread() [osfmk/kern/startup.c] to start executing. processor_start_thread() calls slave_machine_init() [osfmk/ppc/model_dep.c]. slave_machine_init() initializes the processor by calling cpu_machine_init() [osfmk/ppc/cpu.c] and the clock by calling clock_init() [osfmk/kern/clock.c]. We earlier noted the operation of clock_init(), which calls the initialization functions of all available clock devices. cpu_machine_init() calls PE_cpu_machine_init() [iokit/Kernel/IOCPU.cpp], synchronizes the Timebase Register with the master processor, and enables interrupts. // iokit/Kernel/IOCPU.cpp void PE_cpu_machine_init(cpu_id_t target, boolean_t boot) { IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target); if (targetCPU) targetCPU->initCPU(boot); }
|
Категории