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 <sainath.grandhi@intel.com>
Reviewed-by: Xu Anthony <anthony.xu@intel.com>
This commit is contained in:
Sainath Grandhi 2018-11-01 15:21:46 -07:00 committed by lijinxia
parent cf4d191272
commit c85e35d31b
4 changed files with 33 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

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