Skip to contentSkip to conversation

perf/x86: Do not read fixed counter control register if there is none

PATCH In review Petr Tesarik 4 participants 8 messages Jul 17 – Aug 5

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 perf/x86: Do not read fixed counter control register if there is none

When printing out CPU performance registers for debugging, skip MSR_ARCH_PERFMON_FIXED_CTR_CTRL if fixed counters are not implemented.

Since AMD CPUs with PerMonV2 do not implement this register, attempts to read it generate a #GP. In particular, SysRq-P logs something like this:

[   14.748144] [   T1118] sysrq: Show Regs
[   14.748896] [   T1118] unchecked MSR access error: RDMSR from 0x38d at rIP: 0xffffffff937154c6 (native_read_msr+0x6/0x40)
[   14.750878] [   T1118] Call Trace:
[   14.751505] [   T1118]  <TASK>
[   14.752057] [   T1118]  paravirt_read_msr+0x7/0x10
[   14.752940] [   T1118]  perf_event_print_debug+0x135/0x240
[   14.753931] [   T1118]  __handle_sysrq.cold+0x9b/0xde
[   14.754855] [   T1118]  write_sysrq_trigger+0x59/0x80
[   14.755779] [   T1118]  proc_reg_write+0x5a/0xb0
[   14.756631] [   T1118]  vfs_write+0xce/0x430
[   14.757406] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.758322] [   T1118]  ? security_file_fcntl+0x5f/0x120
[   14.759083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.759754] [   T1118]  ? __x64_sys_fcntl+0x80/0x110
[   14.760334] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761005] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761676] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.762270] [   T1118]  ksys_write+0x6a/0xe0
[   14.762776] [   T1118]  do_syscall_64+0xe1/0x610
[   14.763324] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.763995] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.764564] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.765233] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.765806] [   T1118]  ? __x64_sys_ioctl+0x97/0xe0
[   14.766375] [   T1118]  ? __pfx_woken_wake_function+0x10/0x10
[   14.767048] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.767717] [   T1118]  ? get_close_on_exec+0x34/0x40
[   14.768311] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.768985] [   T1118]  ? do_fcntl+0x6da/0x8e0
[   14.769502] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.770083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.772321] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.773166] [   T1118]  ? tty_read+0x150/0x220
[   14.773722] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.774423] [   T1118]  ? filp_flush+0x5b/0x80
[   14.774966] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.775660] [   T1118]  ? filp_close+0x25/0x40
[   14.776214] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.776936] [   T1118]  ? do_dup2+0xae/0x140
[   14.777486] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.778309] [   T1118]  ? ksys_dup3+0x67/0xf0
[   14.778870] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.779600] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.780310] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.780917] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.781613] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.782215] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.782907] [   T1118]  ? ksys_read+0x6a/0xe0
[   14.783429] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.784120] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.784741] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.785431] [   T1118]  ? __ct_user_exit+0x15/0xb0
[   14.786014] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.786706] [   T1118]  ? do_syscall_64+0x98/0x610
[   14.787282] [   T1118]  ? exc_page_fault+0x6d/0x180
[   14.787873] [   T1118]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   14.788612] [   T1118] RIP: 0033:0x7f70d6497e0a
[   14.789186] [   T1118] Code: 08 03 00 00 59 5e 48 83 f8 fc 75 1e 83 e2 39 83 fa 08 75 16 e8 05 ff ff ff 0f 1f 80 00 00 00 00 49 89 ca 48 8b 44 24 20 0f 05 <48> 83 c4 18 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f
[   14.791587] [   T1118] RSP: 002b:00007ffc36a93580 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[   14.792617] [   T1118] RAX: ffffffffffffffda RBX: 00007f70d65f6580 RCX: 00007f70d6497e0a
[   14.793594] [   T1118] RDX: 0000000000000002 RSI: 0000556f34e41c30 RDI: 0000000000000001
[   14.794574] [   T1118] RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
[   14.795563] [   T1118] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
[   14.796537] [   T1118] R13: 0000556f34e41c30 R14: 0000000000000001 R15: 0000000000000000
[   14.797514] [   T1118]  </TASK>
---
 arch/x86/events/core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
arch/x86/events/core.c +5 -2
index d1af33d96d0a3..8310bedfc364f 100644
@@ -1581,13 +1581,16 @@ void perf_event_print_debug(void)
 		rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
 		rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
 		rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
-		rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
 		pr_info("\n");
 		pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
 		pr_info("CPU#%d: status:     %016llx\n", cpu, status);
 		pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-		pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+		if (x86_pmu.fixedctr) {
+			rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+			pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+		}
 		if (pebs_constraints) {
 			rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
 			pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
Signature · 1 line
2.54.0
#1 lore raw
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Medium] Using x86_pmu.fixedctr as a capability flag is conceptually flawed and suppresses valid debug output on Zhaoxin.

Pre-existing issues:
- [High] Zhaoxin PMU fails to initialize x86_pmu.fixedctr, leading to broken fixed counters and unsafe RDMSR accesses.
- [High] Undefined behavior in GENMASK_ULL during Zhaoxin PMU initialization if fixed counters are missing. --

--- Patch [1]: [PATCH 1/1] perf/x86: Do not read fixed counter control register if there is none --- commit d0dd53a6709a65141e2d105b19abad4d851825d4
Author: Petr Tesarik <[email protected]>

