diff --git a/core/interrupts.c b/core/interrupts.c
index 7109fae..f93ce7b 100644
--- a/core/interrupts.c
+++ b/core/interrupts.c
@@ -31,32 +31,15 @@
 #define ICP_CPPR		0x4	/* 8-bit access */
 #define ICP_MFRR		0xc	/* 8-bit access */
 
-struct irq_source {
-	uint32_t			start;
-	uint32_t			end;
-	const struct irq_source_ops	*ops;
-	void				*data;
-	struct list_node		link;
-};
-
 static LIST_HEAD(irq_sources);
 static struct lock irq_lock = LOCK_UNLOCKED;
 
-void register_irq_source(const struct irq_source_ops *ops, void *data,
-			 uint32_t start, uint32_t count)
+void __register_irq_source(struct irq_source *is)
 {
-	struct irq_source *is, *is1;
-
-	is = zalloc(sizeof(struct irq_source));
-	assert(is);
-	is->start = start;
-	is->end = start + count;
-	is->ops = ops;
-	is->data = data;
+	struct irq_source *is1;
 
-	prlog(PR_DEBUG, "IRQ: Registering %04x..%04x ops @%p (data %p) %s\n",
-	      start, start + count - 1, ops, data,
-	      ops->interrupt ? "[Internal]" : "[OS]");
+	prlog(PR_DEBUG, "IRQ: Registering %04x..%04x ops @%p (data %p)\n",
+	      is->start, is->end - 1, is->ops, is->data);
 
 	lock(&irq_lock);
 	list_for_each(&irq_sources, is1, link) {
@@ -72,6 +55,21 @@ void register_irq_source(const struct irq_source_ops *ops, void *data,
 	unlock(&irq_lock);
 }
 
+void register_irq_source(const struct irq_source_ops *ops, void *data,
+			 uint32_t start, uint32_t count)
+{
+	struct irq_source *is;
+
+	is = zalloc(sizeof(struct irq_source));
+	assert(is);
+	is->start = start;
+	is->end = start + count;
+	is->ops = ops;
+	is->data = data;
+
+	__register_irq_source(is);
+}
+
 void unregister_irq_source(uint32_t start, uint32_t count)
 {
 	struct irq_source *is;
@@ -99,6 +97,46 @@ void unregister_irq_source(uint32_t start, uint32_t count)
 	assert(0);
 }
 
+static struct irq_source *irq_find_source(uint32_t isn)
+{
+	struct irq_source *is;
+
+	lock(&irq_lock);
+	list_for_each(&irq_sources, is, link) {
+		if (isn >= is->start && isn < is->end) {
+			unlock(&irq_lock);
+			return is;
+		}
+	}
+	unlock(&irq_lock);
+
+	return NULL;
+}
+
+void adjust_irq_source(struct irq_source *is, uint32_t new_count)
+{
+	struct irq_source *is1;
+	uint32_t new_end = is->start + new_count;
+
+	prlog(PR_DEBUG, "IRQ: Adjusting %04x..%04x to %04x..%04x\n",
+	      is->start, is->end - 1, is->start, new_end - 1);
+
+	lock(&irq_lock);
+	list_for_each(&irq_sources, is1, link) {
+		if (is1 == is)
+			continue;
+		if (new_end > is1->start && is->start < is1->end) {
+			prerror("adjust IRQ source overlap !\n");
+			prerror("  new: %x..%x old: %x..%x\n",
+				is->start, new_end - 1,
+				is1->start, is1->end - 1);
+			assert(0);
+		}
+	}
+	is->end = new_end;
+	unlock(&irq_lock);
+}
+
 /*
  * This takes a 6-bit chip id and returns a 20 bit value representing
  * the PSI interrupt. This includes all the fields above, ie, is a
@@ -341,22 +379,6 @@ uint32_t p8_irq_to_phb(uint32_t irq)
 	return p8_irq_to_block(irq) - P8_IRQ_BLOCK_PHB_BASE;
 }
 
-static struct irq_source *irq_find_source(uint32_t isn)
-{
-	struct irq_source *is;
-
-	lock(&irq_lock);
-	list_for_each(&irq_sources, is, link) {
-		if (isn >= is->start && isn < is->end) {
-			unlock(&irq_lock);
-			return is;
-		}
-	}
-	unlock(&irq_lock);
-
-	return NULL;
-}
-
 bool irq_source_eoi(uint32_t isn)
 {
 	struct irq_source *is = irq_find_source(isn);
@@ -364,7 +386,7 @@ bool irq_source_eoi(uint32_t isn)
 	if (!is || !is->ops->eoi)
 		return false;
 
-	is->ops->eoi(is->data, isn);
+	is->ops->eoi(is, isn);
 	return true;
 }
 
@@ -375,7 +397,7 @@ static int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority)
 	if (!is || !is->ops->set_xive)
 		return OPAL_PARAMETER;
 
-	return is->ops->set_xive(is->data, isn, server, priority);
+	return is->ops->set_xive(is, isn, server, priority);
 }
 opal_call(OPAL_SET_XIVE, opal_set_xive, 3);
 
@@ -386,7 +408,7 @@ static int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority)
 	if (!is || !is->ops->get_xive)
 		return OPAL_PARAMETER;
 
-	return is->ops->get_xive(is->data, isn, server, priority);
+	return is->ops->get_xive(is, isn, server, priority);
 }
 opal_call(OPAL_GET_XIVE, opal_get_xive, 3);
 
@@ -402,7 +424,7 @@ static int64_t opal_handle_interrupt(uint32_t isn, __be64 *outstanding_event_mas
 	}
 
 	/* Run it */
-	is->ops->interrupt(is->data, isn);
+	is->ops->interrupt(is, isn);
 
 	/* Check timers if SLW timer isn't working */
 	if (!slw_timer_ok())
@@ -440,3 +462,4 @@ void init_interrupts(void)
 	}
 }
 
