diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 88359e82f..e3ca06725 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1930,6 +1930,56 @@ vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg) return ret; } +/** + *@pre Pointer vm shall point to SOS_VM + */ +void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry *vmsi) +{ + union apic_icr icr; + struct acrn_vcpu *vcpu; + union msi_addr_reg vmsi_addr; + union msi_data_reg vmsi_data; + uint64_t vdmask = 0UL; + uint32_t vdest, dest = 0U; + uint16_t vcpu_id; + bool phys; + + vmsi_addr.full = vmsi->msi_addr; + vmsi_data.full = (uint32_t)vmsi->msi_data; + + dev_dbg(DBG_LEVEL_LAPICPT, "%s: msi_addr 0x%016lx, msi_data 0x%016lx", + __func__, vmsi->msi_addr, vmsi->msi_data); + + if (vmsi_addr.bits.addr_base == MSI_ADDR_BASE) { + vdest = vmsi_addr.bits.dest_field; + phys = (vmsi_addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS); + /* + * calculate all reachable destination vcpu. + * the delivery mode of vmsi will be forwarded to ICR delievry field + * and handled by hardware. + */ + vlapic_calc_dest_lapic_pt(vm, &vdmask, false, vdest, phys); + dev_dbg(DBG_LEVEL_LAPICPT, "%s: vcpu destination mask 0x%016lx", __func__, vdmask); + + vcpu_id = ffs64(vdmask); + while (vcpu_id != INVALID_BIT_INDEX) { + bitmap_clear_nolock(vcpu_id, &vdmask); + vcpu = vcpu_from_vid(vm, vcpu_id); + dest |= per_cpu(lapic_ldr, pcpuid_from_vcpu(vcpu)); + vcpu_id = ffs64(vdmask); + } + + icr.value = 0UL; + icr.bits.dest_field = dest; + icr.bits.vector = vmsi_data.bits.vector; + icr.bits.delivery_mode = vmsi_data.bits.delivery_mode; + icr.bits.destination_mode = MSI_ADDR_DESTMODE_LOGICAL; + + msr_write(MSR_IA32_EXT_APIC_ICR, icr.value); + dev_dbg(DBG_LEVEL_LAPICPT, "%s: icr.value 0x%016lx", __func__, icr.value); + } +} + /* interrupt context */ static void vlapic_timer_expired(void *data) { diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 0cc2cab3f..d6de4db63 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -417,56 +417,6 @@ int32_t hcall_set_irqline(struct acrn_vm *vm, struct acrn_vm *target_vm, __unuse return ret; } -/** - *@pre Pointer vm shall point to SOS_VM - */ -static void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry *vmsi) -{ - union apic_icr icr; - struct acrn_vcpu *vcpu; - union msi_addr_reg vmsi_addr; - union msi_data_reg vmsi_data; - uint64_t vdmask = 0UL; - uint32_t vdest, dest = 0U; - uint16_t vcpu_id; - bool phys; - - vmsi_addr.full = vmsi->msi_addr; - vmsi_data.full = (uint32_t)vmsi->msi_data; - - dev_dbg(DBG_LEVEL_LAPICPT, "%s: msi_addr 0x%016lx, msi_data 0x%016lx", - __func__, vmsi->msi_addr, vmsi->msi_data); - - if (vmsi_addr.bits.addr_base == MSI_ADDR_BASE) { - vdest = vmsi_addr.bits.dest_field; - phys = (vmsi_addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS); - /* - * calculate all reachable destination vcpu. - * the delivery mode of vmsi will be forwarded to ICR delievry field - * and handled by hardware. - */ - vlapic_calc_dest_lapic_pt(vm, &vdmask, false, vdest, phys); - dev_dbg(DBG_LEVEL_LAPICPT, "%s: vcpu destination mask 0x%016lx", __func__, vdmask); - - vcpu_id = ffs64(vdmask); - while (vcpu_id != INVALID_BIT_INDEX) { - bitmap_clear_nolock(vcpu_id, &vdmask); - vcpu = vcpu_from_vid(vm, vcpu_id); - dest |= per_cpu(lapic_ldr, pcpuid_from_vcpu(vcpu)); - vcpu_id = ffs64(vdmask); - } - - icr.value = 0UL; - icr.bits.dest_field = dest; - icr.bits.vector = vmsi_data.bits.vector; - icr.bits.delivery_mode = vmsi_data.bits.delivery_mode; - icr.bits.destination_mode = MSI_ADDR_DESTMODE_LOGICAL; - - msr_write(MSR_IA32_EXT_APIC_ICR, icr.value); - dev_dbg(DBG_LEVEL_LAPICPT, "%s: icr.value 0x%016lx", __func__, icr.value); - } -} - /** * @brief inject MSI interrupt * diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index 4c6f63ae0..cebda498d 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -160,6 +160,7 @@ int32_t vlapic_set_local_intr(struct acrn_vm *vm, uint16_t vcpu_id_arg, uint32_t * @pre vm != NULL */ int32_t vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg); +void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry *vmsi); void vlapic_receive_intr(struct acrn_vm *vm, bool level, uint32_t dest, bool phys, uint32_t delmode, uint32_t vec, bool rh);