perf/x86: Do not read fixed counter control register if there is none

This patch skips reading the MSR_ARCH_PERFMON_FIXED_CTR_CTRL register during perf debug output if fixed counters are not implemented. This avoids a #GP on AMD CPUs with PerfMonV2 that do not implement this register.

Quoted 7 lines
arch/x86/events/core.c +0 -0
index 576baa9a52c5b..3055d59e0e82f 100644
@@ -1572,13 +1572,16 @@ void perf_event_print_debug(void)
 		rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
 		rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);

arch/x86/events/core.c void perf_event_print_debug(void) · line 1581

Quoted 10 lines
arch/x86/events/core.c +2 -2
 		rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
-		rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
 		pr_info("\n");
 		pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
 		pr_info("CPU#%d: status:     %016llx\n", cpu, status);
 		pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-		pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+		if (x86_pmu.fixedctr) {

[Severity: Medium]
Is it safe to use x86_pmu.fixedctr as a capability flag here?

The x86_pmu.fixedctr field is an MSR address, not a boolean capability flag. While this check works for most architectures, the Zhaoxin PMU driver fails to initialize this field, leaving it as 0. Because of this, the check evaluates to false and inadvertently suppresses the debug output of MSR_ARCH_PERFMON_FIXED_CTR_CTRL on Zhaoxin systems.

arch/x86/events/core.c void perf_event_print_debug(void) · line 1596

Quoted 6 lines
arch/x86/events/core.c +3 -0
+			rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+			pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+		}
 		if (pebs_constraints) {
 			rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
 			pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);

[ ... ]

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under review, but the lack of initialization for x86_pmu.fixedctr causes other issues.

In the Zhaoxin PMU driver setup:

arch/x86/events/zhaoxin/core.c:zhaoxin_pmu

static const struct x86_pmu zhaoxin_pmu __initconst = {
    ...
    /* missing .fixedctr = MSR_ARCH_PERFMON_FIXED_CTR0 */
};

Because this remains 0, x86_pmu_fixed_ctr_addr() returns 0 + idx instead of the correct MSR. This causes fixed counter 0 to silently return without updating in x86_perf_event_update():

arch/x86/events/core.c:x86_perf_event_update() {
    ...
    if (unlikely(!hwc->event_base))
        return 0;
    ...
}

It also leads to unsafe MSR reads when iterating over the fixed counter mask in perf_event_print_debug():

arch/x86/events/core.c:perf_event_print_debug() {
    ...
    for_each_set_bit(idx, fixed_cntr_mask, X86_PMC_IDX_MAX) {
        ...
        rdmsrq(x86_pmu_fixed_ctr_addr(idx), pmc_count);
        ...
    }
}

Could this lead to reads from arbitrary low MSRs like MSR 0, 1, or 2, potentially triggering a system crash if a user programs fixed counter events or triggers SysRq-P?

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under review, but does this bitmask generation in the Zhaoxin PMU initialization risk undefined behavior?

arch/x86/events/zhaoxin/core.c:zhaoxin_pmu_init() {
    ...
    x86_pmu.fixed_cntr_mask64 = GENMASK_ULL(edx.split.num_counters_fixed - 1, 0);
    ...
}

If a hypervisor configures the CPU to report 0 fixed counters, edx.split.num_counters_fixed - 1 wraps to -1. Expanding GENMASK_ULL(-1, 0) results in a right-shift by 64, which is undefined behavior in C. On x86, this yields ~0ULL, making the kernel assume 64 fixed counters exist.

Could this cause the kernel to attempt reading 64 undefined MSRs during debug output or event initialization, leading to #GP exceptions?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
#2 lore raw
Quoted 30 lines · On Fri, 17 Jul 2026 15:18:58 +0000 [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Medium] Using x86_pmu.fixedctr as a capability flag is conceptually flawed and suppresses valid debug output on Zhaoxin.

Pre-existing issues:
- [High] Zhaoxin PMU fails to initialize x86_pmu.fixedctr, leading to broken fixed counters and unsafe RDMSR accesses.
- [High] Undefined behavior in GENMASK_ULL during Zhaoxin PMU initialization if fixed counters are missing. --

--- Patch [1]: [PATCH 1/1] perf/x86: Do not read fixed counter control register if there is none --- commit d0dd53a6709a65141e2d105b19abad4d851825d4
Author: Petr Tesarik <[email protected]>

perf/x86: Do not read fixed counter control register if there is none

This patch skips reading the MSR_ARCH_PERFMON_FIXED_CTR_CTRL register during perf debug output if fixed counters are not implemented. This avoids a #GP on AMD CPUs with PerfMonV2 that do not implement this register.

Quoted 10 lines
arch/x86/events/core.c +0 -1
index 576baa9a52c5b..3055d59e0e82f 100644
@@ -1572,13 +1572,16 @@ void perf_event_print_debug(void)
 		rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
 		rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
 		rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
-		rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
Quoted 10 lines

arch/x86/events/core.c void perf_event_print_debug(void) · line 1590

