diff options
author | Len Brown <len.brown@intel.com> | 2018-08-07 20:22:28 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2018-11-02 14:06:30 -0400 |
commit | 3404155190ce09a1e5d8407e968fc19aac4493e3 (patch) | |
tree | 827034b69f0d78a3397cc94c5638cc7aaf968d50 | |
parent | d81f50bd34646d8373b989e55180c0fc9af94e0b (diff) | |
download | linux-3404155190ce09a1e5d8407e968fc19aac4493e3.tar.bz2 |
tools/power turbosat: fix AMD APIC-id output
turbostat recently gained a feature adding APIC and X2APIC columns.
While they are disabled by-default, they are enabled with --debug
or when explicitly requested, eg.
$ sudo turbostat --quiet --show Package,Node,Core,CPU,APIC,X2APIC date
But these columns erroneously showed zeros on AMD hardware.
This patch corrects the APIC and X2APIC [sic] columns on AMD.
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 328f62e6ea02..092853123ddb 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1,6 +1,6 @@ /* * turbostat -- show CPU frequency and C-state residency - * on modern Intel turbo-capable processors. + * on modern Intel and AMD processors. * * Copyright (c) 2013 Intel Corporation. * Len Brown <len.brown@intel.com> @@ -71,6 +71,8 @@ unsigned int do_irtl_snb; unsigned int do_irtl_hsw; unsigned int units = 1000000; /* MHz etc */ unsigned int genuine_intel; +unsigned int authentic_amd; +unsigned int max_level, max_extended_level; unsigned int has_invariant_tsc; unsigned int do_nhm_platform_info; unsigned int no_MSR_MISC_PWR_MGMT; @@ -1667,30 +1669,51 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp) void get_apic_id(struct thread_data *t) { - unsigned int eax, ebx, ecx, edx, max_level; + unsigned int eax, ebx, ecx, edx; - eax = ebx = ecx = edx = 0; + if (DO_BIC(BIC_APIC)) { + eax = ebx = ecx = edx = 0; + __cpuid(1, eax, ebx, ecx, edx); - if (!genuine_intel) + t->apic_id = (ebx >> 24) & 0xff; + } + + if (!DO_BIC(BIC_X2APIC)) return; - __cpuid(0, max_level, ebx, ecx, edx); + if (authentic_amd) { + unsigned int topology_extensions; - __cpuid(1, eax, ebx, ecx, edx); - t->apic_id = (ebx >> 24) & 0xf; + if (max_extended_level < 0x8000001e) + return; - if (max_level < 0xb) + eax = ebx = ecx = edx = 0; + __cpuid(0x80000001, eax, ebx, ecx, edx); + topology_extensions = ecx & (1 << 22); + + if (topology_extensions == 0) + return; + + eax = ebx = ecx = edx = 0; + __cpuid(0x8000001e, eax, ebx, ecx, edx); + + t->x2apic_id = eax; return; + } - if (!DO_BIC(BIC_X2APIC)) + if (!genuine_intel) + return; + + if (max_level < 0xb) return; ecx = 0; __cpuid(0xb, eax, ebx, ecx, edx); t->x2apic_id = edx; - if (debug && (t->apic_id != t->x2apic_id)) - fprintf(outf, "cpu%d: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id); + if (debug && (t->apic_id != (t->x2apic_id & 0xff))) + fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n", + t->cpu_id, t->apic_id, t->x2apic_id); } /* @@ -4438,16 +4461,18 @@ void decode_c6_demotion_policy_msr(void) void process_cpuid() { - unsigned int eax, ebx, ecx, edx, max_level, max_extended_level; - unsigned int fms, family, model, stepping; + unsigned int eax, ebx, ecx, edx; + unsigned int fms, family, model, stepping, ecx_flags, edx_flags; unsigned int has_turbo; eax = ebx = ecx = edx = 0; __cpuid(0, max_level, ebx, ecx, edx); - if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) + if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) genuine_intel = 1; + else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) + authentic_amd = 1; if (!quiet) fprintf(outf, "CPUID(0): %.4s%.4s%.4s ", @@ -4461,25 +4486,8 @@ void process_cpuid() family += (fms >> 20) & 0xff; if (family >= 6) model += ((fms >> 16) & 0xf) << 4; - - if (!quiet) { - fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", - max_level, family, model, stepping, family, model, stepping); - fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n", - ecx & (1 << 0) ? "SSE3" : "-", - ecx & (1 << 3) ? "MONITOR" : "-", - ecx & (1 << 6) ? "SMX" : "-", - ecx & (1 << 7) ? "EIST" : "-", - ecx & (1 << 8) ? "TM2" : "-", - edx & (1 << 4) ? "TSC" : "-", - edx & (1 << 5) ? "MSR" : "-", - edx & (1 << 22) ? "ACPI-TM" : "-", - edx & (1 << 28) ? "HT" : "-", - edx & (1 << 29) ? "TM" : "-"); - } - - if (!(edx & (1 << 5))) - errx(1, "CPUID: no MSR"); + ecx_flags = ecx; + edx_flags = edx; /* * check max extended function levels of CPUID. @@ -4489,6 +4497,25 @@ void process_cpuid() ebx = ecx = edx = 0; __cpuid(0x80000000, max_extended_level, ebx, ecx, edx); + if (!quiet) { + fprintf(outf, "0x%x CPUID levels; 0x%x xlevels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", + max_level, max_extended_level, family, model, stepping, family, model, stepping); + fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n", + ecx_flags & (1 << 0) ? "SSE3" : "-", + ecx_flags & (1 << 3) ? "MONITOR" : "-", + ecx_flags & (1 << 6) ? "SMX" : "-", + ecx_flags & (1 << 7) ? "EIST" : "-", + ecx_flags & (1 << 8) ? "TM2" : "-", + edx_flags & (1 << 4) ? "TSC" : "-", + edx_flags & (1 << 5) ? "MSR" : "-", + edx_flags & (1 << 22) ? "ACPI-TM" : "-", + edx_flags & (1 << 28) ? "HT" : "-", + edx_flags & (1 << 29) ? "TM" : "-"); + } + + if (!(edx_flags & (1 << 5))) + errx(1, "CPUID: no MSR"); + if (max_extended_level >= 0x80000007) { /* |