[Skiboot] [PATCH 01/28] interrupts: Add eoi() callback in preparation for XIVE support

Benjamin Herrenschmidt benh at kernel.crashing.org
Thu Jul 7 11:49:52 AEST 2016


This will be used by the XICS emulation in order to EOI the
sources themselves.

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
 core/interrupts.c    | 23 +++++++++++++++++++----
 include/interrupts.h | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/core/interrupts.c b/core/interrupts.c
index aafdea9..db39267 100644
--- a/core/interrupts.c
+++ b/core/interrupts.c
@@ -205,7 +205,8 @@ void reset_cpu_icp(void)
 {
 	void *icp = this_cpu()->icp_regs;
 
-	assert(icp);
+	if (!icp)
+		return;
 
 	/* Clear pending IPIs */
 	out_8(icp + ICP_MFRR, 0xff);
@@ -221,7 +222,8 @@ void icp_send_eoi(uint32_t interrupt)
 {
 	void *icp = this_cpu()->icp_regs;
 
-	assert(icp);
+	if (!icp)
+		return;
 
 	/* Set priority to max, ignore all incoming interrupts */
 	out_be32(icp + ICP_XIRR, interrupt & 0xffffff);
@@ -234,7 +236,8 @@ void icp_prep_for_rvwinkle(void)
 {
 	void *icp = this_cpu()->icp_regs;
 
-	assert(icp);
+	if (!icp)
+		return;
 
 	/* Clear pending IPIs */
 	out_8(icp + ICP_MFRR, 0xff);
@@ -248,7 +251,8 @@ void icp_kick_cpu(struct cpu_thread *cpu)
 {
 	void *icp = cpu->icp_regs;
 
-	assert(icp);
+	if (!icp)
+		return;
 
 	/* Send high priority IPI */
 	out_8(icp + ICP_MFRR, 0);
@@ -353,6 +357,17 @@ static struct irq_source *irq_find_source(uint32_t isn)
 	return NULL;
 }
 
+bool irq_source_eoi(uint32_t isn)
+{
+	struct irq_source *is = irq_find_source(isn);
+
+	if (!is || !is->ops->eoi)
+		return false;
+
+	is->ops->eoi(is->data, isn);
+	return true;
+}
+
 static int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority)
 {
 	struct irq_source *is = irq_find_source(isn);
diff --git a/include/interrupts.h b/include/interrupts.h
index d144dcd..19f542f 100644
--- a/include/interrupts.h
+++ b/include/interrupts.h
@@ -181,6 +181,38 @@
  *
  */
 
+/* Note about interrupt numbers on P9
+ * ==================================
+ *
+ * P9 uses a completely different interrupt controller, XIVE.
+ *
+ * It targets objects using a combination of block number and
+ * index within a block. However, we try to avoid exposing that
+ * split to the OS in order to keep some abstraction in case the
+ * way we allocate these change.
+ *
+ * The lowest level entity in Xive is the EST (state bit array).
+ *
+ * Those are spread between PHBs, PSI bridge and XIVE itself which
+ * provide a large amount of state bits for IPIs and other SW and HW
+ * generated interrupts by sources that don't have their own ESB logic
+ *
+ * Due to that spread, they aren't a good representation of a global
+ * interrupt number.
+ *
+ * Each such source however needs to be targetted at an EAS (IVT)
+ * entry in a table which will control targetting information and
+ * associate that interrupt with a logical number.
+ *
+ * Thus that table entry number represents a good "global interrupt
+ * number". Additionally, for the host OS, we will keep the logical
+ * number equal to the global number.
+ *
+ * The details of how these are assigned on P9 can be found in
+ * hw/xive.c. P9 HW will generally not use the definitions and
+ * functions in this file (or the corresponding core/interrupts.c).
+ */
+
 uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block);
 uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb);
 uint32_t p8_irq_to_chip(uint32_t irq);
@@ -229,6 +261,10 @@ uint32_t p8_irq_to_phb(uint32_t irq);
  * IRQ sources register themselves here. If an "interrupts" callback
  * is provided, then all interrupts in that source will appear in
  * 'opal-interrupts' and will be handled by us.
+ *
+ * The "eoi" callback is optional and can be used for interrupts
+ * requiring a special EOI at the source level. Typically will
+ * be used for XIVE interrupts coming from PHBs.
  */
 struct irq_source_ops {
 	int64_t (*set_xive)(void *data, uint32_t isn, uint16_t server,
@@ -236,6 +272,8 @@ struct irq_source_ops {
 	int64_t (*get_xive)(void *data, uint32_t isn, uint16_t *server,
 			    uint8_t *priority);
 	void (*interrupt)(void *data, uint32_t isn);
+
+	void (*eoi)(void *data, uint32_t isn);
 };
 
 extern void register_irq_source(const struct irq_source_ops *ops, void *data,
@@ -257,4 +295,7 @@ extern void icp_kick_cpu(struct cpu_thread *cpu);
 
 extern void init_interrupts(void);
 
+extern bool irq_source_eoi(uint32_t isn);
+
+
 #endif /* __INTERRUPTS_H */
-- 
2.7.4



More information about the Skiboot mailing list