diff mbox series

[36/61] hw/phb5: Add support for PQ offloading

Message ID 20210719132012.150948-37-hegdevasant@linux.vnet.ibm.com
State Superseded
Headers show
Series P10 Enablement | expand

Commit Message

Vasant Hegde July 19, 2021, 1:19 p.m. UTC
From: Cédric Le Goater <clg@kaod.org>

The POWER9 DD2.0 introduced a StoreEOI operation which had benefits
over the LoadEOI operation : less latency and improved performance for
interrupt handling. Because of load vs. store ordering issues in some
cases, it had to be deactivates. The POWER10 processor has a set
of new features in the XIVE2 and the PHB5 controllers to address this
problem.

At the interrupt controller level, XIVE2 adds a new load offset to the
ESB page which offers the capability to order loads after stores. It
should be enforced by the OS when doing loads if StoreEOI is to be
used.

But this is not enough. The firmware should also carefully configure
the PHB interrupt sources to make sure that operations on the PQ state
bits of a source are routed to a single logic unit : the XIVE2 IC.
The PHB5 introduces a new configuration PQ disable (bit 9) bit for
this purpose.

It disables the check of the PQ state bits when processing new MSI
interrupts. When set, the PHB ignores its local PQ state bits and
forwards unconditionally any MSI trigger to the XIVE2 interrupt
controller. The XIVE2 IC knows from the trigger message that the PQ
bits have not been checked and performs the check using the local PQ
bits. This configuration bit only applies to MSIs and LSIs are still
checked on the PHB to handle the assertion level.

This requires a new XIVE interface to register a HW interrupt source
using the IC ESB pages of the allocated HW interrupt numbers, and not
the ESB pages of the HW source. This is what this change proposes for
MSIs, LSI still being handled the old way.

PQ disable is a requirement for StoreEOI.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
[FB: port to phb4.c]
Signed-off-by: Frederic Barrat <fbarrat@linux.ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
 hw/phb4.c           | 47 ++++++++++++++++++++++++++++++++++++++-------
 hw/xive2.c          | 40 +++++++++++++++++++++++++++++++++++---
 include/phb4-regs.h |  1 +
 include/xive.h      |  2 ++
 4 files changed, 80 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/hw/phb4.c b/hw/phb4.c
index 033f08e6c..6747fcb8f 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -136,8 +136,6 @@  static void phb4_init_hw(struct phb4 *p);
 #define PHBLOGCFG(p, fmt, a...) do {} while (0)
 #endif
 
-#define PHB4_CAN_STORE_EOI(p) XIVE_STORE_EOI_ENABLED
-
 static bool pci_eeh_mmio;
 static bool pci_retry_all;
 static int rx_err_max = PHB4_RX_ERR_MAX;
@@ -152,6 +150,24 @@  static inline bool is_phb5(void)
 	return (proc_gen == proc_gen_p10);
 }
 
+/* PQ offloading on the XIVE IC. */
+static inline bool phb_pq_disable(struct phb4 *p __unused)
+{
+	if (is_phb5())
+		return 1;
+
+	return false;
+}
+
+static inline bool phb_can_store_eoi(struct phb4 *p)
+{
+	if (is_phb5())
+		/* PQ offloading is required for StoreEOI */
+		return XIVE2_STORE_EOI_ENABLED && phb_pq_disable(p);
+
+	return XIVE_STORE_EOI_ENABLED;
+}
+
 /* Note: The "ASB" name is historical, practically this means access via
  * the XSCOM backdoor
  */
@@ -5367,8 +5383,12 @@  static void phb4_init_hw(struct phb4 *p)
 	val = PHB_CTRLR_IRQ_PGSZ_64K;
 	val |= PHB_CTRLR_TCE_CLB_DISABLE; // HW557787 circumvention
 	val |= SETFIELD(PHB_CTRLR_TVT_ADDR_SEL, 0ull, TVT_2_PER_PE);
-	if (PHB4_CAN_STORE_EOI(p))
+	if (phb_pq_disable(p))
+		val |= PHB_CTRLR_IRQ_PQ_DISABLE;
+	if (phb_can_store_eoi(p)) {
 		val |= PHB_CTRLR_IRQ_STORE_EOI;
+		PHBDBG(p, "store EOI is enabled\n");
+	}
 
 	if (!pci_eeh_mmio)
 		val |= PHB_CTRLR_MMIO_EEH_DISABLE;
@@ -5928,16 +5948,29 @@  static void phb4_create(struct dt_node *np)
 
 	/* Compute XIVE source flags depending on PHB revision */
 	irq_flags = 0;
