From: Andi Kleen <[email protected]> Current kernels always test extra registers at boot with RMW cycle, to catch lying virtual machines.
For a new register the standard 0x1ff test value does not work, as 0x1ff is not a valid value and causes an #GP. Add the ability to add custom test values to an extra_reg into the description tables. Signed-off-by: Andi Kleen <[email protected]> --- arch/x86/kernel/cpu/perf_event.h | 15 +++++++++++---- arch/x86/kernel/cpu/perf_event_intel.c | 3 ++- arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c | 5 +++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 3598f67..2a4701c 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -422,23 +422,30 @@ struct extra_reg { u64 valid_mask; int idx; /* per_xxx->regs[] reg index */ bool extra_msr_access; + u64 test_value; }; -#define EVENT_EXTRA_REG(e, ms, m, vm, i) { \ +#define EVENT_EXTRA_REG(e, ms, m, vm, i, t) { \ .event = (e), \ .msr = (ms), \ .config_mask = (m), \ .valid_mask = (vm), \ .idx = EXTRA_REG_##i, \ .extra_msr_access = true, \ + .test_value = t, \ } #define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \ - EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx) + EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx, \ + 0x1ffUL) #define INTEL_UEVENT_EXTRA_REG(event, msr, vm, idx) \ EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT | \ - ARCH_PERFMON_EVENTSEL_UMASK, vm, idx) + ARCH_PERFMON_EVENTSEL_UMASK, vm, idx, 0x1ffUL) + +#define INTEL_UEVENT_EXTRA_REG_TVAL(event, msr, vm, idx, tval) \ + EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT | \ + ARCH_PERFMON_EVENTSEL_UMASK, vm, idx, tval) #define INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(c) \ INTEL_UEVENT_EXTRA_REG(c, \ @@ -446,7 +453,7 @@ struct extra_reg { 0xffff, \ LDLAT) -#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0) +#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0, 0) union perf_capabilities { struct { diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 7c397e8..4df6783 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -3575,7 +3575,8 @@ __init int intel_pmu_init(void) */ if (x86_pmu.extra_regs) { for (er = x86_pmu.extra_regs; er->msr; er++) { - er->extra_msr_access = check_msr(er->msr, 0x1ffUL); + er->extra_msr_access = check_msr(er->msr, + er->test_value); /* Disable LBR select mapping */ if ((er->idx == EXTRA_REG_LBR) && !er->extra_msr_access) x86_pmu.lbr_sel_map = NULL; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c index 2749965..5bfa493 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c @@ -136,11 +136,12 @@ NHMEX_M_PMON_CTL_FLAG_MODE) #define MBOX_INC_SEL_EXTAR_REG(c, r) \ EVENT_EXTRA_REG(MBOX_INC_SEL(c), NHMEX_M0_MSR_PMU_##r, \ - MBOX_INC_SEL_MASK, (u64)-1, NHMEX_M_##r) + MBOX_INC_SEL_MASK, (u64)-1, NHMEX_M_##r, \ + 0x1ffUL) #define MBOX_SET_FLAG_SEL_EXTRA_REG(c, r) \ EVENT_EXTRA_REG(MBOX_SET_FLAG_SEL(c), NHMEX_M0_MSR_PMU_##r, \ MBOX_SET_FLAG_SEL_MASK, \ - (u64)-1, NHMEX_M_##r) + (u64)-1, NHMEX_M_##r, 0x1ffUL) /* NHM-EX Rbox */ #define NHMEX_R_MSR_GLOBAL_CTL 0xe00 -- 2.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

