diff mbox

[v2,15/23] xen/arm: receive Xen events on ARM

Message ID 1344263246-28036-15-git-send-email-stefano.stabellini@eu.citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Stefano Stabellini Aug. 6, 2012, 2:27 p.m. UTC
Compile events.c on ARM.
Parse, map and enable the IRQ to get event notifications from the device
tree (node "/xen").

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 arch/arm/include/asm/xen/events.h |   18 ++++++++++++++++++
 arch/arm/xen/enlighten.c          |   33 +++++++++++++++++++++++++++++++++
 arch/x86/xen/enlighten.c          |    1 +
 arch/x86/xen/irq.c                |    1 +
 arch/x86/xen/xen-ops.h            |    1 -
 drivers/xen/events.c              |   17 ++++++++++++++---
 include/xen/events.h              |    2 ++
 7 files changed, 69 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/include/asm/xen/events.h

Comments

Konrad Rzeszutek Wilk Aug. 7, 2012, 6:30 p.m. UTC | #1
On Mon, Aug 06, 2012 at 03:27:18PM +0100, Stefano Stabellini wrote:
> Compile events.c on ARM.
> Parse, map and enable the IRQ to get event notifications from the device
> tree (node "/xen").
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> ---
>  arch/arm/include/asm/xen/events.h |   18 ++++++++++++++++++
>  arch/arm/xen/enlighten.c          |   33 +++++++++++++++++++++++++++++++++
>  arch/x86/xen/enlighten.c          |    1 +
>  arch/x86/xen/irq.c                |    1 +
>  arch/x86/xen/xen-ops.h            |    1 -
>  drivers/xen/events.c              |   17 ++++++++++++++---
>  include/xen/events.h              |    2 ++
>  7 files changed, 69 insertions(+), 4 deletions(-)
>  create mode 100644 arch/arm/include/asm/xen/events.h
> 
> diff --git a/arch/arm/include/asm/xen/events.h b/arch/arm/include/asm/xen/events.h
> new file mode 100644
> index 0000000..94b4e90
> --- /dev/null
> +++ b/arch/arm/include/asm/xen/events.h
> @@ -0,0 +1,18 @@
> +#ifndef _ASM_ARM_XEN_EVENTS_H
> +#define _ASM_ARM_XEN_EVENTS_H
> +
> +#include <asm/ptrace.h>
> +
> +enum ipi_vector {
> +	XEN_PLACEHOLDER_VECTOR,
> +
> +	/* Xen IPIs go here */
> +	XEN_NR_IPIS,
> +};
> +
> +static inline int xen_irqs_disabled(struct pt_regs *regs)
> +{
> +	return raw_irqs_disabled_flags(regs->ARM_cpsr);
> +}
> +
> +#endif /* _ASM_ARM_XEN_EVENTS_H */
> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index e5e92d5..87b17f0 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -1,4 +1,5 @@
>  #include <xen/xen.h>
> +#include <xen/events.h>
>  #include <xen/grant_table.h>
>  #include <xen/hvm.h>
>  #include <xen/interface/xen.h>
> @@ -9,6 +10,8 @@
>  #include <xen/xenbus.h>
>  #include <asm/xen/hypervisor.h>
>  #include <asm/xen/hypercall.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqreturn.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_irq.h>
> @@ -33,6 +36,8 @@ EXPORT_SYMBOL_GPL(xen_have_vector_callback);
>  int xen_platform_pci_unplug = XEN_UNPLUG_ALL;
>  EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
>  
> +static __read_mostly int xen_events_irq = -1;
> +

So this is global..
>  int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
>  			       unsigned long addr,
>  			       unsigned long mfn, int nr,
> @@ -66,6 +71,9 @@ static int __init xen_guest_init(void)
>  	if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
>  		return 0;
>  	xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
> +	xen_events_irq = irq_of_parse_and_map(node, 0);
> +	pr_info("Xen support found, events_irq=%d gnttab_frame_pfn=%lx\n",
> +			xen_events_irq, xen_hvm_resume_frames);
>  	xen_domain_type = XEN_HVM_DOMAIN;
>  
>  	xen_setup_features();
> @@ -107,3 +115,28 @@ static int __init xen_guest_init(void)
>  	return 0;
>  }
>  core_initcall(xen_guest_init);
> +
> +static irqreturn_t xen_arm_callback(int irq, void *arg)
> +{
> +	xen_hvm_evtchn_do_upcall();
> +	return IRQ_HANDLED;
> +}
> +
> +static int __init xen_init_events(void)
> +{
> +	if (!xen_domain() || xen_events_irq < 0)
> +		return -ENODEV;
> +
> +	xen_init_IRQ();
> +
> +	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
> +			"events", xen_vcpu)) {

But here you are asking for it to be percpu? What if there are other
interrupts on the _other_ CPUs that conflict with it?
> +		pr_err("Error requesting IRQ %d\n", xen_events_irq);
> +		return -EINVAL;
> +	}
> +
> +	enable_percpu_irq(xen_events_irq, 0);