Quoted 7 lines
arch/x86/events/core.c +2 -1
 		pr_info("\n");
 		pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
 		pr_info("CPU#%d: status:     %016llx\n", cpu, status);
 		pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-		pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+		if (x86_pmu.fixedctr) {  

[Severity: Medium]
Is it safe to use x86_pmu.fixedctr as a capability flag here?

Good question. In fact, I thought about it, and yes, introducing a new flag would be the cleanest solution, but it seemed overkill just for this debugging output.

AFAIK the MSR offset of the fixed perf counters cannot be zero, because those MSR addresses have been assigned to other architectural MSRs since Pentium times...

Quoted 5 lines

The x86_pmu.fixedctr field is an MSR address, not a boolean capability flag. While this check works for most architectures, the Zhaoxin PMU driver fails to initialize this field, leaving it as 0. Because of this, the check evaluates to false and inadvertently suppresses the debug output of MSR_ARCH_PERFMON_FIXED_CTR_CTRL on Zhaoxin systems.

I don't know about Zhaoxin. Do these syste have fixed performance counters and a corresponding global control register?

Adding Tony W Wang to the recipient list...

Petr T

--

Quoted 74 lines
Quoted 9 lines
arch/x86/events/core.c +3 -0
+			rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL,
 fixed);
+			pr_info("CPU#%d: fixed:      %016llx\n",
 cpu, fixed);
