[PATCH V6 1/2] perf ignore LBR and extra_rsp

2014-07-14 Thread kan . liang
From: Kan Liang kan.li...@intel.com

x86, perf: Protect LBR and extra_regs against KVM lying

With -cpu host, KVM reports LBR and extra_regs support, if the host has
support.
When the guest perf driver tries to access LBR or extra_regs MSR,
it #GPs all MSR accesses,since KVM doesn't handle LBR and extra_regs support.
So check the related MSRs access right once at initialization time to avoid
the error access at runtime.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to
trigger offcore_rsp #GP

Signed-off-by: Kan Liang kan.li...@intel.com

---
V2: Move the check code to initialization time.
V3: Add flag for each extra register.
Check all LBR MSRs at initialization time.
V4: Remove lbr_msr_access.
For LBR msr, simply set lbr_nr to 0 if check_msr failed.
Disable all extra msrs in creation places if check_msr failed.
V5: Fix check_msr broken
Don't check any more MSRs after the first fail
Return error when checking fail to stop creating the event
Remove the checking code path which never get
V6: Move extra_msr_access to struct extra_reg
Modify and move check_msr function to perf_event_intel.c
Other minor code changes

 arch/x86/kernel/cpu/perf_event.c  |  3 ++
 arch/x86/kernel/cpu/perf_event.h  | 20 
 arch/x86/kernel/cpu/perf_event_intel.c| 66 ++-
 arch/x86/kernel/cpu/perf_event_intel_uncore.h |  4 +-
 4 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 2bdfbff..2879ecd 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -118,6 +118,9 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event 
*event)
continue;
if (event-attr.config1  ~er-valid_mask)
return -EINVAL;
+   /* Check if the extra msrs can be safely accessed*/
+   if (!er-extra_msr_access)
+   return -ENXIO;
 
reg-idx = er-idx;
reg-config = event-attr.config1;
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 3b2f9bd..2e613b2 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -295,22 +295,24 @@ struct extra_reg {
u64 config_mask;
u64 valid_mask;
int idx;  /* per_xxx-regs[] reg index */
+   boolextra_msr_access;
 };
 
-#define EVENT_EXTRA_REG(e, ms, m, vm, i) { \
-   .event = (e),   \
-   .msr = (ms),\
-   .config_mask = (m), \
-   .valid_mask = (vm), \
-   .idx = EXTRA_REG_##i,   \
+#define EVENT_EXTRA_REG(e, ms, m, vm, i, a) {  \
+   .event = (e),   \
+   .msr = (ms),\
+   .config_mask = (m), \
+   .valid_mask = (vm), \
+   .idx = EXTRA_REG_##i,   \
+   .extra_msr_access = (a),\
}
 
 #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, true)
 
 #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, true)
 
 #define INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(c) \
INTEL_UEVENT_EXTRA_REG(c, \
@@ -318,7 +320,7 @@ struct extra_reg {
   0x, \
   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, false)
 
 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 adb02aa..9c234d1 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2173,6 +2173,40 @@ static void intel_snb_check_microcode(void)
}
 }
 
+/*
+ * Under certain circumstances, access certain MSR may cause #GP.
+ * The function tests if the input MSR can be safely accessed.
+ */
+static bool check_msr(unsigned long msr, u64 mask)
+{
+   u64 val_old, val_new, val_tmp;
+
+   /*
+* Read the current value, change it and read it back to see if it
+* matches, this is needed to detect certain hardware emulators
+* (qemu/kvm) that don't trap on the MSR access and always

[PATCH V6 2/2] kvm: ignore LBR and extra rsp

2014-07-14 Thread kan . liang
From: Kan Liang kan.li...@intel.com

With -cpu host KVM reports LBR and extra_regs support, so the perf driver may
accesses the LBR and extra_regs MSRs.
However, there is no LBR and extra_regs virtualization support yet. This could
causes guest to crash.
As a workaround, KVM just simply ignore the LBR and extra_regs MSRs to lie the
guest.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to
trigger offcore_rsp #GP

Signed-off-by: Andi Kleen a...@linux.intel.com
Signed-off-by: Kan Liang kan.li...@intel.com

---
V3: add MSR_LBR_TOS
V4: add MSR_LBR_SELECT and MSR_PEBS_LD_LAT_THRESHOLD
V5: set_msr should return 0 to lie the guest

 arch/x86/kvm/pmu.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index cbecaa9..5fd5b44 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -331,6 +331,18 @@ bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
ret = pmu-version  1;
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   return 1; /* to avoid crashes */
default:
ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)
|| get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0)
@@ -358,6 +370,19 @@ int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 
*data)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
*data = pmu-global_ovf_ctrl;
return 0;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   *data = 0;
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
@@ -409,6 +434,19 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data 
*msr_info)
return 0;
}
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   /* dummy for now */
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V5 1/2] perf ignore LBR and extra_regs

