X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2d21ac55c334faf3a56e5634905ed6987fc787d4..5c9f46613a83ebfc29a5b1f099448259e96a98f0:/osfmk/i386/cpu_topology.c diff --git a/osfmk/i386/cpu_topology.c b/osfmk/i386/cpu_topology.c index 56b3b43a9..e079e6e38 100644 --- a/osfmk/i386/cpu_topology.c +++ b/osfmk/i386/cpu_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All rights reserved. + * Copyright (c) 2007-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -31,19 +31,12 @@ #include #include #include -#include #include #include +#include +#include +#include #include -#include -#include - -//#define TOPO_DEBUG 1 -#if TOPO_DEBUG -#define DBG(x...) kprintf("DBG: " x) -#else -#define DBG(x...) -#endif __private_extern__ void qsort( void * array, @@ -57,8 +50,21 @@ static x86_affinity_set_t *find_cache_affinity(x86_cpu_cache_t *L2_cachep); x86_affinity_set_t *x86_affinities = NULL; static int x86_affinity_count = 0; +extern cpu_data_t cpshadows[]; +/* Re-sort double-mapped CPU data shadows after topology discovery sorts the + * primary CPU data structures by physical/APIC CPU ID. + */ +static void cpu_shadow_sort(int ncpus) { + for (int i = 0; i < ncpus; i++) { + cpu_data_t *cpup = cpu_datap(i); + ptrdiff_t coff = cpup - cpu_datap(0); + + cpup->cd_shadow = &cpshadows[coff]; + } +} + /* - * cpu_topology_start() is called after all processors have been registered + * cpu_topology_sort() is called after all processors have been registered * but before any non-boot processor id started. * We establish canonical logical processor numbering - logical cpus must be * contiguous, zero-based and assigned in physical (local apic id) order. @@ -68,30 +74,31 @@ static int x86_affinity_count = 0; * of processors - in particular, for stopping/starting from CHUD. */ void -cpu_topology_start(void) +cpu_topology_sort(int ncpus) { - int ncpus = machine_info.max_cpus; int i; boolean_t istate; + processor_t lprim = NULL; assert(machine_info.physical_cpu == 1); assert(machine_info.logical_cpu == 1); assert(master_cpu == 0); assert(cpu_number() == 0); assert(cpu_datap(0)->cpu_number == 0); - + /* Lights out for this */ istate = ml_set_interrupts_enabled(FALSE); -#ifdef TOPO_DEBUG - DBG("cpu_topology_start() %d cpu%s registered\n", - ncpus, (ncpus > 1) ? "s" : ""); - for (i = 0; i < ncpus; i++) { - cpu_data_t *cpup = cpu_datap(i); - DBG("\tcpu_data[%d]:0x%08x local apic 0x%x\n", - i, (unsigned) cpup, cpup->cpu_phys_number); + if (topo_dbg) { + TOPO_DBG("cpu_topology_start() %d cpu%s registered\n", + ncpus, (ncpus > 1) ? "s" : ""); + for (i = 0; i < ncpus; i++) { + cpu_data_t *cpup = cpu_datap(i); + TOPO_DBG("\tcpu_data[%d]:%p local apic 0x%x\n", + i, (void *) cpup, cpup->cpu_phys_number); + } } -#endif + /* * Re-order the cpu_data_ptr vector sorting by physical id. * Skip the boot processor, it's required to be correct. @@ -102,49 +109,59 @@ cpu_topology_start(void) sizeof(cpu_data_t *), lapicid_cmp); } -#ifdef TOPO_DEBUG - DBG("cpu_topology_start() after sorting:\n"); - for (i = 0; i < ncpus; i++) { - cpu_data_t *cpup = cpu_datap(i); - DBG("\tcpu_data[%d]:0x%08x local apic 0x%x\n", - i, (unsigned) cpup, cpup->cpu_phys_number); + if (topo_dbg) { + TOPO_DBG("cpu_topology_start() after sorting:\n"); + for (i = 0; i < ncpus; i++) { + cpu_data_t *cpup = cpu_datap(i); + TOPO_DBG("\tcpu_data[%d]:%p local apic 0x%x\n", + i, (void *) cpup, cpup->cpu_phys_number); + } } -#endif /* - * Fix up logical numbers and reset the map kept by the lapic code. + * Finalize logical numbers and map kept by the lapic code. */ - for (i = 1; i < ncpus; i++) { + for (i = 0; i < ncpus; i++) { cpu_data_t *cpup = cpu_datap(i); if (cpup->cpu_number != i) { - kprintf("cpu_datap(%d):0x%08x local apic id 0x%x " + kprintf("cpu_datap(%d):%p local apic id 0x%x " "remapped from %d\n", - i, (unsigned) cpup, cpup->cpu_phys_number, + i, cpup, cpup->cpu_phys_number, cpup->cpu_number); } cpup->cpu_number = i; - cpup->lcpu.lnum = i; lapic_cpu_map(cpup->cpu_phys_number, i); + x86_set_logical_topology(&cpup->lcpu, cpup->cpu_phys_number, i); } + cpu_shadow_sort(ncpus); + x86_validate_topology(); + ml_set_interrupts_enabled(istate); + TOPO_DBG("cpu_topology_start() LLC is L%d\n", topoParms.LLCDepth + 1); + + /* + * Let the CPU Power Management know that the topology is stable. + */ + topoParms.stable = TRUE; + pmCPUStateInit(); /* * Iterate over all logical cpus finding or creating the affinity set - * for their L2 cache. Each affinity set possesses a processor set + * for their LLC cache. Each affinity set possesses a processor set * into which each logical processor is added. */ - DBG("cpu_topology_start() creating affinity sets:\n"); + TOPO_DBG("cpu_topology_start() creating affinity sets:\n"); for (i = 0; i < ncpus; i++) { cpu_data_t *cpup = cpu_datap(i); x86_lcpu_t *lcpup = cpu_to_lcpu(i); - x86_cpu_cache_t *L2_cachep; + x86_cpu_cache_t *LLC_cachep; x86_affinity_set_t *aset; - L2_cachep = lcpup->caches[CPU_CACHE_DEPTH_L2]; - assert(L2_cachep->type == CPU_CACHE_TYPE_UNIF); - aset = find_cache_affinity(L2_cachep); + LLC_cachep = lcpup->caches[topoParms.LLCDepth]; + assert(LLC_cachep->type == CPU_CACHE_TYPE_UNIF); + aset = find_cache_affinity(LLC_cachep); if (aset == NULL) { aset = (x86_affinity_set_t *) kalloc(sizeof(*aset)); if (aset == NULL) @@ -152,32 +169,50 @@ cpu_topology_start(void) aset->next = x86_affinities; x86_affinities = aset; aset->num = x86_affinity_count++; - aset->cache = L2_cachep; + aset->cache = LLC_cachep; aset->pset = (i == master_cpu) ? processor_pset(master_processor) : pset_create(pset_node_root()); if (aset->pset == PROCESSOR_SET_NULL) panic("cpu_topology_start: pset_create"); - DBG("\tnew set %p(%d) pset %p for cache %p\n", + TOPO_DBG("\tnew set %p(%d) pset %p for cache %p\n", aset, aset->num, aset->pset, aset->cache); } - DBG("\tprocessor_init set %p(%d) lcpup %p(%d) cpu %p processor %p\n", - aset, aset->num, lcpup, lcpup->lnum, cpup, cpup->cpu_processor); + TOPO_DBG("\tprocessor_init set %p(%d) lcpup %p(%d) cpu %p processor %p\n", + aset, aset->num, lcpup, lcpup->cpu_num, cpup, cpup->cpu_processor); if (i != master_cpu) processor_init(cpup->cpu_processor, i, aset->pset); + + if (lcpup->core->num_lcpus > 1) { + if (lcpup->lnum == 0) + lprim = cpup->cpu_processor; + + processor_set_primary(cpup->cpu_processor, lprim); + } } +} - /* - * Finally we start all processors (including the boot cpu we're - * running on). - */ - DBG("cpu_topology_start() processor_start():\n"); - for (i = 0; i < ncpus; i++) { - DBG("\tlcpu %d\n", cpu_datap(i)->cpu_number); +/* We got a request to start a CPU. Check that this CPU is within the + * max cpu limit set before we do. + */ +kern_return_t +cpu_topology_start_cpu( int cpunum ) +{ + int ncpus = machine_info.max_cpus; + int i = cpunum; + + /* Decide whether to start a CPU, and actually start it */ + TOPO_DBG("cpu_topology_start() processor_start():\n"); + if( i < ncpus) + { + TOPO_DBG("\tlcpu %d\n", cpu_datap(i)->cpu_number); processor_start(cpu_datap(i)->cpu_processor); + return KERN_SUCCESS; } + else + return KERN_FAILURE; } static int @@ -186,7 +221,7 @@ lapicid_cmp(const void *x, const void *y) cpu_data_t *cpu_x = *((cpu_data_t **)(uintptr_t)x); cpu_data_t *cpu_y = *((cpu_data_t **)(uintptr_t)y); - DBG("lapicid_cmp(%p,%p) (%d,%d)\n", + TOPO_DBG("lapicid_cmp(%p,%p) (%d,%d)\n", x, y, cpu_x->cpu_phys_number, cpu_y->cpu_phys_number); if (cpu_x->cpu_phys_number < cpu_y->cpu_phys_number) return -1; @@ -222,8 +257,7 @@ ml_affinity_to_pset(uint32_t affinity_num) if (affinity_num == aset->num) break; } - return (aset == NULL) ? PROCESSOR_SET_NULL : aset->pset; - + return (aset == NULL) ? PROCESSOR_SET_NULL : aset->pset; } uint64_t @@ -233,7 +267,7 @@ ml_cpu_cache_size(unsigned int level) if (level == 0) { return machine_info.max_mem; - } else if ( 1 <= level && level <= 3) { + } else if ( 1 <= level && level <= MAX_CACHE_DEPTH) { cachep = current_cpu_datap()->lcpu.caches[level-1]; return cachep ? cachep->cache_size : 0; } else { @@ -248,7 +282,7 @@ ml_cpu_cache_sharing(unsigned int level) if (level == 0) { return machine_info.max_cpus; - } else if ( 1 <= level && level <= 3) { + } else if ( 1 <= level && level <= MAX_CACHE_DEPTH) { cachep = current_cpu_datap()->lcpu.caches[level-1]; return cachep ? cachep->nlcpus : 0; } else {