Uh, that is bold. One global to rule them all, eh? Should you make
it at least:
static DEFINE_PER_CPU(int, xen_events_irq);
?

> +
> +	return 0;
> +}
> +postcore_initcall(xen_init_events);
> diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
> index ff962d4..9f8b0ef 100644
> --- a/arch/x86/xen/enlighten.c
> +++ b/arch/x86/xen/enlighten.c
> @@ -33,6 +33,7 @@
>  #include <linux/memblock.h>
>  
>  #include <xen/xen.h>
> +#include <xen/events.h>
>  #include <xen/interface/xen.h>
>  #include <xen/interface/version.h>
>  #include <xen/interface/physdev.h>
> diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
> index 1573376..01a4dc0 100644
> --- a/arch/x86/xen/irq.c
> +++ b/arch/x86/xen/irq.c
> @@ -5,6 +5,7 @@
>  #include <xen/interface/xen.h>
>  #include <xen/interface/sched.h>
>  #include <xen/interface/vcpu.h>
> +#include <xen/events.h>
>  
>  #include <asm/xen/hypercall.h>
>  #include <asm/xen/hypervisor.h>
> diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
> index 202d4c1..2368295 100644
> --- a/arch/x86/xen/xen-ops.h
> +++ b/arch/x86/xen/xen-ops.h
> @@ -35,7 +35,6 @@ void xen_set_pat(u64);
>  
>  char * __init xen_memory_setup(void);
>  void __init xen_arch_setup(void);
> -void __init xen_init_IRQ(void);
>  void xen_enable_sysenter(void);
>  void xen_enable_syscall(void);
>  void xen_vcpu_restore(void);
> diff --git a/drivers/xen/events.c b/drivers/xen/events.c
> index 7595581..5ecb596 100644
> --- a/drivers/xen/events.c
> +++ b/drivers/xen/events.c
> @@ -31,14 +31,16 @@
>  #include <linux/irqnr.h>
>  #include <linux/pci.h>
>  
> +#ifdef CONFIG_X86
>  #include <asm/desc.h>
>  #include <asm/ptrace.h>
>  #include <asm/irq.h>
>  #include <asm/idle.h>
>  #include <asm/io_apic.h>
> -#include <asm/sync_bitops.h>
>  #include <asm/xen/page.h>
>  #include <asm/xen/pci.h>
> +#endif
> +#include <asm/sync_bitops.h>
>  #include <asm/xen/hypercall.h>
>  #include <asm/xen/hypervisor.h>
>  
> @@ -50,6 +52,9 @@
>  #include <xen/interface/event_channel.h>
>  #include <xen/interface/hvm/hvm_op.h>
>  #include <xen/interface/hvm/params.h>
> +#include <xen/interface/physdev.h>
> +#include <xen/interface/sched.h>
> +#include <asm/hw_irq.h>
>  
>  /*
>   * This lock protects updates to the following mapping and reference-count
> @@ -1374,7 +1379,9 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
>  {
>  	struct pt_regs *old_regs = set_irq_regs(regs);
>  
> +#ifdef CONFIG_X86

Please explain this with a comment.

>  	exit_idle();
> +#endif
>  	irq_enter();
>  
>  	__xen_evtchn_do_upcall();
> @@ -1783,9 +1790,9 @@ void xen_callback_vector(void)
>  void xen_callback_vector(void) {}
>  #endif
>  
> -void __init xen_init_IRQ(void)
> +void xen_init_IRQ(void)
>  {
> -	int i, rc;
> +	int i;
>  
>  	evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
>  				    GFP_KERNEL);
> @@ -1801,6 +1808,7 @@ void __init xen_init_IRQ(void)
>  
>  	pirq_needs_eoi = pirq_needs_eoi_flag;
>  
> +#ifdef CONFIG_X86
>  	if (xen_hvm_domain()) {
>  		xen_callback_vector();
>  		native_init_IRQ();
> @@ -1808,6 +1816,7 @@ void __init xen_init_IRQ(void)
>  		 * __acpi_register_gsi can point at the right function */
>  		pci_xen_hvm_init();
>  	} else {
> +		int rc;
>  		struct physdev_pirq_eoi_gmfn eoi_gmfn;
>  
>  		irq_ctx_init(smp_processor_id());
> @@ -1823,4 +1832,6 @@ void __init xen_init_IRQ(void)
>  		} else
>  			pirq_needs_eoi = pirq_check_eoi_map;
>  	}
> +#endif
>  }
> +EXPORT_SYMBOL_GPL(xen_init_IRQ);
> diff --git a/include/xen/events.h b/include/xen/events.h
> index 04399b2..c6bfe01 100644
> --- a/include/xen/events.h
> +++ b/include/xen/events.h
> @@ -109,4 +109,6 @@ int xen_irq_from_gsi(unsigned gsi);
>  /* Determine whether to ignore this IRQ if it is passed to a guest. */
>  int xen_test_irq_shared(int irq);
>  
> +/* initialize Xen IRQ subsystem */
> +void xen_init_IRQ(void);
>  #endif	/* _XEN_EVENTS_H */
> -- 
> 1.7.2.5
Stefano Stabellini Aug. 8, 2012, 6:05 p.m. UTC | #2
On Tue, 7 Aug 2012, Konrad Rzeszutek Wilk wrote:
> On Mon, Aug 06, 2012 at 03:27:18PM +0100, Stefano Stabellini wrote:
> > Compile events.c on ARM.
> > Parse, map and enable the IRQ to get event notifications from the device
> > tree (node "/xen").
> > 
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > ---
> >  arch/arm/include/asm/xen/events.h |   18 ++++++++++++++++++
> >  arch/arm/xen/enlighten.c          |   33 +++++++++++++++++++++++++++++++++
> >  arch/x86/xen/enlighten.c          |    1 +
> >  arch/x86/xen/irq.c                |    1 +
> >  arch/x86/xen/xen-ops.h            |    1 -
> >  drivers/xen/events.c              |   17 ++++++++++++++---
> >  include/xen/events.h              |    2 ++
> >  7 files changed, 69 insertions(+), 4 deletions(-)
> >  create mode 100644 arch/arm/include/asm/xen/events.h
> > 
> > diff --git a/arch/arm/include/asm/xen/events.h b/arch/arm/include/asm/xen/events.h
> > new file mode 100644
> > index 0000000..94b4e90
> > --- /dev/null
> > +++ b/arch/arm/include/asm/xen/events.h
> > @@ -0,0 +1,18 @@
> > +#ifndef _ASM_ARM_XEN_EVENTS_H
> > +#define _ASM_ARM_XEN_EVENTS_H
> > +
> > +#include <asm/ptrace.h>
> > +
> > +enum ipi_vector {
> > +	XEN_PLACEHOLDER_VECTOR,
> > +
> > +	/* Xen IPIs go here */
> > +	XEN_NR_IPIS,
> > +};
> > +
> > +static inline int xen_irqs_disabled(struct pt_regs *regs)
> > +{
> > +	return raw_irqs_disabled_flags(regs->ARM_cpsr);
> > +}
> > +
> > +#endif /* _ASM_ARM_XEN_EVENTS_H */
> > diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> > index e5e92d5..87b17f0 100644
> > --- a/arch/arm/xen/enlighten.c
> > +++ b/arch/arm/xen/enlighten.c
> > @@ -1,4 +1,5 @@
> >  #include <xen/xen.h>
> > +#include <xen/events.h>
> >  #include <xen/grant_table.h>
> >  #include <xen/hvm.h>
> >  #include <xen/interface/xen.h>
> > @@ -9,6 +10,8 @@
> >  #include <xen/xenbus.h>
> >  #include <asm/xen/hypervisor.h>
> >  #include <asm/xen/hypercall.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irqreturn.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/of_irq.h>
> > @@ -33,6 +36,8 @@ EXPORT_SYMBOL_GPL(xen_have_vector_callback);
> >  int xen_platform_pci_unplug = XEN_UNPLUG_ALL;
> >  EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
> >  
> > +static __read_mostly int xen_events_irq = -1;
> > +
> 
> So this is global..
> >  int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
> >  			       unsigned long addr,
> >  			       unsigned long mfn, int nr,
> > @@ -66,6 +71,9 @@ static int __init xen_guest_init(void)
> >  	if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
> >  		return 0;
> >  	xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
> > +	xen_events_irq = irq_of_parse_and_map(node, 0);
> > +	pr_info("Xen support found, events_irq=%d gnttab_frame_pfn=%lx\n",
> > +			xen_events_irq, xen_hvm_resume_frames);
> >  	xen_domain_type = XEN_HVM_DOMAIN;
> >  
> >  	xen_setup_features();
> > @@ -107,3 +115,28 @@ static int __init xen_guest_init(void)
> >  	return 0;
> >  }
> >  core_initcall(xen_guest_init);
> > +
> > +static irqreturn_t xen_arm_callback(int irq, void *arg)
> > +{
> > +	xen_hvm_evtchn_do_upcall();
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int __init xen_init_events(void)
> > +{
> > +	if (!xen_domain() || xen_events_irq < 0)
> > +		return -ENODEV;
> > +
> > +	xen_init_IRQ();
> > +
> > +	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
> > +			"events", xen_vcpu)) {
> 
> But here you are asking for it to be percpu? What if there are other
> interrupts on the _other_ CPUs that conflict with it?
> > +		pr_err("Error requesting IRQ %d\n", xen_events_irq);
> > +		return -EINVAL;
> > +	}
> > +
> > +	enable_percpu_irq(xen_events_irq, 0);
> 
> Uh, that is bold. One global to rule them all, eh? Should you make
> it at least:
> static DEFINE_PER_CPU(int, xen_events_irq);
> ?

