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) {