Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/cpuctl/arch Get CPU topology data for AMD processors.



details:   https://anonhg.NetBSD.org/src/rev/7fb8bce8cf32
branches:  trunk
changeset: 998986:7fb8bce8cf32
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Fri May 10 16:42:57 2019 +0000

description:
Get CPU topology data for AMD processors.

diffstat:

 usr.sbin/cpuctl/arch/cpuctl_i386.h |   3 +-
 usr.sbin/cpuctl/arch/i386-asm.S    |  14 ++++++-
 usr.sbin/cpuctl/arch/i386.c        |  81 +++++++++++++++++++++++++++++++++++++-
 usr.sbin/cpuctl/arch/x86_64-asm.S  |  14 ++++++-
 4 files changed, 107 insertions(+), 5 deletions(-)

diffs (201 lines):

diff -r b7b58c38a04c -r 7fb8bce8cf32 usr.sbin/cpuctl/arch/cpuctl_i386.h
--- a/usr.sbin/cpuctl/arch/cpuctl_i386.h        Fri May 10 16:28:00 2019 +0000
+++ b/usr.sbin/cpuctl/arch/cpuctl_i386.h        Fri May 10 16:42:57 2019 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: cpuctl_i386.h,v 1.2 2013/01/07 23:20:42 dsl Exp $      */
+/*      $NetBSD: cpuctl_i386.h,v 1.3 2019/05/10 16:42:57 mlelstv Exp $      */
 
 /* Interfaces to code in i386-asm.S */
 
@@ -7,3 +7,4 @@
 void x86_cpuid2(uint32_t, uint32_t, uint32_t *);
 uint32_t x86_identify(void);
 uint32_t x86_xgetbv(void);
+uint64_t rdmsr(u_int);
diff -r b7b58c38a04c -r 7fb8bce8cf32 usr.sbin/cpuctl/arch/i386-asm.S
--- a/usr.sbin/cpuctl/arch/i386-asm.S   Fri May 10 16:28:00 2019 +0000
+++ b/usr.sbin/cpuctl/arch/i386-asm.S   Fri May 10 16:42:57 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i386-asm.S,v 1.4 2015/03/01 18:02:42 tnn Exp $ */
+/*     $NetBSD: i386-asm.S,v 1.5 2019/05/10 16:42:57 mlelstv Exp $     */
 
 /*-
  * Copyright (c) 1998, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
@@ -30,6 +30,9 @@
 #include <machine/cputypes.h>
 #include <machine/psl.h>
 
+/* From sys/arch/x86/include/cpufunc.h */
+#define        OPTERON_MSR_PASSCODE    0x9c5a203aU
+
        .text
 
 ENTRY(x86_cpuid2)
@@ -160,3 +163,12 @@
 is486dlc:
        movl    $CPU_486DLC,%eax
        ret
