From 691abe90ff7d4a170b44f1e346eafffd03ab2e99 Mon Sep 17 00:00:00 2001 From: Tao Yuhong Date: Mon, 12 Oct 2020 11:29:04 -0400 Subject: [PATCH] HV: vuart: send msi for pci vuart type if vuart type is pci-vuart, then use MSI interrupt split vuart_toggle_intr() control flow into vuart_trigger_level_intr() & trigger_vmcs9900_msix(), because MSI is edge triggered, no deassertion operation. Only trigger MSI for pci-vuart when assert interrupt. Tracked-On: #5394 Signed-off-by: Tao Yuhong Reviewed-by: Wang, Yu1 Acked-by: Eddie Dong --- hypervisor/dm/vpci/vmcs9900.c | 17 ++++++++++++++++ hypervisor/dm/vuart.c | 33 +++++++++++++++++++++++--------- hypervisor/include/dm/vmcs9900.h | 1 + 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/hypervisor/dm/vpci/vmcs9900.c b/hypervisor/dm/vpci/vmcs9900.c index b27afe314..bc1d02800 100644 --- a/hypervisor/dm/vpci/vmcs9900.c +++ b/hypervisor/dm/vpci/vmcs9900.c @@ -14,6 +14,23 @@ #define MCS9900_MMIO_BAR 0U #define MCS9900_MSIX_BAR 1U +/* + * @pre vdev != NULL + */ +void trigger_vmcs9900_msix(struct pci_vdev *vdev) +{ + struct acrn_vm *vm = vpci2vm(vdev->vpci); + int32_t ret = -1; + struct msix_table_entry *entry = &vdev->msix.table_entries[0]; + + ret = vlapic_inject_msi(vm, entry->addr, entry->data); + + if (ret != 0) { + pr_warn("%2x:%2x.%dfaild injecting msi msi_addr:0x%lx msi_data:0x%x", + vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, entry->addr, entry->data); + } +} + static int32_t read_vmcs9900_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t * val) diff --git a/hypervisor/dm/vuart.c b/hypervisor/dm/vuart.c index 5c07f0778..6671ca61d 100644 --- a/hypervisor/dm/vuart.c +++ b/hypervisor/dm/vuart.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -165,17 +166,11 @@ static struct acrn_vuart *find_vuart_by_port(struct acrn_vm *vm, uint16_t offset return ret_vu; } -/* - * Toggle the COM port's intr pin depending on whether or not we have an - * interrupt condition to report to the processor. - */ -void vuart_toggle_intr(const struct acrn_vuart *vu) +static void vuart_trigger_level_intr(const struct acrn_vuart *vu, bool assert) { - uint8_t intr_reason; union ioapic_rte rte; uint32_t operation; - intr_reason = vuart_intr_reason(vu); vioapic_get_rte(vu->vm, vu->irq, &rte); /* TODO: @@ -187,15 +182,35 @@ void vuart_toggle_intr(const struct acrn_vuart *vu) * we want to make it as an known issue. */ if (rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO) { - operation = (intr_reason != IIR_NOPEND) ? GSI_SET_LOW : GSI_SET_HIGH; + operation = assert ? GSI_SET_LOW : GSI_SET_HIGH; } else { - operation = (intr_reason != IIR_NOPEND) ? GSI_SET_HIGH : GSI_SET_LOW; + operation = assert ? GSI_SET_HIGH : GSI_SET_LOW; } vpic_set_irqline(vm_pic(vu->vm), vu->irq, operation); vioapic_set_irqline_lock(vu->vm, vu->irq, operation); } +/* + * Toggle the COM port's intr pin depending on whether or not we have an + * interrupt condition to report to the processor. + */ +void vuart_toggle_intr(const struct acrn_vuart *vu) +{ + uint8_t intr_reason; + + intr_reason = vuart_intr_reason(vu); + + if ((vu->vdev != NULL) && (intr_reason != IIR_NOPEND)) { + /* FIXME: Toggle is for level trigger interrupt, for edge trigger need refine the logic later. */ + trigger_vmcs9900_msix(vu->vdev); + } else if (intr_reason != IIR_NOPEND) { + vuart_trigger_level_intr(vu, true); + } else { + vuart_trigger_level_intr(vu, false); + } +} + static bool send_to_target(struct acrn_vuart *vu, uint8_t value_u8) { uint64_t rflags; diff --git a/hypervisor/include/dm/vmcs9900.h b/hypervisor/include/dm/vmcs9900.h index 16e658c2a..00bad8d17 100644 --- a/hypervisor/include/dm/vmcs9900.h +++ b/hypervisor/include/dm/vmcs9900.h @@ -11,5 +11,6 @@ #define MCS9900_DEV 0x9900U extern const struct pci_vdev_ops vmcs9900_ops; +void trigger_vmcs9900_msix(struct pci_vdev *vdev); #endif