|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2] x86: Fixup IRQs when CPUs go down during shutdown
Commit fc0c3fa2ad5c ("x86/IO-APIC: fix setup of Xen internally used IRQs
(take 2)") introduced a regression on some hardware where Xen would hang
during shutdown, repeating the following message:
APIC error on CPU0: 08(08), Receive accept error
This appears to be because an interrupt (in this case from the serial
console) destined for a CPU other than the boot CPU is left unhandled so
an APIC error on CPU 0 is generated instead.
To fix this, before taking down the non-boot CPUs, call fixup_irqs()
with a CPU mask of only the boot CPU to reset the IRQ affinities
correctly.
Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
xen/arch/x86/irq.c | 36 ++++++++++++++++++++++--------------
xen/arch/x86/smp.c | 8 ++++++++
xen/arch/x86/smpboot.c | 3 ++-
xen/include/asm-x86/irq.h | 5 +++--
4 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 5f515a0..28337a1 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2328,14 +2328,12 @@ static int __init setup_dump_irqs(void)
}
__initcall(setup_dump_irqs);
-/* A cpu has been removed from cpu_online_mask. Re-set irq affinities. */
-void fixup_irqs(void)
+/* CPU(s) have been removed from mask. Re-set irq affinities. */
+void fixup_irqs(const cpumask_t *mask, bool_t verbose)
{
- unsigned int irq, sp;
+ unsigned int irq;
static int warned;
struct irq_desc *desc;
- irq_guest_action_t *action;
- struct pending_eoi *peoi;
for ( irq = 0; irq < nr_irqs; irq++ )
{
@@ -2355,21 +2353,20 @@ void fixup_irqs(void)
vector = irq_to_vector(irq);
if ( vector >= FIRST_HIPRIORITY_VECTOR &&
vector <= LAST_HIPRIORITY_VECTOR )
- cpumask_and(desc->arch.cpu_mask, desc->arch.cpu_mask,
- &cpu_online_map);
+ cpumask_and(desc->arch.cpu_mask, desc->arch.cpu_mask, mask);
cpumask_copy(&affinity, desc->affinity);
- if ( !desc->action || cpumask_subset(&affinity, &cpu_online_map) )
+ if ( !desc->action || cpumask_subset(&affinity, mask) )
{
spin_unlock(&desc->lock);
continue;
}
- cpumask_and(&affinity, &affinity, &cpu_online_map);
+ cpumask_and(&affinity, &affinity, mask);
if ( cpumask_empty(&affinity) )
{
break_affinity = 1;
- cpumask_copy(&affinity, &cpu_online_map);
+ cpumask_copy(&affinity, mask);
}
if ( desc->handler->disable )
@@ -2385,16 +2382,27 @@ void fixup_irqs(void)
spin_unlock(&desc->lock);
- if ( break_affinity && set_affinity )
- printk("Broke affinity for irq %i\n", irq);
- else if ( !set_affinity )
- printk("Cannot set affinity for irq %i\n", irq);
+ if ( verbose )
+ {
+ if ( break_affinity && set_affinity )
+ printk("Broke affinity for irq %i\n", irq);
+ else if ( !set_affinity )
+ printk("Cannot set affinity for irq %i\n", irq);
+ }
}
/* That doesn't seem sufficient. Give it 1ms. */
local_irq_enable();
mdelay(1);
local_irq_disable();
+}
+
+void fixup_eoi(void)
+{
+ unsigned int irq, sp;
+ struct irq_desc *desc;
+ irq_guest_action_t *action;
+ struct pending_eoi *peoi;
/* Clean up cpu_eoi_map of every interrupt to exclude this CPU. */
for ( irq = 0; irq < nr_irqs; irq++ )
diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c
index 50ff6c2..4446769 100644
--- a/xen/arch/x86/smp.c
+++ b/xen/arch/x86/smp.c
@@ -286,6 +286,7 @@ void __stop_this_cpu(void)
static void stop_this_cpu(void *dummy)
{
+ fixup_eoi();
__stop_this_cpu();
for ( ; ; )
halt();
@@ -298,6 +299,13 @@ static void stop_this_cpu(void *dummy)
void smp_send_stop(void)
{
int timeout = 10;
+ cpumask_t online;
+
+ cpumask_clear(&online);
+ cpumask_set_cpu(smp_processor_id(), &online);
+ local_irq_disable();
+ fixup_irqs(&online, 0);
+ local_irq_enable();
smp_call_function(stop_this_cpu, NULL, 0);
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 5d48bac..1eb16cb 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -922,7 +922,8 @@ void __cpu_disable(void)
/* It's now safe to remove this processor from the online map */
cpumask_clear_cpu(cpu, &cpu_online_map);
- fixup_irqs();
+ fixup_irqs(&cpu_online_map, 1);
+ fixup_eoi();
if ( cpu_disable_scheduler(cpu) )
BUG();
diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h
index fcf37a3..6c8f968 100644
--- a/xen/include/asm-x86/irq.h
+++ b/xen/include/asm-x86/irq.h
@@ -148,8 +148,9 @@ int map_domain_emuirq_pirq(struct domain *d, int pirq, int
irq);
int unmap_domain_pirq_emuirq(struct domain *d, int pirq);
bool_t hvm_domain_use_pirq(const struct domain *, const struct pirq *);
-/* A cpu has been removed from cpu_online_mask. Re-set irq affinities. */
-void fixup_irqs(void);
+/* CPU(s) have been removed from mask. Re-set irq affinities. */
+void fixup_irqs(const cpumask_t *mask, bool_t verbose);
+void fixup_eoi(void);
int init_irq_data(void);
--
2.4.3
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |