From 34b0696be443e123d2d5225613c4604c66eb7a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 2 Mar 2022 06:51:39 +0100 Subject: ppc/pnv: Add support for PHB5 "Address-based trigger" mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the Address-Based Interrupt Trigger mode is activated, the PHB maps the interrupt source number into the interrupt command address. The PHB directly triggers the IC ESB page of the interrupt number and not the notify page of the IC anymore. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 73 ++++++++++++++++++++++++++++++++++++++++++++---- hw/pci-host/trace-events | 2 ++ 2 files changed, 69 insertions(+), 6 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 0b407ac69b..b5b384e9ee 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1669,10 +1669,54 @@ static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, return phb->bus_path; } -static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno, - bool pq_checked) +/* + * Address base trigger mode (POWER10) + * + * Trigger directly the IC ESB page + */ +static void pnv_phb4_xive_notify_abt(PnvPHB4 *phb, uint32_t srcno, + bool pq_checked) +{ + uint64_t notif_port = phb->regs[PHB_INT_NOTIFY_ADDR >> 3]; + uint64_t data = 0; /* trigger data : don't care */ + hwaddr addr; + MemTxResult result; + int esb_shift; + + if (notif_port & PHB_INT_NOTIFY_ADDR_64K) { + esb_shift = 16; + } else { + esb_shift = 12; + } + + /* Compute the address of the IC ESB management page */ + addr = (notif_port & ~PHB_INT_NOTIFY_ADDR_64K); + addr |= (1ull << (esb_shift + 1)) * srcno; + addr |= (1ull << esb_shift); + + /* + * When the PQ state bits are checked on the PHB, the associated + * PQ state bits on the IC should be ignored. Use the unconditional + * trigger offset to inject a trigger on the IC. This is always + * the case for LSIs + */ + if (pq_checked) { + addr |= XIVE_ESB_INJECT; + } + + trace_pnv_phb4_xive_notify_ic(addr, data); + + address_space_stq_be(&address_space_memory, addr, data, + MEMTXATTRS_UNSPECIFIED, &result); + if (result != MEMTX_OK) { + phb_error(phb, "trigger failed @%"HWADDR_PRIx "\n", addr); + return; + } +} + +static void pnv_phb4_xive_notify_ic(PnvPHB4 *phb, uint32_t srcno, + bool pq_checked) { - PnvPHB4 *phb = PNV_PHB4(xf); uint64_t notif_port = phb->regs[PHB_INT_NOTIFY_ADDR >> 3]; uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3]; uint64_t data = offset | srcno; @@ -1682,7 +1726,7 @@ static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno, data |= XIVE_TRIGGER_PQ; } - trace_pnv_phb4_xive_notify(notif_port, data); + trace_pnv_phb4_xive_notify_ic(notif_port, data); address_space_stq_be(&address_space_memory, notif_port, data, MEMTXATTRS_UNSPECIFIED, &result); @@ -1692,6 +1736,18 @@ static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno, } } +static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno, + bool pq_checked) +{ + PnvPHB4 *phb = PNV_PHB4(xf); + + if (phb->regs[PHB_CTRLR >> 3] & PHB_CTRLR_IRQ_ABT_MODE) { + pnv_phb4_xive_notify_abt(phb, srcno, pq_checked); + } else { + pnv_phb4_xive_notify_ic(phb, srcno, pq_checked); + } +} + static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), @@ -1858,10 +1914,15 @@ type_init(pnv_phb4_register_types); void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon) { + uint64_t notif_port = + phb->regs[PHB_INT_NOTIFY_ADDR >> 3] & ~PHB_INT_NOTIFY_ADDR_64K; uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3]; + bool abt = !!(phb->regs[PHB_CTRLR >> 3] & PHB_CTRLR_IRQ_ABT_MODE); - monitor_printf(mon, "PHB4[%x:%x] Source %08x .. %08x\n", + monitor_printf(mon, "PHB4[%x:%x] Source %08x .. %08x %s @%"HWADDR_PRIx"\n", phb->chip_id, phb->phb_id, - offset, offset + phb->xsrc.nr_irqs - 1); + offset, offset + phb->xsrc.nr_irqs - 1, + abt ? "ABT" : "", + notif_port); xive_source_pic_print_info(&phb->xsrc, 0, mon); } diff --git a/hw/pci-host/trace-events b/hw/pci-host/trace-events index 630e9fcc5e..6e5d8d3355 100644 --- a/hw/pci-host/trace-events +++ b/hw/pci-host/trace-events @@ -32,3 +32,5 @@ unin_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64 # pnv_phb4.c pnv_phb4_xive_notify(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64 +pnv_phb4_xive_notify_ic(uint64_t addr, uint64_t data) "addr=@0x%"PRIx64" data=0x%"PRIx64 +pnv_phb4_xive_notify_abt(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64 -- cgit v1.2.3