From c85e35d31bee4bfb3468f436f0fbf7b7b89a52b6 Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Thu, 1 Nov 2018 15:21:46 -0700 Subject: [PATCH] hv: Switch APICv from MMIO to MSR for x2APIC mode of guest vLAPIC When guest switches from xAPIC mode to x2APIC mode of vLAPIC operation, MSRs are used to access vLAPIC. This patch adds APICv support for MSR accesses to vLAPIC. Switching from xAPIC to x2APIC is supported via APIC BASE MSR. Other modifications like disabling and switching back to xAPIC are not supported. Tracked-On: #1626 Signed-off-by: Sainath Grandhi Reviewed-by: Xu Anthony --- hypervisor/arch/x86/guest/vlapic.c | 1 + hypervisor/arch/x86/guest/vmsr.c | 19 +++++++++++++++++++ hypervisor/arch/x86/vmx.c | 12 ++++++++++++ hypervisor/include/arch/x86/vmx.h | 1 + 4 files changed, 33 insertions(+) diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index d716e9f59..91d40fc22 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1718,6 +1718,7 @@ vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new) if ((new & APICBASE_X2APIC) == APICBASE_X2APIC) { vlapic->msr_apicbase = new; vlapic_build_x2apic_id(vlapic); + switch_apicv_mode_x2apic(vlapic->vcpu); return 0; } } diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c index 932c530df..130c5b52b 100644 --- a/hypervisor/arch/x86/guest/vmsr.c +++ b/hypervisor/arch/x86/guest/vmsr.c @@ -427,3 +427,22 @@ int wrmsr_vmexit_handler(struct vcpu *vcpu) return err; } + +void update_msr_bitmap_x2apic_apicv(struct vcpu *vcpu) +{ + uint8_t *msr_bitmap; + + msr_bitmap = vcpu->vm->arch_vm.msr_bitmap; + intercept_x2apic_msrs(msr_bitmap, WRITE); + enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_CUR_COUNT, READ); + /* + * Open read-only interception for write-only + * registers to inject gp on reads. EOI and Self-IPI + * Writes are disabled for EOI, TPR and Self-IPI as + * writes to them are virtualized with Register Virtualization + * Refer to Section 29.1 in Intel SDM Vol. 3 + */ + enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_TPR, DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_EOI, READ); + enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_SELF_IPI, READ); +} diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index f1a76c915..f1b46a176 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -26,6 +26,8 @@ static uint64_t cr4_host_mask; static uint64_t cr4_always_on_mask; static uint64_t cr4_always_off_mask; +void update_msr_bitmap_x2apic_apicv(struct vcpu *vcpu); + bool is_vmx_disabled(void) { uint64_t msr_val; @@ -1052,3 +1054,13 @@ void init_vmcs(struct vcpu *vcpu) init_entry_ctrl(vcpu); init_exit_ctrl(); } + +void switch_apicv_mode_x2apic(struct vcpu *vcpu) +{ + uint32_t value32; + value32 = exec_vmread32(VMX_PROC_VM_EXEC_CONTROLS2); + value32 &= ~VMX_PROCBASED_CTLS2_VAPIC; + value32 |= VMX_PROCBASED_CTLS2_VX2APIC; + exec_vmwrite32(VMX_PROC_VM_EXEC_CONTROLS2, value32); + update_msr_bitmap_x2apic_apicv(vcpu); +} diff --git a/hypervisor/include/arch/x86/vmx.h b/hypervisor/include/arch/x86/vmx.h index 1bd15874d..d4693fcb5 100644 --- a/hypervisor/include/arch/x86/vmx.h +++ b/hypervisor/include/arch/x86/vmx.h @@ -464,6 +464,7 @@ int vmx_wrmsr_pat(struct vcpu *vcpu, uint64_t value); void vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0); void vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4); bool is_vmx_disabled(void); +void switch_apicv_mode_x2apic(struct vcpu *vcpu); static inline enum vm_cpu_mode get_vcpu_mode(const struct vcpu *vcpu) {