All of lore.kernel.org
 help / color / mirror / Atom feed
* Xen spinlock questions
@ 2008-08-04 10:18 Jan Beulich
  2008-08-04 10:24 ` Keir Fraser
  2008-08-04 19:36 ` Jeremy Fitzhardinge
  0 siblings, 2 replies; 29+ messages in thread
From: Jan Beulich @ 2008-08-04 10:18 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 1348 bytes --]

Jeremy,

considering to utilize your pv-ops spinlock implementation for our kernels,
I'd appreciate your opinion on the following thoughts:

1) While the goal of the per-CPU kicker irq appears to be to avoid all CPUs
waiting for a particular lock to get kicked simultaneously, I think this
doesn't have the desired effect. This is because Xen doesn't track what
event channel you poll for (through SCHEDOP_poll), and rather kicks all CPUs
polling for any event channel.

2) While on native not re-enabling interrupts in __raw_spin_lock_flags()
may be tolerable (but perhaps questionable), not doing so at least on
the slow path here seems suspicious.

3) Introducing yet another per-CPU IRQ for this purpose further
tightens scalability. Using a single, IRQF_PER_CPU IRQ should be
sufficient here, as long as it gets properly multiplexed onto individual
event channels (of which we have far more than IRQs). I have a patch
queued for the traditional tree that does just that conversion for the
reschedule and call-function IPIs, which I had long planned to get
submitted (but so far wasn't able to due to lack of testing done on the
migration aspects of it), and once successful was planning on trying to
do something similar for the timer IRQ. I am attaching that (2.6.26 based)
patch just for reference.

Thanks, Jan