2014-07-10 Thread kan . liang
From: Kan Liang kan.li...@intel.com

x86, perf: Protect LBR and extra_regs against KVM lying

With -cpu host, KVM reports LBR and extra_regs support, if the host has support.
When the guest perf driver tries to access LBR or extra_regs MSR,
it #GPs all MSR accesses,since KVM doesn't handle LBR and extra_regs support.
So check the related MSRs access right once at initialization time to avoid the 
error access at runtime.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y 
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Kan Liang kan.li...@intel.com

V2: Move the check code to initialization time.
V3: Add flag for each extra register.
Check all LBR MSRs at initialization time.
V4: Remove lbr_msr_access. For LBR msr, simply set lbr_nr to 0 if check_msr 
failed.
Disable all extra msrs in creation places if check_msr failed.
V5: Fix check_msr broken
Don't check any more MSRs after the first fail
Return error when checking fail to stop creating the event
Remove the checking code path which never get
---
 arch/x86/kernel/cpu/perf_event.c   |  3 +++
 arch/x86/kernel/cpu/perf_event.h   | 45 ++
 arch/x86/kernel/cpu/perf_event_intel.c | 38 +++-
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 2bdfbff..a7c5e4b 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -118,6 +118,9 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event 
*event)
continue;
if (event-attr.config1  ~er-valid_mask)
return -EINVAL;
+   /* Check if the extra msrs can be safely accessed*/
+   if (!x86_pmu.extra_msr_access[er-idx])
+   return -EFAULT;
 
