[KDUMP] pending interrupts problem

From: OBATA Noboru
Date: Thu Oct 27 2005 - 02:52:29 EST


Hi all,

I'm having a problem in kdump on a Pentium 4 box when using SMP
kernel as the second (dump capturing) kernel. Although the use
of SMP kernel as the second kernel is discouraged in
Documentation/kdump/kdump.txt, I hope discussing the problem
here will benefit users in the future.

I tracked down the problem to write a small module (attached)
that can reproduce the problem.

How to reproduce:

- Configure both the first and the second kernels to be
CONFIG_SMP=y
- Boot the first kernel with "maxcpus=1"
- Run "insmod pending-IPI.ko" to oops the second kernel

The module makes IPI (Inter-Processor Interrupt) pending upon a
crash. This is done by:

- Disable local interrupts.
- Send IPI to CPU#0.
- Call panic().

What happens in the second kernel is that it receives the
pending IPI at the first local_irq_enable() in init/main.c, and
the IPI handler calls the uninitialized function pointer
call_data->func in arch/i386/kernel/smp.c.

One way to solve this problem is to implement some blocking
mechanism in the IPI handler so that it prevents itself from
calling the uninitialized pointer.

But pending interrupts on other vectors may cause another
problem. They would cause misrouted IRQs, which are now
addressed by "irqpoll" kernel parameter. But I'm not sure this
solves all the problems.

So another way to solve this problem is to clear all such
pending interrupts before booting the second kernel. This is
more challenging because the pending status (IRR bits ON) in a
local APIC can only be cleared by the acceptance of the
interrupt by CPU core (See section 8.8.4 in "IA-32 Intel(R)
Architecture Software Developer's Manual Vol.3"). That is, we
need to enable the interrupt somewhere in a crashed kernel to
clear the pending status.

Any other ideas to deal with pending interrupts?

Regards,

--
OBATA Noboru (noboru.obata.ar@xxxxxxxxxxx)

/* pending-IPI.c - Panic a kernel with IPI pending */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/smp.h>

int init_module(void)
{
local_irq_disable();

apic_wait_icr_idle();
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(1));
apic_write_around(APIC_ICR, (APIC_DM_FIXED
| APIC_DEST_LOGICAL | 0xfb));

panic("pending-IPI: Bye-bye.");

return 0;
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("OBATA Noboru <noboru.obata.ar@xxxxxxxxxxx>");
MODULE_DESCRIPTION("Panic a kernel with IPI pending");