diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2018-06-20 19:30:35 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2018-06-20 19:30:35 +0000 |
commit | d4bd76807e6d4dc86020e7ecd56467ce0fc55c67 (patch) | |
tree | 4941e9e9e9f34ce6428ab45348467ddec4eac3e3 /sys/arch/amd64 | |
parent | e9ddf331e5ebd06456b8148a42ffe1db7246750c (diff) |
On newer AMD parts, use CoreId (EBX) and NodeId (ECX) from cpuid 0x8000001e
to detect smt cores. As there's no "smt id" on these like there is on Intel
parts, check against other already-id'd cpus to detect which are additional
smt threads on a core.
jmatthew noticed some unusual (non-contiguous) numbering on an single
socket EPYC 7551p but there's no indication that the actual ID numbers
need to be sequential.
"As long as we treat ci_core_id as just a number, that shouldn't be an
issue" and OK kettenis@
ref: 54945 rev 1.14 - PPR for AMD Family 17h Models 00h-0Fh
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/amd64/identcpu.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c index da6a3ca68d5..bbe1c118ac6 100644 --- a/sys/arch/amd64/amd64/identcpu.c +++ b/sys/arch/amd64/amd64/identcpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: identcpu.c,v 1.96 2018/06/07 04:07:28 guenther Exp $ */ +/* $OpenBSD: identcpu.c,v 1.97 2018/06/20 19:30:34 sthen Exp $ */ /* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /* @@ -792,18 +792,36 @@ cpu_topology(struct cpu_info *ci) if (ci->ci_pnfeatset < 0x80000008) goto no_topology; - CPUID(0x80000008, eax, ebx, ecx, edx); - core_bits = (ecx >> 12) & 0xf; - if (core_bits == 0) - goto no_topology; - /* So coreidsize 2 gives 3, 3 gives 7... */ - core_mask = (1 << core_bits) - 1; - /* Core id is the least significant considering mask */ - ci->ci_core_id = apicid & core_mask; - /* Pkg id is the upper remaining bits */ - ci->ci_pkg_id = apicid & ~core_mask; - ci->ci_pkg_id >>= core_bits; + if (ci->ci_pnfeatset >= 0x8000001e) { + struct cpu_info *ci_other; + CPU_INFO_ITERATOR cii; + + CPUID(0x8000001e, eax, ebx, ecx, edx); + ci->ci_core_id = ebx & 0xff; + ci->ci_pkg_id = ecx & 0xff; + ci->ci_smt_id = 0; + CPU_INFO_FOREACH(cii, ci_other) { + if (ci != ci_other && + ci_other->ci_core_id == ci->ci_core_id) + ci->ci_smt_id++; + } + } else { + CPUID(0x80000008, eax, ebx, ecx, edx); + core_bits = (ecx >> 12) & 0xf; + if (core_bits == 0) + goto no_topology; + /* So coreidsize 2 gives 3, 3 gives 7... */ + core_mask = (1 << core_bits) - 1; + /* Core id is the least significant considering mask */ + ci->ci_core_id = apicid & core_mask; + /* Pkg id is the upper remaining bits */ + ci->ci_pkg_id = apicid & ~core_mask; + ci->ci_pkg_id >>= core_bits; + } } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + struct cpu_info *ci_other; + CPU_INFO_ITERATOR cii; + /* We only support leaf 1/4 detection */ if (cpuid_level < 4) goto no_topology; @@ -824,9 +842,15 @@ cpu_topology(struct cpu_info *ci) pkg_bits = core_bits + smt_bits; pkg_mask = -1 << core_bits; - ci->ci_smt_id = apicid & smt_mask; + // ci->ci_smt_id = apicid & smt_mask; ci->ci_core_id = (apicid & core_mask) >> smt_bits; ci->ci_pkg_id = (apicid & pkg_mask) >> pkg_bits; + ci->ci_smt_id = 0; + CPU_INFO_FOREACH(cii, ci_other) { + if (ci != ci_other && + ci_other->ci_core_id == ci->ci_core_id) + ci->ci_smt_id++; + } } else goto no_topology; #ifdef DEBUG |