That is an interesting observation.

Currently Xen is using a per-cpu interrupt (a PPI, using the GIC
terminology), and it makes sense so that we can receive event
notifications on multiple vcpus independently.
The irq range 16-31 is reserved for PPIs and I am assuming that Xen will
be able to find one spare, the same one, for all vcpus.
In fact the third field corresponding to the interrupt in the DT (0xf08
in my dts) contains the cpu mask and it is set to 0xf (the maximum)
right now.

Maybe I should just BUG_ON(xen_events_irq > 31 || xen_events_irq < 16)?

The versioning of the hypervisor node on the DT is going to help us make
any changes to the interface in the future.
diff mbox

Patch

diff --git a/arch/arm/include/asm/xen/events.h b/arch/arm/include/asm/xen/events.h
new file mode 100644
index 0000000..94b4e90
--- /dev/null
+++ b/arch/arm/include/asm/xen/events.h
@@ -0,0 +1,18 @@ 
+#ifndef _ASM_ARM_XEN_EVENTS_H
+#define _ASM_ARM_XEN_EVENTS_H
+
+#include <asm/ptrace.h>
+
+enum ipi_vector {
+	XEN_PLACEHOLDER_VECTOR,
+
+	/* Xen IPIs go here */
+	XEN_NR_IPIS,
+};
+
+static inline int xen_irqs_disabled(struct pt_regs *regs)
+{
+	return raw_irqs_disabled_flags(regs->ARM_cpsr);
+}
+
+#endif /* _ASM_ARM_XEN_EVENTS_H */
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index e5e92d5..87b17f0 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -1,4 +1,5 @@ 
 #include <xen/xen.h>