[-- Attachment #2: xen-ipi-per-cpu-irq.patch --]
[-- Type: text/plain, Size: 17002 bytes --]

From: jbeulich@novell.com
Subject: fold IPIs onto a single IRQ each
Patch-mainline: obsolete

If this is reasonable, a similar change should be done for per-CPU VIRQs.

Index: head-2008-07-21/arch/x86/kernel/genapic_xen_64.c
===================================================================
--- head-2008-07-21.orig/arch/x86/kernel/genapic_xen_64.c	2008-07-15 14:50:28.000000000 +0200
+++ head-2008-07-21/arch/x86/kernel/genapic_xen_64.c	2008-07-22 08:25:52.000000000 +0200
@@ -24,13 +24,9 @@
 #include <asm/genapic.h>
 #include <xen/evtchn.h>
 
-DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
-
 static inline void __send_IPI_one(unsigned int cpu, int vector)
 {
-	int irq = per_cpu(ipi_to_irq, cpu)[vector];
-	BUG_ON(irq < 0);
-	notify_remote_via_irq(irq);
+	notify_remote_via_ipi(vector, cpu);
 }
 
 void xen_send_IPI_shortcut(unsigned int shortcut, int vector)
Index: head-2008-07-21/arch/x86/kernel/ipi-xen.c
===================================================================
--- head-2008-07-21.orig/arch/x86/kernel/ipi-xen.c	2008-07-21 17:42:48.000000000 +0200
+++ head-2008-07-21/arch/x86/kernel/ipi-xen.c	2008-07-22 08:25:52.000000000 +0200
@@ -49,15 +49,6 @@ static inline int __prepare_ICR2(unsigne
 }
 #else
 #include <xen/evtchn.h>
-
-DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
-
-static inline void __send_IPI_one(unsigned int cpu, int vector)
-{
-	int irq = per_cpu(ipi_to_irq, cpu)[vector];
-	BUG_ON(irq < 0);
-	notify_remote_via_irq(irq);
-}
 #endif
 
 void __send_IPI_shortcut(unsigned int shortcut, int vector)
@@ -91,14 +82,14 @@ void __send_IPI_shortcut(unsigned int sh
 
 	switch (shortcut) {
 	case APIC_DEST_SELF:
-		__send_IPI_one(smp_processor_id(), vector);
+		notify_remote_via_ipi(vector, smp_processor_id());
 		break;
 	case APIC_DEST_ALLBUT:
 		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
 			if (cpu == smp_processor_id())
 				continue;
 			if (cpu_isset(cpu, cpu_online_map)) {
-				__send_IPI_one(cpu, vector);
+				notify_remote_via_ipi(vector, cpu);
 			}
 		}
 		break;
@@ -168,7 +159,7 @@ void send_IPI_mask_bitmask(cpumask_t cpu
 #else
 	for (cpu = 0; cpu < NR_CPUS; ++cpu)
 		if (cpu_isset(cpu, cpumask))
-			__send_IPI_one(cpu, vector);
+			notify_remote_via_ipi(vector, cpu);
 #endif
 	local_irq_restore(flags);
 }
Index: head-2008-07-21/drivers/xen/Kconfig
===================================================================
--- head-2008-07-21.orig/drivers/xen/Kconfig	2008-07-22 08:23:14.000000000 +0200
+++ head-2008-07-21/drivers/xen/Kconfig	2008-07-22 08:25:52.000000000 +0200
@@ -4,6 +4,7 @@
 
 config XEN
 	bool
+	select IRQ_PER_CPU if SMP
 
 if XEN
 config XEN_INTERFACE_VERSION
@@ -290,6 +291,9 @@ config HAVE_IRQ_IGNORE_UNHANDLED
 config GENERIC_HARDIRQS_NO__DO_IRQ
 	def_bool y
 
+config IRQ_PER_CPU
+	bool
+
 config NO_IDLE_HZ
 	def_bool y
 
Index: head-2008-07-21/drivers/xen/core/evtchn.c
===================================================================
--- head-2008-07-21.orig/drivers/xen/core/evtchn.c	2008-07-22 08:25:47.000000000 +0200
+++ head-2008-07-21/drivers/xen/core/evtchn.c	2008-07-22 08:25:52.000000000 +0200
@@ -57,6 +57,22 @@ static DEFINE_SPINLOCK(irq_mapping_updat
 static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
 	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
 
+/* IRQ <-> IPI mapping. */
+#ifndef NR_IPIS
+#define NR_IPIS 1
+#endif
+#if defined(CONFIG_SMP) && defined(CONFIG_X86)
+static int ipi_to_irq[NR_IPIS] __read_mostly = {[0 ... NR_IPIS-1] = -1};
+static DEFINE_PER_CPU(int[NR_IPIS], ipi_to_evtchn) = {[0 ... NR_IPIS-1] = -1};
+#else
+#define PER_CPU_IPI_IRQ
+#endif
+#if !defined(CONFIG_SMP) || !defined(PER_CPU_IPI_IRQ)
+#define BUG_IF_IPI(irq) BUG_ON(type_from_irq(irq) == IRQT_IPI)
+#else
+#define BUG_IF_IPI(irq) ((void)(irq))
+#endif
+
 /* Packed IRQ information: binding type, sub-type index, and event channel. */
 static u32 irq_info[NR_IRQS];
 
@@ -83,10 +99,12 @@ static inline u32 mk_irq_info(u32 type, 
  * Accessors for packed IRQ information.
  */
 
+#ifdef PER_CPU_IPI_IRQ
 static inline unsigned int evtchn_from_irq(int irq)
 {
 	return (u16)(irq_info[irq]);
 }
+#endif
 
 static inline unsigned int index_from_irq(int irq)
 {
@@ -98,14 +116,27 @@ static inline unsigned int type_from_irq
 	return (u8)(irq_info[irq] >> 24);
 }
 
+#ifndef PER_CPU_IPI_IRQ
+static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq, unsigned int cpu)
+{
+	BUG_ON(type_from_irq(irq) != IRQT_IPI);
+	return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)];
+}
+
+static inline unsigned int evtchn_from_irq(unsigned int irq)
+{
+	if (type_from_irq(irq) != IRQT_IPI)
+		return (u16)(irq_info[irq]);
+	return evtchn_from_per_cpu_irq(irq, smp_processor_id());
+}
+#endif
+
 /* IRQ <-> VIRQ mapping. */
 DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
 
-/* IRQ <-> IPI mapping. */
-#ifndef NR_IPIS
-#define NR_IPIS 1
-#endif
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
 DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1};
