Hi, Ingo,
As tip/master is a moving target, I am splitting the previous kdump/reboot
virtualization-disable code series[1] into smaller series so the simpler
parts can be included sooner. This first series is just for making
nmi_shootdown_cpus() usable by non-kdump code, by moving their generic
parts to reboot.c.
They are exactly the same patches I've sent as 01-08 in the previous
series.
The NMI IPIs method used by nmi_shootdown_cpus() is the only way
we can make sure VMX is disabled on all CPUs before rebooting, on
emergency_restart(), because CPUs may have IRQs disabled. That's why I
will reuse nmi_shootdown_cpus() for the emergency_restart code when
VMX is enabled.
The virtualization-specific parts should come soon, after I implement
the suggestions by Eric and Avi, by making the virtualization-disabling
functions inline so they can be used directly by the core code (instead
of using the function pointer tricks from my previous series).
[1] http://marc.info/?l=linux-kernel&m=122591590923455&w=2
--
Eduardo
We need to know on which CPU we are running on, and we don't want to be
preempted while doing this.
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/reboot.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index d0c9c77..c495687 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -582,6 +582,7 @@ static struct notifier_block crash_nmi_nb = {
void nmi_shootdown_cpus(nmi_shootdown_cb callback)
{
unsigned long msecs;
+ local_irq_disable();
/* Make a note of crashing cpu. Will be used in NMI callback.*/
crashing_cpu = safe_smp_processor_id();
--
1.5.5.GIT
The reboot code will use a different function on crash_nmi_callback().
Adding a function pointer parameter to nmi_shootdown_cpus() for that.
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/crash.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 75c468c..f23c2be 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -29,10 +29,13 @@
#include <mach_ipi.h>
+typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
+static nmi_shootdown_cb shootdown_callback;
static atomic_t waiting_for_crash_ipi;
@@ -74,7 +77,7 @@ static int crash_nmi_callback(struct notifier_block *self,
return NOTIFY_STOP;
local_irq_disable();
- kdump_nmi_callback(cpu, (struct die_args *)data);
+ shootdown_callback(cpu, (struct die_args *)data);
atomic_dec(&waiting_for_crash_ipi);
/* Assume hlt works */
@@ -97,13 +100,15 @@ static struct notifier_block crash_nmi_nb = {
.notifier_call = crash_nmi_callback,
};
-static void nmi_shootdown_cpus(void)
+static void nmi_shootdown_cpus(nmi_shootdown_cb callback)
{
unsigned long msecs;
/* Make a note of crashing cpu. Will be used in NMI callback.*/
crashing_cpu = safe_smp_processor_id();
+ shootdown_callback = callback;
+
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
/* Would it be better to replace the trap vector here? */
if (register_die_notifier(&crash_nmi_nb))
@@ -126,7 +131,7 @@ static void nmi_shootdown_cpus(void)
static void kdump_nmi_shootdown_cpus(void)
{
- nmi_shootdown_cpus();
+ nmi_shootdown_cpus(kdump_nmi_callback);
disable_local_APIC();
}
--
1.5.5.GIT
The NMI CPU-halting code will be used on non-kdump cases, also
(e.g. emergency_reboot when virtualization is enabled).
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/crash.c | 31 ++++++++++++++++++++-----------
1 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 2685538..6047542 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -35,19 +35,34 @@ static int crashing_cpu;
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
static atomic_t waiting_for_crash_ipi;
-static int crash_nmi_callback(struct notifier_block *self,
- unsigned long val, void *data)
+static void kdump_nmi_callback(int cpu, struct die_args *args)
{
struct pt_regs *regs;
#ifdef CONFIG_X86_32
struct pt_regs fixed_regs;
#endif
+
+ regs = args->regs;
+
+#ifdef CONFIG_X86_32
+ if (!user_mode_vm(regs)) {
+ crash_fixup_ss_esp(&fixed_regs, regs);
+ regs = &fixed_regs;
+ }
+#endif
+ crash_save_cpu(regs, cpu);
+
+ disable_local_APIC();
+}
+
+static int crash_nmi_callback(struct notifier_block *self,
+ unsigned long val, void *data)
+{
int cpu;
if (val != DIE_NMI_IPI)
return NOTIFY_OK;
- regs = ((struct die_args *)data)->regs;
cpu = raw_smp_processor_id();
/* Don't do anything if this handler is invoked on crashing cpu.
@@ -58,14 +73,8 @@ static int crash_nmi_callback(struct notifier_block *self,
return NOTIFY_STOP;
local_irq_disable();
-#ifdef CONFIG_X86_32
- if (!user_mode_vm(regs)) {
- crash_fixup_ss_esp(&fixed_regs, regs);
- regs = &fixed_regs;
- }
-#endif
- crash_save_cpu(regs, cpu);
- disable_local_APIC();
+ kdump_nmi_callback(cpu, (struct die_args *)data);
+
atomic_dec(&waiting_for_crash_ipi);
/* Assume hlt works */
halt();
--
1.5.5.GIT
Add prototype to asm/reboot.h.
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/include/asm/reboot.h | 5 +++++
arch/x86/kernel/crash.c | 3 +--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h
index df77103..562d4fd 100644
--- a/arch/x86/include/asm/reboot.h
+++ b/arch/x86/include/asm/reboot.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_REBOOT_H
#define _ASM_X86_REBOOT_H
+#include <linux/kdebug.h>
+
struct pt_regs;
struct machine_ops {
@@ -18,4 +20,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs);
void native_machine_shutdown(void);
void machine_real_restart(const unsigned char *code, int length);
+typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+void nmi_shootdown_cpus(nmi_shootdown_cb callback);
+
#endif /* _ASM_X86_REBOOT_H */
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index f23c2be..fb298d1 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -29,7 +29,6 @@
#include <mach_ipi.h>
-typedef void (*nmi_shootdown_cb)(int, struct die_args*);
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
@@ -100,7 +99,7 @@ static struct notifier_block crash_nmi_nb = {
.notifier_call = crash_nmi_callback,
};
-static void nmi_shootdown_cpus(nmi_shootdown_cb callback)
+void nmi_shootdown_cpus(nmi_shootdown_cb callback)
{
unsigned long msecs;
--
1.5.5.GIT
The X86_LOCAL_APIC #ifdef was for kdump. For !SMP, the function simply
does nothing.
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/reboot.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 82fa28f..d0c9c77 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -524,7 +524,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
#endif
-#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
+#if defined(CONFIG_SMP)
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
@@ -573,6 +573,12 @@ static struct notifier_block crash_nmi_nb = {
.notifier_call = crash_nmi_callback,
};
+/* Halt all other CPUs, calling the specified function on each of them
+ *
+ * This function can be used to halt all other CPUs on crash
+ * or emergency reboot time. The function passed as parameter
+ * will be called inside a NMI handler on all CPUs.
+ */
void nmi_shootdown_cpus(nmi_shootdown_cb callback)
{
unsigned long msecs;
@@ -601,4 +607,9 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
/* Leave the nmi callback set */
}
+#else /* !CONFIG_SMP */
+void nmi_shootdown_cpus(nmi_shootdown_cb callback)
+{
+ /* No other CPUs to shoot down */
+}
#endif
--
1.5.5.GIT
Now nmi_shootdown_cpus() is ready to be used by non-kdump code also.
Move it to reboot.c.
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/crash.c | 76 ------------------------------------------
arch/x86/kernel/reboot.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 76 deletions(-)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index fb298d1..d84a852 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -32,12 +32,6 @@
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
-/* This keeps a track of which one is crashing cpu. */
-static int crashing_cpu;
-static nmi_shootdown_cb shootdown_callback;
-
-static atomic_t waiting_for_crash_ipi;
-
static void kdump_nmi_callback(int cpu, struct die_args *args)
{
struct pt_regs *regs;
@@ -58,76 +52,6 @@ static void kdump_nmi_callback(int cpu, struct die_args *args)
disable_local_APIC();
}
-static int crash_nmi_callback(struct notifier_block *self,
- unsigned long val, void *data)
-{
- int cpu;
-
- if (val != DIE_NMI_IPI)
- return NOTIFY_OK;
-
- cpu = raw_smp_processor_id();
-
- /* Don't do anything if this handler is invoked on crashing cpu.
- * Otherwise, system will completely hang. Crashing cpu can get
- * an NMI if system was initially booted with nmi_watchdog parameter.
- */
- if (cpu == crashing_cpu)
- return NOTIFY_STOP;
- local_irq_disable();
-
- shootdown_callback(cpu, (struct die_args *)data);
-
- atomic_dec(&waiting_for_crash_ipi);
- /* Assume hlt works */
- halt();
- for (;;)
- cpu_relax();
-
- return 1;
-}
-
-static void smp_send_nmi_allbutself(void)
-{
- cpumask_t mask = cpu_online_map;
- cpu_clear(safe_smp_processor_id(), mask);
- if (!cpus_empty(mask))
- send_IPI_mask(mask, NMI_VECTOR);
-}
-
-static struct notifier_block crash_nmi_nb = {
- .notifier_call = crash_nmi_callback,
-};
-
-void nmi_shootdown_cpus(nmi_shootdown_cb callback)
-{
- unsigned long msecs;
-
- /* Make a note of crashing cpu. Will be used in NMI callback.*/
- crashing_cpu = safe_smp_processor_id();
-
- shootdown_callback = callback;
-
- atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
- /* Would it be better to replace the trap vector here? */
- if (register_die_notifier(&crash_nmi_nb))
- return; /* return what? */
- /* Ensure the new callback function is set before sending
- * out the NMI
- */
- wmb();
-
- smp_send_nmi_allbutself();
-
- msecs = 1000; /* Wait at most a second for the other cpus to stop */
- while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
- mdelay(1);
- msecs--;
- }
-
- /* Leave the nmi callback set */
-}
-
static void kdump_nmi_shootdown_cpus(void)
{
nmi_shootdown_cpus(kdump_nmi_callback);
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 34f8d37..82fa28f 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -21,6 +21,9 @@
# include <asm/iommu.h>
#endif
+#include <mach_ipi.h>
+
+
/*
* Power off function, if any
*/
@@ -519,3 +522,83 @@ void machine_crash_shutdown(struct pt_regs *regs)
machine_ops.crash_shutdown(regs);
}
#endif
+
+
+#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
+
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu;
+static nmi_shootdown_cb shootdown_callback;
+
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ int cpu;
+
+ if (val != DIE_NMI_IPI)
+ return NOTIFY_OK;
+
+ cpu = raw_smp_processor_id();
+
+ /* Don't do anything if this handler is invoked on crashing cpu.
+ * Otherwise, system will completely hang. Crashing cpu can get
+ * an NMI if system was initially booted with nmi_watchdog parameter.
+ */
+ if (cpu == crashing_cpu)
+ return NOTIFY_STOP;
+ local_irq_disable();
+
+ shootdown_callback(cpu, (struct die_args *)data);
+
+ atomic_dec(&waiting_for_crash_ipi);
+ /* Assume hlt works */
+ halt();
+ for (;;)
+ cpu_relax();
+
+ return 1;
+}
+
+static void smp_send_nmi_allbutself(void)
+{
+ cpumask_t mask = cpu_online_map;
+ cpu_clear(safe_smp_processor_id(), mask);
+ if (!cpus_empty(mask))
+ send_IPI_mask(mask, NMI_VECTOR);
+}
+
+static struct notifier_block crash_nmi_nb = {
+ .notifier_call = crash_nmi_callback,
+};
+
+void nmi_shootdown_cpus(nmi_shootdown_cb callback)
+{
+ unsigned long msecs;
+
+ /* Make a note of crashing cpu. Will be used in NMI callback.*/
+ crashing_cpu = safe_smp_processor_id();
+
+ shootdown_callback = callback;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+ /* Would it be better to replace the trap vector here? */
+ if (register_die_notifier(&crash_nmi_nb))
+ return; /* return what? */
+ /* Ensure the new callback function is set before sending
+ * out the NMI
+ */
+ wmb();
+
+ smp_send_nmi_allbutself();
+
+ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+ mdelay(1);
+ msecs--;
+ }
+
+ /* Leave the nmi callback set */
+}
+#endif
--
1.5.5.GIT
This variable will be moved to non-kdump-specific code.
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/crash.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 6047542..ed2f0f9 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -29,10 +29,11 @@
#include <mach_ipi.h>
+#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
+
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
-#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
static atomic_t waiting_for_crash_ipi;
static void kdump_nmi_callback(int cpu, struct die_args *args)
@@ -100,6 +101,9 @@ static void nmi_shootdown_cpus(void)
{
unsigned long msecs;
+ /* Make a note of crashing cpu. Will be used in NMI callback.*/
+ crashing_cpu = safe_smp_processor_id();
+
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
/* Would it be better to replace the trap vector here? */
if (register_die_notifier(&crash_nmi_nb))
@@ -140,8 +144,6 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
/* The kernel is broken so disable interrupts */
local_irq_disable();
- /* Make a note of crashing cpu. Will be used in NMI callback.*/
- crashing_cpu = safe_smp_processor_id();
nmi_shootdown_cpus();
lapic_shutdown();
#if defined(CONFIG_X86_IO_APIC)
--
1.5.5.GIT
For the kdump-specific code that was living on nmi_shootdown_cpus().
Signed-off-by: Eduardo Habkost <[email protected]>
---
arch/x86/kernel/crash.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index ed2f0f9..75c468c 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -122,10 +122,17 @@ static void nmi_shootdown_cpus(void)
}
/* Leave the nmi callback set */
+}
+
+static void kdump_nmi_shootdown_cpus(void)
+{
+ nmi_shootdown_cpus();
+
disable_local_APIC();
}
+
#else
-static void nmi_shootdown_cpus(void)
+static void kdump_nmi_shootdown_cpus(void)
{
/* There are no cpus to shootdown */
}
@@ -144,7 +151,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
/* The kernel is broken so disable interrupts */
local_irq_disable();
- nmi_shootdown_cpus();
+ kdump_nmi_shootdown_cpus();
lapic_shutdown();
#if defined(CONFIG_X86_IO_APIC)
disable_IO_APIC();
--
1.5.5.GIT
* Eduardo Habkost <[email protected]> wrote:
> Hi, Ingo,
>
> As tip/master is a moving target, I am splitting the previous
> kdump/reboot virtualization-disable code series[1] into smaller
> series so the simpler parts can be included sooner. This first
> series is just for making nmi_shootdown_cpus() usable by non-kdump
> code, by moving their generic parts to reboot.c.
applied them to tip/x86/crashdump, thanks Eduardo!
this branch btw. is an append-only non-rebasing tree that is not a
moving target, you can access it via:
http://people.redhat.com/mingo/tip.git/README
and then do:
git checkout -b x86/crashdump tip/x86/crashdump
it has the following changes queued up currently:
Eduardo Habkost (8):
x86 kdump: extract kdump-specific code from crash_nmi_callback()
x86 kdump: move crashing_cpu assignment to nmi_shootdown_cpus()
x86 kdump: create kdump_nmi_shootdown_cpus()
x86 kdump: make kdump_nmi_callback() a function ptr on crash_nmi_callback()
x86 kdump: make nmi_shootdown_cpus() non-static
x86: move nmi_shootdown_cpus() to reboot.c
x86: make nmi_shootdown_cpus() available on !SMP and !X86_LOCAL_APIC
x86: disable IRQs before doing anything on nmi_shootdown_cpus()
Huang Ying (3):
kexec/i386: remove PAGE_SIZE alignment from relocate_kernel
kexec/i386: allocate page table pages dynamically
kexec/i386: setup kexec page table in C
if you prefer less flux then you can send patches against that branch,
we'll sort out interaction with other trees.
Ingo