Skip to content

Commit 6af2ed5

Browse files
Janakarajan Natarajanshuahkh
authored andcommitted
cpupower: mperf_monitor: Update cpupower to use the RDPRU instruction
AMD Zen 2 introduces the RDPRU instruction which can be used to access some processor registers which are typically only accessible in privilege level 0. ECX specifies the register to read and EDX:EAX will contain the value read. ECX: 0 - Register MPERF 1 - Register APERF This has the added advantage of not having to use the msr module, since the userspace to kernel transitions which occur during each read_msr() might cause APERF and MPERF to go out of sync. Signed-off-by: Janakarajan Natarajan <[email protected]> Acked-by: Thomas Renninger <[email protected]> Signed-off-by: Shuah Khan <[email protected]>
1 parent 7adafe5 commit 6af2ed5

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

tools/power/cpupower/utils/helpers/cpuid.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
131131
if (ext_cpuid_level >= 0x80000007 &&
132132
(cpuid_edx(0x80000007) & (1 << 9)))
133133
cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
134+
135+
if (ext_cpuid_level >= 0x80000008 &&
136+
cpuid_ebx(0x80000008) & (1 << 4))
137+
cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
134138
}
135139

136140
if (cpu_info->vendor == X86_VENDOR_INTEL) {

tools/power/cpupower/utils/helpers/helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
6969
#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010
7070
#define CPUPOWER_CAP_IS_SNB 0x00000020
7171
#define CPUPOWER_CAP_INTEL_IDA 0x00000040
72+
#define CPUPOWER_CAP_AMD_RDPRU 0x00000080
7273

7374
#define CPUPOWER_AMD_CPBDIS 0x02000000
7475

tools/power/cpupower/utils/idle_monitor/mperf_monitor.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#define MSR_APERF 0xE8
2020
#define MSR_MPERF 0xE7
2121

22+
#define RDPRU ".byte 0x0f, 0x01, 0xfd"
23+
#define RDPRU_ECX_MPERF 0
24+
#define RDPRU_ECX_APERF 1
25+
2226
#define MSR_TSC 0x10
2327

2428
#define MSR_AMD_HWCR 0xc0010015
@@ -89,6 +93,8 @@ static int mperf_get_tsc(unsigned long long *tsc)
8993
static int get_aperf_mperf(int cpu, unsigned long long *aval,
9094
unsigned long long *mval)
9195
{
96+
unsigned long low_a, high_a;
97+
unsigned long low_m, high_m;
9298
int ret;
9399

94100
/*
@@ -101,6 +107,20 @@ static int get_aperf_mperf(int cpu, unsigned long long *aval,
101107
return 1;
102108
}
103109

110+
if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_RDPRU) {
111+
asm volatile(RDPRU
112+
: "=a" (low_a), "=d" (high_a)
113+
: "c" (RDPRU_ECX_APERF));
114+
asm volatile(RDPRU
115+
: "=a" (low_m), "=d" (high_m)
116+
: "c" (RDPRU_ECX_MPERF));
117+
118+
*aval = ((low_a) | (high_a) << 32);
119+
*mval = ((low_m) | (high_m) << 32);
120+
121+
return 0;
122+
}
123+
104124
ret = read_msr(cpu, MSR_APERF, aval);
105125
ret |= read_msr(cpu, MSR_MPERF, mval);
106126

0 commit comments

Comments
 (0)