aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/phb4.c47
-rw-r--r--hw/xive2.c40
-rw-r--r--include/phb4-regs.h1
-rw-r--r--include/xive.h2
4 files changed, 80 insertions, 10 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index e074fa2..d2d9f9e 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
*/
@@ -5366,8 +5382,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;
@@ -5927,16 +5947,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 a267df6..49c9467 100644
--- a/hw/xive2.c
+++ b/hw/xive2.c
@@ -2578,8 +2578,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);
@@ -2588,7 +2588,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);
@@ -2604,6 +2603,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 03b53ae..1395228 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 dc1b25d..faaef2a 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);