|
@@ -23,6 +23,7 @@
|
|
|
int kdump_status[NR_CPUS];
|
|
|
static atomic_t kdump_cpu_frozen;
|
|
|
atomic_t kdump_in_progress;
|
|
|
+static int kdump_freeze_monarch;
|
|
|
static int kdump_on_init = 1;
|
|
|
static int kdump_on_fatal_mca = 1;
|
|
|
|
|
@@ -108,6 +109,33 @@ machine_crash_shutdown(struct pt_regs *pt)
|
|
|
*/
|
|
|
kexec_disable_iosapic();
|
|
|
#ifdef CONFIG_SMP
|
|
|
+ /*
|
|
|
+ * If kdump_on_init is set and an INIT is asserted here, kdump will
|
|
|
+ * be started again via INIT monarch.
|
|
|
+ */
|
|
|
+ local_irq_disable();
|
|
|
+ ia64_set_psr_mc(); /* mask MCA/INIT */
|
|
|
+ if (atomic_inc_return(&kdump_in_progress) != 1)
|
|
|
+ unw_init_running(kdump_cpu_freeze, NULL);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Now this cpu is ready for kdump.
|
|
|
+ * Stop all others by IPI or INIT. They could receive INIT from
|
|
|
+ * outside and might be INIT monarch, but only thing they have to
|
|
|
+ * do is falling into kdump_cpu_freeze().
|
|
|
+ *
|
|
|
+ * If an INIT is asserted here:
|
|
|
+ * - All receivers might be slaves, since some of cpus could already
|
|
|
+ * be frozen and INIT might be masked on monarch. In this case,
|
|
|
+ * all slaves will park in while (monarch_cpu == -1) loop before
|
|
|
+ * DIE_INIT_SLAVE_ENTER that for waiting monarch enters.
|
|
|
+ * => TBD: freeze all slaves
|
|
|
+ * - One might be a monarch, but INIT rendezvous will fail since
|
|
|
+ * at least this cpu already have INIT masked so it never join
|
|
|
+ * to the rendezvous. In this case, all slaves and monarch will
|
|
|
+ * be frozen after timeout of the INIT rendezvous.
|
|
|
+ * => TBD: freeze them without waiting timeout
|
|
|
+ */
|
|
|
kdump_smp_send_stop();
|
|
|
/* not all cpu response to IPI, send INIT to freeze them */
|
|
|
if (kdump_wait_cpu_freeze() && kdump_on_init) {
|
|
@@ -177,13 +205,18 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
|
|
|
switch (val) {
|
|
|
case DIE_INIT_MONARCH_PROCESS:
|
|
|
if (kdump_on_init) {
|
|
|
- atomic_set(&kdump_in_progress, 1);
|
|
|
+ if (atomic_inc_return(&kdump_in_progress) != 1)
|
|
|
+ kdump_freeze_monarch = 1;
|
|
|
*(nd->monarch_cpu) = -1;
|
|
|
}
|
|
|
break;
|
|
|
case DIE_INIT_MONARCH_LEAVE:
|
|
|
- if (kdump_on_init)
|
|
|
- machine_kdump_on_init();
|
|
|
+ if (kdump_on_init) {
|
|
|
+ if (kdump_freeze_monarch)
|
|
|
+ unw_init_running(kdump_cpu_freeze, NULL);
|
|
|
+ else
|
|
|
+ machine_kdump_on_init();
|
|
|
+ }
|
|
|
break;
|
|
|
case DIE_INIT_SLAVE_LEAVE:
|
|
|
if (atomic_read(&kdump_in_progress))
|
|
@@ -196,9 +229,11 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
|
|
|
case DIE_MCA_MONARCH_LEAVE:
|
|
|
/* *(nd->data) indicate if MCA is recoverable */
|
|
|
if (kdump_on_fatal_mca && !(*(nd->data))) {
|
|
|
- atomic_set(&kdump_in_progress, 1);
|
|
|
- *(nd->monarch_cpu) = -1;
|
|
|
- machine_kdump_on_init();
|
|
|
+ if (atomic_inc_return(&kdump_in_progress) == 1) {
|
|
|
+ *(nd->monarch_cpu) = -1;
|
|
|
+ machine_kdump_on_init();
|
|
|
+ }
|
|
|
+ /* We got fatal MCA while kdump!? No way!! */
|
|
|
}
|
|
|
break;
|
|
|
}
|