From: Joerg Roedel <[email protected]>

Now that CPUID state is shared across all planes, cpu_caps can be
shared as well.

Signed-off-by: Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/kvm_host.h | 33 +++++++++++++++++----------------
 arch/x86/kvm/cpuid.c            | 18 +++++++++---------
 arch/x86/kvm/cpuid.h            | 17 +++++++++--------
 arch/x86/kvm/svm/svm.c          |  4 ++--
 arch/x86/kvm/vmx/vmx.c          |  2 +-
 5 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 3a64bdae6e23..b0d040528f9d 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -800,6 +800,23 @@ struct kvm_vcpu_arch_common {
        struct kvm_cpuid_entry2 *cpuid_entries;
        bool cpuid_dynamic_bits_dirty;
        bool is_amd_compatible;
+
+       /*
+        * cpu_caps holds the effective guest capabilities, i.e. the features
+        * the vCPU is allowed to use.  Typically, but not always, features can
+        * be used by the guest if and only if both KVM and userspace want to
+        * expose the feature to the guest.
+        *
+        * A common exception is for virtualization holes, i.e. when KVM can't
+        * prevent the guest from using a feature, in which case the vCPU "has"
+        * the feature regardless of what KVM or userspace desires.
+        *
+        * Note, features that don't require KVM involvement in any way are
+        * NOT enforced/sanitized by KVM, i.e. are taken verbatim from the
+        * guest CPUID provided by userspace.
+        */
+       u32 cpu_caps[NR_KVM_CPU_CAPS];
+
 };
 
 int kvm_arch_vcpu_common_init(struct kvm_vcpu_common *common);
@@ -925,22 +942,6 @@ struct kvm_vcpu_arch {
 
        int halt_request; /* real mode on Intel only */
 
-       /*
-        * cpu_caps holds the effective guest capabilities, i.e. the features
-        * the vCPU is allowed to use.  Typically, but not always, features can
-        * be used by the guest if and only if both KVM and userspace want to
-        * expose the feature to the guest.
-        *
-        * A common exception is for virtualization holes, i.e. when KVM can't
-        * prevent the guest from using a feature, in which case the vCPU "has"
-        * the feature regardless of what KVM or userspace desires.
-        *
-        * Note, features that don't require KVM involvement in any way are
-        * NOT enforced/sanitized by KVM, i.e. are taken verbatim from the
-        * guest CPUID provided by userspace.
-        */
-       u32 cpu_caps[NR_KVM_CPU_CAPS];
-
        u64 reserved_gpa_bits;
        int maxphyaddr;
 
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 6d948d63306c..27e2f7e25038 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -284,7 +284,7 @@ static __always_inline void 
kvm_update_feature_runtime(struct kvm_vcpu *vcpu,
                                                       bool has_feature)
 {
        cpuid_entry_change(entry, x86_feature, has_feature);
-       guest_cpu_cap_change(vcpu, x86_feature, has_feature);
+       guest_cpu_cap_change(vcpu->common, x86_feature, has_feature);
 }
 
 static void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
@@ -382,7 +382,7 @@ void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        bool allow_gbpages;
        int i;
 
-       memset(vcpu->arch.cpu_caps, 0, sizeof(vcpu->arch.cpu_caps));
+       memset(common->arch.cpu_caps, 0, sizeof(common->arch.cpu_caps));
        BUILD_BUG_ON(ARRAY_SIZE(reverse_cpuid) != NR_KVM_CPU_CAPS);
 
        /*
@@ -408,9 +408,9 @@ void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
                 * in guest CPUID.  Note, this includes features that are
                 * supported by KVM but aren't advertised to userspace!
                 */
-               vcpu->arch.cpu_caps[i] = kvm_cpu_caps[i] |
-                                        cpuid_get_reg_unsafe(&emulated, 
cpuid.reg);
-               vcpu->arch.cpu_caps[i] &= cpuid_get_reg_unsafe(entry, 
cpuid.reg);
+               common->arch.cpu_caps[i] = kvm_cpu_caps[i] |
+                                          cpuid_get_reg_unsafe(&emulated, 
cpuid.reg);
+               common->arch.cpu_caps[i] &= cpuid_get_reg_unsafe(entry, 
cpuid.reg);
        }
 
        kvm_update_cpuid_runtime(vcpu);