reg-idx = er-idx;
reg-config = event-attr.config1;
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 3b2f9bd..992c678 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -464,6 +464,12 @@ struct x86_pmu {
 */
struct extra_reg *extra_regs;
unsigned int er_flags;
+   /*
+* EXTRA REG MSR can be accessed
+* The extra registers are completely unrelated to each other.
+* So it needs a flag for each extra register.
+*/
+   boolextra_msr_access[EXTRA_REG_MAX];
 
/*
 * Intel host/guest support (KVM)
@@ -525,6 +531,45 @@ extern u64 __read_mostly hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
+/*
+ * Under certain circumstances, access certain MSR may cause #GP.
+ * The function tests if the input MSR can be safely accessed.
+ */
+static inline bool check_msr(unsigned long msr)
+{
+   u64 val_old, val_new, val_tmp;
+
+   /*
+* Read the current value, change it and read it back to see if it
+* matches, this is needed to detect certain hardware emulators
+* (qemu/kvm) that don't trap on the MSR access and always return 0s.
+*/
+   if (rdmsrl_safe(msr, val_old))
+   goto msr_fail;
+   /*
+* Only chagne it slightly,
+* since the higher bits of some MSRs cannot be updated by wrmsrl.
+* E.g. MSR_LBR_TOS
+*/
+   val_tmp = val_old ^ 0x3UL;
+   if (wrmsrl_safe(msr, val_tmp) ||
+   rdmsrl_safe(msr, val_new))
+   goto msr_fail;
+
+   if (val_new != val_tmp)
+   goto msr_fail;
+
+   /* Here it's sure that the MSR can be safely accessed.
+* Restore the old value and return.
+*/
+   wrmsrl(msr, val_old);
+
+   return true;
+
+msr_fail:
+   return false;
+}
+
 u64 x86_perf_event_update(struct perf_event *event);
 
 static inline unsigned int x86_pmu_config_addr(int index)
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c 
b/arch/x86/kernel/cpu/perf_event_intel.c
index adb02aa..953b2b2 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2262,7 +2262,8 @@ __init int intel_pmu_init(void)
union cpuid10_ebx ebx;
struct event_constraint *c;
unsigned int unused;
-   int version;
+   int version, i;
+   struct extra_reg *er;
 
if (!cpu_has(boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
switch (boot_cpu_data.x86) {
@@ -2565,6 +2566,41 @@ __init int intel_pmu_init(void)
}
}
 
+   /*
+* Access LBR MSR may cause #GP

[PATCH V5 2/2] kvm: ignore LBR and extra_reg

2014-07-10 Thread kan . liang
From: Kan Liang kan.li...@intel.com

With -cpu host KVM reports LBR and extra_regs support, so the perf driver may 
accesses the LBR and extra_regs MSRs.
However, there is no LBR and extra_regs virtualization support yet. This could 
causes guest to crash.
As a workaround, KVM just simply ignore the LBR and extra_regs MSRs to lie the 
guest.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y 
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Andi Kleen a...@linux.intel.com
Signed-off-by: Kan Liang kan.li...@intel.com

V3: add MSR_LBR_TOS
V4: add MSR_LBR_SELECT and MSR_PEBS_LD_LAT_THRESHOLD
V5: set_msr should return 0 to lie the guest
---
 arch/x86/kvm/pmu.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index cbecaa9..5fd5b44 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -331,6 +331,18 @@ bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
ret = pmu-version  1;
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   return 1; /* to avoid crashes */
default:
ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)
|| get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0)
@@ -358,6 +370,19 @@ int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 
*data)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
*data = pmu-global_ovf_ctrl;
return 0;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   *data = 0;
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
@@ -409,6 +434,19 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data 
*msr_info)
return 0;
}
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   /* dummy for now */
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 1/2] perf ignore LBR and extra_regs.

2014-07-08 Thread kan . liang
From: Kan Liang kan.li...@intel.com

x86, perf: Protect LBR and extra_regs against KVM lying

With -cpu host, KVM reports LBR and extra_regs support, if the host has support.
When the guest perf driver tries to access LBR or extra_regs MSR,
it #GPs all MSR accesses,since KVM doesn't handle LBR and extra_regs support.
So check the related MSRs access right once at initialization time to avoid the 
error access at runtime.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y 
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Kan Liang kan.li...@intel.com

V2: Move the check code to initialization time.
V3: Add flag for each extra register.
Check all LBR MSRs at initialization time.
V4: Remove lbr_msr_access. For LBR msr, simply set lbr_nr to 0 if check_msr 
failed.
Disable all extra msrs in creation places if check_msr failed.
---
 arch/x86/kernel/cpu/perf_event.c   |  3 +++
 arch/x86/kernel/cpu/perf_event.h   | 21 +
 arch/x86/kernel/cpu/perf_event_intel.c | 43 +++---
 3 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 2bdfbff..f0e8022 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -118,6 +118,9 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event 
*event)
continue;
if (event-attr.config1  ~er-valid_mask)
return -EINVAL;
+   /* Check if the extra msrs can be safely accessed*/
+   if (!x86_pmu.extra_msr_access[er-idx])
+   continue;
 
