From 1026f1754c2efca5ae9b5490dcd07fb468218c52 Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Mon, 10 Jun 2019 15:20:52 -0700 Subject: [PATCH] hv: Shuffle logic in vlapic_set_apicbase API implementation This patch changes the code in vlapic_set_apicbase for the following reasons 1) Better readability as it first checks if the new value programmed into MSR is any different from the existing value cached in guest structures 2) Check if both bits 11:10 are set before enabling x2APIC mode for guest. Current code does not check if Bit 11 is set. 3) Add TODO in the comments, to detail about the current gaps in IA32_APIC_BASE MSR emulation. Tracked-On: #3253 Signed-off-by: Sainath Grandhi Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vlapic.c | 48 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 14 deletions(-) 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;