+#endif
 
 /* Reference counts for bindings to IRQs. */
 static int irq_bindcount[NR_IRQS];
@@ -133,8 +164,14 @@ static void bind_evtchn_to_cpu(unsigned 
 
 	BUG_ON(!test_bit(chn, s->evtchn_mask));
 
-	if (irq != -1)
-		irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+	if (irq != -1) {
+		struct irq_desc *desc = irq_desc + irq;
+
+		if (!(desc->status & IRQ_PER_CPU))
+			desc->affinity = cpumask_of_cpu(cpu);
+		else
+			cpu_set(cpu, desc->affinity);
+	}
 
 	clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
 	set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
@@ -428,6 +465,7 @@ static int bind_virq_to_irq(unsigned int
 	return irq;
 }
 
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
 static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
 {
 	struct evtchn_bind_ipi bind_ipi;
@@ -459,6 +497,7 @@ static int bind_ipi_to_irq(unsigned int 
 	spin_unlock(&irq_mapping_update_lock);
 	return irq;
 }
+#endif
 
 static void unbind_from_irq(unsigned int irq)
 {
@@ -466,6 +505,7 @@ static void unbind_from_irq(unsigned int
 	unsigned int cpu;
 	int evtchn = evtchn_from_irq(irq);
 
+	BUG_IF_IPI(irq);
 	spin_lock(&irq_mapping_update_lock);
 
 	if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) {
@@ -479,10 +519,12 @@ static void unbind_from_irq(unsigned int
 			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
 				[index_from_irq(irq)] = -1;
 			break;
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
 		case IRQT_IPI:
 			per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
 				[index_from_irq(irq)] = -1;
 			break;
+#endif
 		default:
 			break;
 		}
@@ -501,6 +543,44 @@ static void unbind_from_irq(unsigned int
 	spin_unlock(&irq_mapping_update_lock);
 }
 
+#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ)
+void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu)
+{
+	struct evtchn_close close;
+	int evtchn = evtchn_from_per_cpu_irq(irq, cpu);
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if (VALID_EVTCHN(evtchn)) {
+		struct irq_desc *desc = irq_desc + irq;
+
+		cpu_clear(cpu, desc->affinity);
+		BUG_ON(irq_bindcount[irq] <= 1);
+		irq_bindcount[irq]--;
+
+		close.port = evtchn;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+			BUG();
+
+		switch (type_from_irq(irq)) {
+		case IRQT_IPI:
+			per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = -1;
+			break;
+		default:
+			BUG();
+			break;
+		}
+
+		/* Closed ports are implicitly re-bound to VCPU0. */
+		bind_evtchn_to_cpu(evtchn, 0);
+
+		evtchn_to_irq[evtchn] = -1;
+	}
+
+	spin_unlock(&irq_mapping_update_lock);
+}
+#endif /* CONFIG_SMP && !PER_CPU_IPI_IRQ */
+
 int bind_caller_port_to_irqhandler(
 	unsigned int caller_port,
 	irq_handler_t handler,
@@ -595,6 +675,8 @@ int bind_virq_to_irqhandler(
 }
 EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
 
+#ifdef CONFIG_SMP
+#ifdef PER_CPU_IPI_IRQ
 int bind_ipi_to_irqhandler(
 	unsigned int ipi,
 	unsigned int cpu,
@@ -617,7 +699,72 @@ int bind_ipi_to_irqhandler(
 
 	return irq;
 }
-EXPORT_SYMBOL_GPL(bind_ipi_to_irqhandler);
+#else
+int __cpuinit bind_ipi_to_irqaction(
+	unsigned int ipi,
+	unsigned int cpu,
+	struct irqaction *action)
+{
+	struct evtchn_bind_ipi bind_ipi;
+	int evtchn, irq, retval = 0;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if (per_cpu(ipi_to_evtchn, cpu)[ipi] != -1) {
+		spin_unlock(&irq_mapping_update_lock);
+		return -EBUSY;
+	}
+
+	if ((irq = ipi_to_irq[ipi]) == -1) {
+		if ((irq = find_unbound_irq()) < 0) {
+			spin_unlock(&irq_mapping_update_lock);
+			return irq;
+		}
+
+		/* Extra reference so count will never drop to zero. */
+		irq_bindcount[irq]++;
+
+		ipi_to_irq[ipi] = irq;
+		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, 0);
+		irq_desc[irq].handle_irq = handle_percpu_irq;
+		retval = 1;
+	}
+
+	bind_ipi.vcpu = cpu;
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
+					&bind_ipi) != 0)
+		BUG();
+
+	evtchn = bind_ipi.port;
+	evtchn_to_irq[evtchn] = irq;
+	per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
+
+	bind_evtchn_to_cpu(evtchn, cpu);
+
+	irq_bindcount[irq]++;
+
+	spin_unlock(&irq_mapping_update_lock);
+
+	if (retval == 0) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		unmask_evtchn(evtchn);
+		local_irq_restore(flags);
+	} else {
+		action->flags |= IRQF_PERCPU;
+		retval = setup_irq(irq, action);
+		if (retval) {
+			unbind_from_per_cpu_irq(irq, cpu);
+			BUG_ON(retval > 0);
+			irq = retval;
+		}
+	}
+
+	return irq;
+}
+#endif /* PER_CPU_IPI_IRQ */
+#endif /* CONFIG_SMP */
 
 void unbind_from_irqhandler(unsigned int irq, void *dev_id)
 {
@@ -643,6 +790,7 @@ static void rebind_irq_to_cpu(unsigned i
 {
 	int evtchn = evtchn_from_irq(irq);
 
+	BUG_IF_IPI(irq);
 	if (VALID_EVTCHN(evtchn))
 		rebind_evtchn_to_cpu(evtchn, tcpu);
 }
@@ -726,6 +874,7 @@ static struct irq_chip dynirq_chip = {
 	.unmask   = unmask_dynirq,
 	.mask_ack = ack_dynirq,
 	.ack      = ack_dynirq,
+	.eoi      = end_dynirq,
 	.end      = end_dynirq,
 #ifdef CONFIG_SMP
 	.set_affinity = set_affinity_irq,
@@ -870,10 +1019,21 @@ int irq_ignore_unhandled(unsigned int ir
 	return !!(irq_status.flags & XENIRQSTAT_shared);
 }
 
+#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ)
+void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu)
+{
+	int evtchn = evtchn_from_per_cpu_irq(ipi_to_irq[ipi], cpu);
+
+	if (VALID_EVTCHN(evtchn))
+		notify_remote_via_evtchn(evtchn);
+}
+#endif
+
 void notify_remote_via_irq(int irq)
 {
 	int evtchn = evtchn_from_irq(irq);
 
+	BUG_IF_IPI(irq);
 	if (VALID_EVTCHN(evtchn))
 		notify_remote_via_evtchn(evtchn);
 }
@@ -881,6 +1041,7 @@ EXPORT_SYMBOL_GPL(notify_remote_via_irq)
 
 int irq_to_evtchn_port(int irq)
 {
+	BUG_IF_IPI(irq);
 	return evtchn_from_irq(irq);
 }
 EXPORT_SYMBOL_GPL(irq_to_evtchn_port);
@@ -958,11 +1119,16 @@ static void restore_cpu_virqs(unsigned i
 
 static void restore_cpu_ipis(unsigned int cpu)
 {
+#ifdef CONFIG_SMP
 	struct evtchn_bind_ipi bind_ipi;
 	int ipi, irq, evtchn;
 
 	for (ipi = 0; ipi < NR_IPIS; ipi++) {
+#ifdef PER_CPU_IPI_IRQ
 		if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
+#else
+		if ((irq = ipi_to_irq[ipi]) == -1)
+#endif
 			continue;
 
 		BUG_ON(irq_info[irq] != mk_irq_info(IRQT_IPI, ipi, 0));
@@ -976,13 +1142,19 @@ static void restore_cpu_ipis(unsigned in
 
 		/* Record the new mapping. */
 		evtchn_to_irq[evtchn] = irq;
+#ifdef PER_CPU_IPI_IRQ
 		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
+#else
+		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, 0);
+		per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
+#endif
 		bind_evtchn_to_cpu(evtchn, cpu);
 
 		/* Ready for use. */
 		unmask_evtchn(evtchn);
 
 	}
+#endif
 }
 
 static int evtchn_resume(struct sys_device *dev)
@@ -1007,8 +1179,17 @@ static int evtchn_resume(struct sys_devi
 
 	for_each_possible_cpu(cpu) {
 		restore_cpu_virqs(cpu);
+#ifdef PER_CPU_IPI_IRQ
 		restore_cpu_ipis(cpu);
+#else
+		/* No IPI <-> event-channel mappings. */
+		for (irq = 0; irq < NR_IPIS; ++irq)
+			per_cpu(ipi_to_evtchn, cpu)[irq] = -1;
+#endif
 	}
+#ifndef PER_CPU_IPI_IRQ
+	restore_cpu_ipis(smp_processor_id());
+#endif
 
 	return 0;
 }
Index: head-2008-07-21/drivers/xen/core/smpboot.c
===================================================================
--- head-2008-07-21.orig/drivers/xen/core/smpboot.c	2008-07-22 16:17:27.000000000 +0200
+++ head-2008-07-21/drivers/xen/core/smpboot.c	2008-07-22 16:19:31.000000000 +0200
@@ -52,10 +52,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 #endif
 
-static DEFINE_PER_CPU(int, resched_irq);
-static DEFINE_PER_CPU(int, callfunc_irq);
-static char resched_name[NR_CPUS][15];
-static char callfunc_name[NR_CPUS][15];
+static int resched_irq = -1, callfunc_irq = -1;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
@@ -112,31 +109,36 @@ remove_siblinginfo(unsigned int cpu)
 
 static int __cpuinit xen_smp_intr_init(unsigned int cpu)
 {
+	static struct irqaction resched_action = {
+		.handler =	smp_reschedule_interrupt,
+		.flags =	IRQF_DISABLED,
+		.name =		"resched"
+	}, callfunc_action = {
+		.handler =	smp_call_function_interrupt,
+		.flags =	IRQF_DISABLED,
+		.name =		"callfunc"
+	};
 	int rc;
 
-	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
-
-	sprintf(resched_name[cpu], "resched%u", cpu);
-	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
-				    cpu,
-				    smp_reschedule_interrupt,
-				    IRQF_DISABLED|IRQF_NOBALANCING,
-				    resched_name[cpu],
-				    NULL);
+	rc = bind_ipi_to_irqaction(RESCHEDULE_VECTOR,
+				   cpu,
+				   &resched_action);
 	if (rc < 0)
 		goto fail;
-	per_cpu(resched_irq, cpu) = rc;
-
-	sprintf(callfunc_name[cpu], "callfunc%u", cpu);
-	rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
-				    cpu,
-				    smp_call_function_interrupt,
-				    IRQF_DISABLED|IRQF_NOBALANCING,
-				    callfunc_name[cpu],
-				    NULL);
+	if (resched_irq < 0)
+		resched_irq = rc;
+	else
+		BUG_ON(resched_irq != rc);
+
+	rc = bind_ipi_to_irqaction(CALL_FUNCTION_VECTOR,
+				   cpu,
+				   &callfunc_action);
 	if (rc < 0)
 		goto fail;
-	per_cpu(callfunc_irq, cpu) = rc;
+	if (callfunc_irq < 0)
+		callfunc_irq = rc;
+	else
+		BUG_ON(callfunc_irq != rc);
 
 	if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
 		goto fail;
@@ -144,10 +146,10 @@ static int __cpuinit xen_smp_intr_init(u
 	return 0;
 
  fail:
-	if (per_cpu(resched_irq, cpu) >= 0)
-		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
-	if (per_cpu(callfunc_irq, cpu) >= 0)
-		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+	if (resched_irq >= 0)
+		unbind_from_per_cpu_irq(resched_irq, cpu);
+	if (callfunc_irq >= 0)
+		unbind_from_per_cpu_irq(callfunc_irq, cpu);
 	return rc;
 }
 
@@ -157,8 +159,8 @@ static void __cpuexit xen_smp_intr_exit(
 	if (cpu != 0)
 		local_teardown_timer(cpu);
 
-	unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
-	unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+	unbind_from_per_cpu_irq(resched_irq, cpu);
+	unbind_from_per_cpu_irq(callfunc_irq, cpu);
 }
 #endif
 
Index: head-2008-07-21/include/xen/evtchn.h
===================================================================
--- head-2008-07-21.orig/include/xen/evtchn.h	2008-07-22 08:25:47.000000000 +0200
+++ head-2008-07-21/include/xen/evtchn.h	2008-07-22 08:25:52.000000000 +0200
@@ -78,6 +78,8 @@ int bind_virq_to_irqhandler(
 	unsigned long irqflags,
 	const char *devname,
 	void *dev_id);
+#if defined(CONFIG_SMP) && !defined(MODULE)
+#ifndef CONFIG_X86
 int bind_ipi_to_irqhandler(
 	unsigned int ipi,
 	unsigned int cpu,
@@ -85,6 +87,13 @@ int bind_ipi_to_irqhandler(
 	unsigned long irqflags,
 	const char *devname,
 	void *dev_id);
+#else
+int bind_ipi_to_irqaction(
+	unsigned int ipi,
+	unsigned int cpu,
+	struct irqaction *action);
+#endif
+#endif
 
 /*
  * Common unbind function for all event sources. Takes IRQ to unbind from.
@@ -93,6 +102,11 @@ int bind_ipi_to_irqhandler(
  */
 void unbind_from_irqhandler(unsigned int irq, void *dev_id);
 
+#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
+/* Specialized unbind function for per-CPU IRQs. */
+void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu);
+#endif
+
 #ifndef CONFIG_XEN
 void irq_resume(void);
 #endif
@@ -152,4 +166,8 @@ int clear_pirq_hw_action(int pirq);
 #define PIRQ_END 5
 #define PIRQ_ACK 6
 
+#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
+void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu);
+#endif
+
 #endif /* __ASM_EVTCHN_H__ */

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2008-08-18 10:01 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-04 10:18 Xen spinlock questions Jan Beulich
2008-08-04 10:24 ` Keir Fraser
2008-08-11 12:22   ` Jan Beulich
2008-08-11 12:25     ` Keir Fraser
2008-08-11 14:41     ` Keir Fraser
2008-08-11 18:11       ` Jeremy Fitzhardinge
2008-08-11 18:31         ` Keir Fraser
2008-08-11 18:49           ` Jeremy Fitzhardinge
2008-08-12  9:00             ` Keir Fraser
2008-08-12 16:33               ` Jeremy Fitzhardinge
2008-08-12 17:00                 ` Keir Fraser
2008-08-15 12:15                   ` Jan Beulich
2008-08-15 13:01                     ` Keir Fraser
2008-08-15 14:06                       ` Jan Beulich
2008-08-18 10:01                         ` Keir Fraser
2008-08-15 17:12                       ` Jeremy Fitzhardinge
2008-08-11 18:10     ` Jeremy Fitzhardinge
2008-08-13  7:17       ` Jan Beulich
2008-08-04 19:36 ` Jeremy Fitzhardinge
2008-08-05  6:32   ` Jan Beulich
2008-08-05  7:33     ` Keir Fraser
2008-08-05 18:09     ` Jeremy Fitzhardinge
2008-08-06  7:15       ` Jan Beulich
2008-08-06  8:47         ` Jeremy Fitzhardinge
2008-08-06  9:35           ` Jan Beulich
2008-08-06 17:53             ` Jeremy Fitzhardinge
2008-08-06 20:21             ` Jeremy Fitzhardinge
2008-08-07  7:21               ` Jan Beulich
2008-08-07 15:47                 ` Jeremy Fitzhardinge

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.