reg-idx = er-idx;
reg-config = event-attr.config1;
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 3b2f9bd..85725c5 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -464,6 +464,12 @@ struct x86_pmu {
 */
struct extra_reg *extra_regs;
unsigned int er_flags;
+   /*
+* EXTRA REG MSR can be accessed
+* The extra registers are completely unrelated to each other.
+* So it needs a flag for each extra register.
+*/
+   boolextra_msr_access[EXTRA_REG_MAX];
 
/*
 * Intel host/guest support (KVM)
@@ -525,6 +531,21 @@ extern u64 __read_mostly hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
+/*
+ * Under certain circumstances, access certain MSR may cause #GP.
+ * The function tests if the input MSR can be safely accessed.
+ */
+static inline bool check_msr(unsigned long msr)
+{
+   u64 value;
+
+   if (rdmsrl_safe(msr, value)  0)
+   return false;
+   if (wrmsrl_safe(msr, value)  0)
+   return false;
+   return true;
+}
+
 u64 x86_perf_event_update(struct perf_event *event);
 
 static inline unsigned int x86_pmu_config_addr(int index)
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c 
b/arch/x86/kernel/cpu/perf_event_intel.c
index adb02aa..2be44be 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1471,11 +1471,14 @@ static void intel_fixup_er(struct perf_event *event, 
int idx)
 {
event-hw.extra_reg.idx = idx;
 
-   if (idx == EXTRA_REG_RSP_0) {
+   /* The extra_reg doesn't update if msrs cannot be accessed safely */
+   if ((idx == EXTRA_REG_RSP_0) 
+   x86_pmu.extra_msr_access[EXTRA_REG_RSP_0]) {
event-hw.config = ~INTEL_ARCH_EVENT_MASK;
event-hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_0].event;
event-hw.extra_reg.reg = MSR_OFFCORE_RSP_0;
-   } else if (idx == EXTRA_REG_RSP_1) {
+   } else if ((idx == EXTRA_REG_RSP_1) 
+   x86_pmu.extra_msr_access[EXTRA_REG_RSP_1]) {
event-hw.config = ~INTEL_ARCH_EVENT_MASK;
event-hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_1].event;
event-hw.extra_reg.reg = MSR_OFFCORE_RSP_1;
@@ -2262,7 +2265,9 @@ __init int intel_pmu_init(void)
union cpuid10_ebx ebx;
struct event_constraint *c;
unsigned int unused;
-   int version;
+   int version, i;
+   struct extra_reg *er;
+   bool access;
 
if (!cpu_has(boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
switch (boot_cpu_data.x86) {
@@ -2565,6 +2570,38 @@ __init int intel_pmu_init(void)
}
}
 
+   /*
+* Access LBR MSR may cause #GP under certain circumstances.
+* E.g. KVM

[PATCH V4 2/2] kvm: ignore LBR and extra_regs

2014-07-08 Thread kan . liang
From: Kan Liang kan.li...@intel.com

With -cpu host KVM reports LBR and extra_regs support, so the perf driver may 
accesses the LBR and extra_regs MSRs.
However, there is no LBR and extra_regs virtualization support yet. This could 
causes guest to crash.
As a workaround, KVM just simply ignore the LBR and extra_regs MSRs to lie the 
guest.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y 
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Andi Kleen a...@linux.intel.com
Signed-off-by: Kan Liang kan.li...@intel.com

V3: add MSR_LBR_TOS
V4: add MSR_LBR_SELECT and MSR_PEBS_LD_LAT_THRESHOLD
---
 arch/x86/kvm/pmu.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index cbecaa9..cf0ed39 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -331,6 +331,18 @@ bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
ret = pmu-version  1;
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   return 1; /* to avoid crashes */
default:
ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)
|| get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0)
@@ -358,6 +370,19 @@ int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 
*data)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
*data = pmu-global_ovf_ctrl;
return 0;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   *data = 0;
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
@@ -409,6 +434,19 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data 
*msr_info)
return 0;
}
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_SELECT:
+   case MSR_PEBS_LD_LAT_THRESHOLD:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   /* dummy for now */
+   break;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 1/2] perf ignore LBR and offcore_rsp.

2014-07-07 Thread kan . liang
From: Kan Liang kan.li...@intel.com

x86, perf: Protect LBR and offcore rsp against KVM lying

With -cpu host, KVM reports LBR and offcore support, if the host has support.
When the guest perf driver tries to access LBR or offcore_rsp MSR,
it #GPs all MSR accesses,since KVM doesn't handle LBR and offcore support.
So check the related MSRs access right once at initialization time to avoid the 
error access at runtime.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y 
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Kan Liang kan.li...@intel.com

