mirror of
https://abf.rosa.ru/djam/kernel-xen.git
synced 2025-02-23 15:52:46 +00:00
792 lines
22 KiB
Text
792 lines
22 KiB
Text
![]() |
From: jbeulich@novell.com
|
||
|
Subject: fold IPIs onto a single IRQ each
|
||
|
Patch-mainline: obsolete
|
||
|
|
||
|
--- sle11sp1-2010-03-29.orig/arch/x86/kernel/apic/ipi-xen.c 2009-11-06 10:52:02.000000000 +0100
|
||
|
+++ sle11sp1-2010-03-29/arch/x86/kernel/apic/ipi-xen.c 2009-11-06 11:10:20.000000000 +0100
|
||
|
@@ -21,31 +21,22 @@
|
||
|
|
||
|
#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);
|
||
|
-}
|
||
|
-
|
||
|
static void __send_IPI_shortcut(unsigned int shortcut, int vector)
|
||
|
{
|
||
|
unsigned int cpu;
|
||
|
|
||
|
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_each_online_cpu(cpu)
|
||
|
if (cpu != smp_processor_id())
|
||
|
- __send_IPI_one(cpu, vector);
|
||
|
+ notify_remote_via_ipi(vector, cpu);
|
||
|
break;
|
||
|
case APIC_DEST_ALLINC:
|
||
|
for_each_online_cpu(cpu)
|
||
|
- __send_IPI_one(cpu, vector);
|
||
|
+ notify_remote_via_ipi(vector, cpu);
|
||
|
break;
|
||
|
default:
|
||
|
printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
|
||
|
@@ -63,7 +54,7 @@ void xen_send_IPI_mask_allbutself(const
|
||
|
WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
|
||
|
for_each_cpu_and(cpu, cpumask, cpu_online_mask)
|
||
|
if (cpu != smp_processor_id())
|
||
|
- __send_IPI_one(cpu, vector);
|
||
|
+ notify_remote_via_ipi(vector, cpu);
|
||
|
local_irq_restore(flags);
|
||
|
}
|
||
|
|
||
|
@@ -75,7 +66,7 @@ void xen_send_IPI_mask(const struct cpum
|
||
|
local_irq_save(flags);
|
||
|
WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
|
||
|
for_each_cpu_and(cpu, cpumask, cpu_online_mask)
|
||
|
- __send_IPI_one(cpu, vector);
|
||
|
+ notify_remote_via_ipi(vector, cpu);
|
||
|
local_irq_restore(flags);
|
||
|
}
|
||
|
|
||
|
--- sle11sp1-2010-03-29.orig/arch/x86/kernel/irq-xen.c 2010-01-07 11:22:00.000000000 +0100
|
||
|
+++ sle11sp1-2010-03-29/arch/x86/kernel/irq-xen.c 2010-01-07 11:22:50.000000000 +0100
|
||
|
@@ -312,6 +312,7 @@ void fixup_irqs(void)
|
||
|
|
||
|
affinity = desc->affinity;
|
||
|
if (!irq_has_action(irq) ||
|
||
|
+ (desc->status & IRQ_PER_CPU) ||
|
||
|
cpumask_equal(affinity, cpu_online_mask)) {
|
||
|
spin_unlock(&desc->lock);
|
||
|
continue;
|
||
|
--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-29 09:12:59.000000000 +0200
|
||
|
+++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:13:07.000000000 +0200
|
||
|
@@ -4,6 +4,7 @@
|
||
|
|
||
|
config XEN
|
||
|
bool
|
||
|
+ select IRQ_PER_CPU if SMP
|
||
|
|
||
|
if XEN
|
||
|
config XEN_INTERFACE_VERSION
|
||
|
@@ -350,6 +351,9 @@ endmenu
|
||
|
config HAVE_IRQ_IGNORE_UNHANDLED
|
||
|
def_bool y
|
||
|
|
||
|
+config IRQ_PER_CPU
|
||
|
+ bool
|
||
|
+
|
||
|
config NO_IDLE_HZ
|
||
|
def_bool y
|
||
|
|
||
|
--- sle11sp1-2010-03-29.orig/drivers/xen/core/evtchn.c 2010-02-09 17:18:45.000000000 +0100
|
||
|
+++ sle11sp1-2010-03-29/drivers/xen/core/evtchn.c 2010-02-09 17:18:51.000000000 +0100
|
||
|
@@ -58,6 +58,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);
|
||
|
+#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
|
||
|
+
|
||
|
/* Binding types. */
|
||
|
enum {
|
||
|
IRQT_UNBOUND,
|
||
|
@@ -116,12 +132,14 @@ 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)
|
||
|
{
|
||
|
const struct irq_cfg *cfg = irq_cfg(irq);
|
||
|
|
||
|
return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
static inline unsigned int index_from_irq(int irq)
|
||
|
{
|
||
|
@@ -138,14 +156,32 @@ static inline unsigned int type_from_irq
|
||
|
return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND;
|
||
|
}
|
||
|
|
||
|
+#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) {
|
||
|
+ const struct irq_cfg *cfg = irq_cfg(irq);
|
||
|
+
|
||
|
+ return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
|
||
|
+ }
|
||
|
+ return evtchn_from_per_cpu_irq(irq, smp_processor_id());
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
/* IRQ <-> VIRQ mapping. */
|
||
|
DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
|
||
|
|
||
|
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
|
||
|
/* IRQ <-> IPI mapping. */
|
||
|
-#ifndef NR_IPIS
|
||
|
-#define NR_IPIS 1
|
||
|
-#endif
|
||
|
DEFINE_PER_CPU(int[NR_IPIS], ipi_to_irq) = {[0 ... NR_IPIS-1] = -1};
|
||
|
+#endif
|
||
|
|
||
|
#ifdef CONFIG_SMP
|
||
|
|
||
|
@@ -169,8 +205,14 @@ static void bind_evtchn_to_cpu(unsigned
|
||
|
|
||
|
BUG_ON(!test_bit(chn, s->evtchn_mask));
|
||
|
|
||
|
- if (irq != -1)
|
||
|
- cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
|
||
|
+ if (irq != -1) {
|
||
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
||
|
+
|
||
|
+ if (!(desc->status & IRQ_PER_CPU))
|
||
|
+ cpumask_copy(desc->affinity, cpumask_of(cpu));
|
||
|
+ else
|
||
|
+ cpumask_set_cpu(cpu, desc->affinity);
|
||
|
+ }
|
||
|
|
||
|
clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_evtchn[chn]));
|
||
|
set_bit(chn, per_cpu(cpu_evtchn_mask, cpu));
|
||
|
@@ -344,7 +386,7 @@ asmlinkage void __irq_entry evtchn_do_up
|
||
|
|
||
|
static struct irq_chip dynirq_chip;
|
||
|
|
||
|
-static int find_unbound_irq(unsigned int cpu)
|
||
|
+static int find_unbound_irq(unsigned int cpu, bool percpu)
|
||
|
{
|
||
|
static int warned;
|
||
|
int irq;
|
||
|
@@ -354,10 +396,19 @@ static int find_unbound_irq(unsigned int
|
||
|
struct irq_cfg *cfg = desc->chip_data;
|
||
|
|
||
|
if (!cfg->bindcount) {
|
||
|
+ irq_flow_handler_t handle;
|
||
|
+ const char *name;
|
||
|
+
|
||
|
desc->status |= IRQ_NOPROBE;
|
||
|
+ if (!percpu) {
|
||
|
+ handle = handle_level_irq;
|
||
|
+ name = "level";
|
||
|
+ } else {
|
||
|
+ handle = handle_percpu_irq;
|
||
|
+ name = "percpu";
|
||
|
+ }
|
||
|
set_irq_chip_and_handler_name(irq, &dynirq_chip,
|
||
|
- handle_level_irq,
|
||
|
- "level");
|
||
|
+ handle, name);
|
||
|
return irq;
|
||
|
}
|
||
|
}
|
||
|
@@ -378,7 +429,7 @@ static int bind_caller_port_to_irq(unsig
|
||
|
spin_lock(&irq_mapping_update_lock);
|
||
|
|
||
|
if ((irq = evtchn_to_irq[caller_port]) == -1) {
|
||
|
- if ((irq = find_unbound_irq(smp_processor_id())) < 0)
|
||
|
+ if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0)
|
||
|
goto out;
|
||
|
|
||
|
evtchn_to_irq[caller_port] = irq;
|
||
|
@@ -401,7 +452,7 @@ static int bind_local_port_to_irq(unsign
|
||
|
|
||
|
BUG_ON(evtchn_to_irq[local_port] != -1);
|
||
|
|
||
|
- if ((irq = find_unbound_irq(smp_processor_id())) < 0) {
|
||
|
+ if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0) {
|
||
|
struct evtchn_close close = { .port = local_port };
|
||
|
if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
|
||
|
BUG();
|
||
|
@@ -454,7 +505,7 @@ static int bind_virq_to_irq(unsigned int
|
||
|
spin_lock(&irq_mapping_update_lock);
|
||
|
|
||
|
if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
|
||
|
- if ((irq = find_unbound_irq(cpu)) < 0)
|
||
|
+ if ((irq = find_unbound_irq(cpu, false)) < 0)
|
||
|
goto out;
|
||
|
|
||
|
bind_virq.virq = virq;
|
||
|
@@ -479,6 +530,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;
|
||
|
@@ -487,7 +539,7 @@ static int bind_ipi_to_irq(unsigned int
|
||
|
spin_lock(&irq_mapping_update_lock);
|
||
|
|
||
|
if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
|
||
|
- if ((irq = find_unbound_irq(cpu)) < 0)
|
||
|
+ if ((irq = find_unbound_irq(cpu, false)) < 0)
|
||
|
goto out;
|
||
|
|
||
|
bind_ipi.vcpu = cpu;
|
||
|
@@ -510,6 +562,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)
|
||
|
{
|
||
|
@@ -517,6 +570,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_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) {
|
||
|
@@ -530,10 +584,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;
|
||
|
}
|
||
|
@@ -556,6 +612,46 @@ 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_to_desc(irq);
|
||
|
+
|
||
|
+ mask_evtchn(evtchn);
|
||
|
+
|
||
|
+ BUG_ON(irq_cfg(irq)->bindcount <= 1);
|
||
|
+ irq_cfg(irq)->bindcount--;
|
||
|
+ cpumask_clear_cpu(cpu, desc->affinity);
|
||
|
+
|
||
|
+ 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)] = 0;
|
||
|
+ 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,
|
||
|
@@ -650,6 +746,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,
|
||
|
@@ -673,7 +771,71 @@ 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 (VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi])) {
|
||
|
+ spin_unlock(&irq_mapping_update_lock);
|
||
|
+ return -EBUSY;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((irq = ipi_to_irq[ipi]) == -1) {
|
||
|
+ if ((irq = find_unbound_irq(cpu, true)) < 0) {
|
||
|
+ spin_unlock(&irq_mapping_update_lock);
|
||
|
+ return irq;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Extra reference so count will never drop to zero. */
|
||
|
+ irq_cfg(irq)->bindcount++;
|
||
|
+
|
||
|
+ ipi_to_irq[ipi] = irq;
|
||
|
+ irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, 0);
|
||
|
+ 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_cfg(irq)->bindcount++;
|
||
|
+
|
||
|
+ 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 | IRQF_NO_SUSPEND;
|
||
|
+ 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)
|
||
|
{
|
||
|
@@ -699,6 +861,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);
|
||
|
}
|
||
|
@@ -784,6 +947,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,
|
||
|
@@ -963,10 +1127,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);
|
||
|
}
|
||
|
@@ -974,6 +1149,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);
|
||
|
@@ -1089,11 +1265,17 @@ 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
|
||
|
+ || !VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi]))
|
||
|
+#endif
|
||
|
continue;
|
||
|
|
||
|
BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_IPI, ipi, 0));
|
||
|
@@ -1107,13 +1289,18 @@ static void restore_cpu_ipis(unsigned in
|
||
|
|
||
|
/* Record the new mapping. */
|
||
|
evtchn_to_irq[evtchn] = irq;
|
||
|
+#ifdef PER_CPU_IPI_IRQ
|
||
|
irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn);
|
||
|
+#else
|
||
|
+ per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
|
||
|
+#endif
|
||
|
bind_evtchn_to_cpu(evtchn, cpu);
|
||
|
|
||
|
/* Ready for use. */
|
||
|
if (!(irq_to_desc(irq)->status & IRQ_DISABLED))
|
||
|
unmask_evtchn(evtchn);
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
static int evtchn_resume(struct sys_device *dev)
|
||
|
--- sle11sp1-2010-03-29.orig/drivers/xen/core/smpboot.c 2010-03-22 12:57:24.000000000 +0100
|
||
|
+++ sle11sp1-2010-03-29/drivers/xen/core/smpboot.c 2010-03-22 12:57:46.000000000 +0100
|
||
|
@@ -40,14 +40,10 @@ cpumask_var_t vcpu_initialized_mask;
|
||
|
DEFINE_PER_CPU(struct cpuinfo_x86, cpu_info);
|
||
|
EXPORT_PER_CPU_SYMBOL(cpu_info);
|
||
|
|
||
|
-static DEFINE_PER_CPU(int, resched_irq);
|
||
|
-static DEFINE_PER_CPU(int, callfunc_irq);
|
||
|
-static DEFINE_PER_CPU(int, call1func_irq);
|
||
|
-static DEFINE_PER_CPU(int, reboot_irq);
|
||
|
-static char resched_name[NR_CPUS][15];
|
||
|
-static char callfunc_name[NR_CPUS][15];
|
||
|
-static char call1func_name[NR_CPUS][15];
|
||
|
-static char reboot_name[NR_CPUS][15];
|
||
|
+static int __read_mostly resched_irq = -1;
|
||
|
+static int __read_mostly callfunc_irq = -1;
|
||
|
+static int __read_mostly call1func_irq = -1;
|
||
|
+static int __read_mostly reboot_irq = -1;
|
||
|
|
||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||
|
#define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
|
||
|
@@ -109,58 +105,68 @@ 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"
|
||
|
+ }, call1func_action = {
|
||
|
+ .handler = smp_call_function_single_interrupt,
|
||
|
+ .flags = IRQF_DISABLED,
|
||
|
+ .name = "call1func"
|
||
|
+ }, reboot_action = {
|
||
|
+ .handler = smp_reboot_interrupt,
|
||
|
+ .flags = IRQF_DISABLED,
|
||
|
+ .name = "reboot"
|
||
|
+ };
|
||
|
int rc;
|
||
|
|
||
|
- per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) =
|
||
|
- per_cpu(call1func_irq, cpu) = per_cpu(reboot_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);
|
||
|
+ return rc;
|
||
|
+ 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;
|
||
|
-
|
||
|
- sprintf(call1func_name[cpu], "call1func%u", cpu);
|
||
|
- rc = bind_ipi_to_irqhandler(CALL_FUNC_SINGLE_VECTOR,
|
||
|
- cpu,
|
||
|
- smp_call_function_single_interrupt,
|
||
|
- IRQF_DISABLED|IRQF_NOBALANCING,
|
||
|
- call1func_name[cpu],
|
||
|
- NULL);
|
||
|
+ goto unbind_resched;
|
||
|
+ if (callfunc_irq < 0)
|
||
|
+ callfunc_irq = rc;
|
||
|
+ else
|
||
|
+ BUG_ON(callfunc_irq != rc);
|
||
|
+
|
||
|
+ rc = bind_ipi_to_irqaction(CALL_FUNC_SINGLE_VECTOR,
|
||
|
+ cpu,
|
||
|
+ &call1func_action);
|
||
|
if (rc < 0)
|
||
|
- goto fail;
|
||
|
- per_cpu(call1func_irq, cpu) = rc;
|
||
|
-
|
||
|
- sprintf(reboot_name[cpu], "reboot%u", cpu);
|
||
|
- rc = bind_ipi_to_irqhandler(REBOOT_VECTOR,
|
||
|
- cpu,
|
||
|
- smp_reboot_interrupt,
|
||
|
- IRQF_DISABLED|IRQF_NOBALANCING,
|
||
|
- reboot_name[cpu],
|
||
|
- NULL);
|
||
|
+ goto unbind_call;
|
||
|
+ if (call1func_irq < 0)
|
||
|
+ call1func_irq = rc;
|
||
|
+ else
|
||
|
+ BUG_ON(call1func_irq != rc);
|
||
|
+
|
||
|
+ rc = bind_ipi_to_irqaction(REBOOT_VECTOR,
|
||
|
+ cpu,
|
||
|
+ &reboot_action);
|
||
|
if (rc < 0)
|
||
|
- goto fail;
|
||
|
- per_cpu(reboot_irq, cpu) = rc;
|
||
|
+ goto unbind_call1;
|
||
|
+ if (reboot_irq < 0)
|
||
|
+ reboot_irq = rc;
|
||
|
+ else
|
||
|
+ BUG_ON(reboot_irq != rc);
|
||
|
|
||
|
rc = xen_spinlock_init(cpu);
|
||
|
if (rc < 0)
|
||
|
- goto fail;
|
||
|
+ goto unbind_reboot;
|
||
|
|
||
|
if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
|
||
|
goto fail;
|
||
|
@@ -168,15 +174,15 @@ 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 (per_cpu(call1func_irq, cpu) >= 0)
|
||
|
- unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
|
||
|
- if (per_cpu(reboot_irq, cpu) >= 0)
|
||
|
- unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
|
||
|
xen_spinlock_cleanup(cpu);
|
||
|
+ unbind_reboot:
|
||
|
+ unbind_from_per_cpu_irq(reboot_irq, cpu);
|
||
|
+ unbind_call1:
|
||
|
+ unbind_from_per_cpu_irq(call1func_irq, cpu);
|
||
|
+ unbind_call:
|
||
|
+ unbind_from_per_cpu_irq(callfunc_irq, cpu);
|
||
|
+ unbind_resched:
|
||
|
+ unbind_from_per_cpu_irq(resched_irq, cpu);
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
@@ -186,10 +192,10 @@ static void __cpuinit 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_irqhandler(per_cpu(call1func_irq, cpu), NULL);
|
||
|
- unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
|
||
|
+ unbind_from_per_cpu_irq(resched_irq, cpu);
|
||
|
+ unbind_from_per_cpu_irq(callfunc_irq, cpu);
|
||
|
+ unbind_from_per_cpu_irq(call1func_irq, cpu);
|
||
|
+ unbind_from_per_cpu_irq(reboot_irq, cpu);
|
||
|
xen_spinlock_cleanup(cpu);
|
||
|
}
|
||
|
#endif
|
||
|
--- sle11sp1-2010-03-29.orig/drivers/xen/core/spinlock.c 2010-02-24 16:14:47.000000000 +0100
|
||
|
+++ sle11sp1-2010-03-29/drivers/xen/core/spinlock.c 2010-02-23 14:25:31.000000000 +0100
|
||
|
@@ -14,8 +14,7 @@
|
||
|
|
||
|
#ifdef TICKET_SHIFT
|
||
|
|
||
|
-static DEFINE_PER_CPU(int, spinlock_irq) = -1;
|
||
|
-static char spinlock_name[NR_CPUS][15];
|
||
|
+static int __read_mostly spinlock_irq = -1;
|
||
|
|
||
|
struct spinning {
|
||
|
raw_spinlock_t *lock;
|
||
|
@@ -32,29 +31,31 @@ static DEFINE_PER_CPU(raw_rwlock_t, spin
|
||
|
|
||
|
int __cpuinit xen_spinlock_init(unsigned int cpu)
|
||
|
{
|
||
|
+ static struct irqaction spinlock_action = {
|
||
|
+ .handler = smp_reschedule_interrupt,
|
||
|
+ .flags = IRQF_DISABLED,
|
||
|
+ .name = "spinlock"
|
||
|
+ };
|
||
|
int rc;
|
||
|
|
||
|
- sprintf(spinlock_name[cpu], "spinlock%u", cpu);
|
||
|
- rc = bind_ipi_to_irqhandler(SPIN_UNLOCK_VECTOR,
|
||
|
- cpu,
|
||
|
- smp_reschedule_interrupt,
|
||
|
- IRQF_DISABLED|IRQF_NOBALANCING,
|
||
|
- spinlock_name[cpu],
|
||
|
- NULL);
|
||
|
+ rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR,
|
||
|
+ cpu,
|
||
|
+ &spinlock_action);
|
||
|
if (rc < 0)
|
||
|
return rc;
|
||
|
|
||
|
- disable_irq(rc); /* make sure it's never delivered */
|
||
|
- per_cpu(spinlock_irq, cpu) = rc;
|
||
|
+ if (spinlock_irq < 0) {
|
||
|
+ disable_irq(rc); /* make sure it's never delivered */
|
||
|
+ spinlock_irq = rc;
|
||
|
+ } else
|
||
|
+ BUG_ON(spinlock_irq != rc);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void __cpuinit xen_spinlock_cleanup(unsigned int cpu)
|
||
|
{
|
||
|
- if (per_cpu(spinlock_irq, cpu) >= 0)
|
||
|
- unbind_from_irqhandler(per_cpu(spinlock_irq, cpu), NULL);
|
||
|
- per_cpu(spinlock_irq, cpu) = -1;
|
||
|
+ unbind_from_per_cpu_irq(spinlock_irq, cpu);
|
||
|
}
|
||
|
|
||
|
static unsigned int spin_adjust(struct spinning *spinning,
|
||
|
@@ -84,7 +85,7 @@ unsigned int xen_spin_adjust(const raw_s
|
||
|
bool xen_spin_wait(raw_spinlock_t *lock, unsigned int *ptok,
|
||
|
unsigned int flags)
|
||
|
{
|
||
|
- int irq = percpu_read(spinlock_irq);
|
||
|
+ int irq = spinlock_irq;
|
||
|
bool rc;
|
||
|
typeof(vcpu_info(0)->evtchn_upcall_mask) upcall_mask;
|
||
|
raw_rwlock_t *rm_lock;
|
||
|
@@ -240,7 +241,7 @@ void xen_spin_kick(raw_spinlock_t *lock,
|
||
|
raw_local_irq_restore(flags);
|
||
|
|
||
|
if (unlikely(spinning)) {
|
||
|
- notify_remote_via_irq(per_cpu(spinlock_irq, cpu));
|
||
|
+ notify_remote_via_ipi(SPIN_UNLOCK_VECTOR, cpu);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
--- sle11sp1-2010-03-29.orig/include/xen/evtchn.h 2009-12-18 10:13:12.000000000 +0100
|
||
|
+++ sle11sp1-2010-03-29/include/xen/evtchn.h 2009-12-18 10:13:26.000000000 +0100
|
||
|
@@ -92,6 +92,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,
|
||
|
@@ -99,6 +101,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.
|
||
|
@@ -107,6 +116,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
|
||
|
@@ -184,5 +198,9 @@ void xen_poll_irq(int irq);
|
||
|
void notify_remote_via_irq(int irq);
|
||
|
int irq_to_evtchn_port(int irq);
|
||
|
|
||
|
+#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__ */
|
||
|
#endif /* CONFIG_PARAVIRT_XEN */
|