+
+ENTRY(rdmsr_locked)
+       movl    4(%esp), %ecx
+       pushl   %edi
+       movl    $OPTERON_MSR_PASSCODE, %edi
+       rdmsr
+       popl    %edi
+       ret
+END(rdmsr_locked)
diff -r b7b58c38a04c -r 7fb8bce8cf32 usr.sbin/cpuctl/arch/i386.c
--- a/usr.sbin/cpuctl/arch/i386.c       Fri May 10 16:28:00 2019 +0000
+++ b/usr.sbin/cpuctl/arch/i386.c       Fri May 10 16:42:57 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i386.c,v 1.95 2019/03/24 04:43:54 msaitoh Exp $        */
+/*     $NetBSD: i386.c,v 1.96 2019/05/10 16:42:57 mlelstv Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: i386.c,v 1.95 2019/03/24 04:43:54 msaitoh Exp $");
+__RCSID("$NetBSD: i386.c,v 1.96 2019/05/10 16:42:57 mlelstv Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -119,6 +119,7 @@
        uint8_t         ci_coreid;
        uint8_t         ci_smtid;
        uint32_t        ci_initapicid;
+       uint32_t        ci_max_ext_cpuid;
 
        uint32_t        ci_cur_xsave;
        uint32_t        ci_max_xsave;
@@ -1925,6 +1926,76 @@
 }
 
 static void
+identifycpu_cpuids_amd(struct cpu_info *ci)
+{
+       const char *cpuname = ci->ci_dev;
+       u_int lp_max, core_max;
+       int n, cpu_family, apic_id, smt_bits, core_bits = 0;
+       uint32_t descs[4];
+
+       apic_id = ci->ci_initapicid;
+       cpu_family = CPUID_TO_FAMILY(ci->ci_signature);
+
+       if (cpu_family < 0xf)
+               return;
+
+       if ((ci->ci_feat_val[0] & CPUID_HTT) != 0) {
+               x86_cpuid(1, descs);
+               lp_max = __SHIFTOUT(descs[1], CPUID_HTT_CORES);
+
+               if (cpu_family >= 0x10 && ci->ci_max_ext_cpuid >= 0x8000008) {
+                       x86_cpuid(0x8000008, descs);
+                       core_max = (descs[2] & 0xff) + 1;
+                       n = (descs[2] >> 12) & 0x0f;
+                       if (n != 0)
+                               core_bits = n;
+               }
+       } else {
+               lp_max = 1;
+       }
+       core_max = lp_max;
+
+       smt_bits = ilog2((lp_max / core_max) - 1) + 1;
+       if (core_bits == 0)
+               core_bits = ilog2(core_max - 1) + 1;
+
+       if (cpu_family < 0x11) {
+               const uint64_t reg = rdmsr(MSR_NB_CFG);
+               if ((reg & NB_CFG_INITAPICCPUIDLO) == 0) {
+                       const u_int node_id = apic_id & __BITS(0, 2);
+                       apic_id = (cpu_family == 0xf) ?
+                               (apic_id >> core_bits) | (node_id << core_bits) :
+                               (apic_id >> 5) | (node_id << 2);
+               }
+       }
+
+       if (cpu_family == 0x17) {
+               x86_cpuid(0x8000001e, descs);
+               const u_int threads = ((descs[1] >> 8) & 0xff) + 1;
+               smt_bits = ilog2(threads);
+               core_bits -= smt_bits;
+       }
+
+       if (smt_bits + core_bits) {
+               if (smt_bits + core_bits < 32)
+                       ci->ci_packageid = 0;
+       }
+       if (core_bits) {
+               u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
+               ci->ci_coreid = __SHIFTOUT(apic_id, core_mask);
+       }
+       if (smt_bits) {
+               u_int smt_mask = __BITS(0, smt_bits - 1);
+               ci->ci_smtid = __SHIFTOUT(apic_id, smt_mask);
+       }
+
+       aprint_verbose("%s: Cluster/Package ID %u\n", cpuname,
+           ci->ci_packageid);
+       aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid);
+       aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid);
+}
+
+static void
 identifycpu_cpuids(struct cpu_info *ci)
 {
        const char *cpuname = ci->ci_dev;
@@ -1936,6 +2007,8 @@
 
        if (cpu_vendor == CPUVENDOR_INTEL)
                identifycpu_cpuids_intel(ci);
+       else if (cpu_vendor == CPUVENDOR_AMD)
+               identifycpu_cpuids_amd(ci);
 }
 
 void
@@ -2213,6 +2286,10 @@
 
        if (cpu_vendor == CPUVENDOR_AMD) {
                x86_cpuid(0x80000000, descs);
+               if (descs[0] >= 0x80000000)
+                       ci->ci_max_ext_cpuid = descs[0];
+               else
+                       ci->ci_max_ext_cpuid = 0;
                if (descs[0] >= 0x80000007)
                        powernow_probe(ci);
 
diff -r b7b58c38a04c -r 7fb8bce8cf32 usr.sbin/cpuctl/arch/x86_64-asm.S
--- a/usr.sbin/cpuctl/arch/x86_64-asm.S Fri May 10 16:28:00 2019 +0000
+++ b/usr.sbin/cpuctl/arch/x86_64-asm.S Fri May 10 16:42:57 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: x86_64-asm.S,v 1.5 2015/03/01 18:02:42 tnn Exp $       */
+/*     $NetBSD: x86_64-asm.S,v 1.6 2019/05/10 16:42:57 mlelstv Exp $   */
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -28,6 +28,9 @@
 
 #include <machine/asm.h>
 
+/* From sys/arch/x86/include/cpufunc.h */
+#define        OPTERON_MSR_PASSCODE    0x9c5a203aU
+
        .text
 
 ENTRY(x86_cpuid2)
@@ -51,3 +54,12 @@
 ENTRY(x86_identify)
        movl    $-1,%eax
        ret
+
+ENTRY(rdmsr)
+       movq    %rdi, %rcx
+       xorq    %rax, %rax
+       movl    $OPTERON_MSR_PASSCODE, %edi
+       rdmsr
+       shlq    $32, %rdx
+       orq     %rdx, %rax
+       ret



Home | Main Index | Thread Index | Old Index