aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-02-18 11:07:32 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2023-02-18 11:07:32 -0800
commit5e725d112e1a54c2611d5dffd124a79415d0f0de (patch)
tree3ab2bd78733e0558c2bd6556ed25f11f7bddfc0e
parent0c2822b116e300ca6e3b7f98623deb760a93a1d2 (diff)
parent2c10b61421a28e95a46ab489fd56c0f442ff6952 (diff)
downloadlinux-5e725d112e1a54c2611d5dffd124a79415d0f0de.tar.gz
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm/x86 fixes from Paolo Bonzini: - zero all padding for KVM_GET_DEBUGREGS - fix rST warning - disable vPMU support on hybrid CPUs * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: kvm: initialize all of the kvm_debugregs structure before sending it to userspace perf/x86: Refuse to export capabilities for hybrid PMUs KVM: x86/pmu: Disable vPMU support on hybrid CPUs (host PMUs) Documentation/hw-vuln: Fix rST warning
-rw-r--r--Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst3
-rw-r--r--arch/x86/events/core.c12
-rw-r--r--arch/x86/kvm/pmu.h26
-rw-r--r--arch/x86/kvm/x86.c3
4 files changed, 28 insertions, 16 deletions
diff --git a/Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst b/Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst
index ec6e9f5bcf9e89..875616d675fe6b 100644
--- a/Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst
+++ b/Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst
@@ -88,5 +88,4 @@ capability to override those interceptions, but since this is not common, the
mitigation that covers this path is not enabled by default.
The mitigation for the KVM_CAP_X86_DISABLE_EXITS capability can be turned on
-using the boolean module parameter mitigate_smt_rsb, e.g.:
- kvm.mitigate_smt_rsb=1
+using the boolean module parameter mitigate_smt_rsb, e.g. ``kvm.mitigate_smt_rsb=1``.
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 85a63a41c47185..d096b04bf80e80 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2974,17 +2974,19 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
{
- if (!x86_pmu_initialized()) {
+ /* This API doesn't currently support enumerating hybrid PMUs. */
+ if (WARN_ON_ONCE(cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) ||
+ !x86_pmu_initialized()) {
memset(cap, 0, sizeof(*cap));
return;
}
- cap->version = x86_pmu.version;
/*
- * KVM doesn't support the hybrid PMU yet.
- * Return the common value in global x86_pmu,
- * which available for all cores.
+ * Note, hybrid CPU models get tracked as having hybrid PMUs even when
+ * all E-cores are disabled via BIOS. When E-cores are disabled, the
+ * base PMU holds the correct number of counters for P-cores.
*/
+ cap->version = x86_pmu.version;
cap->num_counters_gp = x86_pmu.num_counters;
cap->num_counters_fixed = x86_pmu.num_counters_fixed;
cap->bit_width_gp = x86_pmu.cntval_bits;
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index cdb91009701dd1..ee67ba6250949e 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -165,15 +165,27 @@ static inline void kvm_init_pmu_capability(void)
{
bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL;
- perf_get_x86_pmu_capability(&kvm_pmu_cap);
-
- /*
- * For Intel, only support guest architectural pmu
- * on a host with architectural pmu.
- */
- if ((is_intel && !kvm_pmu_cap.version) || !kvm_pmu_cap.num_counters_gp)
+ /*
+ * Hybrid PMUs don't play nice with virtualization without careful
+ * configuration by userspace, and KVM's APIs for reporting supported
+ * vPMU features do not account for hybrid PMUs. Disable vPMU support
+ * for hybrid PMUs until KVM gains a way to let userspace opt-in.
+ */
+ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
enable_pmu = false;
+ if (enable_pmu) {
+ perf_get_x86_pmu_capability(&kvm_pmu_cap);
+
+ /*
+ * For Intel, only support guest architectural pmu
+ * on a host with architectural pmu.
+ */
+ if ((is_intel && !kvm_pmu_cap.version) ||
+ !kvm_pmu_cap.num_counters_gp)
+ enable_pmu = false;
+ }
+
if (!enable_pmu) {
memset(&kvm_pmu_cap, 0, sizeof(kvm_pmu_cap));
return;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f0fa3de2ceb882..a2c299d47e69cc 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5263,12 +5263,11 @@ static void kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu,
{
unsigned long val;
+ memset(dbgregs, 0, sizeof(*dbgregs));
memcpy(dbgregs->db, vcpu->arch.db, sizeof(vcpu->arch.db));
kvm_get_dr(vcpu, 6, &val);
dbgregs->dr6 = val;
dbgregs->dr7 = vcpu->arch.dr7;
- dbgregs->flags = 0;
- memset(&dbgregs->reserved, 0, sizeof(dbgregs->reserved));
}
static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,