+		}
 		if (pebs_constraints) {
arch/x86/events/core.c +0 -0
 			rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
 			pr_info("CPU#%d: pebs:       %016llx\n",

cpu, pebs);

[ ... ]

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under review, but the lack of initialization for x86_pmu.fixedctr causes other issues.

In the Zhaoxin PMU driver setup:

arch/x86/events/zhaoxin/core.c:zhaoxin_pmu

static const struct x86_pmu zhaoxin_pmu __initconst = {
    ...
    /* missing .fixedctr = MSR_ARCH_PERFMON_FIXED_CTR0 */
};

Because this remains 0, x86_pmu_fixed_ctr_addr() returns 0 + idx instead of the correct MSR. This causes fixed counter 0 to silently return without updating in x86_perf_event_update():

arch/x86/events/core.c:x86_perf_event_update() {
    ...
    if (unlikely(!hwc->event_base))
        return 0;
    ...
}

It also leads to unsafe MSR reads when iterating over the fixed counter mask in perf_event_print_debug():

arch/x86/events/core.c:perf_event_print_debug() {
    ...
    for_each_set_bit(idx, fixed_cntr_mask, X86_PMC_IDX_MAX) {
        ...
        rdmsrq(x86_pmu_fixed_ctr_addr(idx), pmc_count);
        ...
    }
}

Could this lead to reads from arbitrary low MSRs like MSR 0, 1, or 2, potentially triggering a system crash if a user programs fixed counter events or triggers SysRq-P?

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under review, but does this bitmask generation in the Zhaoxin PMU initialization risk undefined behavior?

arch/x86/events/zhaoxin/core.c:zhaoxin_pmu_init() {
    ...
    x86_pmu.fixed_cntr_mask64 =

GENMASK_ULL(edx.split.num_counters_fixed - 1, 0); ... }

If a hypervisor configures the CPU to report 0 fixed counters, edx.split.num_counters_fixed - 1 wraps to -1. Expanding GENMASK_ULL(-1, 0) results in a right-shift by 64, which is undefined behavior in C. On x86, this yields ~0ULL, making the kernel assume 64 fixed counters exist.

Could this cause the kernel to attempt reading 64 undefined MSRs during debug output or event initialization, leading to #GP exceptions?

#3 lore raw
Quoted 52 lines · Petr Tesarik
Quoted 30 lines · On Fri, 17 Jul 2026 15:18:58 +0000 [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Medium] Using x86_pmu.fixedctr as a capability flag is conceptually flawed and suppresses valid debug output on Zhaoxin.

Pre-existing issues:
- [High] Zhaoxin PMU fails to initialize x86_pmu.fixedctr, leading to broken fixed counters and unsafe RDMSR accesses.
- [High] Undefined behavior in GENMASK_ULL during Zhaoxin PMU initialization if fixed counters are missing. --

--- Patch [1]: [PATCH 1/1] perf/x86: Do not read fixed counter control register if there is none --- commit d0dd53a6709a65141e2d105b19abad4d851825d4
Author: Petr Tesarik <[email protected]>

perf/x86: Do not read fixed counter control register if there is none

This patch skips reading the MSR_ARCH_PERFMON_FIXED_CTR_CTRL register during perf debug output if fixed counters are not implemented. This avoids a #GP on AMD CPUs with PerfMonV2 that do not implement this register.

Quoted 10 lines
arch/x86/events/core.c +0 -1
index 576baa9a52c5b..3055d59e0e82f 100644
@@ -1572,13 +1572,16 @@ void perf_event_print_debug(void)
  		rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
  		rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
  		rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
-		rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
Quoted 10 lines

arch/x86/events/core.c void perf_event_print_debug(void) · line 1590

Quoted 7 lines
arch/x86/events/core.c +2 -1
  		pr_info("\n");
  		pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
  		pr_info("CPU#%d: status:     %016llx\n", cpu, status);
  		pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-		pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+		if (x86_pmu.fixedctr) {

[Severity: Medium]
Is it safe to use x86_pmu.fixedctr as a capability flag here?

Good question. In fact, I thought about it, and yes, introducing a new flag would be the cleanest solution, but it seemed overkill just for this debugging output.

AFAIK the MSR offset of the fixed perf counters cannot be zero, because those MSR addresses have been assigned to other architectural MSRs since Pentium times...

Quoted 9 lines
Quoted 5 lines

The x86_pmu.fixedctr field is an MSR address, not a boolean capability flag. While this check works for most architectures, the Zhaoxin PMU driver fails to initialize this field, leaving it as 0. Because of this, the check evaluates to false and inadvertently suppresses the debug output of MSR_ARCH_PERFMON_FIXED_CTR_CTRL on Zhaoxin systems.

I don't know about Zhaoxin. Do these syste have fixed performance counters and a corresponding global control register?

Yes, Zhaoxin system have fixed performance counters and a corresponding global control register.

Quoted 31 lines

Adding Tony W Wang to the recipient list...

Petr T

--

Quoted 25 lines
Quoted 9 lines
arch/x86/events/core.c +3 -0
+			rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL,
 fixed);
+			pr_info("CPU#%d: fixed:      %016llx\n",
 cpu, fixed);
+		}
  		if (pebs_constraints) {

rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
pr_info("CPU#%d: pebs: %016llx\n",
cpu, pebs);

[ ... ]

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under review, but the lack of initialization for x86_pmu.fixedctr causes other issues.

In the Zhaoxin PMU driver setup:

arch/x86/events/zhaoxin/core.c:zhaoxin_pmu

static const struct x86_pmu zhaoxin_pmu __initconst = {
     ...
     /* missing .fixedctr = MSR_ARCH_PERFMON_FIXED_CTR0 */
};

This issue has indeed resulted in an “perf -e instructions” bug on Zhaoxin processors. Although Tanze submitted a patch in 2025, it seems it has not yet been merged to mainstream.
https://lkml.org/lkml/2025/6/19/141

Quoted 45 lines
Quoted 45 lines

Because this remains 0, x86_pmu_fixed_ctr_addr() returns 0 + idx instead of the correct MSR. This causes fixed counter 0 to silently return without updating in x86_perf_event_update():

arch/x86/events/core.c:x86_perf_event_update() {
     ...
     if (unlikely(!hwc->event_base))
         return 0;
     ...
}

It also leads to unsafe MSR reads when iterating over the fixed counter mask in perf_event_print_debug():

arch/x86/events/core.c:perf_event_print_debug() {
     ...
     for_each_set_bit(idx, fixed_cntr_mask, X86_PMC_IDX_MAX) {
         ...
         rdmsrq(x86_pmu_fixed_ctr_addr(idx), pmc_count);
         ...
     }
}

Could this lead to reads from arbitrary low MSRs like MSR 0, 1, or 2, potentially triggering a system crash if a user programs fixed counter events or triggers SysRq-P?

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under review, but does this bitmask generation in the Zhaoxin PMU initialization risk undefined behavior?

arch/x86/events/zhaoxin/core.c:zhaoxin_pmu_init() {
     ...
     x86_pmu.fixed_cntr_mask64 =

GENMASK_ULL(edx.split.num_counters_fixed - 1, 0); ... }

If a hypervisor configures the CPU to report 0 fixed counters, edx.split.num_counters_fixed - 1 wraps to -1. Expanding GENMASK_ULL(-1, 0) results in a right-shift by 64, which is undefined behavior in C. On x86, this yields ~0ULL, making the kernel assume 64 fixed counters exist.

Quoted 4 lines
Quoted 4 lines

Could this cause the kernel to attempt reading 64 undefined MSRs during debug output or event initialization, leading to #GP exceptions?

This issue may exist. Can the code be changed as follows?

if (edx.split.num_counters_fixed == 0) {
    x86_pmu.fixed_cntr_mask64 = 0;
} else {
    x86_pmu.fixed_cntr_mask64 = 

GENMASK_ULL(edx.split.num_counters_fixed - 1, 0);
}

In addition, this issue also appears to exist in the Intel PMU driver, should we fix them together?

Sincerely!
TonyWWang-oc

#4 lore raw
In reply to Petr Tesarik
Quoted 84 lines · Petr Tesarik

[You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

When printing out CPU performance registers for debugging, skip MSR_ARCH_PERFMON_FIXED_CTR_CTRL if fixed counters are not implemented.

Since AMD CPUs with PerMonV2 do not implement this register, attempts to read it generate a #GP. In particular, SysRq-P logs something like this:

[   14.748144] [   T1118] sysrq: Show Regs
[   14.748896] [   T1118] unchecked MSR access error: RDMSR from 0x38d at rIP: 0xffffffff937154c6 (native_read_msr+0x6/0x40)
[   14.750878] [   T1118] Call Trace:
[   14.751505] [   T1118]  <TASK>
[   14.752057] [   T1118]  paravirt_read_msr+0x7/0x10
[   14.752940] [   T1118]  perf_event_print_debug+0x135/0x240
[   14.753931] [   T1118]  __handle_sysrq.cold+0x9b/0xde
[   14.754855] [   T1118]  write_sysrq_trigger+0x59/0x80
[   14.755779] [   T1118]  proc_reg_write+0x5a/0xb0
[   14.756631] [   T1118]  vfs_write+0xce/0x430
[   14.757406] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.758322] [   T1118]  ? security_file_fcntl+0x5f/0x120
[   14.759083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.759754] [   T1118]  ? __x64_sys_fcntl+0x80/0x110
[   14.760334] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761005] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761676] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.762270] [   T1118]  ksys_write+0x6a/0xe0
[   14.762776] [   T1118]  do_syscall_64+0xe1/0x610
[   14.763324] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.763995] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.764564] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.765233] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.765806] [   T1118]  ? __x64_sys_ioctl+0x97/0xe0
[   14.766375] [   T1118]  ? __pfx_woken_wake_function+0x10/0x10
[   14.767048] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.767717] [   T1118]  ? get_close_on_exec+0x34/0x40
[   14.768311] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.768985] [   T1118]  ? do_fcntl+0x6da/0x8e0
[   14.769502] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.770083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.772321] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.773166] [   T1118]  ? tty_read+0x150/0x220
[   14.773722] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.774423] [   T1118]  ? filp_flush+0x5b/0x80
[   14.774966] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.775660] [   T1118]  ? filp_close+0x25/0x40
[   14.776214] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.776936] [   T1118]  ? do_dup2+0xae/0x140
[   14.777486] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.778309] [   T1118]  ? ksys_dup3+0x67/0xf0
[   14.778870] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.779600] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.780310] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.780917] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.781613] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.782215] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.782907] [   T1118]  ? ksys_read+0x6a/0xe0
[   14.783429] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.784120] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.784741] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.785431] [   T1118]  ? __ct_user_exit+0x15/0xb0
[   14.786014] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.786706] [   T1118]  ? do_syscall_64+0x98/0x610
[   14.787282] [   T1118]  ? exc_page_fault+0x6d/0x180
[   14.787873] [   T1118]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   14.788612] [   T1118] RIP: 0033:0x7f70d6497e0a
[   14.789186] [   T1118] Code: 08 03 00 00 59 5e 48 83 f8 fc 75 1e 83 e2 39 83 fa 08 75 16 e8 05 ff ff ff 0f 1f 80 00 00 00 00 49 89 ca 48 8b 44 24 20 0f 05 <48> 83 c4 18 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f
[   14.791587] [   T1118] RSP: 002b:00007ffc36a93580 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[   14.792617] [   T1118] RAX: ffffffffffffffda RBX: 00007f70d65f6580 RCX: 00007f70d6497e0a
[   14.793594] [   T1118] RDX: 0000000000000002 RSI: 0000556f34e41c30 RDI: 0000000000000001
[   14.794574] [   T1118] RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
[   14.795563] [   T1118] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
[   14.796537] [   T1118] R13: 0000556f34e41c30 R14: 0000000000000001 R15: 0000000000000000
[   14.797514] [   T1118]  </TASK>
---
 arch/x86/events/core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
