diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 19c22a5c7..1b555a384 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -54,9 +54,10 @@ static inline uint32_t prio(uint32_t x) } #define VLAPIC_VERSION (16U) - #define APICBASE_BSP 0x00000100UL #define APICBASE_X2APIC 0x00000400U +#define APICBASE_XAPIC 0x00000800U +#define APICBASE_LAPIC_MODE (APICBASE_XAPIC | APICBASE_X2APIC) #define APICBASE_ENABLED 0x00000800UL #define LOGICAL_ID_MASK 0xFU #define CLUSTER_ID_MASK 0xFFFF0U @@ -1763,20 +1764,39 @@ int32_t vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new) { int32_t ret = 0; uint64_t changed; - changed = vlapic->msr_apicbase ^ new; + bool change_in_vlapic_mode = false; - if ((changed == APICBASE_X2APIC) && ((new & APICBASE_X2APIC) == APICBASE_X2APIC)) { - atomic_set64(&vlapic->msr_apicbase, changed); - vlapic_build_x2apic_id(vlapic); - switch_apicv_mode_x2apic(vlapic->vcpu); - ret = 0; - } else if (vlapic->msr_apicbase != new) { - dev_dbg(ACRN_DBG_LAPIC, - "NOT support to change APIC_BASE MSR from %#lx to %#lx", - vlapic->msr_apicbase, new); - ret = -1; - } else { - /* No other state currently, do nothing */ + + if (vlapic->msr_apicbase != new) { + changed = vlapic->msr_apicbase ^ new; + change_in_vlapic_mode = ((changed & APICBASE_LAPIC_MODE) != 0U); + + /* + * TODO: Logic to check for change in Reserved Bits and Inject GP + */ + + + /* + * Logic to check for change in Bits 11:10 for vLAPIC mode switch + */ + if (change_in_vlapic_mode) { + if ((new & APICBASE_LAPIC_MODE) == + (APICBASE_XAPIC | APICBASE_X2APIC)) { + vlapic->msr_apicbase = new; + vlapic_build_x2apic_id(vlapic); + switch_apicv_mode_x2apic(vlapic->vcpu); + } else { + /* + * TODO: Logic to check for Invalid transitions, Invalid State + * and mode switch according to SDM 10.12.5 + * Fig. 10-27 + */ + } + } + + /* + * TODO: Logic to check for change in Bits 35:12 and Bit 7 and emulate + */ } return ret;