V2: Move the check code to initialization time.
V3: Add flag for each extra register.
Check all LBR MSRs at initialization time.
---
 arch/x86/kernel/cpu/perf_event.h   | 30 +--
 arch/x86/kernel/cpu/perf_event_intel.c | 39 +-
 arch/x86/kernel/cpu/perf_event_intel_lbr.c |  4 +--
 3 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 3b2f9bd..7e286d7 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -458,12 +458,19 @@ struct x86_pmu {
u64 lbr_sel_mask;  /* LBR_SELECT valid bits */
const int   *lbr_sel_map;  /* lbr_select mappings */
boollbr_double_abort;  /* duplicated lbr aborts */
-
+   boollbr_msr_access;/* LBR MSR can be accessed */
/*
 * Extra registers for events
 */
struct extra_reg *extra_regs;
unsigned int er_flags;
+   /*
+* EXTRA REG MSR can be accessed
+* The extra offcore registers are completely unrelated to each other.
+* So it needs a flag for each extra register.
+* The extra offcore MSRs are MSR_OFFCORE_RSP_0 and MSR_OFFCORE_RSP_1.
+*/
+   boolextra_msr_access[2];
 
/*
 * Intel host/guest support (KVM)
@@ -525,6 +532,21 @@ extern u64 __read_mostly hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
+/*
+ * Under certain circumstances, access certain MSR may cause #GP.
+ * The function tests if the input MSR can be safely accessed.
+ */
+static inline bool check_msr(unsigned long msr)
+{
+   u64 value;
+
+   if (rdmsrl_safe(msr, value)  0)
+   return false;
+   if (wrmsrl_safe(msr, value)  0)
+   return false;
+   return true;
+}
+
 u64 x86_perf_event_update(struct perf_event *event);
 
 static inline unsigned int x86_pmu_config_addr(int index)
@@ -555,7 +577,11 @@ static inline void __x86_pmu_enable_event(struct 
hw_perf_event *hwc,
 {
u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
 
-   if (hwc-extra_reg.reg)
+   if (hwc-extra_reg.reg 
+   ((hwc-extra_reg.idx == EXTRA_REG_RSP_0) ?
+   x86_pmu.extra_msr_access[0] : true) 
+   ((hwc-extra_reg.idx == EXTRA_REG_RSP_1) ?
+   x86_pmu.extra_msr_access[1] : true))
wrmsrl(hwc-extra_reg.reg, hwc-extra_reg.config);
wrmsrl(hwc-config_base, (hwc-config | enable_mask)  ~disable_mask);
 }
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c 
b/arch/x86/kernel/cpu/perf_event_intel.c
index adb02aa..3d18765 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2262,7 +2262,7 @@ __init int intel_pmu_init(void)
union cpuid10_ebx ebx;
struct event_constraint *c;
unsigned int unused;
-   int version;
+   int version, i;
 
if (!cpu_has(boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
switch (boot_cpu_data.x86) {
@@ -2565,6 +2565,43 @@ __init int intel_pmu_init(void)
}
}
 
+   /*
+* Access LBR MSR may cause #GP under certain circumstances.
+* E.g. KVM doesn't support LBR MSR
+* Check all LBT MSR here.
+* Disable LBR access if any LBR MSRs can not be accessed.
+*/
+   if (x86_pmu.lbr_nr) {
+   x86_pmu.lbr_msr_access = check_msr(x86_pmu.lbr_tos);
+   for (i = 0; i  x86_pmu.lbr_nr; i++) {
+   x86_pmu.lbr_msr_access =
+   check_msr(x86_pmu.lbr_from + i);
+   x86_pmu.lbr_msr_access =
+   check_msr(x86_pmu.lbr_to + i);
+   }
+   }
+   /*
+* Access extra MSR may cause #GP under certain circumstances.
+* E.g. KVM doesn't support offcore event

[PATCH V3 2/2] kvm: ignore LBR and offcore rsp

2014-07-07 Thread kan . liang
From: Kan Liang kan.li...@intel.com

With -cpu host KVM reports LBR and offcore support, so the perf driver may 
accesses the LBR and offcore MSRs.
However, there is no LBR and offcore virtualization support yet. This could 
causes guest to crash.
As a workaround, KVM just simply ignore the LBR and offcore_rsp MSRs to lie the 
guest.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y 
(for host kernel).
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n (for guest kernel).
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Andi Kleen a...@linux.intel.com
Signed-off-by: Kan Liang kan.li...@intel.com
---
 arch/x86/kvm/pmu.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index cbecaa9..f79125a 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -331,6 +331,16 @@ bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
ret = pmu-version  1;
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   return 1; /* to avoid crashes */
default:
ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)
|| get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0)
@@ -358,6 +368,17 @@ int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 
*data)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
*data = pmu-global_ovf_ctrl;
return 0;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   *data = 0;
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
@@ -409,6 +430,17 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data 
*msr_info)
return 0;
}
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   case MSR_LBR_TOS:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   /* dummy for now */
+   break;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V2 3/3] kvm: ignore LBR and offcore rsp