arch/x86/events/core.c +0 -0
index d1af33d96d0a3..8310bedfc364f 100644

arch/x86/events/core.c void perf_event_print_debug(void) · line 1583

Quoted 3 lines
arch/x86/events/core.c +0 -0
@@ -1581,13 +1581,16 @@ void perf_event_print_debug(void)
                rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
                rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
                rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);

GLOBAL_{CTRL,STATUS,OVF_CTRL} functionality is also provided via different MSRs for AMD PMU version 2 and I assume that reading the ones above will also raise #GPs. If they don't, the reported values will surely be incorrect.

Quoted 18 lines
arch/x86/events/core.c +5 -3
-               rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
                pr_info("\n");
                pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
                pr_info("CPU#%d: status:     %016llx\n", cpu, status);
                pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-               pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+               if (x86_pmu.fixedctr) {
+                       rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+                       pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+               }
                if (pebs_constraints) {
                        rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
                        pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
--

2.54.0

#5 lore raw
Quoted 80 lines · On Mon, 20 Jul 2026 14:57:25 +0530 Sandipan Das <[email protected]> wrote:
Quoted 79 lines · Petr Tesarik

[You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

When printing out CPU performance registers for debugging, skip MSR_ARCH_PERFMON_FIXED_CTR_CTRL if fixed counters are not implemented.

Since AMD CPUs with PerMonV2 do not implement this register, attempts to read it generate a #GP. In particular, SysRq-P logs something like this:

[   14.748144] [   T1118] sysrq: Show Regs
[   14.748896] [   T1118] unchecked MSR access error: RDMSR from 0x38d at rIP: 0xffffffff937154c6 (native_read_msr+0x6/0x40)
[   14.750878] [   T1118] Call Trace:
[   14.751505] [   T1118]  <TASK>
[   14.752057] [   T1118]  paravirt_read_msr+0x7/0x10
[   14.752940] [   T1118]  perf_event_print_debug+0x135/0x240
[   14.753931] [   T1118]  __handle_sysrq.cold+0x9b/0xde
[   14.754855] [   T1118]  write_sysrq_trigger+0x59/0x80
[   14.755779] [   T1118]  proc_reg_write+0x5a/0xb0
[   14.756631] [   T1118]  vfs_write+0xce/0x430
[   14.757406] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.758322] [   T1118]  ? security_file_fcntl+0x5f/0x120
[   14.759083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.759754] [   T1118]  ? __x64_sys_fcntl+0x80/0x110
[   14.760334] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761005] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761676] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.762270] [   T1118]  ksys_write+0x6a/0xe0
[   14.762776] [   T1118]  do_syscall_64+0xe1/0x610
[   14.763324] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.763995] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.764564] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.765233] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.765806] [   T1118]  ? __x64_sys_ioctl+0x97/0xe0
[   14.766375] [   T1118]  ? __pfx_woken_wake_function+0x10/0x10
[   14.767048] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.767717] [   T1118]  ? get_close_on_exec+0x34/0x40
[   14.768311] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.768985] [   T1118]  ? do_fcntl+0x6da/0x8e0
[   14.769502] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.770083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.772321] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.773166] [   T1118]  ? tty_read+0x150/0x220
[   14.773722] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.774423] [   T1118]  ? filp_flush+0x5b/0x80
[   14.774966] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.775660] [   T1118]  ? filp_close+0x25/0x40
[   14.776214] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.776936] [   T1118]  ? do_dup2+0xae/0x140
[   14.777486] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.778309] [   T1118]  ? ksys_dup3+0x67/0xf0
[   14.778870] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.779600] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.780310] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.780917] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.781613] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.782215] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.782907] [   T1118]  ? ksys_read+0x6a/0xe0
[   14.783429] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.784120] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.784741] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.785431] [   T1118]  ? __ct_user_exit+0x15/0xb0
[   14.786014] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.786706] [   T1118]  ? do_syscall_64+0x98/0x610
[   14.787282] [   T1118]  ? exc_page_fault+0x6d/0x180
[   14.787873] [   T1118]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   14.788612] [   T1118] RIP: 0033:0x7f70d6497e0a
[   14.789186] [   T1118] Code: 08 03 00 00 59 5e 48 83 f8 fc 75 1e 83 e2 39 83 fa 08 75 16 e8 05 ff ff ff 0f 1f 80 00 00 00 00 49 89 ca 48 8b 44 24 20 0f 05 <48> 83 c4 18 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f
[   14.791587] [   T1118] RSP: 002b:00007ffc36a93580 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[   14.792617] [   T1118] RAX: ffffffffffffffda RBX: 00007f70d65f6580 RCX: 00007f70d6497e0a
[   14.793594] [   T1118] RDX: 0000000000000002 RSI: 0000556f34e41c30 RDI: 0000000000000001
[   14.794574] [   T1118] RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
[   14.795563] [   T1118] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
[   14.796537] [   T1118] R13: 0000556f34e41c30 R14: 0000000000000001 R15: 0000000000000000
[   14.797514] [   T1118]  </TASK>
---
 arch/x86/events/core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