+#include <xen/events.h>
 #include <xen/grant_table.h>
 #include <xen/hvm.h>
 #include <xen/interface/xen.h>
@@ -9,6 +10,8 @@ 
 #include <xen/xenbus.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -33,6 +36,8 @@  EXPORT_SYMBOL_GPL(xen_have_vector_callback);
 int xen_platform_pci_unplug = XEN_UNPLUG_ALL;
 EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
 
+static __read_mostly int xen_events_irq = -1;
+
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 			       unsigned long addr,
 			       unsigned long mfn, int nr,
@@ -66,6 +71,9 @@  static int __init xen_guest_init(void)
 	if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
 		return 0;
 	xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
+	xen_events_irq = irq_of_parse_and_map(node, 0);
+	pr_info("Xen support found, events_irq=%d gnttab_frame_pfn=%lx\n",
+			xen_events_irq, xen_hvm_resume_frames);
 	xen_domain_type = XEN_HVM_DOMAIN;
 
 	xen_setup_features();
@@ -107,3 +115,28 @@  static int __init xen_guest_init(void)
 	return 0;
 }
 core_initcall(xen_guest_init);
+
+static irqreturn_t xen_arm_callback(int irq, void *arg)
+{
+	xen_hvm_evtchn_do_upcall();
+	return IRQ_HANDLED;
+}
+
+static int __init xen_init_events(void)
+{
+	if (!xen_domain() || xen_events_irq < 0)
+		return -ENODEV;
+
+	xen_init_IRQ();
+
+	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
+			"events", xen_vcpu)) {
+		pr_err("Error requesting IRQ %d\n", xen_events_irq);
+		return -EINVAL;
+	}
+
+	enable_percpu_irq(xen_events_irq, 0);
+
+	return 0;
+}
+postcore_initcall(xen_init_events);
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index ff962d4..9f8b0ef 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -33,6 +33,7 @@ 
 #include <linux/memblock.h>
 
 #include <xen/xen.h>
