From 20c80ea72a364c7f0db5b97f9b3827e1cb4c3966 Mon Sep 17 00:00:00 2001 From: "Zheng, Gen" Date: Wed, 18 Jul 2018 23:41:08 +0800 Subject: [PATCH] HV: bug fix on emulating msi message from guest Current code has a mistake associating destination with redirectionhint. So just use the destination mode to work out destination mode. When injecting the msi interrupt to vcpu in hypervisor layer, current code ingnores the redirection hint(RH) bit of msi address message from guest, and just use the destination mode and destination ID. So correctly before injecting, check the RH bit, if set, choose the vcpu that has lowest priority to inject msi. Signed-off-by: Zheng, Gen Reviewed-by: Zhao, Yakui Reviewed-by: Yin, Fengwei Acked-by: Eddie Dong --- hypervisor/arch/x86/assign.c | 5 ++--- hypervisor/arch/x86/guest/vioapic.c | 2 +- hypervisor/arch/x86/guest/vlapic.c | 13 +++++++------ hypervisor/include/arch/x86/guest/vlapic.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/hypervisor/arch/x86/assign.c b/hypervisor/arch/x86/assign.c index 141003f6a..57b8b6d93 100644 --- a/hypervisor/arch/x86/assign.c +++ b/hypervisor/arch/x86/assign.c @@ -200,9 +200,8 @@ static void ptdev_build_physical_msi(struct vm *vm, struct ptdev_msi_info *info, /* get physical destination cpu mask */ dest = (info->vmsi_addr >> 12) & 0xffU; - phys = ((info->vmsi_addr & - (MSI_ADDR_RH | MSI_ADDR_LOG)) != - (MSI_ADDR_RH | MSI_ADDR_LOG)); + phys = ((info->vmsi_addr & MSI_ADDR_LOG) != MSI_ADDR_LOG); + calcvdest(vm, &vdmask, dest, phys); pdmask = vcpumask2pcpumask(vm, vdmask); diff --git a/hypervisor/arch/x86/guest/vioapic.c b/hypervisor/arch/x86/guest/vioapic.c index e3baa3498..1715b0f14 100644 --- a/hypervisor/arch/x86/guest/vioapic.c +++ b/hypervisor/arch/x86/guest/vioapic.c @@ -93,7 +93,7 @@ vioapic_send_intr(struct vioapic *vioapic, uint8_t pin) vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC; dest = (uint32_t)(rte.full >> IOAPIC_RTE_DEST_SHIFT); - vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector); + vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector, false); } static void diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 15b501252..4df270e96 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1654,7 +1654,7 @@ vlapic_set_apicbase(struct vlapic *vlapic, uint64_t new) void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys, - uint32_t delmode, uint32_t vec) + uint32_t delmode, uint32_t vec, bool rh) { bool lowprio; uint16_t vcpu_id; @@ -1668,7 +1668,7 @@ vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys, "vlapic intr invalid delmode %#x", delmode); return; } - lowprio = (delmode == IOAPIC_RTE_DELLOPRI); + lowprio = (delmode == IOAPIC_RTE_DELLOPRI) || rh; /* * We don't provide any virtual interrupt redirection hardware so @@ -1856,7 +1856,7 @@ vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg) { uint32_t delmode, vec; uint32_t dest; - bool phys; + bool phys, rh; dev_dbg(ACRN_DBG_LAPIC, "lapic MSI addr: %#lx msg: %#lx", addr, msg); @@ -1877,15 +1877,16 @@ vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg) * physical otherwise. */ dest = (uint32_t)(addr >> 12U) & 0xffU; - phys = ((addr & (MSI_ADDR_RH | MSI_ADDR_LOG)) != - (MSI_ADDR_RH | MSI_ADDR_LOG)); + phys = ((addr & MSI_ADDR_LOG) != MSI_ADDR_LOG); + rh = ((addr & MSI_ADDR_RH) == MSI_ADDR_RH); + delmode = (uint32_t)msg & APIC_DELMODE_MASK; vec = (uint32_t)msg & 0xffU; dev_dbg(ACRN_DBG_LAPIC, "lapic MSI %s dest %#x, vec %u", phys ? "physical" : "logical", dest, vec); - vlapic_deliver_intr(vm, LAPIC_TRIG_EDGE, dest, phys, delmode, vec); + vlapic_deliver_intr(vm, LAPIC_TRIG_EDGE, dest, phys, delmode, vec, rh); return 0; } diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index e0efd8e06..a96d837cb 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -96,7 +96,7 @@ int vlapic_set_local_intr(struct vm *vm, uint16_t vcpu_id, uint32_t vector); int vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg); void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, - bool phys, uint32_t delmode, uint32_t vec); + bool phys, uint32_t delmode, uint32_t vec, bool rh); /* Reset the trigger-mode bits for all vectors to be edge-triggered */ void vlapic_reset_tmr(struct vlapic *vlapic);