-	if (PHB4_CAN_STORE_EOI(p))
+	if (phb_can_store_eoi(p))
 		irq_flags |= XIVE_SRC_STORE_EOI;
 	else
 		irq_flags |= XIVE_SRC_TRIGGER_PAGE;
 
 	if (is_phb5()) {
-		/* Register all interrupt sources with XIVE */
-		xive2_register_hw_source(p->base_msi, p->num_irqs - 8, 16,
-					 p->int_mmio, irq_flags, NULL, NULL);
+		/*
+		 * Register sources with XIVE. If offloading is on, use the
+		 * ESB pages of the XIVE IC for the MSI sources instead of the
+		 * ESB pages of the PHB.
+		 */
+		if (phb_pq_disable(p)) {
+			xive2_register_esb_source(p->base_msi, p->num_irqs - 8);
+		} else {
+			xive2_register_hw_source(p->base_msi,
+						 p->num_irqs - 8, 16,
+						 p->int_mmio, irq_flags,
+						 NULL, NULL);
+		}
 
+		/*
+		 * LSI sources always use the ESB pages of the PHB.
+		 */
 		xive2_register_hw_source(p->base_lsi, 8, 16,
 					 p->int_mmio + ((p->num_irqs - 8) << 16),
 					 XIVE_SRC_LSI, p, &phb4_lsi_ops);
diff --git a/hw/xive2.c b/hw/xive2.c
index d0a098009..9f9ccb325 100644
--- a/hw/xive2.c
+++ b/hw/xive2.c
@@ -2584,8 +2584,8 @@  void xive2_register_hw_source(uint32_t base, uint32_t count, uint32_t shift,
 			       false, data, ops);
 }
 
-void xive2_register_ipi_source(uint32_t base, uint32_t count, void *data,
-			      const struct irq_source_ops *ops)
+static void __xive2_register_esb_source(uint32_t base, uint32_t count,
+				void *data, const struct irq_source_ops *ops)
 {
 	struct xive_src *s;
 	struct xive *x = xive_from_isn(base);
@@ -2594,7 +2594,6 @@  void xive2_register_ipi_source(uint32_t base, uint32_t count, void *data,
 	uint32_t flags = XIVE_SRC_EOI_PAGE1 | XIVE_SRC_TRIGGER_PAGE;
 
 	assert(x);
-	assert(base >= x->int_base && (base + count) <= x->int_ipi_top);
 
 	s = malloc(sizeof(struct xive_src));
 	assert(s);
@@ -2610,6 +2609,41 @@  void xive2_register_ipi_source(uint32_t base, uint32_t count, void *data,
 			       flags, false, data, ops);
 }
 
+/*
+ * Check that IPI sources have interrupt numbers in the IPI interrupt
+ * number range
+ */
+void xive2_register_ipi_source(uint32_t base, uint32_t count, void *data,
+			       const struct irq_source_ops *ops)
+{
+	struct xive *x = xive_from_isn(base);
+
+	assert(x);
+	assert(base >= x->int_base && (base + count) <= x->int_ipi_top);
+
+	__xive2_register_esb_source(base, count, data, ops);
+}
+
+/*
+ * Some HW sources (PHB) can disable the use of their own ESB pages
+ * and offload all the checks on ESB pages of the IC. The interrupt
+ * numbers are not necessarily in the IPI range.
+ */
+void xive2_register_esb_source(uint32_t base, uint32_t count)
+{
+	__xive2_register_esb_source(base, count, NULL, NULL);
+}
+
+uint64_t xive2_get_esb_base(uint32_t base)
+{
+	struct xive *x = xive_from_isn(base);
+	uint32_t base_idx = GIRQ_TO_IDX(base);
+
+	assert(x);
+
+	return (uint64_t) x->esb_base + (1ul << XIVE_ESB_SHIFT) * base_idx;
+}
+
 static void xive_set_quirks(struct xive *x, struct proc_chip *chip __unused)
 {
 	uint64_t quirks = 0;
diff --git a/include/phb4-regs.h b/include/phb4-regs.h
index 03b53ae01..139522814 100644
--- a/include/phb4-regs.h
+++ b/include/phb4-regs.h
@@ -101,6 +101,7 @@ 
 
 #define PHB_VERSION			0x800
 #define PHB_CTRLR			0x810
+#define   PHB_CTRLR_IRQ_PQ_DISABLE	PPC_BIT(9)	/* PHB5 */
 #define   PHB_CTRLR_IRQ_PGSZ_64K	PPC_BIT(11)
 #define   PHB_CTRLR_IRQ_STORE_EOI	PPC_BIT(12)
 #define   PHB_CTRLR_MMIO_RD_STRICT	PPC_BIT(13)
diff --git a/include/xive.h b/include/xive.h
index dc1b25d03..faaef2aeb 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -86,6 +86,8 @@  void xive2_register_hw_source(uint32_t base, uint32_t count, uint32_t shift,
 			     const struct irq_source_ops *ops);
 void xive2_register_ipi_source(uint32_t base, uint32_t count, void *data,
 			      const struct irq_source_ops *ops);
+void xive2_register_esb_source(uint32_t base, uint32_t count);
+uint64_t xive2_get_esb_base(uint32_t girq);
 void xive2_cpu_callin(struct cpu_thread *cpu);
 void *xive2_get_trigger_port(uint32_t girq);