2014-07-02 Thread kan . liang
From: Kan Liang kan.li...@intel.com

With -cpu host KVM reports LBR and offcore support, so the perf driver may 
accesses the LBR and offcore MSRs.
However, there is no LBR and offcore virtualization support yet. This could 
causes guest to crash.
As a workaround, KVM just simply ignore the LBR and offcore_rsp MSRs to lie the 
guest.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y.
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n.
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Andi Kleen a...@linux.intel.com
Signed-off-by: Kan Liang kan.li...@intel.com
---
 arch/x86/kvm/pmu.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index cbecaa9..ad9b4fa 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -331,6 +331,15 @@ bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
ret = pmu-version  1;
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   return 1; /* to avoid crashes */
default:
ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)
|| get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0)
@@ -358,6 +367,16 @@ int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 
*data)
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
*data = pmu-global_ovf_ctrl;
return 0;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   *data = 0;
+   return 0;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
@@ -409,6 +428,16 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data 
*msr_info)
return 0;
}
break;
+   case MSR_OFFCORE_RSP_0:
+   case MSR_OFFCORE_RSP_1:
+   /* At most 8-deep LBR for core and atom */
+   case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 7:
+   case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 7:
+   /* 16-deep LBR for core i3/i5/i7 series processors */
+   case MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 15:
+   case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 15:
+   /* dummy for now */
+   break;
default:
if ((pmc = get_gp_pmc(pmu, index, MSR_IA32_PERFCTR0)) ||
(pmc = get_fixed_pmc(pmu, index))) {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V2 1/3] perf ignore LBR and offcore_rsp.

2014-07-02 Thread kan . liang
From: Kan Liang kan.li...@intel.com

x86, perf: Protect LBR and offcore rsp against KVM lying

With -cpu host, KVM reports LBR and offcore support, if the host has support.
When the guest perf driver tries to access LBR or offcore_rsp MSR,
it #GPs all MSR accesses,since KVM doesn't handle LBR and offcore support.
So check the related MSRs access right once at initialization time to avoid the 
error access at runtime.

For reproducing the issue, please build the kernel with CONFIG_KVM_INTEL = y.
And CONFIG_PARAVIRT = n and CONFIG_KVM_GUEST = n.
Start the guest with -cpu host.
Run perf record with --branch-any or --branch-filter in guest to trigger LBR 
#GP.
Run perf stat offcore events (E.g. LLC-loads/LLC-load-misses ...) in guest to 
trigger offcore_rsp #GP

Signed-off-by: Andi Kleen a...@linux.intel.com
Signed-off-by: Kan Liang kan.li...@intel.com

