summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2018-06-20 19:30:35 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2018-06-20 19:30:35 +0000
commitd4bd76807e6d4dc86020e7ecd56467ce0fc55c67 (patch)
tree4941e9e9e9f34ce6428ab45348467ddec4eac3e3 /sys/arch/amd64
parente9ddf331e5ebd06456b8148a42ffe1db7246750c (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.c50
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