* [PATCH 1/7] KVM: x86: Give host userspace full control of MSR_IA32_MISC_ENABLES
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-11 0:57 ` [PATCH 2/7] KVM: VMX: Give host userspace full control of MSR_IA32_PERF_CAPABILITIES Sean Christopherson
` (6 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Give userspace full control of the read-only bits in MISC_ENABLES, i.e.
do not modify bits on PMU refresh and do not preserve existing bits when
userspace writes MISC_ENABLES. With a few exceptions where KVM doesn't
expose the necessary controls to userspace _and_ there is a clear cut
association with CPUID, e.g. reserved CR4 bits, KVM does not own the vCPU
and should not manipulate the vCPU model on behalf of "dummy user space".
The argument that KVM is doing userspace a favor because "the order of
setting vPMU capabilities and MSR_IA32_MISC_ENABLE is not strictly
guaranteed" is specious, as attempting to configure MSRs on behalf of
userspace inevitably leads to edge cases precisely because KVM does not
prescribe a specific order of initialization.
Example #1: intel_pmu_refresh() consumes and modifies the vCPU's
MSR_IA32_PERF_CAPABILITIES, and so assumes userspace initializes config
MSRs before setting the guest CPUID model. If userspace sets CPUID
first, then KVM will mark PEBS as available when arch.perf_capabilities
is initialized with a non-zero PEBS format, thus creating a bad vCPU
model if userspace later disables PEBS by writing PERF_CAPABILITIES.
Example #2: intel_pmu_refresh() does not clear PERF_CAP_PEBS_MASK in
MSR_IA32_PERF_CAPABILITIES if there is no vPMU, making KVM inconsistent
in its desire to be consistent.
Example #3: intel_pmu_refresh() does not clear MSR_IA32_MISC_ENABLE_EMON
if KVM_SET_CPUID2 is called multiple times, first with a vPMU, then
without a vPMU. While slightly contrived, it's plausible a VMM could
reflect KVM's default vCPU and then operate on KVM's copy of CPUID to
later clear the vPMU settings, e.g. see KVM's selftests.
Example #4: Enumerating an Intel vCPU on an AMD host will not call into
intel_pmu_refresh() at any point, and so the BTS and PEBS "unavailable"
bits will be left clear, without any way for userspace to set them.
Keep the "R" behavior of the bit 7, "EMON available", for the guest.
Unlike the BTS and PEBS bits, which are fully "RO", the EMON bit can be
written with a different value, but that new value is ignored.
Cc: Like Xu <likexu@tencent.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/pmu_intel.c | 5 -----
arch/x86/kvm/x86.c | 24 +++++++++++-------------
2 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 422f0a6562ac..3b324ce0b142 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -536,8 +536,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
pmu->pebs_enable_mask = ~0ull;
pmu->pebs_data_cfg_mask = ~0ull;
- vcpu->arch.ia32_misc_enable_msr |= MSR_IA32_MISC_ENABLE_PMU_RO_MASK;
-
entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
if (!entry || !vcpu->kvm->arch.enable_pmu)
return;
@@ -548,8 +546,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
if (!pmu->version)
return;
- vcpu->arch.ia32_misc_enable_msr |= MSR_IA32_MISC_ENABLE_EMON;
-
pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
kvm_pmu_cap.num_counters_gp);
eax.split.bit_width = min_t(int, eax.split.bit_width,
@@ -611,7 +607,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1);
if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_FORMAT) {
- vcpu->arch.ia32_misc_enable_msr &= ~MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL;
if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_BASELINE) {
pmu->pebs_enable_mask = counter_mask;
pmu->reserved_bits &= ~ICL_EVENTSEL_ADAPTIVE;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2318a99139fa..5d1beb7d310e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3550,21 +3550,17 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_IA32_MISC_ENABLE: {
u64 old_val = vcpu->arch.ia32_misc_enable_msr;
- u64 pmu_mask = MSR_IA32_MISC_ENABLE_PMU_RO_MASK |
- MSR_IA32_MISC_ENABLE_EMON;
- /* RO bits */
- if (!msr_info->host_initiated &&
- ((old_val ^ data) & MSR_IA32_MISC_ENABLE_PMU_RO_MASK))
- return 1;
+ if (!msr_info->host_initiated) {
+ /* RO bits */
+ if ((old_val ^ data) & MSR_IA32_MISC_ENABLE_PMU_RO_MASK)
+ return 1;
+
+ /* R bits, i.e. writes are ignored, but don't fault. */
+ data = data & ~MSR_IA32_MISC_ENABLE_EMON;
+ data |= old_val & MSR_IA32_MISC_ENABLE_EMON;
+ }
- /*
- * For a dummy user space, the order of setting vPMU capabilities and
- * initialising MSR_IA32_MISC_ENABLE is not strictly guaranteed, so to
- * avoid inconsistent functionality we keep the vPMU bits unchanged here.
- */
- data &= ~pmu_mask;
- data |= old_val & pmu_mask;
if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT) &&
((old_val ^ data) & MSR_IA32_MISC_ENABLE_MWAIT)) {
if (!guest_cpuid_has(vcpu, X86_FEATURE_XMM3))
@@ -11552,6 +11548,8 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vcpu->arch.smbase = 0x30000;
vcpu->arch.msr_misc_features_enables = 0;
+ vcpu->arch.ia32_misc_enable_msr = MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL |
+ MSR_IA32_MISC_ENABLE_BTS_UNAVAIL;
__kvm_set_xcr(vcpu, 0, XFEATURE_MASK_FP);
__kvm_set_msr(vcpu, MSR_IA32_XSS, 0, true);
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 2/7] KVM: VMX: Give host userspace full control of MSR_IA32_PERF_CAPABILITIES
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
2022-06-11 0:57 ` [PATCH 1/7] KVM: x86: Give host userspace full control of MSR_IA32_MISC_ENABLES Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-11 0:57 ` [PATCH 3/7] Revert "KVM: x86/pmu: Accept 0 for absent PMU MSRs when host-initiated if !enable_pmu" Sean Christopherson
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Do not clear manipulate MSR_IA32_PERF_CAPABILITIES in intel_pmu_refresh(),
i.e. give userspace full control over capability/read-only MSRs. KVM is
not a babysitter, it is userspace's responsiblity to provide a valid and
coherent vCPU model.
Attempting to "help" the guest by forcing a consistent model creates edge
cases, and ironicially leads to inconsistent behavior.
Example #1: KVM doesn't do intel_pmu_refresh() when userspace writes
the MSR.
Example #2: KVM doesn't clear the bits when the PMU is disabled, or when
there's no architectural PMU.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/pmu_intel.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 3b324ce0b142..b62012766226 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -619,8 +619,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
pmu->pebs_enable_mask =
~((1ull << pmu->nr_arch_gp_counters) - 1);
}
- } else {
- vcpu->arch.perf_capabilities &= ~PERF_CAP_PEBS_MASK;
}
}
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 3/7] Revert "KVM: x86/pmu: Accept 0 for absent PMU MSRs when host-initiated if !enable_pmu"
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
2022-06-11 0:57 ` [PATCH 1/7] KVM: x86: Give host userspace full control of MSR_IA32_MISC_ENABLES Sean Christopherson
2022-06-11 0:57 ` [PATCH 2/7] KVM: VMX: Give host userspace full control of MSR_IA32_PERF_CAPABILITIES Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-11 0:57 ` [PATCH 4/7] Revert "KVM: x86: always allow host-initiated writes to PMU MSRs" Sean Christopherson
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Eating reads and writes to all "PMU" MSRs when there is no PMU is wildly
broken as it results in allowing accesses to _any_ MSR on Intel CPUs
as intel_is_valid_msr() returns true for all host_initiated accesses.
A revert of commit d1c88a402056 ("KVM: x86: always allow host-initiated
writes to PMU MSRs") will soon follow.
This reverts commit 8e6a58e28b34e8d247e772159b8fa8f6bae39192.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/pmu.c | 8 --------
arch/x86/kvm/svm/pmu.c | 11 +----------
2 files changed, 1 insertion(+), 18 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 6a32092460d3..87483e503c46 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -442,19 +442,11 @@ static void kvm_pmu_mark_pmc_in_use(struct kvm_vcpu *vcpu, u32 msr)
int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
- if (msr_info->host_initiated && !vcpu->kvm->arch.enable_pmu) {
- msr_info->data = 0;
- return 0;
- }
-
return static_call(kvm_x86_pmu_get_msr)(vcpu, msr_info);
}
int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
- if (msr_info->host_initiated && !vcpu->kvm->arch.enable_pmu)
- return !!msr_info->data;
-
kvm_pmu_mark_pmc_in_use(vcpu, msr_info->index);
return static_call(kvm_x86_pmu_set_msr)(vcpu, msr_info);
}
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index fe520b2649b5..256244b8f89c 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -182,16 +182,7 @@ static struct kvm_pmc *amd_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
static bool amd_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr, bool host_initiated)
{
/* All MSRs refer to exactly one PMC, so msr_idx_to_pmc is enough. */
- if (!host_initiated)
- return false;
-
- switch (msr) {
- case MSR_K7_EVNTSEL0 ... MSR_K7_PERFCTR3:
- case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
- return true;
- default:
- return false;
- }
+ return false;
}
static struct kvm_pmc *amd_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr)
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 4/7] Revert "KVM: x86: always allow host-initiated writes to PMU MSRs"
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
` (2 preceding siblings ...)
2022-06-11 0:57 ` [PATCH 3/7] Revert "KVM: x86/pmu: Accept 0 for absent PMU MSRs when host-initiated if !enable_pmu" Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-11 0:57 ` [PATCH 5/7] KVM: VMX: Use vcpu_get_perf_capabilities() to get guest-visible value Sean Christopherson
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Revert the hack to allow host-initiated accesses to all "PMU" MSRs,
as intel_is_valid_msr() returns true for _all_ MSRs, regardless of whether
or not it has a snowball's chance in hell of actually being a PMU MSR.
That mostly gets papered over by the actual get/set helpers only handling
MSRs that they knows about, except there's the minor detail that
kvm_pmu_{g,s}et_msr() eat reads and writes when the PMU is disabled.
I.e. KVM will happy allow reads and writes to _any_ MSR if the PMU is
disabled, either via module param or capability.
This reverts commit d1c88a4020567ba4da52f778bcd9619d87e4ea75.
Fixes: d1c88a402056 ("KVM: x86: always allow host-initiated writes to PMU MSRs")
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/pmu.c | 4 ++--
arch/x86/kvm/pmu.h | 4 ++--
arch/x86/kvm/svm/pmu.c | 2 +-
arch/x86/kvm/vmx/pmu_intel.c | 27 ++++++++++-----------------
arch/x86/kvm/x86.c | 10 +++++-----
5 files changed, 20 insertions(+), 27 deletions(-)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 87483e503c46..02f9e4f245bd 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -425,10 +425,10 @@ void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
}
}
-bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr, bool host_initiated)
+bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
{
return static_call(kvm_x86_pmu_msr_idx_to_pmc)(vcpu, msr) ||
- static_call(kvm_x86_pmu_is_valid_msr)(vcpu, msr, host_initiated);
+ static_call(kvm_x86_pmu_is_valid_msr)(vcpu, msr);
}
static void kvm_pmu_mark_pmc_in_use(struct kvm_vcpu *vcpu, u32 msr)
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index c1b61671ba1e..5cc5721f260b 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -32,7 +32,7 @@ struct kvm_pmu_ops {
unsigned int idx, u64 *mask);
struct kvm_pmc *(*msr_idx_to_pmc)(struct kvm_vcpu *vcpu, u32 msr);
bool (*is_valid_rdpmc_ecx)(struct kvm_vcpu *vcpu, unsigned int idx);
- bool (*is_valid_msr)(struct kvm_vcpu *vcpu, u32 msr, bool host_initiated);
+ bool (*is_valid_msr)(struct kvm_vcpu *vcpu, u32 msr);
int (*get_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
void (*refresh)(struct kvm_vcpu *vcpu);
@@ -189,7 +189,7 @@ void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu);
void kvm_pmu_handle_event(struct kvm_vcpu *vcpu);
int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data);
bool kvm_pmu_is_valid_rdpmc_ecx(struct kvm_vcpu *vcpu, unsigned int idx);
-bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr, bool host_initiated);
+bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr);
int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
void kvm_pmu_refresh(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index 256244b8f89c..f24613a108c5 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -179,7 +179,7 @@ static struct kvm_pmc *amd_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
return &counters[idx];
}
-static bool amd_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr, bool host_initiated)
+static bool amd_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
{
/* All MSRs refer to exactly one PMC, so msr_idx_to_pmc is enough. */
return false;
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index b62012766226..b1aae60cf061 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -196,45 +196,38 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index)
return ret;
}
-static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr, bool host_initiated)
+static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
u64 perf_capabilities = vcpu->arch.perf_capabilities;
+ int ret;
switch (msr) {
case MSR_CORE_PERF_FIXED_CTR_CTRL:
case MSR_CORE_PERF_GLOBAL_STATUS:
case MSR_CORE_PERF_GLOBAL_CTRL:
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- if (host_initiated)
- return true;
- return pmu->version > 1;
+ ret = pmu->version > 1;
break;
case MSR_IA32_PEBS_ENABLE:
- if (host_initiated)
- return true;
- return perf_capabilities & PERF_CAP_PEBS_FORMAT;
+ ret = perf_capabilities & PERF_CAP_PEBS_FORMAT;
break;
case MSR_IA32_DS_AREA:
- if (host_initiated)
- return true;
- return guest_cpuid_has(vcpu, X86_FEATURE_DS);
+ ret = guest_cpuid_has(vcpu, X86_FEATURE_DS);
break;
case MSR_PEBS_DATA_CFG:
- if (host_initiated)
- return true;
- return (perf_capabilities & PERF_CAP_PEBS_BASELINE) &&
+ ret = (perf_capabilities & PERF_CAP_PEBS_BASELINE) &&
((perf_capabilities & PERF_CAP_PEBS_FORMAT) > 3);
break;
default:
- if (host_initiated)
- return true;
- return get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
+ ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
get_fixed_pmc(pmu, msr) || get_fw_gp_pmc(pmu, msr) ||
intel_pmu_is_valid_lbr_msr(vcpu, msr);
break;
}
+
+ return ret;
}
static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr)
@@ -596,7 +589,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
INTEL_PMC_MAX_GENERIC, pmu->nr_arch_fixed_counters);
nested_vmx_pmu_refresh(vcpu,
- intel_is_valid_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, false));
+ intel_is_valid_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL));
if (cpuid_model_is_consistent(vcpu))
x86_perf_get_lbr(&lbr_desc->records);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5d1beb7d310e..25f471adb8b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3704,7 +3704,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
fallthrough;
case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL1:
- if (kvm_pmu_is_valid_msr(vcpu, msr, msr_info->host_initiated))
+ if (kvm_pmu_is_valid_msr(vcpu, msr))
return kvm_pmu_set_msr(vcpu, msr_info);
if (pr || data != 0)
@@ -3787,7 +3787,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
#endif
default:
- if (kvm_pmu_is_valid_msr(vcpu, msr, msr_info->host_initiated))
+ if (kvm_pmu_is_valid_msr(vcpu, msr))
return kvm_pmu_set_msr(vcpu, msr_info);
return KVM_MSR_RET_INVALID;
}
@@ -3867,7 +3867,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = 0;
break;
case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
- if (kvm_pmu_is_valid_msr(vcpu, msr_info->index, msr_info->host_initiated))
+ if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info);
if (!msr_info->host_initiated)
return 1;
@@ -3877,7 +3877,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3:
case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR1:
case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL1:
- if (kvm_pmu_is_valid_msr(vcpu, msr_info->index, msr_info->host_initiated))
+ if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info);
msr_info->data = 0;
break;
@@ -4123,7 +4123,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
#endif
default:
- if (kvm_pmu_is_valid_msr(vcpu, msr_info->index, msr_info->host_initiated))
+ if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info);
return KVM_MSR_RET_INVALID;
}
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 5/7] KVM: VMX: Use vcpu_get_perf_capabilities() to get guest-visible value
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
` (3 preceding siblings ...)
2022-06-11 0:57 ` [PATCH 4/7] Revert "KVM: x86: always allow host-initiated writes to PMU MSRs" Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-11 0:57 ` [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs Sean Christopherson
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Use vcpu_get_perf_capabilities() when querying MSR_IA32_PERF_CAPABILITIES
from the guest's perspective, e.g. to update the vPMU and to determine
which MSRs exist. If userspace ignores MSR_IA32_PERF_CAPABILITIES but
clear X86_FEATURE_PDCM, the guest should see '0'.
Fixes: 902caeb6841a ("KVM: x86/pmu: Add PEBS_DATA_CFG MSR emulation to support adaptive PEBS")
Fixes: c59a1f106f5c ("KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS")
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/pmu_intel.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index b1aae60cf061..53ccba896e77 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -199,7 +199,7 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index)
static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- u64 perf_capabilities = vcpu->arch.perf_capabilities;
+ u64 perf_capabilities;
int ret;
switch (msr) {
@@ -210,12 +210,13 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
ret = pmu->version > 1;
break;
case MSR_IA32_PEBS_ENABLE:
- ret = perf_capabilities & PERF_CAP_PEBS_FORMAT;
+ ret = vcpu_get_perf_capabilities(vcpu) & PERF_CAP_PEBS_FORMAT;
break;
case MSR_IA32_DS_AREA:
ret = guest_cpuid_has(vcpu, X86_FEATURE_DS);
break;
case MSR_PEBS_DATA_CFG:
+ perf_capabilities = vcpu_get_perf_capabilities(vcpu);
ret = (perf_capabilities & PERF_CAP_PEBS_BASELINE) &&
((perf_capabilities & PERF_CAP_PEBS_FORMAT) > 3);
break;
@@ -515,6 +516,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
struct kvm_cpuid_entry2 *entry;
union cpuid10_eax eax;
union cpuid10_edx edx;
+ u64 perf_capabilities;
u64 counter_mask;
int i;
@@ -599,8 +601,9 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
if (lbr_desc->records.nr)
bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1);
- if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_FORMAT) {
- if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_BASELINE) {
+ perf_capabilities = vcpu_get_perf_capabilities(vcpu);
+ if (perf_capabilities & PERF_CAP_PEBS_FORMAT) {
+ if (perf_capabilities & PERF_CAP_PEBS_BASELINE) {
pmu->pebs_enable_mask = counter_mask;
pmu->reserved_bits &= ~ICL_EVENTSEL_ADAPTIVE;
for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
` (4 preceding siblings ...)
2022-06-11 0:57 ` [PATCH 5/7] KVM: VMX: Use vcpu_get_perf_capabilities() to get guest-visible value Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-13 14:09 ` Sean Christopherson
2022-06-14 7:45 ` Vitaly Kuznetsov
2022-06-11 0:57 ` [PATCH 7/7] KVM: x86: Ignore benign host writes to "unsupported" F15H_PERF_CTL MSRs Sean Christopherson
2022-06-20 14:31 ` [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Paolo Bonzini
7 siblings, 2 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Ignore host userspace reads and writes of '0' to PEBS and BTS MSRs that
KVM reports in the MSR-to-save list, but the MSRs are ultimately
unsupported. All MSRs in said list must be writable by userspace, e.g.
if userspace sends the list back at KVM without filtering out the MSRs it
doesn't need.
8183a538cd95 ("KVM: x86/pmu: Add IA32_DS_AREA MSR emulation to support guest DS")
902caeb6841a ("KVM: x86/pmu: Add PEBS_DATA_CFG MSR emulation to support adaptive PEBS")
c59a1f106f5c ("KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS")
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/x86.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 25f471adb8b8..655fb0b3bba4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3786,6 +3786,16 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
vcpu->arch.guest_fpu.xfd_err = data;
break;
#endif
+ case MSR_IA32_PEBS_ENABLE:
+ case MSR_IA32_DS_AREA:
+ case MSR_PEBS_DATA_CFG:
+ if (kvm_pmu_is_valid_msr(vcpu, msr))
+ return kvm_pmu_set_msr(vcpu, msr_info);
+ /*
+ * Userspace is allowed to write '0' to MSRs that KVM reports
+ * as to-be-saved, even if an MSRs isn't fully supported.
+ */
+ return !msr_info->host_initiated || data;
default:
if (kvm_pmu_is_valid_msr(vcpu, msr))
return kvm_pmu_set_msr(vcpu, msr_info);
@@ -4122,6 +4132,16 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = vcpu->arch.guest_fpu.xfd_err;
break;
#endif
+ case MSR_IA32_PEBS_ENABLE:
+ case MSR_IA32_DS_AREA:
+ case MSR_PEBS_DATA_CFG:
+ if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
+ return kvm_pmu_get_msr(vcpu, msr_info);
+ /*
+ * Userspace is allowed to read MSRs that KVM reports as
+ * to-be-saved, even if an MSR isn't fully supported.
+ */
+ return !msr_info->host_initiated;
default:
if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info);
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs
2022-06-11 0:57 ` [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs Sean Christopherson
@ 2022-06-13 14:09 ` Sean Christopherson
2022-06-20 14:29 ` Paolo Bonzini
2022-06-14 7:45 ` Vitaly Kuznetsov
1 sibling, 1 reply; 12+ messages in thread
From: Sean Christopherson @ 2022-06-13 14:09 UTC (permalink / raw)
To: Paolo Bonzini, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
On Sat, Jun 11, 2022, Sean Christopherson wrote:
> @@ -4122,6 +4132,16 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
> msr_info->data = vcpu->arch.guest_fpu.xfd_err;
> break;
> #endif
> + case MSR_IA32_PEBS_ENABLE:
> + case MSR_IA32_DS_AREA:
> + case MSR_PEBS_DATA_CFG:
> + if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
> + return kvm_pmu_get_msr(vcpu, msr_info);
> + /*
> + * Userspace is allowed to read MSRs that KVM reports as
> + * to-be-saved, even if an MSR isn't fully supported.
> + */
> + return !msr_info->host_initiated;
Gah, this needs to set msr_info->data.
/*
* Userspace is allowed to read MSRs that KVM reports as
* to-be-saved, even if an MSR isn't fully supported.
*/
if (!msr_info->host_initiated)
return 1;
msr_info->data = 0;
> default:
> if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
> return kvm_pmu_get_msr(vcpu, msr_info);
> --
> 2.36.1.476.g0c4daa206d-goog
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs
2022-06-13 14:09 ` Sean Christopherson
@ 2022-06-20 14:29 ` Paolo Bonzini
0 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2022-06-20 14:29 UTC (permalink / raw)
To: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
On 6/13/22 16:09, Sean Christopherson wrote:
> On Sat, Jun 11, 2022, Sean Christopherson wrote:
>> @@ -4122,6 +4132,16 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>> msr_info->data = vcpu->arch.guest_fpu.xfd_err;
>> break;
>> #endif
>> + case MSR_IA32_PEBS_ENABLE:
>> + case MSR_IA32_DS_AREA:
>> + case MSR_PEBS_DATA_CFG:
>> + if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
>> + return kvm_pmu_get_msr(vcpu, msr_info);
>> + /*
>> + * Userspace is allowed to read MSRs that KVM reports as
>> + * to-be-saved, even if an MSR isn't fully supported.
>> + */
>> + return !msr_info->host_initiated;
>
> Gah, this needs to set msr_info->data.
Might also reuse the F15H case:
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 70364d40e3f7..be39968149e6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3877,9 +3877,16 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu,
struct msr_data *msr_info)
case MSR_DRAM_ENERGY_STATUS: /* DRAM controller */
msr_info->data = 0;
break;
+ case MSR_IA32_PEBS_ENABLE:
+ case MSR_IA32_DS_AREA:
+ case MSR_PEBS_DATA_CFG:
case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info);
+ /*
+ * Userspace is allowed to read MSRs that KVM reports as
+ * to-be-saved, even if an MSR isn't fully supported.
+ */
if (!msr_info->host_initiated)
return 1;
msr_info->data = 0;
Paolo
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs
2022-06-11 0:57 ` [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs Sean Christopherson
2022-06-13 14:09 ` Sean Christopherson
@ 2022-06-14 7:45 ` Vitaly Kuznetsov
1 sibling, 0 replies; 12+ messages in thread
From: Vitaly Kuznetsov @ 2022-06-14 7:45 UTC (permalink / raw)
To: Sean Christopherson
Cc: Wanpeng Li, Jim Mattson, Joerg Roedel, kvm, linux-kernel, Like Xu,
Paolo Bonzini
Sean Christopherson <seanjc@google.com> writes:
> Ignore host userspace reads and writes of '0' to PEBS and BTS MSRs that
> KVM reports in the MSR-to-save list, but the MSRs are ultimately
> unsupported. All MSRs in said list must be writable by userspace, e.g.
> if userspace sends the list back at KVM without filtering out the MSRs it
> doesn't need.
>
> 8183a538cd95 ("KVM: x86/pmu: Add IA32_DS_AREA MSR emulation to support guest DS")
> 902caeb6841a ("KVM: x86/pmu: Add PEBS_DATA_CFG MSR emulation to support adaptive PEBS")
> c59a1f106f5c ("KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS")
These are 'Fixes:' tags I suppose?
...
--
Vitaly
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 7/7] KVM: x86: Ignore benign host writes to "unsupported" F15H_PERF_CTL MSRs
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
` (5 preceding siblings ...)
2022-06-11 0:57 ` [PATCH 6/7] KVM: x86: Ignore benign host accesses to "unsupported" PEBS and BTS MSRs Sean Christopherson
@ 2022-06-11 0:57 ` Sean Christopherson
2022-06-20 14:31 ` [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Paolo Bonzini
7 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2022-06-11 0:57 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
Joerg Roedel, kvm, linux-kernel, Like Xu
Ignore host userspace writes of '0' to F15H_PERF_CTL MSRs KVM reports
in the MSR-to-save list, but the MSRs are ultimately unsupported. All
MSRs in said list must be writable by userspace, e.g. if userspace sends
the list back at KVM without filtering out the MSRs it doesn't need.
Note, reads of said MSRs already have the desired behavior.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/x86.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 655fb0b3bba4..2fc556ac8a70 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3789,6 +3789,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_IA32_PEBS_ENABLE:
case MSR_IA32_DS_AREA:
case MSR_PEBS_DATA_CFG:
+ case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
if (kvm_pmu_is_valid_msr(vcpu, msr))
return kvm_pmu_set_msr(vcpu, msr_info);
/*
--
2.36.1.476.g0c4daa206d-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission
2022-06-11 0:57 [PATCH 0/7] KVM: x86: Attempt to wrangle PEBS/PMU into submission Sean Christopherson
` (6 preceding siblings ...)
2022-06-11 0:57 ` [PATCH 7/7] KVM: x86: Ignore benign host writes to "unsupported" F15H_PERF_CTL MSRs Sean Christopherson
@ 2022-06-20 14:31 ` Paolo Bonzini
7 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2022-06-20 14:31 UTC (permalink / raw)
To: Sean Christopherson
Cc: Vitaly Kuznetsov, Wanpeng Li, Jim Mattson, Joerg Roedel, kvm,
linux-kernel, Like Xu
Queued, thanks.
Paolo
^ permalink raw reply [flat|nested] 12+ messages in thread