V2: Move the check code to initialization time.
---
 arch/x86/kernel/cpu/perf_event.h   | 19 +--
 arch/x86/kernel/cpu/perf_event_intel.c |  7 +++
 arch/x86/kernel/cpu/perf_event_intel_lbr.c |  4 ++--
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 3b2f9bd..5d977b2 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -458,12 +458,13 @@ struct x86_pmu {
u64 lbr_sel_mask;  /* LBR_SELECT valid bits */
const int   *lbr_sel_map;  /* lbr_select mappings */
boollbr_double_abort;  /* duplicated lbr aborts */
-
+   boollbr_msr_access;/* LBR MSR can be accessed */
/*
 * Extra registers for events
 */
struct extra_reg *extra_regs;
unsigned int er_flags;
+   boolextra_msr_access;  /* EXTRA REG MSR can be 
accessed */
 
/*
 * Intel host/guest support (KVM)
@@ -525,6 +526,20 @@ extern u64 __read_mostly hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
+/* 
+ * Under certain circumstances, access certain MSR may cause #GP.
+ * The function tests if the input MSR can be safely accessed.
+ */
+static inline bool test_msr_access(unsigned long msr)
+{
+   u64 value;
+   if (rdmsrl_safe(msr, value)  0)
+   return false;
+   if (wrmsrl_safe(msr, value)  0)
+   return false;
+   return true;
+}
+
 u64 x86_perf_event_update(struct perf_event *event);
 
 static inline unsigned int x86_pmu_config_addr(int index)
@@ -555,7 +570,7 @@ static inline void __x86_pmu_enable_event(struct 
hw_perf_event *hwc,
 {
u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
 
-   if (hwc-extra_reg.reg)
+   if (hwc-extra_reg.reg  x86_pmu.extra_msr_access)
wrmsrl(hwc-extra_reg.reg, hwc-extra_reg.config);
wrmsrl(hwc-config_base, (hwc-config | enable_mask)  ~disable_mask);
 }
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c 
b/arch/x86/kernel/cpu/perf_event_intel.c
index adb02aa..8011d42 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2565,6 +2565,13 @@ __init int intel_pmu_init(void)
}
}
 