@@ -428,7 +428,7 @@ void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
         */
        allow_gbpages = tdp_enabled ? boot_cpu_has(X86_FEATURE_GBPAGES) :
                                      guest_cpu_cap_has(vcpu, 
X86_FEATURE_GBPAGES);
-       guest_cpu_cap_change(vcpu, X86_FEATURE_GBPAGES, allow_gbpages);
+       guest_cpu_cap_change(common, X86_FEATURE_GBPAGES, allow_gbpages);
 
        best = kvm_find_cpuid_entry(vcpu, 1);
        if (best && apic) {
@@ -536,8 +536,8 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct 
kvm_cpuid_entry2 *e2,
        swap(common->arch.cpuid_entries, e2);
        swap(common->arch.cpuid_nent, nent);
 
-       memcpy(vcpu_caps, vcpu->arch.cpu_caps, sizeof(vcpu_caps));
-       BUILD_BUG_ON(sizeof(vcpu_caps) != sizeof(vcpu->arch.cpu_caps));
+       memcpy(vcpu_caps, common->arch.cpu_caps, sizeof(vcpu_caps));
+       BUILD_BUG_ON(sizeof(vcpu_caps) != sizeof(common->arch.cpu_caps));
 
        /*
         * KVM does not correctly handle changing guest CPUID after KVM_RUN or
@@ -582,7 +582,7 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct 
kvm_cpuid_entry2 *e2,
        return 0;
 
 err:
-       memcpy(vcpu->arch.cpu_caps, vcpu_caps, sizeof(vcpu_caps));
+       memcpy(common->arch.cpu_caps, vcpu_caps, sizeof(vcpu_caps));
        swap(common->arch.cpuid_entries, e2);
        swap(common->arch.cpuid_nent, nent);
        return r;
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 143ea8531611..75abf447eabf 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -239,36 +239,37 @@ static __always_inline bool guest_pv_has(struct kvm_vcpu 
*vcpu,
        return vcpu->arch.pv_cpuid.features & (1u << kvm_feature);
 }
 
-static __always_inline void guest_cpu_cap_set(struct kvm_vcpu *vcpu,
+static __always_inline void guest_cpu_cap_set(struct kvm_vcpu_common *common,
                                              unsigned int x86_feature)
 {
        unsigned int x86_leaf = __feature_leaf(x86_feature);
 
-       vcpu->arch.cpu_caps[x86_leaf] |= __feature_bit(x86_feature);
+       common->arch.cpu_caps[x86_leaf] |= __feature_bit(x86_feature);
 }
 
-static __always_inline void guest_cpu_cap_clear(struct kvm_vcpu *vcpu,
+static __always_inline void guest_cpu_cap_clear(struct kvm_vcpu_common *common,
                                                unsigned int x86_feature)
 {
        unsigned int x86_leaf = __feature_leaf(x86_feature);
 
-       vcpu->arch.cpu_caps[x86_leaf] &= ~__feature_bit(x86_feature);
+       common->arch.cpu_caps[x86_leaf] &= ~__feature_bit(x86_feature);
 }
 
-static __always_inline void guest_cpu_cap_change(struct kvm_vcpu *vcpu,
+static __always_inline void guest_cpu_cap_change(struct kvm_vcpu_common 
*common,
                                                 unsigned int x86_feature,
                                                 bool guest_has_cap)
 {
        if (guest_has_cap)
-               guest_cpu_cap_set(vcpu, x86_feature);
+               guest_cpu_cap_set(common, x86_feature);
        else
-               guest_cpu_cap_clear(vcpu, x86_feature);
+               guest_cpu_cap_clear(common, x86_feature);
 }
 
 static __always_inline bool guest_cpu_cap_has(struct kvm_vcpu *vcpu,
                                              unsigned int x86_feature)
 {
        unsigned int x86_leaf = __feature_leaf(x86_feature);
+       struct kvm_vcpu_common *common = vcpu->common;
 
        /*
         * Except for MWAIT, querying dynamic feature bits is disallowed, so
@@ -278,7 +279,7 @@ static __always_inline bool guest_cpu_cap_has(struct 
kvm_vcpu *vcpu,
                     x86_feature == X86_FEATURE_OSXSAVE ||
                     x86_feature == X86_FEATURE_OSPKE);
 
-       return vcpu->arch.cpu_caps[x86_leaf] & __feature_bit(x86_feature);
+       return common->arch.cpu_caps[x86_leaf] & __feature_bit(x86_feature);
 }
 
 static inline bool kvm_vcpu_is_legal_cr3(struct kvm_vcpu *vcpu, unsigned long 
cr3)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 612db7ad8b2a..0b57dde29e40 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -4706,7 +4706,7 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu 
*vcpu)
         * XSS on VM-Enter/VM-Exit.  Failure to do so would effectively give
         * the guest read/write access to the host's XSS.
         */
-       guest_cpu_cap_change(vcpu, X86_FEATURE_XSAVES,
+       guest_cpu_cap_change(vcpu->common, X86_FEATURE_XSAVES,
                             boot_cpu_has(X86_FEATURE_XSAVES) &&
                             guest_cpu_cap_has(vcpu, X86_FEATURE_XSAVE));
 
@@ -4716,7 +4716,7 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu 
*vcpu)
         * SVM on Intel is bonkers and extremely unlikely to work).
         */
        if (guest_cpuid_is_intel_compatible(vcpu))
-               guest_cpu_cap_clear(vcpu, X86_FEATURE_V_VMSAVE_VMLOAD);
+               guest_cpu_cap_clear(vcpu->common, X86_FEATURE_V_VMSAVE_VMLOAD);
 
        if (is_sev_guest(vcpu))
                sev_vcpu_after_set_cpuid(svm);
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 62e180651143..d10aa5f60cad 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7994,7 +7994,7 @@ void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
         * set if and only if XSAVE is supported.
         */
        if (!guest_cpu_cap_has(vcpu, X86_FEATURE_XSAVE))
-               guest_cpu_cap_clear(vcpu, X86_FEATURE_XSAVES);
+               guest_cpu_cap_clear(vcpu->common, X86_FEATURE_XSAVES);
 
        vmx_setup_uret_msrs(vmx);
 
-- 
2.53.0


Reply via email to