+
diff --git a/hw/npu.c b/hw/npu.c
index 34b4f26..7944f9a 100644
--- a/hw/npu.c
+++ b/hw/npu.c
@@ -700,12 +700,10 @@ static int npu_isn_valid(struct npu *p, uint32_t isn)
 	return true;
 }
 
-static int64_t npu_lsi_get_xive(void *data,
-				    uint32_t isn,
-				    uint16_t *server,
-				    uint8_t *prio)
+static int64_t npu_lsi_get_xive(struct irq_source *is, uint32_t isn,
+				uint16_t *server, uint8_t *prio)
 {
-	struct npu *p = data;
+	struct npu *p = is->data;
 	uint32_t irq = NPU_IRQ_NUM(isn);
 	uint64_t lxive;
 
@@ -724,12 +722,10 @@ static int64_t npu_lsi_get_xive(void *data,
 	return OPAL_SUCCESS;
 }
 
-static int64_t npu_lsi_set_xive(void *data,
-				    uint32_t isn,
-				    uint16_t server,
-				    uint8_t prio)
+static int64_t npu_lsi_set_xive(struct irq_source *is, uint32_t isn,
+				uint16_t server, uint8_t prio)
 {
-	struct npu *p = data;
+	struct npu *p = is->data;
 	uint32_t irq = NPU_IRQ_NUM(isn);
 	uint64_t lxive;
 
@@ -754,9 +750,9 @@ static int64_t npu_lsi_set_xive(void *data,
 	return OPAL_SUCCESS;
 }
 
-static void npu_err_interrupt(void *data, uint32_t isn)
+static void npu_err_interrupt(struct irq_source *is, uint32_t isn)
 {
-	struct npu *p = data;
+	struct npu *p = is->data;
 	uint32_t irq = NPU_IRQ_NUM(isn);
 
 	if (!npu_isn_valid(p, isn))
@@ -1898,3 +1894,4 @@ void probe_npu(void)
 	dt_for_each_compatible(dt_root, np, "ibm,power8-npu-pciex")
 		npu_create_phb(np);
 }
+
diff --git a/hw/p7ioc-phb.c b/hw/p7ioc-phb.c
index 6f5a6ab..52ff952 100644
--- a/hw/p7ioc-phb.c
+++ b/hw/p7ioc-phb.c
@@ -2362,10 +2362,10 @@ static const struct phb_ops p7ioc_phb_ops = {
 };
 
 /* p7ioc_phb_get_xive - Interrupt control from OPAL */
-static int64_t p7ioc_msi_get_xive(void *data, uint32_t isn,
+static int64_t p7ioc_msi_get_xive(struct irq_source *is, uint32_t isn,
 				  uint16_t *server, uint8_t *prio)
 {
-	struct p7ioc_phb *p = data;
+	struct p7ioc_phb *p = is->data;
 	uint32_t irq, fbuid = P7_IRQ_FBUID(isn);
 	uint64_t xive;
 
@@ -2382,10 +2382,10 @@ static int64_t p7ioc_msi_get_xive(void *data, uint32_t isn,
 }
 
 /* p7ioc_phb_set_xive - Interrupt control from OPAL */
-static int64_t p7ioc_msi_set_xive(void *data, uint32_t isn,
+static int64_t p7ioc_msi_set_xive(struct irq_source *is, uint32_t isn,
 				  uint16_t server, uint8_t prio)
 {
-	struct p7ioc_phb *p = data;
+	struct p7ioc_phb *p = is->data;
 	uint32_t irq, fbuid = P7_IRQ_FBUID(isn);
 	uint64_t xive, m_server, m_prio;
 
@@ -2422,10 +2422,10 @@ static int64_t p7ioc_msi_set_xive(void *data, uint32_t isn,
 }
 
 /* p7ioc_phb_get_xive - Interrupt control from OPAL */
-static int64_t p7ioc_lsi_get_xive(void *data, uint32_t isn,
+static int64_t p7ioc_lsi_get_xive(struct irq_source *is, uint32_t isn,
 				  uint16_t *server, uint8_t *prio)
 {
-	struct p7ioc_phb *p = data;
+	struct p7ioc_phb *p = is->data;
 	uint32_t irq = (isn & 0x7);
 	uint32_t fbuid = P7_IRQ_FBUID(isn);
 	uint64_t xive;
@@ -2441,10 +2441,10 @@ static int64_t p7ioc_lsi_get_xive(void *data, uint32_t isn,
 }
 
 /* p7ioc_phb_set_xive - Interrupt control from OPAL */
-static int64_t p7ioc_lsi_set_xive(void *data, uint32_t isn,
+static int64_t p7ioc_lsi_set_xive(struct irq_source *is, uint32_t isn,
 				  uint16_t server, uint8_t prio)
 {
-	struct p7ioc_phb *p = data;
+	struct p7ioc_phb *p = is->data;
 	uint32_t irq = (isn & 0x7);
 	uint32_t fbuid = P7_IRQ_FBUID(isn);
 	uint64_t xive, m_server, m_prio;
@@ -2481,9 +2481,9 @@ static int64_t p7ioc_lsi_set_xive(void *data, uint32_t isn,
 	return OPAL_SUCCESS;
 }
 
-static void p7ioc_phb_err_interrupt(void *data, uint32_t isn)
+static void p7ioc_phb_err_interrupt(struct irq_source *is, uint32_t isn)
 {
-	struct p7ioc_phb *p = data;
+	struct p7ioc_phb *p = is->data;
 	uint64_t peev0, peev1;
 
 	PHBDBG(p, "Got interrupt 0x%04x\n", isn);
@@ -3264,3 +3264,4 @@ void p7ioc_phb_reset(struct phb *phb)
 	out_be64(ioc->regs + P7IOC_CIn_LEM_ERR_MASK_AND(ci_idx), 0);
 }
 
+
diff --git a/hw/p7ioc.c b/hw/p7ioc.c
index 85a0a51..db758bb 100644
--- a/hw/p7ioc.c
+++ b/hw/p7ioc.c
@@ -190,10 +190,10 @@ static const struct io_hub_ops p7ioc_hub_ops = {
 	.reset		= p7ioc_reset,
 };
 
-static int64_t p7ioc_rgc_get_xive(void *data, uint32_t isn,
+static int64_t p7ioc_rgc_get_xive(struct irq_source *is, uint32_t isn,
 				  uint16_t *server, uint8_t *prio)
 {
-	struct p7ioc *ioc = data;
+	struct p7ioc *ioc = is->data;
 	uint32_t irq = (isn & 0xf);
 	uint32_t fbuid = P7_IRQ_FBUID(isn);
 	uint64_t xive;
@@ -208,10 +208,10 @@ static int64_t p7ioc_rgc_get_xive(void *data, uint32_t isn,
 	return OPAL_SUCCESS;
  }
 
-static int64_t p7ioc_rgc_set_xive(void *data, uint32_t isn,
+static int64_t p7ioc_rgc_set_xive(struct irq_source *is, uint32_t isn,
 				  uint16_t server, uint8_t prio)
 {
-	struct p7ioc *ioc = data;
+	struct p7ioc *ioc = is->data;
 	uint32_t irq = (isn & 0xf);
 	uint32_t fbuid = P7_IRQ_FBUID(isn);
 	uint64_t xive;
@@ -566,9 +566,9 @@ static bool p7ioc_check_GEM(struct p7ioc *ioc)
 	return false;
 }
 
-static void p7ioc_rgc_interrupt(void *data, uint32_t isn)
+static void p7ioc_rgc_interrupt(struct irq_source *is, uint32_t isn)
 {
-	struct p7ioc *ioc = data;
+	struct p7ioc *ioc = is->data;
 
 	printf("Got RGC interrupt 0x%04x\n", isn);
 
@@ -678,3 +678,4 @@ void probe_p7ioc(void)
 		p7ioc_create_hub(np);
 }
 
+
diff --git a/hw/phb3.c b/hw/phb3.c
index 8e4c544..4d0b683 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -1602,12 +1602,10 @@ static void phb3_read_phb_status(struct phb3 *p,
 	}
 }
 
-static int64_t phb3_msi_get_xive(void *data,
-				 uint32_t isn,
-				 uint16_t *server,
-				 uint8_t *prio)
+static int64_t phb3_msi_get_xive(struct irq_source *is, uint32_t isn,
+				 uint16_t *server, uint8_t *prio)
 {
-	struct phb3 *p = data;
+	struct phb3 *p = is->data;
 	uint32_t chip, index, irq;
 	uint64_t ive;
 
@@ -1631,12 +1629,10 @@ static int64_t phb3_msi_get_xive(void *data,
 	return OPAL_SUCCESS;
 }
 
-static int64_t phb3_msi_set_xive(void *data,
-				 uint32_t isn,
-				 uint16_t server,
-				 uint8_t prio)
+static int64_t phb3_msi_set_xive(struct irq_source *is, uint32_t isn,
+				 uint16_t server, uint8_t prio)
 {
-	struct phb3 *p = data;
+	struct phb3 *p = is->data;
 	uint32_t chip, index;
 	uint64_t *cache, ive_num, data64, m_server, m_prio, ivc;
 	uint32_t *ive;
@@ -1716,12 +1712,10 @@ static int64_t phb3_msi_set_xive(void *data,
 	return OPAL_SUCCESS;
 }
 
-static int64_t phb3_lsi_get_xive(void *data,
-				 uint32_t isn,
-				 uint16_t *server,
-				 uint8_t *prio)
+static int64_t phb3_lsi_get_xive(struct irq_source *is, uint32_t isn,
+				 uint16_t *server, uint8_t *prio)
 {
-	struct phb3 *p = data;
+	struct phb3 *p = is->data;
 	uint32_t chip, index, irq;
 	uint64_t lxive;
 
@@ -1742,12 +1736,10 @@ static int64_t phb3_lsi_get_xive(void *data,
 	return OPAL_SUCCESS;
 }
 
-static int64_t phb3_lsi_set_xive(void *data,
-				 uint32_t isn,
-				 uint16_t server,
-				 uint8_t prio)
+static int64_t phb3_lsi_set_xive(struct irq_source *is, uint32_t isn,
+				 uint16_t server, uint8_t prio)
 {
-	struct phb3 *p = data;
+	struct phb3 *p = is->data;
 	uint32_t chip, index, irq, entry;
 	uint64_t lxive;
 
@@ -1785,9 +1777,9 @@ static int64_t phb3_lsi_set_xive(void *data,
 	return OPAL_SUCCESS;
 }
 
-static void phb3_err_interrupt(void *data, uint32_t isn)
+static void phb3_err_interrupt(struct irq_source *is, uint32_t isn)
 {
-	struct phb3 *p = data;
+	struct phb3 *p = is->data;
 
 	PHBDBG(p, "Got interrupt 0x%08x\n", isn);
 
@@ -4733,3 +4725,4 @@ void probe_phb3(void)
 	dt_for_each_compatible(dt_root, np, "ibm,power8-pciex")
 		phb3_create(np);
 }
+
diff --git a/hw/phb4.c b/hw/phb4.c
index cf5742b..e0fb266 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -2991,7 +2991,7 @@ static bool phb4_calculate_windows(struct phb4 *p)
 }
 
 
-static int64_t phb4_get_xive(void *data __unused, uint32_t isn,
+static int64_t phb4_get_xive(struct irq_source *is __unused, uint32_t isn,
 			     uint16_t *server, uint8_t *prio)
 {
 	uint32_t target_id;
@@ -3003,10 +3003,10 @@ static int64_t phb4_get_xive(void *data __unused, uint32_t isn,
 		return OPAL_PARAMETER;
 }
 
-static int64_t phb4_set_xive(void *data, uint32_t isn,
+static int64_t phb4_set_xive(struct irq_source *is, uint32_t isn,
 			     uint16_t server, uint8_t prio)
 {
-	struct phb4 *p = data;
+	struct phb4 *p = is->data;
 	uint32_t idx = isn - p->base_msi;
 	void *mmio_base;
 
@@ -3027,9 +3027,9 @@ static int64_t phb4_set_xive(void *data, uint32_t isn,
 	return OPAL_SUCCESS;
 }
 
-static void phb4_eoi(void *data, uint32_t isn)
+static void phb4_eoi(struct irq_source *is, uint32_t isn)
 {
-	struct phb4 *p = data;
+	struct phb4 *p = is->data;
 	uint32_t idx = isn - p->base_msi;
 	void *mmio_base;
 	uint8_t eoi_val;
diff --git a/hw/psi.c b/hw/psi.c
index 0823ec8..b02863e 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -343,9 +343,9 @@ bool psi_poll_fsp_interrupt(struct psi *psi)
 	return !!(in_be64(psi->regs + PSIHB_CR) & PSIHB_CR_FSP_IRQ);
 }
 
-static void psi_interrupt(void *data, uint32_t isn __unused)
+static void psi_interrupt(struct irq_source *is, uint32_t isn __unused)
 {
-	struct psi *psi = data;
+	struct psi *psi = is->data;
 	u64 val;
 
 	val = in_be64(psi->regs + PSIHB_CR);
@@ -395,10 +395,10 @@ static void psi_interrupt(void *data, uint32_t isn __unused)
 	fsp_console_poll(NULL);
 }
 
-static int64_t psi_p7_set_xive(void *data, uint32_t isn __unused,
-				   uint16_t server, uint8_t priority)
+static int64_t psi_p7_set_xive(struct irq_source *is, uint32_t isn __unused,
+			       uint16_t server, uint8_t priority)
 {
-	struct psi *psi = data;
+	struct psi *psi = is->data;
 	uint64_t xivr;
 
 	if (!psi->working)
@@ -414,10 +414,10 @@ static int64_t psi_p7_set_xive(void *data, uint32_t isn __unused,
 	return OPAL_SUCCESS;
 }
 
-static int64_t psi_p7_get_xive(void *data, uint32_t isn __unused,
-				uint16_t *server, uint8_t *priority)
+static int64_t psi_p7_get_xive(struct irq_source *is, uint32_t isn __unused,
+			       uint16_t *server, uint8_t *priority)
 {
-	struct psi *psi = data;
+	struct psi *psi = is->data;
 	uint64_t xivr;
 
 	if (!psi->working)
@@ -432,10 +432,10 @@ static int64_t psi_p7_get_xive(void *data, uint32_t isn __unused,
 	return OPAL_SUCCESS;
 }
 
-static int64_t psi_p8_set_xive(void *data, uint32_t isn,
-				   uint16_t server, uint8_t priority)
+static int64_t psi_p8_set_xive(struct irq_source *is, uint32_t isn,
+			       uint16_t server, uint8_t priority)
 {
-	struct psi *psi = data;
+	struct psi *psi = is->data;
 	uint64_t xivr_p, xivr;
 
 	switch(isn & 7) {
@@ -471,10 +471,10 @@ static int64_t psi_p8_set_xive(void *data, uint32_t isn,
 	return OPAL_SUCCESS;
 }
 
-static int64_t psi_p8_get_xive(void *data, uint32_t isn __unused,
-				   uint16_t *server, uint8_t *priority)
+static int64_t psi_p8_get_xive(struct irq_source *is, uint32_t isn __unused,
+			       uint16_t *server, uint8_t *priority)
 {
-	struct psi *psi = data;
+	struct psi *psi = is->data;
 	uint64_t xivr_p, xivr;
 
 	switch(isn & 7) {
@@ -919,3 +919,4 @@ void psi_init(void)
 	dt_for_each_compatible(dt_root, np, "ibm,psihb-x")
 		psi_init_psihb(np);
 }
+
diff --git a/include/interrupts.h b/include/interrupts.h
index 0380c59..9926d72 100644
--- a/include/interrupts.h
+++ b/include/interrupts.h
@@ -256,6 +256,8 @@ uint32_t p8_irq_to_phb(uint32_t irq);
  * functions in this file (or the corresponding core/interrupts.c).
  */
 
+struct irq_source;
+
 /*
  * IRQ sources register themselves here. If an "interrupts" callback
  * is provided, then all interrupts in that source will appear in
@@ -266,18 +268,27 @@ uint32_t p8_irq_to_phb(uint32_t irq);
  * be used for XIVE interrupts coming from PHBs.
  */
 struct irq_source_ops {
-	int64_t (*set_xive)(void *data, uint32_t isn, uint16_t server,
-			    uint8_t priority);
-	int64_t (*get_xive)(void *data, uint32_t isn, uint16_t *server,
-			    uint8_t *priority);
-	void (*interrupt)(void *data, uint32_t isn);
+	int64_t (*set_xive)(struct irq_source *is, uint32_t isn,
+			    uint16_t server, uint8_t priority);
+	int64_t (*get_xive)(struct irq_source *is, uint32_t isn,
+			    uint16_t *server, uint8_t *priority);
+	void (*interrupt)(struct irq_source *is, uint32_t isn);
+	void (*eoi)(struct irq_source *is, uint32_t isn);
+};
 
-	void (*eoi)(void *data, uint32_t isn);
+struct irq_source {
+	uint32_t			start;
+	uint32_t			end;
+	const struct irq_source_ops	*ops;
+	void				*data;
+	struct list_node		link;
 };
 
+extern void __register_irq_source(struct irq_source *is);
 extern void register_irq_source(const struct irq_source_ops *ops, void *data,
 				uint32_t start, uint32_t count);
 extern void unregister_irq_source(uint32_t start, uint32_t count);
+extern void adjust_irq_source(struct irq_source *is, uint32_t new_count);
 
 extern uint32_t get_psi_interrupt(uint32_t chip_id);
 
@@ -299,3 +310,4 @@ extern bool irq_source_eoi(uint32_t isn);
 
 #endif /* __INTERRUPTS_H */
 
+
