From 6a4dcce3906953d48f559d118396c20e68a8a42e Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Thu, 1 Nov 2018 14:44:23 -0700 Subject: [PATCH] hv: APIs for building x2APIC ID and LDR x2APIC ID and LDR are in different format compared to xAPIC mode of operation. This patch adds code to build ID and LDR when guest uses vLAPIC in x2APIC mode. Tracked-On: #1626 Signed-off-by: Sainath Grandhi Reviewed-by: Xu Anthony --- hypervisor/arch/x86/guest/vlapic.c | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 46c140c0d..914b13e91 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -49,6 +49,8 @@ static inline uint32_t prio(uint32_t x) #define APICBASE_BSP 0x00000100UL #define APICBASE_X2APIC 0x00000400U #define APICBASE_ENABLED 0x00000800UL +#define LOGICAL_ID_MASK 0xFU +#define CLUSTER_ID_MASK 0xFFFF0U #define ACRN_DBG_LAPIC 6U @@ -102,6 +104,8 @@ static void vlapic_set_error(struct acrn_vlapic *vlapic, uint32_t mask); static void vlapic_timer_expired(void *data); +static inline bool is_x2apic_enabled(const struct acrn_vlapic *vlapic); + static struct acrn_vlapic * vm_lapic_from_vcpu_id(struct vm *vm, uint16_t vcpu_id) { @@ -180,13 +184,29 @@ vlapic_build_id(const struct acrn_vlapic *vlapic) } #endif - lapic_regs_id = (uint32_t)vlapic_id << APIC_ID_SHIFT; + if (is_x2apic_enabled(vlapic)) { + lapic_regs_id = vlapic_id; + } else { + lapic_regs_id = (uint32_t)vlapic_id << APIC_ID_SHIFT; + } dev_dbg(ACRN_DBG_LAPIC, "vlapic APIC PAGE ID : 0x%08x", lapic_regs_id); return lapic_regs_id; } +static inline void vlapic_build_x2apic_id(struct acrn_vlapic *vlapic) +{ + struct lapic_regs *lapic; + uint32_t logical_id, cluster_id; + + lapic = &(vlapic->apic_page); + lapic->id.v = vlapic_build_id(vlapic); + logical_id = lapic->id.v & LOGICAL_ID_MASK; + cluster_id = (lapic->id.v & CLUSTER_ID_MASK) >> 4U; + lapic->ldr.v = (cluster_id << 16U) | (1U << logical_id); +} + static void vlapic_dfr_write_handler(struct acrn_vlapic *vlapic) { @@ -1672,6 +1692,17 @@ static int vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new) { + uint64_t changed; + changed = vlapic->msr_apicbase ^ new; + + if (changed == APICBASE_X2APIC) { + if ((new & APICBASE_X2APIC) == APICBASE_X2APIC) { + vlapic->msr_apicbase = new; + vlapic_build_x2apic_id(vlapic); + return 0; + } + } + if (vlapic->msr_apicbase != new) { dev_dbg(ACRN_DBG_LAPIC, "NOT support to change APIC_BASE MSR from %#lx to %#lx",