diff --git a/hypervisor/arch/x86/guest/assign.c b/hypervisor/arch/x86/guest/assign.c index 4d9938fd0..9c1857bfb 100644 --- a/hypervisor/arch/x86/guest/assign.c +++ b/hypervisor/arch/x86/guest/assign.c @@ -512,7 +512,7 @@ void ptirq_softirq(uint16_t pcpu_id) } else { if (vmsi != NULL) { /* TODO: vmsi destmode check required */ - (void)vlapic_intr_msi(entry->vm, vmsi->addr.full, vmsi->data.full); + (void)vlapic_inject_msi(entry->vm, vmsi->addr.full, vmsi->data.full); dev_dbg(DBG_LEVEL_PTIRQ, "dev-assign: irq=0x%x MSI VR: 0x%x-0x%x", entry->allocated_pirq, vmsi->data.bits.vector, irq_to_vector(entry->allocated_pirq)); diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index e3ca06725..d320238cb 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1873,7 +1873,7 @@ vlapic_set_local_intr(struct acrn_vm *vm, uint16_t vcpu_id_arg, uint32_t lvt_ind } /** - * @brief Inject MSI to target VM. + * @brief Inject MSI to target VM for case that local APIC is virtualized. * * @param[in] vm Pointer to VM data structure * @param[in] addr MSI address. @@ -1884,8 +1884,7 @@ vlapic_set_local_intr(struct acrn_vm *vm, uint16_t vcpu_id_arg, uint32_t lvt_ind * * @pre vm != NULL */ -int32_t -vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg) +static int32_t inject_msi_for_non_lapic_pt(struct acrn_vm *vm, uint64_t addr, uint64_t msg) { uint32_t delmode, vec; uint32_t dest; @@ -1933,7 +1932,7 @@ vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg) /** *@pre Pointer vm shall point to SOS_VM */ -void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry *vmsi) +static void inject_msi_for_lapic_pt(struct acrn_vm *vm, uint64_t addr, uint64_t data) { union apic_icr icr; struct acrn_vcpu *vcpu; @@ -1944,11 +1943,11 @@ void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry *vmsi) uint16_t vcpu_id; bool phys; - vmsi_addr.full = vmsi->msi_addr; - vmsi_data.full = (uint32_t)vmsi->msi_data; + vmsi_addr.full = addr; + vmsi_data.full = (uint32_t)data; dev_dbg(DBG_LEVEL_LAPICPT, "%s: msi_addr 0x%016lx, msi_data 0x%016lx", - __func__, vmsi->msi_addr, vmsi->msi_data); + __func__, addr, data); if (vmsi_addr.bits.addr_base == MSI_ADDR_BASE) { vdest = vmsi_addr.bits.dest_field; @@ -1980,6 +1979,49 @@ void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry *vmsi) } } +/** + * @brief Inject MSI to target VM for both virtual local APIC and local APIC pass-through cases. + * + * @param[in] vm Pointer to VM data structure. + * @param[in] addr MSI address. + * @param[in] data MSI data. + * + * @retval 0 on success. + * @retval -1 on error that addr is invalid. + * + * @pre vm != NULL + */ +int32_t vlapic_inject_msi(struct acrn_vm *vm, uint64_t addr, uint64_t data) +{ + int32_t ret = -1; + + /* For target cpu with lapic pt, send ipi instead of injection via vlapic */ + if (is_lapic_pt_configured(vm)) { + enum vm_vlapic_mode vlapic_mode = check_vm_vlapic_mode(vm); + + if (vlapic_mode == VM_VLAPIC_X2APIC) { + /* + * All the vCPUs of VM are in x2APIC mode and LAPIC is PT + * Inject the vMSI as an IPI directly to VM + */ + inject_msi_for_lapic_pt(vm, addr, data); + ret = 0; + } else if (vlapic_mode == VM_VLAPIC_XAPIC) { + /* + * All the vCPUs of VM are in xAPIC and use vLAPIC + * Inject using vLAPIC + */ + ret = inject_msi_for_non_lapic_pt(vm, addr, data); + } else { + /* Returns error for VM_VLAPIC_DISABLED and VM_VLAPIC_TRANSITION cases*/ + } + } else { + ret = inject_msi_for_non_lapic_pt(vm, addr, data); + } + + return ret; +} + /* interrupt context */ static void vlapic_timer_expired(void *data) { diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index d6de4db63..5be2ef10e 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -438,32 +438,7 @@ int32_t hcall_inject_msi(struct acrn_vm *vm, struct acrn_vm *target_vm, __unused struct acrn_msi_entry msi; if (copy_from_gpa(vm, &msi, param2, sizeof(msi)) == 0) { - /* For target cpu with lapic pt, send ipi instead of injection via vlapic */ - if (is_lapic_pt_configured(target_vm)) { - enum vm_vlapic_mode vlapic_mode = check_vm_vlapic_mode(target_vm); - - if (vlapic_mode == VM_VLAPIC_X2APIC) { - /* - * All the vCPUs of VM are in x2APIC mode and LAPIC is PT - * Inject the vMSI as an IPI directly to VM - */ - inject_msi_lapic_pt(target_vm, &msi); - ret = 0; - } else if (vlapic_mode == VM_VLAPIC_XAPIC) { - /* - * All the vCPUs of VM are in xAPIC and use vLAPIC - * Inject using vLAPIC - */ - ret = vlapic_intr_msi(target_vm, msi.msi_addr, msi.msi_data); - } else { - /* - * For cases VM_VLAPIC_DISABLED and VM_VLAPIC_TRANSITION - * Silently drop interrupt - */ - } - } else { - ret = vlapic_intr_msi(target_vm, msi.msi_addr, msi.msi_data); - } + ret = vlapic_inject_msi(target_vm, msi.msi_addr, msi.msi_data); } } diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index cebda498d..1ec99e320 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -152,15 +152,15 @@ int32_t vlapic_set_local_intr(struct acrn_vm *vm, uint16_t vcpu_id_arg, uint32_t * * @param[in] vm Pointer to VM data structure * @param[in] addr MSI address. - * @param[in] msg MSI data. + * @param[in] data MSI data. * * @retval 0 on success. * @retval -1 on error that addr is invalid. * * @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); +int32_t vlapic_inject_msi(struct acrn_vm *vm, uint64_t addr, uint64_t data); + void vlapic_receive_intr(struct acrn_vm *vm, bool level, uint32_t dest, bool phys, uint32_t delmode, uint32_t vec, bool rh);