Quoted 12 lines

arch/x86/events/core.c void perf_event_print_debug(void) · line 1583

Quoted 8 lines
arch/x86/events/core.c +0 -0
index d1af33d96d0a3..8310bedfc364f 100644
@@ -1581,13 +1581,16 @@ void perf_event_print_debug(void)
                rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
                rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
                rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);  

GLOBAL_{CTRL,STATUS,OVF_CTRL} functionality is also provided via different MSRs for AMD PMU version 2 and I assume that reading the ones above will also raise #GPs. If they don't, the reported values will surely be incorrect.

They do not raise #GPs on my Ryzen 7 system, but that's about the only system I have tried.

Honetly, I was very unsure about the availability of the feauture(s) and what the appropriate checks would be; that was the reason to include you as a recipient. What is the AMD-recommended method to check whether a CPU supports global perf control MSRs? Does x86.pmu_version even work? If yes, should I then simply make the actual MSR numbers conditional on AMD/Intel?

Any guidance welcome.

Petr T

Quoted 20 lines
Quoted 19 lines
arch/x86/events/core.c +5 -3
-               rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
                pr_info("\n");
                pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
                pr_info("CPU#%d: status:     %016llx\n", cpu, status);
                pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-               pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+               if (x86_pmu.fixedctr) {
+                       rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+                       pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+               }
                if (pebs_constraints) {
                        rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
                        pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
--

2.54.0

#6 lore raw
Quoted 96 lines · Petr Tesarik
Quoted 80 lines · On Mon, 20 Jul 2026 14:57:25 +0530 Sandipan Das <[email protected]> wrote:
Quoted 79 lines · Petr Tesarik

[You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

When printing out CPU performance registers for debugging, skip MSR_ARCH_PERFMON_FIXED_CTR_CTRL if fixed counters are not implemented.

Since AMD CPUs with PerMonV2 do not implement this register, attempts to read it generate a #GP. In particular, SysRq-P logs something like this:

[   14.748144] [   T1118] sysrq: Show Regs
[   14.748896] [   T1118] unchecked MSR access error: RDMSR from 0x38d at rIP: 0xffffffff937154c6 (native_read_msr+0x6/0x40)
[   14.750878] [   T1118] Call Trace:
[   14.751505] [   T1118]  <TASK>
[   14.752057] [   T1118]  paravirt_read_msr+0x7/0x10
[   14.752940] [   T1118]  perf_event_print_debug+0x135/0x240
[   14.753931] [   T1118]  __handle_sysrq.cold+0x9b/0xde
[   14.754855] [   T1118]  write_sysrq_trigger+0x59/0x80
[   14.755779] [   T1118]  proc_reg_write+0x5a/0xb0
[   14.756631] [   T1118]  vfs_write+0xce/0x430
[   14.757406] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.758322] [   T1118]  ? security_file_fcntl+0x5f/0x120
[   14.759083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.759754] [   T1118]  ? __x64_sys_fcntl+0x80/0x110
[   14.760334] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761005] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761676] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.762270] [   T1118]  ksys_write+0x6a/0xe0
[   14.762776] [   T1118]  do_syscall_64+0xe1/0x610
[   14.763324] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.763995] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.764564] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.765233] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.765806] [   T1118]  ? __x64_sys_ioctl+0x97/0xe0
[   14.766375] [   T1118]  ? __pfx_woken_wake_function+0x10/0x10
[   14.767048] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.767717] [   T1118]  ? get_close_on_exec+0x34/0x40
[   14.768311] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.768985] [   T1118]  ? do_fcntl+0x6da/0x8e0
[   14.769502] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.770083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.772321] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.773166] [   T1118]  ? tty_read+0x150/0x220
[   14.773722] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.774423] [   T1118]  ? filp_flush+0x5b/0x80
[   14.774966] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.775660] [   T1118]  ? filp_close+0x25/0x40
[   14.776214] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.776936] [   T1118]  ? do_dup2+0xae/0x140
[   14.777486] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.778309] [   T1118]  ? ksys_dup3+0x67/0xf0
[   14.778870] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.779600] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.780310] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.780917] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.781613] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.782215] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.782907] [   T1118]  ? ksys_read+0x6a/0xe0
[   14.783429] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.784120] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.784741] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.785431] [   T1118]  ? __ct_user_exit+0x15/0xb0
[   14.786014] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.786706] [   T1118]  ? do_syscall_64+0x98/0x610
[   14.787282] [   T1118]  ? exc_page_fault+0x6d/0x180
[   14.787873] [   T1118]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   14.788612] [   T1118] RIP: 0033:0x7f70d6497e0a
[   14.789186] [   T1118] Code: 08 03 00 00 59 5e 48 83 f8 fc 75 1e 83 e2 39 83 fa 08 75 16 e8 05 ff ff ff 0f 1f 80 00 00 00 00 49 89 ca 48 8b 44 24 20 0f 05 <48> 83 c4 18 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f
[   14.791587] [   T1118] RSP: 002b:00007ffc36a93580 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[   14.792617] [   T1118] RAX: ffffffffffffffda RBX: 00007f70d65f6580 RCX: 00007f70d6497e0a
[   14.793594] [   T1118] RDX: 0000000000000002 RSI: 0000556f34e41c30 RDI: 0000000000000001
[   14.794574] [   T1118] RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
[   14.795563] [   T1118] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
[   14.796537] [   T1118] R13: 0000556f34e41c30 R14: 0000000000000001 R15: 0000000000000000
[   14.797514] [   T1118]  </TASK>
---
 arch/x86/events/core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
