--- mp_machdep.c.orig 2010-06-22 12:20:10.000000000 -0400 +++ mp_machdep.c 2010-07-15 15:14:13.000000000 -0400 @@ -177,19 +177,76 @@ mem_range_AP_init(void) } static void -topo_probe_0xb(void) +topo_probe_amd(void) +{ + + /* AMD processors do not support HTT. */ + cpu_cores = (amd_feature2 & AMDID2_CMP) != 0 ? + (cpu_procinfo2 & AMDID_CMP_CORES) + 1 : 1; + cpu_logical = 1; +} + +static void +topo_probe_0x4(void) { + u_int p[4]; + int cores; + int i; + int level; int logical; - int p[4]; - int bits; int type; + + cpu_logical = (cpu_feature & CPUID_HTT) != 0 ? + (cpu_procinfo & CPUID_HTT_CORES) >> 16 : 1; + if (cpu_logical == 1) { + cpu_cores = 1; + return; + } + + /* We only support three levels for now. */ + for (i = 0; i < 3; i++) { + cpuid_count(0x04, i, p); + type = p[0] & 0x1f; + level = (p[0] >> 5) & 0x7; + logical = ((p[0] >> 14) & 0xfff) + 1; + cores = ((p[0] >> 26) & 0x3f) + 1; + if (type == 0) + break; + if (level == 1 && cpu_logical == logical * cores) { + cpu_cores = cores; + cpu_logical = logical; + break; + } + } + if (cpu_cores == 0) + cpu_cores = 1; + if (cpu_logical > 1) + hyperthreading_cpus = logical_cpus = cpu_logical; +} + +static void +topo_probe_0xb(void) +{ + u_int p[4]; + int bits; int cnt; int i; + int logical; + int type; int x; - /* We only support two levels for now. */ + /* We only support three levels for now. */ for (i = 0; i < 3; i++) { - cpuid_count(0x0B, i, p); + cpuid_count(0x0b, i, p); + + /* + * Fall back if it is not really supported. + */ + if (i == 0 && p[1] == 0) { + topo_probe_0x4(); + return; + } + bits = p[0] & 0x1f; logical = p[1] &= 0xffff; type = (p[2] >> 8) & 0xff; @@ -213,76 +270,6 @@ topo_probe_0xb(void) } static void -topo_probe_0x4(void) -{ - u_int threads_per_cache, p[4]; - u_int htt, cmp; - int i; - - htt = cmp = 1; - /* - * If this CPU supports HTT or CMP then mention the - * number of physical/logical cores it contains. - */ - if (cpu_feature & CPUID_HTT) - htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16; - if (cpu_vendor_id == CPU_VENDOR_AMD && (amd_feature2 & AMDID2_CMP)) - cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1; - else if (cpu_vendor_id == CPU_VENDOR_INTEL && (cpu_high >= 4)) { - cpuid_count(4, 0, p); - if ((p[0] & 0x1f) != 0) - cmp = ((p[0] >> 26) & 0x3f) + 1; - } - cpu_cores = cmp; - cpu_logical = htt / cmp; - - /* Setup the initial logical CPUs info. */ - if (cpu_feature & CPUID_HTT) - logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; - - /* - * Work out if hyperthreading is *really* enabled. This - * is made really ugly by the fact that processors lie: Dual - * core processors claim to be hyperthreaded even when they're - * not, presumably because they want to be treated the same - * way as HTT with respect to per-cpu software licensing. - * At the time of writing (May 12, 2005) the only hyperthreaded - * cpus are from Intel, and Intel's dual-core processors can be - * identified via the "deterministic cache parameters" cpuid - * calls. - */ - /* - * First determine if this is an Intel processor which claims - * to have hyperthreading support. - */ - if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) { - /* - * If the "deterministic cache parameters" cpuid calls - * are available, use them. - */ - if (cpu_high >= 4) { - /* Ask the processor about the L1 cache. */ - for (i = 0; i < 1; i++) { - cpuid_count(4, i, p); - threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1; - if (hyperthreading_cpus < threads_per_cache) - hyperthreading_cpus = threads_per_cache; - if ((p[0] & 0x1f) == 0) - break; - } - } - - /* - * If the deterministic cache parameters are not - * available, or if no caches were reported to exist, - * just accept what the HTT flag indicated. - */ - if (hyperthreading_cpus == 0) - hyperthreading_cpus = logical_cpus; - } -} - -static void topo_probe(void) { static int cpu_topo_probed = 0; @@ -291,10 +278,14 @@ topo_probe(void) return; logical_cpus = logical_cpus_mask = 0; - if (cpu_high >= 0xb) - topo_probe_0xb(); - else if (cpu_high) - topo_probe_0x4(); + if (cpu_vendor_id == CPU_VENDOR_AMD) + topo_probe_amd(); + else if (cpu_vendor_id == CPU_VENDOR_INTEL) { + if (cpu_high >= 0xb) + topo_probe_0xb(); + else if (cpu_high >= 0x4) + topo_probe_0x4(); + } if (cpu_cores == 0) cpu_cores = mp_ncpus > 0 ? mp_ncpus : 1; if (cpu_logical == 0)