+   /* Access LBR MSR may cause #GP under certain circumstances. E.g. KVM 
doesn't support LBR MSR */
+   if (x86_pmu.lbr_nr)
+   x86_pmu.lbr_msr_access = test_msr_access(x86_pmu.lbr_tos)  
test_msr_access(x86_pmu.lbr_from);
+   /* Access extra MSR may cause #GP under certain circumstances. E.g. KVM 
doesn't support offcore event */
+   if (x86_pmu.extra_regs)
+   x86_pmu.extra_msr_access = 
test_msr_access(x86_pmu.extra_regs-msr);
+
/* Support full width counters using alternative MSR range */
if (x86_pmu.intel_cap.full_width_write) {
x86_pmu.max_period = x86_pmu.cntval_mask;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c 
b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 9dd2459..9508d1e 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -172,7 +172,7 @@ static void intel_pmu_lbr_reset_64(void)
 
 void intel_pmu_lbr_reset(void)
 {
-   if (!x86_pmu.lbr_nr)
+   if (!x86_pmu.lbr_nr  || !x86_pmu.lbr_msr_access)
return;
 
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
@@ -334,7 +334,7 @@ void intel_pmu_lbr_read(void)
 {
struct cpu_hw_events *cpuc = __get_cpu_var(cpu_hw_events);
 
-   if (!cpuc-lbr_users)
+   if (!cpuc-lbr_users || !x86_pmu.lbr_msr_access)
return;
 
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo

[PATCH V2 2/3] perf protect LBR when Intel PT is enabled.

2014-07-02 Thread kan . liang
From: Kan Liang kan.li...@intel.com

If RTIT_CTL.TraceEn=1, any attempt to read or write the LBR or LER MSRs, 
including LBR_TOS, will result in a #GP.
Since Intel PT can be enabled/disabled at runtime, LBR MSRs have to be 
protected by _safe() at runtime.

Signed-off-by: Kan Liang kan.li...@intel.com
---
 arch/x86/kernel/cpu/perf_event.h   |  1 -
 arch/x86/kernel/cpu/perf_event_intel.c |  3 ---
 arch/x86/kernel/cpu/perf_event_intel_lbr.c | 38 +-
 3 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 5d977b2..fafb809 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -458,7 +458,6 @@ struct x86_pmu {
u64 lbr_sel_mask;  /* LBR_SELECT valid bits */
const int   *lbr_sel_map;  /* lbr_select mappings */
boollbr_double_abort;  /* duplicated lbr aborts */
-   boollbr_msr_access;/* LBR MSR can be accessed */
/*
 * Extra registers for events
 */
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c 
b/arch/x86/kernel/cpu/perf_event_intel.c
index 8011d42..ddd3590 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2565,9 +2565,6 @@ __init int intel_pmu_init(void)
}
}
 
-   /* Access LBR MSR may cause #GP under certain circumstances. E.g. KVM 
doesn't support LBR MSR */
-   if (x86_pmu.lbr_nr)
-   x86_pmu.lbr_msr_access = test_msr_access(x86_pmu.lbr_tos)  
test_msr_access(x86_pmu.lbr_from);
/* Access extra MSR may cause #GP under certain circumstances. E.g. KVM 
doesn't support offcore event */
if (x86_pmu.extra_regs)
x86_pmu.extra_msr_access = 
test_msr_access(x86_pmu.extra_regs-msr);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c 
b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 9508d1e..980b8dc 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -157,7 +157,7 @@ static void intel_pmu_lbr_reset_32(void)
int i;
 
for (i = 0; i  x86_pmu.lbr_nr; i++)
-   wrmsrl(x86_pmu.lbr_from + i, 0);
+   wrmsrl_safe(x86_pmu.lbr_from + i, 0ULL);
 }
 
 static void intel_pmu_lbr_reset_64(void)
@@ -165,14 +165,14 @@ static void intel_pmu_lbr_reset_64(void)
int i;
 
for (i = 0; i  x86_pmu.lbr_nr; i++) {
-   wrmsrl(x86_pmu.lbr_from + i, 0);
-   wrmsrl(x86_pmu.lbr_to   + i, 0);
+   wrmsrl_safe(x86_pmu.lbr_from + i, 0ULL);
+   wrmsrl_safe(x86_pmu.lbr_to   + i, 0ULL);
}
 }
 
 void intel_pmu_lbr_reset(void)
 {
-   if (!x86_pmu.lbr_nr  || !x86_pmu.lbr_msr_access)
+   if (!x86_pmu.lbr_nr)
return;
 
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
@@ -237,19 +237,14 @@ void intel_pmu_lbr_disable_all(void)
 /*
  * TOS = most recently recorded branch
  */
-static inline u64 intel_pmu_lbr_tos(void)
+static inline int intel_pmu_lbr_tos(u64 *tos)
 {
-   u64 tos;
-
-   rdmsrl(x86_pmu.lbr_tos, tos);
-
-   return tos;
+   return rdmsrl_safe(x86_pmu.lbr_tos, tos);
 }
 
-static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
+static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc, u64 tos)
 {
unsigned long mask = x86_pmu.lbr_nr - 1;
-   u64 tos = intel_pmu_lbr_tos();
int i;
 
for (i = 0; i  x86_pmu.lbr_nr; i++) {
@@ -278,11 +273,10 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events 
*cpuc)
  * is the same as the linear address, allowing us to merge the LIP and EIP
  * LBR formats.
  */
-static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
+static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc, u64 tos)
 {
unsigned long mask = x86_pmu.lbr_nr - 1;
int lbr_format = x86_pmu.intel_cap.lbr_format;
-   u64 tos = intel_pmu_lbr_tos();
int i;
int out = 0;
 
@@ -333,14 +327,24 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events 
*cpuc)
 void intel_pmu_lbr_read(void)
 {
struct cpu_hw_events *cpuc = __get_cpu_var(cpu_hw_events);
+   u64 tos;
 
-   if (!cpuc-lbr_users || !x86_pmu.lbr_msr_access)
+   if (!cpuc-lbr_users)
+   return;
+
+   /*
+* If KVM doesn't support LBR MSRs or Intel PT is enabled,
+* accessing LBR MSRs cause GP#.
+* Since Intel PT can be enabled/disabled at runtime,
+* checking the LBR MSRs access right here.
+*/
+   if (intel_pmu_lbr_tos(tos)  0)
return;
 
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
-   intel_pmu_lbr_read_32(cpuc);
+   intel_pmu_lbr_read_32(cpuc, tos);
else
-   intel_pmu_lbr_read_64(cpuc);
+   intel_pmu_lbr_read_64(cpuc, tos