* [PATCH 01/11] KVM: x86/pmu: Update comments for AMD gp counters
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-23 19:50 ` Jim Mattson
2022-02-21 11:51 ` [PATCH 02/11] KVM: x86/pmu: Extract check_pmu_event_filter() from the same semantics Like Xu
` (9 subsequent siblings)
10 siblings, 1 reply; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
The obsolete comment could more accurately state that AMD platforms
have two base MSR addresses and two different maximum numbers
for gp counters, depending on the X86_FEATURE_PERFCTR_CORE feature.
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index b1a02993782b..c4692f0ff87e 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -34,7 +34,7 @@
* However AMD doesn't support fixed-counters;
* - There are three types of index to access perf counters (PMC):
* 1. MSR (named msr): For example Intel has MSR_IA32_PERFCTRn and AMD
- * has MSR_K7_PERFCTRn.
+ * has MSR_F15H_PERF_CTRn or MSR_K7_PERFCTRn.
* 2. MSR Index (named idx): This normally is used by RDPMC instruction.
* For instance AMD RDPMC instruction uses 0000_0003h in ECX to access
* C001_0007h (MSR_K7_PERCTR3). Intel has a similar mechanism, except
@@ -46,7 +46,8 @@
* between pmc and perf counters is as the following:
* * Intel: [0 .. INTEL_PMC_MAX_GENERIC-1] <=> gp counters
* [INTEL_PMC_IDX_FIXED .. INTEL_PMC_IDX_FIXED + 2] <=> fixed
- * * AMD: [0 .. AMD64_NUM_COUNTERS-1] <=> gp counters
+ * * AMD: [0 .. AMD64_NUM_COUNTERS-1] or
+ * [0 .. AMD64_NUM_COUNTERS_CORE-1] <=> gp counters
*/
static void kvm_pmi_trigger_fn(struct irq_work *irq_work)
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 01/11] KVM: x86/pmu: Update comments for AMD gp counters
2022-02-21 11:51 ` [PATCH 01/11] KVM: x86/pmu: Update comments for AMD gp counters Like Xu
@ 2022-02-23 19:50 ` Jim Mattson
0 siblings, 0 replies; 14+ messages in thread
From: Jim Mattson @ 2022-02-23 19:50 UTC (permalink / raw)
To: Like Xu
Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
Joerg Roedel, kvm, linux-kernel, Like Xu
On Mon, Feb 21, 2022 at 3:52 AM Like Xu <like.xu.linux@gmail.com> wrote:
>
> From: Like Xu <likexu@tencent.com>
>
> The obsolete comment could more accurately state that AMD platforms
> have two base MSR addresses and two different maximum numbers
> for gp counters, depending on the X86_FEATURE_PERFCTR_CORE feature.
>
> Signed-off-by: Like Xu <likexu@tencent.com>
> ---
> arch/x86/kvm/pmu.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index b1a02993782b..c4692f0ff87e 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -34,7 +34,7 @@
> * However AMD doesn't support fixed-counters;
> * - There are three types of index to access perf counters (PMC):
> * 1. MSR (named msr): For example Intel has MSR_IA32_PERFCTRn and AMD
> - * has MSR_K7_PERFCTRn.
> + * has MSR_F15H_PERF_CTRn or MSR_K7_PERFCTRn.
"Or" sounds exclusive. Maybe it would be better to say:
has MSR_K7_PERFCTRn and, for families 15H and later,
MSR_F15H_PERF_CTRn, where MSR_F15H_PERF_CTR[0-3] are aliased to
MSR_K7_PERFCTRn.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 02/11] KVM: x86/pmu: Extract check_pmu_event_filter() from the same semantics
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
2022-02-21 11:51 ` [PATCH 01/11] KVM: x86/pmu: Update comments for AMD gp counters Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 03/11] KVM: x86/pmu: Pass only "struct kvm_pmc *pmc" to reprogram_counter() Like Xu
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
Checking the kvm->arch.pmu_event_filter policy in both gp and fixed
code paths was somewhat redundant, so common parts can be extracted,
which reduces code footprint and improves readability.
Signed-off-by: Like Xu <likexu@tencent.com>
Reviewed-by: Wanpeng Li <wanpengli@tencent.com>
---
arch/x86/kvm/pmu.c | 61 +++++++++++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 25 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index c4692f0ff87e..78527b118f72 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -180,13 +180,43 @@ static int cmp_u64(const void *a, const void *b)
return *(__u64 *)a - *(__u64 *)b;
}
+static bool check_pmu_event_filter(struct kvm_pmc *pmc)
+{
+ struct kvm_pmu_event_filter *filter;
+ struct kvm *kvm = pmc->vcpu->kvm;
+ bool allow_event = true;
+ __u64 key;
+ int idx;
+
+ filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
+ if (!filter)
+ goto out;
+
+ if (pmc_is_gp(pmc)) {
+ key = pmc->eventsel & AMD64_RAW_EVENT_MASK_NB;
+ if (bsearch(&key, filter->events, filter->nevents,
+ sizeof(__u64), cmp_u64))
+ allow_event = filter->action == KVM_PMU_EVENT_ALLOW;
+ else
+ allow_event = filter->action == KVM_PMU_EVENT_DENY;
+ } else {
+ idx = pmc->idx - INTEL_PMC_IDX_FIXED;
+ if (filter->action == KVM_PMU_EVENT_DENY &&
+ test_bit(idx, (ulong *)&filter->fixed_counter_bitmap))
+ allow_event = false;
+ if (filter->action == KVM_PMU_EVENT_ALLOW &&
+ !test_bit(idx, (ulong *)&filter->fixed_counter_bitmap))
+ allow_event = false;
+ }
+
+out:
+ return allow_event;
+}
+
void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
{
u64 config;
u32 type = PERF_TYPE_RAW;
- struct kvm *kvm = pmc->vcpu->kvm;
- struct kvm_pmu_event_filter *filter;
- bool allow_event = true;
if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
printk_once("kvm pmu: pin control bit is ignored\n");
@@ -198,17 +228,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc))
return;
- filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
- if (filter) {
- __u64 key = eventsel & AMD64_RAW_EVENT_MASK_NB;
-
- if (bsearch(&key, filter->events, filter->nevents,
- sizeof(__u64), cmp_u64))
- allow_event = filter->action == KVM_PMU_EVENT_ALLOW;
- else
- allow_event = filter->action == KVM_PMU_EVENT_DENY;
- }
- if (!allow_event)
+ if (!check_pmu_event_filter(pmc))
return;
if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
@@ -243,23 +263,14 @@ void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
{
unsigned en_field = ctrl & 0x3;
bool pmi = ctrl & 0x8;
- struct kvm_pmu_event_filter *filter;
- struct kvm *kvm = pmc->vcpu->kvm;
pmc_pause_counter(pmc);
if (!en_field || !pmc_is_enabled(pmc))
return;
- filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
- if (filter) {
- if (filter->action == KVM_PMU_EVENT_DENY &&
- test_bit(idx, (ulong *)&filter->fixed_counter_bitmap))
- return;
- if (filter->action == KVM_PMU_EVENT_ALLOW &&
- !test_bit(idx, (ulong *)&filter->fixed_counter_bitmap))
- return;
- }
+ if (!check_pmu_event_filter(pmc))
+ return;
if (pmc->current_config == (u64)ctrl && pmc_resume_counter(pmc))
return;
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 03/11] KVM: x86/pmu: Pass only "struct kvm_pmc *pmc" to reprogram_counter()
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
2022-02-21 11:51 ` [PATCH 01/11] KVM: x86/pmu: Update comments for AMD gp counters Like Xu
2022-02-21 11:51 ` [PATCH 02/11] KVM: x86/pmu: Extract check_pmu_event_filter() from the same semantics Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 04/11] KVM: x86/pmu: Drop "u64 eventsel" for reprogram_gp_counter() Like Xu
` (7 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
Passing the reference "struct kvm_pmc *pmc" when creating
pmc->perf_event is sufficient. This change helps to simplify the
calling convention by replacing reprogram_{gp, fixed}_counter()
with reprogram_counter() seamlessly.
No functional change intended.
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 17 +++++------------
arch/x86/kvm/pmu.h | 2 +-
arch/x86/kvm/vmx/pmu_intel.c | 32 ++++++++++++++++++--------------
3 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 78527b118f72..125bdfdbaa7a 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -286,18 +286,13 @@ void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
}
EXPORT_SYMBOL_GPL(reprogram_fixed_counter);
-void reprogram_counter(struct kvm_pmu *pmu, int pmc_idx)
+void reprogram_counter(struct kvm_pmc *pmc)
{
- struct kvm_pmc *pmc = kvm_x86_ops.pmu_ops->pmc_idx_to_pmc(pmu, pmc_idx);
-
- if (!pmc)
- return;
-
if (pmc_is_gp(pmc))
reprogram_gp_counter(pmc, pmc->eventsel);
else {
- int idx = pmc_idx - INTEL_PMC_IDX_FIXED;
- u8 ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, idx);
+ int idx = pmc->idx - INTEL_PMC_IDX_FIXED;
+ u8 ctrl = fixed_ctrl_field(pmc_to_pmu(pmc)->fixed_ctr_ctrl, idx);
reprogram_fixed_counter(pmc, ctrl, idx);
}
@@ -316,8 +311,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
clear_bit(bit, pmu->reprogram_pmi);
continue;
}
-
- reprogram_counter(pmu, bit);
+ reprogram_counter(pmc);
}
/*
@@ -503,13 +497,12 @@ void kvm_pmu_destroy(struct kvm_vcpu *vcpu)
static void kvm_pmu_incr_counter(struct kvm_pmc *pmc)
{
- struct kvm_pmu *pmu = pmc_to_pmu(pmc);
u64 prev_count;
prev_count = pmc->counter;
pmc->counter = (pmc->counter + 1) & pmc_bitmask(pmc);
- reprogram_counter(pmu, pmc->idx);
+ reprogram_counter(pmc);
if (pmc->counter < prev_count)
__kvm_perf_overflow(pmc, false);
}
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 7a7b8d5b775e..b529c54dc309 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -142,7 +142,7 @@ static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value)
void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel);
void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int fixed_idx);
-void reprogram_counter(struct kvm_pmu *pmu, int pmc_idx);
+void reprogram_counter(struct kvm_pmc *pmc);
void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu);
void kvm_pmu_handle_event(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 466d18fc0c5d..049ce5519fb5 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -56,16 +56,32 @@ static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
pmu->fixed_ctr_ctrl = data;
}
+static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
+{
+ if (pmc_idx < INTEL_PMC_IDX_FIXED)
+ return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + pmc_idx,
+ MSR_P6_EVNTSEL0);
+ else {
+ u32 idx = pmc_idx - INTEL_PMC_IDX_FIXED;
+
+ return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0);
+ }
+}
+
/* function is called when global control register has been updated. */
static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data)
{
int bit;
u64 diff = pmu->global_ctrl ^ data;
+ struct kvm_pmc *pmc;
pmu->global_ctrl = data;
- for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX)
- reprogram_counter(pmu, bit);
+ for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX) {
+ pmc = intel_pmc_idx_to_pmc(pmu, bit);
+ if (pmc)
+ reprogram_counter(pmc);
+ }
}
static unsigned int intel_pmc_perf_hw_id(struct kvm_pmc *pmc)
@@ -101,18 +117,6 @@ static bool intel_pmc_is_enabled(struct kvm_pmc *pmc)
return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
}
-static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
-{
- if (pmc_idx < INTEL_PMC_IDX_FIXED)
- return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + pmc_idx,
- MSR_P6_EVNTSEL0);
- else {
- u32 idx = pmc_idx - INTEL_PMC_IDX_FIXED;
-
- return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0);
- }
-}
-
static bool intel_is_valid_rdpmc_ecx(struct kvm_vcpu *vcpu, unsigned int idx)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 04/11] KVM: x86/pmu: Drop "u64 eventsel" for reprogram_gp_counter()
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (2 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 03/11] KVM: x86/pmu: Pass only "struct kvm_pmc *pmc" to reprogram_counter() Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 05/11] KVM: x86/pmu: Drop "u8 ctrl, int idx" for reprogram_fixed_counter() Like Xu
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
Because inside reprogram_gp_counter(), it is bound to assign the requested
eventel to pmc->eventsel, this assignment step can be moved forward, thus
simplifying the passing of parameters to "struct kvm_pmc *pmc" only.
No functional change intended.
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 7 +++----
arch/x86/kvm/pmu.h | 2 +-
arch/x86/kvm/svm/pmu.c | 3 ++-
arch/x86/kvm/vmx/pmu_intel.c | 3 ++-
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 125bdfdbaa7a..482a78956dd0 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -213,16 +213,15 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc)
return allow_event;
}
-void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+void reprogram_gp_counter(struct kvm_pmc *pmc)
{
u64 config;
u32 type = PERF_TYPE_RAW;
+ u64 eventsel = pmc->eventsel;
if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
printk_once("kvm pmu: pin control bit is ignored\n");
- pmc->eventsel = eventsel;
-
pmc_pause_counter(pmc);
if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc))
@@ -289,7 +288,7 @@ EXPORT_SYMBOL_GPL(reprogram_fixed_counter);
void reprogram_counter(struct kvm_pmc *pmc)
{
if (pmc_is_gp(pmc))
- reprogram_gp_counter(pmc, pmc->eventsel);
+ reprogram_gp_counter(pmc);
else {
int idx = pmc->idx - INTEL_PMC_IDX_FIXED;
u8 ctrl = fixed_ctrl_field(pmc_to_pmu(pmc)->fixed_ctr_ctrl, idx);
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index b529c54dc309..4db50c290c62 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -140,7 +140,7 @@ static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value)
return sample_period;
}
-void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel);
+void reprogram_gp_counter(struct kvm_pmc *pmc);
void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int fixed_idx);
void reprogram_counter(struct kvm_pmc *pmc);
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index 5aa45f13b16d..db839578e8be 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -265,7 +265,8 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (data == pmc->eventsel)
return 0;
if (!(data & pmu->reserved_bits)) {
- reprogram_gp_counter(pmc, data);
+ pmc->eventsel = data;
+ reprogram_gp_counter(pmc);
return 0;
}
}
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 049ce5519fb5..1ed7d23d6738 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -448,7 +448,8 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (data == pmc->eventsel)
return 0;
if (!(data & pmu->reserved_bits)) {
- reprogram_gp_counter(pmc, data);
+ pmc->eventsel = data;
+ reprogram_gp_counter(pmc);
return 0;
}
} else if (intel_pmu_handle_lbr_msrs_access(vcpu, msr_info, false))
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 05/11] KVM: x86/pmu: Drop "u8 ctrl, int idx" for reprogram_fixed_counter()
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (3 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 04/11] KVM: x86/pmu: Drop "u64 eventsel" for reprogram_gp_counter() Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 06/11] KVM: x86/pmu: Use only the uniformly exported interface reprogram_counter() Like Xu
` (5 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
Since afrer reprogram_fixed_counter() is called, it's bound to assign
the requested fixed_ctr_ctrl to pmu->fixed_ctr_ctrl, this assignment step
can be moved forward (the stale value for diff is saved extra early),
thus simplifying the passing of parameters.
No functional change intended.
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 13 ++++++-------
arch/x86/kvm/pmu.h | 2 +-
arch/x86/kvm/vmx/pmu_intel.c | 16 ++++++++--------
3 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 482a78956dd0..7c90d5d196a4 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -258,8 +258,11 @@ void reprogram_gp_counter(struct kvm_pmc *pmc)
}
EXPORT_SYMBOL_GPL(reprogram_gp_counter);
-void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
+void reprogram_fixed_counter(struct kvm_pmc *pmc)
{
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+ int idx = pmc->idx - INTEL_PMC_IDX_FIXED;
+ u8 ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, idx);
unsigned en_field = ctrl & 0x3;
bool pmi = ctrl & 0x8;
@@ -289,12 +292,8 @@ void reprogram_counter(struct kvm_pmc *pmc)
{
if (pmc_is_gp(pmc))
reprogram_gp_counter(pmc);
- else {
- int idx = pmc->idx - INTEL_PMC_IDX_FIXED;
- u8 ctrl = fixed_ctrl_field(pmc_to_pmu(pmc)->fixed_ctr_ctrl, idx);
-
- reprogram_fixed_counter(pmc, ctrl, idx);
- }
+ else
+ reprogram_fixed_counter(pmc);
}
EXPORT_SYMBOL_GPL(reprogram_counter);
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 4db50c290c62..70a982c3cdad 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -141,7 +141,7 @@ static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value)
}
void reprogram_gp_counter(struct kvm_pmc *pmc);
-void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int fixed_idx);
+void reprogram_fixed_counter(struct kvm_pmc *pmc);
void reprogram_counter(struct kvm_pmc *pmc);
void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 1ed7d23d6738..cc4a092f0d67 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -37,23 +37,23 @@ static int fixed_pmc_events[] = {1, 0, 7};
static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
{
+ struct kvm_pmc *pmc;
+ u8 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
int i;
+ pmu->fixed_ctr_ctrl = data;
for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
u8 new_ctrl = fixed_ctrl_field(data, i);
- u8 old_ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, i);
- struct kvm_pmc *pmc;
-
- pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
+ u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
if (old_ctrl == new_ctrl)
continue;
- __set_bit(INTEL_PMC_IDX_FIXED + i, pmu->pmc_in_use);
- reprogram_fixed_counter(pmc, new_ctrl, i);
- }
+ pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
- pmu->fixed_ctr_ctrl = data;
+ __set_bit(INTEL_PMC_IDX_FIXED + i, pmu->pmc_in_use);
+ reprogram_fixed_counter(pmc);
+ }
}
static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 06/11] KVM: x86/pmu: Use only the uniformly exported interface reprogram_counter()
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (4 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 05/11] KVM: x86/pmu: Drop "u8 ctrl, int idx" for reprogram_fixed_counter() Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 07/11] KVM: x86/pmu: Use PERF_TYPE_RAW to merge reprogram_{gp, fixed}counter() Like Xu
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
Since reprogram_counter(), reprogram_{gp, fixed}_counter() currently have
the same incoming parameter "struct kvm_pmc *pmc", the callers can simplify
the conetxt by using uniformly exported interface, which makes reprogram_
{gp, fixed}_counter() static and eliminates EXPORT_SYMBOL_GPL.
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 6 ++----
arch/x86/kvm/pmu.h | 2 --
arch/x86/kvm/svm/pmu.c | 2 +-
arch/x86/kvm/vmx/pmu_intel.c | 4 ++--
4 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 7c90d5d196a4..5816af6b6494 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -213,7 +213,7 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc)
return allow_event;
}
-void reprogram_gp_counter(struct kvm_pmc *pmc)
+static void reprogram_gp_counter(struct kvm_pmc *pmc)
{
u64 config;
u32 type = PERF_TYPE_RAW;
@@ -256,9 +256,8 @@ void reprogram_gp_counter(struct kvm_pmc *pmc)
(eventsel & HSW_IN_TX),
(eventsel & HSW_IN_TX_CHECKPOINTED));
}
-EXPORT_SYMBOL_GPL(reprogram_gp_counter);
-void reprogram_fixed_counter(struct kvm_pmc *pmc)
+static void reprogram_fixed_counter(struct kvm_pmc *pmc)
{
struct kvm_pmu *pmu = pmc_to_pmu(pmc);
int idx = pmc->idx - INTEL_PMC_IDX_FIXED;
@@ -286,7 +285,6 @@ void reprogram_fixed_counter(struct kvm_pmc *pmc)
!(en_field & 0x1), /* exclude kernel */
pmi, false, false);
}
-EXPORT_SYMBOL_GPL(reprogram_fixed_counter);
void reprogram_counter(struct kvm_pmc *pmc)
{
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 70a982c3cdad..201b99628423 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -140,8 +140,6 @@ static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value)
return sample_period;
}
-void reprogram_gp_counter(struct kvm_pmc *pmc);
-void reprogram_fixed_counter(struct kvm_pmc *pmc);
void reprogram_counter(struct kvm_pmc *pmc);
void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index db839578e8be..b264e8117be1 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -266,7 +266,7 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
return 0;
if (!(data & pmu->reserved_bits)) {
pmc->eventsel = data;
- reprogram_gp_counter(pmc);
+ reprogram_counter(pmc);
return 0;
}
}
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index cc4a092f0d67..a69d2aeb7526 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -52,7 +52,7 @@ static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
__set_bit(INTEL_PMC_IDX_FIXED + i, pmu->pmc_in_use);
- reprogram_fixed_counter(pmc);
+ reprogram_counter(pmc);
}
}
@@ -449,7 +449,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
return 0;
if (!(data & pmu->reserved_bits)) {
pmc->eventsel = data;
- reprogram_gp_counter(pmc);
+ reprogram_counter(pmc);
return 0;
}
} else if (intel_pmu_handle_lbr_msrs_access(vcpu, msr_info, false))
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 07/11] KVM: x86/pmu: Use PERF_TYPE_RAW to merge reprogram_{gp, fixed}counter()
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (5 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 06/11] KVM: x86/pmu: Use only the uniformly exported interface reprogram_counter() Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 08/11] perf: x86/core: Add interface to query perfmon_event_map[] directly Like Xu
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu, Peter Zijlstra
From: Like Xu <likexu@tencent.com>
The code sketch for reprogram_{gp, fixed}_counter() is similar, while the
fixed counter using the PERF_TYPE_HARDWAR type and the gp being
able to use either PERF_TYPE_HARDWAR or PERF_TYPE_RAW type
depending on the pmc->eventsel value.
After 'commit 761875634a5e ("KVM: x86/pmu: Setup pmc->eventsel
for fixed PMCs")', the pmc->eventsel of the fixed counter will also have
been setup with the same semantic value and will not be changed during
the guest runtime. But essentially, "the HARDWARE is just a convenience
wrapper over RAW IIRC", quoated from Peterz. So it could be pretty safe
to use the PERF_TYPE_RAW type only to program both gp and fixed
counters naturally in the reprogram_counter().
To make the gp and fixed counters more semantically symmetrical,
the selection of EVENTSEL_{USER, OS, INT} bits is temporarily translated
via fixed_ctr_ctrl before the pmc_reprogram_counter() call.
Practically, this change drops the guest pmu support on the hosts without
X86_FEATURE_ARCH_PERFMON (the oldest Pentium 4), where the
PERF_TYPE_HARDWAR is intentionally introduced so that hosts can
map the architectural guest PMU events to their own.
Cc: Peter Zijlstra <peterz@infradead.org>
Suggested-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 106 +++++++++++------------------------
arch/x86/kvm/vmx/pmu_intel.c | 2 +-
2 files changed, 35 insertions(+), 73 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 5816af6b6494..edd51ec7711d 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -213,35 +213,44 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc)
return allow_event;
}
-static void reprogram_gp_counter(struct kvm_pmc *pmc)
+static inline bool pmc_speculative_in_use(struct kvm_pmc *pmc)
{
- u64 config;
- u32 type = PERF_TYPE_RAW;
- u64 eventsel = pmc->eventsel;
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
- if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
- printk_once("kvm pmu: pin control bit is ignored\n");
+ if (pmc_is_fixed(pmc))
+ return fixed_ctrl_field(pmu->fixed_ctr_ctrl,
+ pmc->idx - INTEL_PMC_IDX_FIXED) & 0x3;
+
+ return pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE;
+}
+
+void reprogram_counter(struct kvm_pmc *pmc)
+{
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+ u64 eventsel = pmc->eventsel;
+ u8 fixed_ctr_ctrl;
pmc_pause_counter(pmc);
- if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc))
+ if (!pmc_speculative_in_use(pmc) || !pmc_is_enabled(pmc))
return;
if (!check_pmu_event_filter(pmc))
return;
- if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
- ARCH_PERFMON_EVENTSEL_INV |
- ARCH_PERFMON_EVENTSEL_CMASK |
- HSW_IN_TX |
- HSW_IN_TX_CHECKPOINTED))) {
- config = kvm_x86_ops.pmu_ops->pmc_perf_hw_id(pmc);
- if (config != PERF_COUNT_HW_MAX)
- type = PERF_TYPE_HARDWARE;
- }
+ if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
+ printk_once("kvm pmu: pin control bit is ignored\n");
- if (type == PERF_TYPE_RAW)
- config = eventsel & AMD64_RAW_EVENT_MASK;
+ if (pmc_is_fixed(pmc)) {
+ fixed_ctr_ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl,
+ pmc->idx - INTEL_PMC_IDX_FIXED);
+ if (fixed_ctr_ctrl & 0x1)
+ eventsel |= ARCH_PERFMON_EVENTSEL_OS;
+ if (fixed_ctr_ctrl & 0x2)
+ eventsel |= ARCH_PERFMON_EVENTSEL_USR;
+ if (fixed_ctr_ctrl & 0x8)
+ eventsel |= ARCH_PERFMON_EVENTSEL_INT;
+ }
if (pmc->current_config == eventsel && pmc_resume_counter(pmc))
return;
@@ -249,49 +258,13 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc)
pmc_release_perf_event(pmc);
pmc->current_config = eventsel;
- pmc_reprogram_counter(pmc, type, config,
- !(eventsel & ARCH_PERFMON_EVENTSEL_USR),
- !(eventsel & ARCH_PERFMON_EVENTSEL_OS),
- eventsel & ARCH_PERFMON_EVENTSEL_INT,
- (eventsel & HSW_IN_TX),
- (eventsel & HSW_IN_TX_CHECKPOINTED));
-}
-
-static void reprogram_fixed_counter(struct kvm_pmc *pmc)
-{
- struct kvm_pmu *pmu = pmc_to_pmu(pmc);
- int idx = pmc->idx - INTEL_PMC_IDX_FIXED;
- u8 ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, idx);
- unsigned en_field = ctrl & 0x3;
- bool pmi = ctrl & 0x8;
-
- pmc_pause_counter(pmc);
-
- if (!en_field || !pmc_is_enabled(pmc))
- return;
-
- if (!check_pmu_event_filter(pmc))
- return;
-
- if (pmc->current_config == (u64)ctrl && pmc_resume_counter(pmc))
- return;
-
- pmc_release_perf_event(pmc);
-
- pmc->current_config = (u64)ctrl;
- pmc_reprogram_counter(pmc, PERF_TYPE_HARDWARE,
- kvm_x86_ops.pmu_ops->pmc_perf_hw_id(pmc),
- !(en_field & 0x2), /* exclude user */
- !(en_field & 0x1), /* exclude kernel */
- pmi, false, false);
-}
-
-void reprogram_counter(struct kvm_pmc *pmc)
-{
- if (pmc_is_gp(pmc))
- reprogram_gp_counter(pmc);
- else
- reprogram_fixed_counter(pmc);
+ pmc_reprogram_counter(pmc, PERF_TYPE_RAW,
+ (eventsel & AMD64_RAW_EVENT_MASK),
+ !(eventsel & ARCH_PERFMON_EVENTSEL_USR),
+ !(eventsel & ARCH_PERFMON_EVENTSEL_OS),
+ eventsel & ARCH_PERFMON_EVENTSEL_INT,
+ (eventsel & HSW_IN_TX),
+ (eventsel & HSW_IN_TX_CHECKPOINTED));
}
EXPORT_SYMBOL_GPL(reprogram_counter);
@@ -449,17 +422,6 @@ void kvm_pmu_init(struct kvm_vcpu *vcpu)
kvm_pmu_refresh(vcpu);
}
-static inline bool pmc_speculative_in_use(struct kvm_pmc *pmc)
-{
- struct kvm_pmu *pmu = pmc_to_pmu(pmc);
-
- if (pmc_is_fixed(pmc))
- return fixed_ctrl_field(pmu->fixed_ctr_ctrl,
- pmc->idx - INTEL_PMC_IDX_FIXED) & 0x3;
-
- return pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE;
-}
-
/* Release perf_events for vPMCs that have been unused for a full time slice. */
void kvm_pmu_cleanup(struct kvm_vcpu *vcpu)
{
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index a69d2aeb7526..98a01f6a9d5d 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -492,7 +492,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
pmu->reserved_bits = 0xffffffff00200000ull;
entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
- if (!entry || !enable_pmu)
+ if (!entry || !enable_pmu || !boot_cpu_has(X86_FEATURE_ARCH_PERFMON))
return;
eax.full = entry->eax;
edx.full = entry->edx;
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 08/11] perf: x86/core: Add interface to query perfmon_event_map[] directly
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (6 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 07/11] KVM: x86/pmu: Use PERF_TYPE_RAW to merge reprogram_{gp, fixed}counter() Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 11:51 ` [PATCH 09/11] KVM: x86/pmu: Replace pmc_perf_hw_id() with perf_get_hw_event_config() Like Xu
` (2 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu, Peter Zijlstra
From: Like Xu <likexu@tencent.com>
Currently, we have [intel|knc|p4|p6]_perfmon_event_map on the Intel
platforms and amd_[f17h]_perfmon_event_map on the AMD platforms.
Early clumsy KVM code or other potential perf_event users may have
hard-coded these perfmon_maps (e.g., arch/x86/kvm/svm/pmu.c), so
it would not make sense to program a common hardware event based
on the generic "enum perf_hw_id" once the two tables do not match.
Just provide an interface for callers outside the perf subsystem to get
the counter config based on the perfmon_event_map currently in use,
and it also helps to save bytes.
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/events/core.c | 11 +++++++++++
arch/x86/include/asm/perf_event.h | 6 ++++++
2 files changed, 17 insertions(+)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index e686c5e0537b..e760a1348c62 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2996,3 +2996,14 @@ void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
cap->events_mask_len = x86_pmu.events_mask_len;
}
EXPORT_SYMBOL_GPL(perf_get_x86_pmu_capability);
+
+u64 perf_get_hw_event_config(int hw_event)
+{
+ int max = x86_pmu.max_events;
+
+ if (hw_event < max)
+ return x86_pmu.event_map(array_index_nospec(hw_event, max));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(perf_get_hw_event_config);
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 8fc1b5003713..822927045406 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -477,6 +477,7 @@ struct x86_pmu_lbr {
};
extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
+extern u64 perf_get_hw_event_config(int hw_event);
extern void perf_check_microcode(void);
extern void perf_clear_dirty_counters(void);
extern int x86_perf_rdpmc_index(struct perf_event *event);
@@ -486,6 +487,11 @@ static inline void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
memset(cap, 0, sizeof(*cap));
}
+static inline u64 perf_get_hw_event_config(int hw_event)
+{
+ return 0;
+}
+
static inline void perf_events_lapic_init(void) { }
static inline void perf_check_microcode(void) { }
#endif
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 09/11] KVM: x86/pmu: Replace pmc_perf_hw_id() with perf_get_hw_event_config()
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (7 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 08/11] perf: x86/core: Add interface to query perfmon_event_map[] directly Like Xu
@ 2022-02-21 11:51 ` Like Xu
2022-02-21 20:57 ` kernel test robot
2022-02-21 11:52 ` [PATCH 10/11] KVM: x86/pmu: Drop amd_event_mapping[] in the KVM context Like Xu
2022-02-21 11:52 ` [PATCH 11/11] KVM: x86/pmu: Protect kvm->arch.pmu_event_filter with SRCU Like Xu
10 siblings, 1 reply; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:51 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
With the help of perf_get_hw_event_config(), KVM could query the correct
EVENTSEL_{EVENT, UMASK} pair of a kernel-generic hw event directly from
the different *_perfmon_event_map[] by the kernel's pre-defined perf_hw_id.
Also extend the bit range of the comparison field to
AMD64_RAW_EVENT_MASK_NB to prevent AMD from
defining EventSelect[11:8] into perfmon_event_map[] one day.
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index edd51ec7711d..a6bfcbd3412d 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -468,13 +468,8 @@ static void kvm_pmu_incr_counter(struct kvm_pmc *pmc)
static inline bool eventsel_match_perf_hw_id(struct kvm_pmc *pmc,
unsigned int perf_hw_id)
{
- u64 old_eventsel = pmc->eventsel;
- unsigned int config;
-
- pmc->eventsel &= (ARCH_PERFMON_EVENTSEL_EVENT | ARCH_PERFMON_EVENTSEL_UMASK);
- config = kvm_x86_ops.pmu_ops->pmc_perf_hw_id(pmc);
- pmc->eventsel = old_eventsel;
- return config == perf_hw_id;
+ return !((pmc->eventsel ^ perf_get_hw_event_config(perf_hw_id)) &&
+ AMD64_RAW_EVENT_MASK_NB);
}
static inline bool cpl_is_matched(struct kvm_pmc *pmc)
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 09/11] KVM: x86/pmu: Replace pmc_perf_hw_id() with perf_get_hw_event_config()
2022-02-21 11:51 ` [PATCH 09/11] KVM: x86/pmu: Replace pmc_perf_hw_id() with perf_get_hw_event_config() Like Xu
@ 2022-02-21 20:57 ` kernel test robot
0 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2022-02-21 20:57 UTC (permalink / raw)
To: Like Xu, Paolo Bonzini, Jim Mattson
Cc: llvm, kbuild-all, Sean Christopherson, Vitaly Kuznetsov,
Wanpeng Li, Joerg Roedel, kvm, linux-kernel, Like Xu
Hi Like,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on kvm/master]
[also build test WARNING on linus/master v5.17-rc5 next-20220217]
[cannot apply to tip/perf/core mst-vhost/linux-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Like-Xu/KVM-x86-pmu-Get-rid-of-PERF_TYPE_HARDWAR-and-other-minor-fixes/20220221-195359
base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git master
config: x86_64-randconfig-c007-20220221 (https://download.01.org/0day-ci/archive/20220222/202202220414.dzxjtMiF-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project d271fc04d5b97b12e6b797c6067d3c96a8d7470e)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/29bdfb8b85a85f36e3fca739146845d7050a372d
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Like-Xu/KVM-x86-pmu-Get-rid-of-PERF_TYPE_HARDWAR-and-other-minor-fixes/20220221-195359
git checkout 29bdfb8b85a85f36e3fca739146845d7050a372d
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash arch/x86/kvm/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> arch/x86/kvm/pmu.c:471:66: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
return !((pmc->eventsel ^ perf_get_hw_event_config(perf_hw_id)) &&
^
arch/x86/kvm/pmu.c:471:66: note: use '&' for a bitwise operation
return !((pmc->eventsel ^ perf_get_hw_event_config(perf_hw_id)) &&
^~
&
arch/x86/kvm/pmu.c:471:66: note: remove constant to silence this warning
return !((pmc->eventsel ^ perf_get_hw_event_config(perf_hw_id)) &&
~^~
1 warning generated.
vim +471 arch/x86/kvm/pmu.c
467
468 static inline bool eventsel_match_perf_hw_id(struct kvm_pmc *pmc,
469 unsigned int perf_hw_id)
470 {
> 471 return !((pmc->eventsel ^ perf_get_hw_event_config(perf_hw_id)) &&
472 AMD64_RAW_EVENT_MASK_NB);
473 }
474
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 10/11] KVM: x86/pmu: Drop amd_event_mapping[] in the KVM context
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (8 preceding siblings ...)
2022-02-21 11:51 ` [PATCH 09/11] KVM: x86/pmu: Replace pmc_perf_hw_id() with perf_get_hw_event_config() Like Xu
@ 2022-02-21 11:52 ` Like Xu
2022-02-21 11:52 ` [PATCH 11/11] KVM: x86/pmu: Protect kvm->arch.pmu_event_filter with SRCU Like Xu
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:52 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
All gp or fixed counters have been reprogrammed using PERF_TYPE_RAW,
which means that the table that maps perf_hw_id to event select values is
no longer useful, at least for AMD.
For Intel, the logic to check if the pmu event reported by Intel cpuid is
not available is still required, in which case pmc_perf_hw_id() could be
renamed to hw_event_is_unavail() and a bool value is returned to replace
the semantics of "PERF_COUNT_HW_MAX+1".
Signed-off-by: Like Xu <likexu@tencent.com>
---
arch/x86/kvm/pmu.c | 6 +++---
arch/x86/kvm/pmu.h | 2 +-
arch/x86/kvm/svm/pmu.c | 34 +++-------------------------------
arch/x86/kvm/vmx/pmu_intel.c | 11 ++++-------
4 files changed, 11 insertions(+), 42 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index a6bfcbd3412d..40a6e778b3d9 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -112,9 +112,6 @@ static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
.config = config,
};
- if (type == PERF_TYPE_HARDWARE && config >= PERF_COUNT_HW_MAX)
- return;
-
attr.sample_period = get_sample_period(pmc, pmc->counter);
if (in_tx)
@@ -188,6 +185,9 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc)
__u64 key;
int idx;
+ if (kvm_x86_ops.pmu_ops->hw_event_is_unavail(pmc))
+ return false;
+
filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
if (!filter)
goto out;
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 201b99628423..a2b4037759a2 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -24,7 +24,7 @@ struct kvm_event_hw_type_mapping {
};
struct kvm_pmu_ops {
- unsigned int (*pmc_perf_hw_id)(struct kvm_pmc *pmc);
+ bool (*hw_event_is_unavail)(struct kvm_pmc *pmc);
bool (*pmc_is_enabled)(struct kvm_pmc *pmc);
struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx);
struct kvm_pmc *(*rdpmc_ecx_to_pmc)(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index b264e8117be1..031962a5e50f 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -33,18 +33,6 @@ enum index {
INDEX_ERROR,
};
-/* duplicated from amd_perfmon_event_map, K7 and above should work. */
-static struct kvm_event_hw_type_mapping amd_event_mapping[] = {
- [0] = { 0x76, 0x00, PERF_COUNT_HW_CPU_CYCLES },
- [1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS },
- [2] = { 0x7d, 0x07, PERF_COUNT_HW_CACHE_REFERENCES },
- [3] = { 0x7e, 0x07, PERF_COUNT_HW_CACHE_MISSES },
- [4] = { 0xc2, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
- [5] = { 0xc3, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
- [6] = { 0xd0, 0x00, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
- [7] = { 0xd1, 0x00, PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
-};
-
static unsigned int get_msr_base(struct kvm_pmu *pmu, enum pmu_type type)
{
struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu);
@@ -138,25 +126,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
return &pmu->gp_counters[msr_to_index(msr)];
}
-static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc)
+static bool amd_hw_event_is_unavail(struct kvm_pmc *pmc)
{
- u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
- u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
- int i;
-
- /* return PERF_COUNT_HW_MAX as AMD doesn't have fixed events */
- if (WARN_ON(pmc_is_fixed(pmc)))
- return PERF_COUNT_HW_MAX;
-
- for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++)
- if (amd_event_mapping[i].eventsel == event_select
- && amd_event_mapping[i].unit_mask == unit_mask)
- break;
-
- if (i == ARRAY_SIZE(amd_event_mapping))
- return PERF_COUNT_HW_MAX;
-
- return amd_event_mapping[i].event_type;
+ return false;
}
/* check if a PMC is enabled by comparing it against global_ctrl bits. Because
@@ -322,7 +294,7 @@ static void amd_pmu_reset(struct kvm_vcpu *vcpu)
}
struct kvm_pmu_ops amd_pmu_ops = {
- .pmc_perf_hw_id = amd_pmc_perf_hw_id,
+ .hw_event_is_unavail = amd_hw_event_is_unavail,
.pmc_is_enabled = amd_pmc_is_enabled,
.pmc_idx_to_pmc = amd_pmc_idx_to_pmc,
.rdpmc_ecx_to_pmc = amd_rdpmc_ecx_to_pmc,
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 98a01f6a9d5d..58ea46bd92ac 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -84,7 +84,7 @@ static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data)
}
}
-static unsigned int intel_pmc_perf_hw_id(struct kvm_pmc *pmc)
+static bool intel_hw_event_is_unavail(struct kvm_pmc *pmc)
{
struct kvm_pmu *pmu = pmc_to_pmu(pmc);
u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
@@ -98,15 +98,12 @@ static unsigned int intel_pmc_perf_hw_id(struct kvm_pmc *pmc)
/* disable event that reported as not present by cpuid */
if ((i < 7) && !(pmu->available_event_types & (1 << i)))
- return PERF_COUNT_HW_MAX + 1;
+ return true;
break;
}
- if (i == ARRAY_SIZE(intel_arch_events))
- return PERF_COUNT_HW_MAX;
-
- return intel_arch_events[i].event_type;
+ return false;
}
/* check if a PMC is enabled by comparing it with globl_ctrl bits. */
@@ -720,7 +717,7 @@ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
}
struct kvm_pmu_ops intel_pmu_ops = {
- .pmc_perf_hw_id = intel_pmc_perf_hw_id,
+ .hw_event_is_unavail = intel_hw_event_is_unavail,
.pmc_is_enabled = intel_pmc_is_enabled,
.pmc_idx_to_pmc = intel_pmc_idx_to_pmc,
.rdpmc_ecx_to_pmc = intel_rdpmc_ecx_to_pmc,
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 11/11] KVM: x86/pmu: Protect kvm->arch.pmu_event_filter with SRCU
2022-02-21 11:51 [PATCH 00/11] KVM: x86/pmu: Get rid of PERF_TYPE_HARDWAR and other minor fixes Like Xu
` (9 preceding siblings ...)
2022-02-21 11:52 ` [PATCH 10/11] KVM: x86/pmu: Drop amd_event_mapping[] in the KVM context Like Xu
@ 2022-02-21 11:52 ` Like Xu
10 siblings, 0 replies; 14+ messages in thread
From: Like Xu @ 2022-02-21 11:52 UTC (permalink / raw)
To: Paolo Bonzini, Jim Mattson
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Joerg Roedel,
kvm, linux-kernel, Like Xu
From: Like Xu <likexu@tencent.com>
Similar to "kvm->arch.msr_filter", KVM should guarantee that vCPUs will
see either the previous filter or the new filter when user space calls
KVM_SET_PMU_EVENT_FILTER ioctl with the vCPU running so that guest
pmu events with identical settings in both the old and new filter have
deterministic behavior.
Fixes: 66bb8a065f5a ("KVM: x86: PMU Event Filter")
Signed-off-by: Like Xu <likexu@tencent.com>
Reviewed-by: Wanpeng Li <wanpengli@tencent.com>
---
arch/x86/kvm/pmu.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 40a6e778b3d9..84f0fcbba820 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -183,11 +183,12 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc)
struct kvm *kvm = pmc->vcpu->kvm;
bool allow_event = true;
__u64 key;
- int idx;
+ int idx, srcu_idx;
if (kvm_x86_ops.pmu_ops->hw_event_is_unavail(pmc))
return false;
+ srcu_idx = srcu_read_lock(&kvm->srcu);
filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
if (!filter)
goto out;
@@ -210,6 +211,7 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc)
}
out:
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
return allow_event;
}
--
2.35.0
^ permalink raw reply related [flat|nested] 14+ messages in thread