From: Suravee Suthikulpanit <[email protected]>

Since AVIC only virtualizes xAPIC hardware for the guest, we need to:
    * Intercept APIC BAR msr accesses to disable x2APIC
    * Intercept CPUID access to not advertise x2APIC support
    * Hide x2APIC support when checking via KVM ioctl

Signed-off-by: Suravee Suthikulpanit <[email protected]>
---
 arch/x86/kvm/svm.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index a177781..02cd8d0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -228,6 +228,7 @@ static const struct svm_direct_access_msrs {
        { .index = MSR_IA32_LASTBRANCHTOIP,             .always = false },
        { .index = MSR_IA32_LASTINTFROMIP,              .always = false },
        { .index = MSR_IA32_LASTINTTOIP,                .always = false },
+       { .index = MSR_IA32_APICBASE,                   .always = false },
        { .index = MSR_INVALID,                         .always = false },
 };
 
@@ -855,6 +856,9 @@ static void svm_vcpu_init_msrpm(u32 *msrpm)
 
                set_msr_interception(msrpm, direct_access_msrs[i].index, 1, 1);
        }
+
+       if (avic)
+               set_msr_interception(msrpm, MSR_IA32_APICBASE, 1, 1);
 }
 
 static void add_msr_offset(u32 offset)
@@ -3490,6 +3494,18 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct 
msr_data *msr_info)
                        msr_info->data = 0x1E;
                }
                break;
+       case MSR_IA32_APICBASE:
+               if (avic) {
+                       /* Note:
+                        * For AVIC, we need to disable X2APIC
+                        * and enable XAPIC
+                        */
+                       kvm_get_msr_common(vcpu, msr_info);
+                       msr_info->data &= ~X2APIC_ENABLE;
+                       msr_info->data |= XAPIC_ENABLE;
+                       break;
+               }
+               /* Follow through if not AVIC */
        default:
                return kvm_get_msr_common(vcpu, msr_info);
        }
@@ -3618,6 +3634,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct 
msr_data *msr)
        case MSR_VM_IGNNE:
                vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", 
ecx, data);
                break;
+       case MSR_IA32_APICBASE:
+               if (avic)
+                       avic_update_vapic_bar(to_svm(vcpu), data);
+               /* Follow through */
        default:
                return kvm_set_msr_common(vcpu, msr);
        }
@@ -4754,11 +4774,26 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 
        /* Update nrips enabled cache */
        svm->nrips_enabled = !!guest_cpuid_has_nrips(&svm->vcpu);
+
+       /* Do not support X2APIC when enable AVIC */
+       if (avic) {
+               int i;
+
+               for (i = 0 ; i < vcpu->arch.cpuid_nent ; i++) {
+                       if (vcpu->arch.cpuid_entries[i].function == 1)
+                               vcpu->arch.cpuid_entries[i].ecx &= ~(1 << 21);
+               }
+       }
 }
 
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
        switch (func) {
+       case 0x00000001:
+               /* Do not support X2APIC when enable AVIC */
+               if (avic)
+                       entry->ecx &= ~(1 << 21);
+               break;
        case 0x80000001:
                if (nested)
                        entry->ecx |= (1 << 2); /* Set SVM bit */
-- 
1.9.1

Reply via email to