Quoted 12 lines

arch/x86/events/core.c void perf_event_print_debug(void) · line 1583

Quoted 8 lines
arch/x86/events/core.c +0 -0
index d1af33d96d0a3..8310bedfc364f 100644
@@ -1581,13 +1581,16 @@ void perf_event_print_debug(void)
                rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
                rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
                rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);

GLOBAL_{CTRL,STATUS,OVF_CTRL} functionality is also provided via different MSRs for AMD PMU version 2 and I assume that reading the ones above will also raise #GPs. If they don't, the reported values will surely be incorrect.

Quoted 2 lines

They do not raise #GPs on my Ryzen 7 system, but that's about the only system I have tried.

Perhaps it is based on Zen 3 or older where x86_pmu.version is set to 0.

Quoted 10 lines

Honetly, I was very unsure about the availability of the feauture(s) and what the appropriate checks would be; that was the reason to include you as a recipient. What is the AMD-recommended method to check whether a CPU supports global perf control MSRs? Does x86.pmu_version even work? If yes, should I then simply make the actual MSR numbers conditional on AMD/Intel?

Any guidance welcome.

AMD processors with X86_FEATURE_PERFMON_V2 also set x86_pmu.version to 2. I think that it is better to move the parts that require the use of vendor-specific MSRs to a new callback implemented in arch/x86/events/{intel,amd,zhaoxin}/* instead of making additions to perf_event_print_debug().

I'm also not sure why MSR_CORE_PERF_GLOBAL_OVF_CTRL is read here because this as well as its AMD counterpart, MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, are both write-only MSRs.

Mind if I send a cleanup?

Quoted 22 lines
Quoted 21 lines
Quoted 20 lines
arch/x86/events/core.c +5 -3
-               rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
 
                pr_info("\n");
                pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
                pr_info("CPU#%d: status:     %016llx\n", cpu, status);
                pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-               pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+
+               if (x86_pmu.fixedctr) {
+                       rdmsrq(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+                       pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+               }
                if (pebs_constraints) {
                        rdmsrq(MSR_IA32_PEBS_ENABLE, pebs);
                        pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
--

2.54.0

#7 lore raw
Quoted 119 lines · On Tue, 4 Aug 2026 12:30:36 +0530 Sandipan Das <[email protected]> wrote:
Quoted 96 lines · Petr Tesarik
Quoted 80 lines · On Mon, 20 Jul 2026 14:57:25 +0530 Sandipan Das <[email protected]> wrote:
Quoted 79 lines · Petr Tesarik

[You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

When printing out CPU performance registers for debugging, skip MSR_ARCH_PERFMON_FIXED_CTR_CTRL if fixed counters are not implemented.

Since AMD CPUs with PerMonV2 do not implement this register, attempts to read it generate a #GP. In particular, SysRq-P logs something like this:

[   14.748144] [   T1118] sysrq: Show Regs
[   14.748896] [   T1118] unchecked MSR access error: RDMSR from 0x38d at rIP: 0xffffffff937154c6 (native_read_msr+0x6/0x40)
[   14.750878] [   T1118] Call Trace:
[   14.751505] [   T1118]  <TASK>
[   14.752057] [   T1118]  paravirt_read_msr+0x7/0x10
[   14.752940] [   T1118]  perf_event_print_debug+0x135/0x240
[   14.753931] [   T1118]  __handle_sysrq.cold+0x9b/0xde
[   14.754855] [   T1118]  write_sysrq_trigger+0x59/0x80
[   14.755779] [   T1118]  proc_reg_write+0x5a/0xb0
[   14.756631] [   T1118]  vfs_write+0xce/0x430
[   14.757406] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.758322] [   T1118]  ? security_file_fcntl+0x5f/0x120
[   14.759083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.759754] [   T1118]  ? __x64_sys_fcntl+0x80/0x110
[   14.760334] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761005] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.761676] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.762270] [   T1118]  ksys_write+0x6a/0xe0
[   14.762776] [   T1118]  do_syscall_64+0xe1/0x610
[   14.763324] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.763995] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.764564] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.765233] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.765806] [   T1118]  ? __x64_sys_ioctl+0x97/0xe0
[   14.766375] [   T1118]  ? __pfx_woken_wake_function+0x10/0x10
[   14.767048] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.767717] [   T1118]  ? get_close_on_exec+0x34/0x40
[   14.768311] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.768985] [   T1118]  ? do_fcntl+0x6da/0x8e0
[   14.769502] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.770083] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.772321] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.773166] [   T1118]  ? tty_read+0x150/0x220
[   14.773722] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.774423] [   T1118]  ? filp_flush+0x5b/0x80
[   14.774966] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.775660] [   T1118]  ? filp_close+0x25/0x40
[   14.776214] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.776936] [   T1118]  ? do_dup2+0xae/0x140
[   14.777486] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.778309] [   T1118]  ? ksys_dup3+0x67/0xf0
[   14.778870] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.779600] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.780310] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.780917] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.781613] [   T1118]  ? do_syscall_64+0x205/0x610
[   14.782215] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.782907] [   T1118]  ? ksys_read+0x6a/0xe0
[   14.783429] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.784120] [   T1118]  ? __ct_user_enter+0x27/0xc0
[   14.784741] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.785431] [   T1118]  ? __ct_user_exit+0x15/0xb0
[   14.786014] [   T1118]  ? srso_alias_return_thunk+0x5/0xfbef5
[   14.786706] [   T1118]  ? do_syscall_64+0x98/0x610
[   14.787282] [   T1118]  ? exc_page_fault+0x6d/0x180
[   14.787873] [   T1118]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   14.788612] [   T1118] RIP: 0033:0x7f70d6497e0a
[   14.789186] [   T1118] Code: 08 03 00 00 59 5e 48 83 f8 fc 75 1e 83 e2 39 83 fa 08 75 16 e8 05 ff ff ff 0f 1f 80 00 00 00 00 49 89 ca 48 8b 44 24 20 0f 05 <48> 83 c4 18 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f
[   14.791587] [   T1118] RSP: 002b:00007ffc36a93580 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[   14.792617] [   T1118] RAX: ffffffffffffffda RBX: 00007f70d65f6580 RCX: 00007f70d6497e0a
[   14.793594] [   T1118] RDX: 0000000000000002 RSI: 0000556f34e41c30 RDI: 0000000000000001
[   14.794574] [   T1118] RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
[   14.795563] [   T1118] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
[   14.796537] [   T1118] R13: 0000556f34e41c30 R14: 0000000000000001 R15: 0000000000000000
[   14.797514] [   T1118]  </TASK>
---
 arch/x86/events/core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
Quoted 12 lines

arch/x86/events/core.c void perf_event_print_debug(void) · line 1583

Quoted 8 lines
arch/x86/events/core.c +0 -0
index d1af33d96d0a3..8310bedfc364f 100644
@@ -1581,13 +1581,16 @@ void perf_event_print_debug(void)
                rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
                rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status);
                rdmsrq(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);  

GLOBAL_{CTRL,STATUS,OVF_CTRL} functionality is also provided via different MSRs for AMD PMU version 2 and I assume that reading the ones above will also raise #GPs. If they don't, the reported values will surely be incorrect.

Quoted 2 lines

They do not raise #GPs on my Ryzen 7 system, but that's about the only system I have tried.

Perhaps it is based on Zen 3 or older where x86_pmu.version is set to 0.

Quoted 10 lines

Honetly, I was very unsure about the availability of the feauture(s) and what the appropriate checks would be; that was the reason to include you as a recipient. What is the AMD-recommended method to check whether a CPU supports global perf control MSRs? Does x86.pmu_version even work? If yes, should I then simply make the actual MSR numbers conditional on AMD/Intel?

Any guidance welcome.

AMD processors with X86_FEATURE_PERFMON_V2 also set x86_pmu.version to 2. I think that it is better to move the parts that require the use of vendor-specific MSRs to a new callback implemented in arch/x86/events/{intel,amd,zhaoxin}/* instead of making additions to perf_event_print_debug().

Quoted 5 lines

I'm also not sure why MSR_CORE_PERF_GLOBAL_OVF_CTRL is read here because this as well as its AMD counterpart, MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, are both write-only MSRs.

Mind if I send a cleanup?

I've absolutely no issue with that. Go ahead and send your better version! The only thing that has annoyed me is the Oops splat every time I use SysRq+P on my AMD laptop. ;-)

Cheers
Petr T