+#include <xen/events.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>
 #include <xen/interface/physdev.h>
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 1573376..01a4dc0 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -5,6 +5,7 @@ 
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/vcpu.h>
+#include <xen/events.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 202d4c1..2368295 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -35,7 +35,6 @@  void xen_set_pat(u64);
 
 char * __init xen_memory_setup(void);
 void __init xen_arch_setup(void);
-void __init xen_init_IRQ(void);
 void xen_enable_sysenter(void);
 void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 7595581..5ecb596 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -31,14 +31,16 @@ 
 #include <linux/irqnr.h>
 #include <linux/pci.h>
 
+#ifdef CONFIG_X86
 #include <asm/desc.h>
 #include <asm/ptrace.h>
 #include <asm/irq.h>
 #include <asm/idle.h>
 #include <asm/io_apic.h>
-#include <asm/sync_bitops.h>
 #include <asm/xen/page.h>
 #include <asm/xen/pci.h>
+#endif
+#include <asm/sync_bitops.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
 
@@ -50,6 +52,9 @@ 
 #include <xen/interface/event_channel.h>
 #include <xen/interface/hvm/hvm_op.h>
 #include <xen/interface/hvm/params.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/sched.h>
+#include <asm/hw_irq.h>
 
 /*
  * This lock protects updates to the following mapping and reference-count
@@ -1374,7 +1379,9 @@  void xen_evtchn_do_upcall(struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
+#ifdef CONFIG_X86
 	exit_idle();
+#endif
 	irq_enter();
 
 	__xen_evtchn_do_upcall();
@@ -1783,9 +1790,9 @@  void xen_callback_vector(void)
 void xen_callback_vector(void) {}
 #endif
 
-void __init xen_init_IRQ(void)
+void xen_init_IRQ(void)
 {
-	int i, rc;
+	int i;
 
 	evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
 				    GFP_KERNEL);
@@ -1801,6 +1808,7 @@  void __init xen_init_IRQ(void)
 
 	pirq_needs_eoi = pirq_needs_eoi_flag;
 
+#ifdef CONFIG_X86
 	if (xen_hvm_domain()) {
 		xen_callback_vector();
 		native_init_IRQ();
@@ -1808,6 +1816,7 @@  void __init xen_init_IRQ(void)
 		 * __acpi_register_gsi can point at the right function */
 		pci_xen_hvm_init();
 	} else {
+		int rc;
 		struct physdev_pirq_eoi_gmfn eoi_gmfn;
 
 		irq_ctx_init(smp_processor_id());
@@ -1823,4 +1832,6 @@  void __init xen_init_IRQ(void)
 		} else
 			pirq_needs_eoi = pirq_check_eoi_map;
 	}
+#endif
 }
+EXPORT_SYMBOL_GPL(xen_init_IRQ);
diff --git a/include/xen/events.h b/include/xen/events.h
index 04399b2..c6bfe01 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -109,4 +109,6 @@  int xen_irq_from_gsi(unsigned gsi);
 /* Determine whether to ignore this IRQ if it is passed to a guest. */
 int xen_test_irq_shared(int irq);
 
+/* initialize Xen IRQ subsystem */
+void xen_init_IRQ(void);
 #endif	/* _XEN_EVENTS_H */