All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues
@ 2018-07-12  1:27 Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 1/6] MIPS: Make play_dead() work for kexec Dengcheng Zhu
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

The issues are mentioned in patches 1/4/5/6. I will update kdump
documentation for MIPS if the series gets accepted. Testing has been done 
on single core i6500/Boston with IOCU, dual core i6500 without IOCU, and
dual core interAptiv without IOCU.

Changes:

v2 - v1:
* Tested on MIPS32R2 platform in addition to MIPS64R6.
* Added patches #5 and #6.
* In patch #2, removed the unnecessary inclusion of asm/mipsmtregs.h

Dengcheng Zhu (6):
  MIPS: Make play_dead() work for kexec
  MIPS: kexec: Let the new kernel handle all CPUs
  MIPS: kexec: Deprecate (relocated_)kexec_smp_wait
  MIPS: kexec: Do not flush system wide caches in machine_kexec()
  MIPS: kexec: Relax memory restriction
  MIPS: kexec: Use prepare method from generic platform as default
    option

 arch/mips/cavium-octeon/setup.c       |  2 +-
 arch/mips/cavium-octeon/smp.c         | 35 ++++++++-------
 arch/mips/generic/Makefile            |  1 -
 arch/mips/generic/kexec.c             | 44 ------------------
 arch/mips/include/asm/kexec.h         |  9 ++--
 arch/mips/include/asm/smp.h           |  4 +-
 arch/mips/kernel/crash.c              |  4 +-
 arch/mips/kernel/machine_kexec.c      | 77 ++++++++++++++++++++++++++-----
 arch/mips/kernel/process.c            |  2 +-
 arch/mips/kernel/relocate_kernel.S    | 39 ----------------
 arch/mips/kernel/smp-bmips.c          | 11 +++--
 arch/mips/kernel/smp-cps.c            | 59 ++++++++++++++----------
 arch/mips/loongson64/loongson-3/smp.c | 85 ++++++++++++++++++-----------------
 13 files changed, 186 insertions(+), 186 deletions(-)
 delete mode 100644 arch/mips/generic/kexec.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/6] MIPS: Make play_dead() work for kexec
  2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
@ 2018-07-12  1:27 ` Dengcheng Zhu
  2018-08-30 23:20   ` Paul Burton
  2018-07-12  1:27 ` [PATCH v2 2/6] MIPS: kexec: Let the new kernel handle all CPUs Dengcheng Zhu
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

Extract play_dead() from CONFIG_HOTPLUG_CPU and share with CONFIG_KEXEC.
Also, add one parameter to it to avoid doing unnecessary things in the case
of kexec.

This is needed to correctly support SMP new kernel in kexec. Before doing
this, all non-crashing CPUs are waiting for the reboot signal
(kexec_ready_to_reboot) to jump to kexec_start_address in kexec_smp_wait(),
which creates some problems like incorrect CPU topology upon booting from
new UP kernel, sluggish performance in MT environment during and after
reboot, new SMP kernel not able to bring up secondary CPU etc.

It would make sense to let the new (SMP) kernel manage all CPUs, instead of
crashing CPU booting from reboot_code_buffer whereas others jumping to
kexec_start_address. To do this, play_dead() is well suitable for preparing
a boot environment for the new kernel.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
---
 arch/mips/cavium-octeon/smp.c         | 35 ++++++++-------
 arch/mips/include/asm/smp.h           |  4 +-
 arch/mips/kernel/process.c            |  2 +-
 arch/mips/kernel/smp-bmips.c          | 11 +++--
 arch/mips/kernel/smp-cps.c            | 59 ++++++++++++++----------
 arch/mips/loongson64/loongson-3/smp.c | 85 ++++++++++++++++++-----------------
 6 files changed, 112 insertions(+), 84 deletions(-)

diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 75e7c86..31150a8 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -280,11 +280,30 @@ static void octeon_smp_finish(void)
 	local_irq_enable();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
 
 /* State of each CPU. */
 DEFINE_PER_CPU(int, cpu_state);
 
+void play_dead(bool kexec)
+{
+	int cpu = cpu_number_map(cvmx_get_core_num());
+
+	if (!kexec)
+		idle_task_exit();
+	octeon_processor_boot = 0xff;
+	per_cpu(cpu_state, cpu) = CPU_DEAD;
+
+	mb();
+
+	while (1)	/* core will be reset here */
+		;
+}
+
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
+
+#ifdef CONFIG_HOTPLUG_CPU
+
 static int octeon_cpu_disable(void)
 {
 	unsigned int cpu = smp_processor_id();
@@ -343,20 +362,6 @@ static void octeon_cpu_die(unsigned int cpu)
 	cvmx_write_csr(CVMX_CIU_PP_RST, 0);
 }
 
-void play_dead(void)
-{
-	int cpu = cpu_number_map(cvmx_get_core_num());
-
-	idle_task_exit();
-	octeon_processor_boot = 0xff;
-	per_cpu(cpu_state, cpu) = CPU_DEAD;
-
-	mb();
-
-	while (1)	/* core will be reset here */
-		;
-}
-
 static void start_after_reset(void)
 {
 	kernel_entry(0, 0, 0);	/* set a2 = 0 for secondary core */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 88ebd83..3176053 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -77,8 +77,10 @@ static inline void __cpu_die(unsigned int cpu)
 
 	mp_ops->cpu_die(cpu);
 }
+#endif
 
-extern void play_dead(void);
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+extern void play_dead(bool kexec);
 #endif
 
 /*
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 8d85046..1aa24bb 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -53,7 +53,7 @@
 #ifdef CONFIG_HOTPLUG_CPU
 void arch_cpu_idle_dead(void)
 {
-	play_dead();
+	play_dead(false);
 }
 #endif
 
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 159e83a..e1c11bd 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -381,9 +381,14 @@ static void bmips_cpu_die(unsigned int cpu)
 {
 }
 
-void __ref play_dead(void)
+#endif /* CONFIG_HOTPLUG_CPU */
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+
+void __ref play_dead(bool kexec)
 {
-	idle_task_exit();
+	if (!kexec)
+		idle_task_exit();
 
 	/* flush data cache */
 	_dma_cache_wback_inv(0, ~0);
@@ -409,7 +414,7 @@ void __ref play_dead(void)
 	: : : "memory");
 }
 
-#endif /* CONFIG_HOTPLUG_CPU */
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
 
 const struct plat_smp_ops bmips43xx_smp_ops = {
 	.smp_setup		= bmips_smp_setup,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 03f1026..4615702 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -398,27 +398,7 @@ static void cps_smp_finish(void)
 	local_irq_enable();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-static int cps_cpu_disable(void)
-{
-	unsigned cpu = smp_processor_id();
-	struct core_boot_config *core_cfg;
-
-	if (!cpu)
-		return -EBUSY;
-
-	if (!cps_pm_support_state(CPS_PM_POWER_GATED))
-		return -EINVAL;
-
-	core_cfg = &mips_cps_core_bootcfg[cpu_core(&current_cpu_data)];
-	atomic_sub(1 << cpu_vpe_id(&current_cpu_data), &core_cfg->vpe_mask);
-	smp_mb__after_atomic();
-	set_cpu_online(cpu, false);
-	calculate_cpu_foreign_map();
-
-	return 0;
-}
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
 
 static unsigned cpu_death_sibling;
 static enum {
@@ -426,12 +406,18 @@ static enum {
 	CPU_DEATH_POWER,
 } cpu_death;
 
-void play_dead(void)
+void play_dead(bool kexec)
 {
 	unsigned int cpu, core, vpe_id;
 
 	local_irq_disable();
-	idle_task_exit();
+	/*
+	 * Don't bother dealing with idle task's mm as we are executing the
+	 * new kernel.
+	 */
+	if (!kexec)
+		idle_task_exit();
+
 	cpu = smp_processor_id();
 	core = cpu_core(&cpu_data[cpu]);
 	cpu_death = CPU_DEATH_POWER;
@@ -454,7 +440,8 @@ void play_dead(void)
 	}
 
 	/* This CPU has chosen its way out */
-	(void)cpu_report_death();
+	if (!kexec)
+		(void)cpu_report_death();
 
 	if (cpu_death == CPU_DEATH_HALT) {
 		vpe_id = cpu_vpe_id(&cpu_data[cpu]);
@@ -480,6 +467,30 @@ void play_dead(void)
 	panic("Failed to offline CPU %u", cpu);
 }
 
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int cps_cpu_disable(void)
+{
+	unsigned cpu = smp_processor_id();
+	struct core_boot_config *core_cfg;
+
+	if (!cpu)
+		return -EBUSY;
+
+	if (!cps_pm_support_state(CPS_PM_POWER_GATED))
+		return -EINVAL;
+
+	core_cfg = &mips_cps_core_bootcfg[cpu_core(&current_cpu_data)];
+	atomic_sub(1 << cpu_vpe_id(&current_cpu_data), &core_cfg->vpe_mask);
+	smp_mb__after_atomic();
+	set_cpu_online(cpu, false);
+	calculate_cpu_foreign_map();
+
+	return 0;
+}
+
 static void wait_for_sibling_halt(void *ptr_cpu)
 {
 	unsigned cpu = (unsigned long)ptr_cpu;
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index 8501109..d426ce2 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -455,6 +455,47 @@ static void loongson3_cpu_die(unsigned int cpu)
 	mb();
 }
 
+static int loongson3_disable_clock(unsigned int cpu)
+{
+	uint64_t core_id = cpu_core(&cpu_data[cpu]);
+	uint64_t package_id = cpu_data[cpu].package;
+
+	if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
+		LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
+	} else {
+		if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
+			LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
+	}
+	return 0;
+}
+
+static int loongson3_enable_clock(unsigned int cpu)
+{
+	uint64_t core_id = cpu_core(&cpu_data[cpu]);
+	uint64_t package_id = cpu_data[cpu].package;
+
+	if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
+		LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
+	} else {
+		if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
+			LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
+	}
+	return 0;
+}
+
+static int register_loongson3_notifier(void)
+{
+	return cpuhp_setup_state_nocalls(CPUHP_MIPS_SOC_PREPARE,
+					 "mips/loongson:prepare",
+					 loongson3_enable_clock,
+					 loongson3_disable_clock);
+}
+early_initcall(register_loongson3_notifier);
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+
 /* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
  * flush all L1 entries at first. Then, another core (usually Core 0) can
  * safely disable the clock of the target core. loongson3_play_dead() is
@@ -668,13 +709,14 @@ static void loongson3b_play_dead(int *state_addr)
 		: "a1");
 }
 
-void play_dead(void)
+void play_dead(bool kexec)
 {
 	int *state_addr;
 	unsigned int cpu = smp_processor_id();
 	void (*play_dead_at_ckseg1)(int *);
 
-	idle_task_exit();
+	if (!kexec)
+		idle_task_exit();
 	switch (read_c0_prid() & PRID_REV_MASK) {
 	case PRID_REV_LOONGSON3A_R1:
 	default:
@@ -697,44 +739,7 @@ void play_dead(void)
 	play_dead_at_ckseg1(state_addr);
 }
 
-static int loongson3_disable_clock(unsigned int cpu)
-{
-	uint64_t core_id = cpu_core(&cpu_data[cpu]);
-	uint64_t package_id = cpu_data[cpu].package;
-
-	if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
-		LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
-	} else {
-		if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
-			LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
-	}
-	return 0;
-}
-
-static int loongson3_enable_clock(unsigned int cpu)
-{
-	uint64_t core_id = cpu_core(&cpu_data[cpu]);
-	uint64_t package_id = cpu_data[cpu].package;
-
-	if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
-		LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
-	} else {
-		if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
-			LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
-	}
-	return 0;
-}
-
-static int register_loongson3_notifier(void)
-{
-	return cpuhp_setup_state_nocalls(CPUHP_MIPS_SOC_PREPARE,
-					 "mips/loongson:prepare",
-					 loongson3_enable_clock,
-					 loongson3_disable_clock);
-}
-early_initcall(register_loongson3_notifier);
-
-#endif
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
 
 const struct plat_smp_ops loongson3_smp_ops = {
 	.send_ipi_single = loongson3_send_ipi_single,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/6] MIPS: kexec: Let the new kernel handle all CPUs
  2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 1/6] MIPS: Make play_dead() work for kexec Dengcheng Zhu
@ 2018-07-12  1:27 ` Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 3/6] MIPS: kexec: Deprecate (relocated_)kexec_smp_wait Dengcheng Zhu
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

Use the new play_dead() interface to prepare an environment for the new
kernel. Do not rely on non-crashing CPUs jumping to kexec_start_address.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
---
Changes:

* Removed "#include <asm/mipsmtregs.h>", which is unnecessary.

 arch/mips/cavium-octeon/setup.c  |  2 +-
 arch/mips/include/asm/kexec.h    |  1 +
 arch/mips/kernel/crash.c         |  4 +++-
 arch/mips/kernel/machine_kexec.c | 27 +++++++++++++++++++++++----
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index a8034d0..3a1f7fa 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -95,7 +95,7 @@ static void octeon_kexec_smp_down(void *ignored)
 	"	sync						\n"
 	"	synci	($0)					\n");
 
-	relocated_kexec_smp_wait(NULL);
+	kexec_smp_reboot();
 }
 #endif
 
diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index 493a3cc..8f1d0ef 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -45,6 +45,7 @@ extern const unsigned char kexec_smp_wait[];
 extern unsigned long secondary_kexec_args[4];
 extern void (*relocated_kexec_smp_wait) (void *);
 extern atomic_t kexec_ready_to_reboot;
+extern void kexec_smp_reboot(void);
 extern void (*_crash_smp_send_stop)(void);
 #endif
 #endif
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
index d455363..6d43200 100644
--- a/arch/mips/kernel/crash.c
+++ b/arch/mips/kernel/crash.c
@@ -43,7 +43,9 @@ static void crash_shutdown_secondary(void *passed_regs)
 
 	while (!atomic_read(&kexec_ready_to_reboot))
 		cpu_relax();
-	relocated_kexec_smp_wait(NULL);
+
+	kexec_smp_reboot();
+
 	/* NOTREACHED */
 }
 
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 8b574bc..7111fa8 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -19,6 +19,10 @@ extern const size_t relocate_new_kernel_size;
 extern unsigned long kexec_start_address;
 extern unsigned long kexec_indirection_page;
 
+static unsigned long reboot_code_buffer;
+
+typedef void (*noretfun_t)(void) __noreturn;
+
 int (*_machine_kexec_prepare)(struct kimage *) = NULL;
 void (*_machine_kexec_shutdown)(void) = NULL;
 void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
@@ -26,6 +30,19 @@ void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
 void (*relocated_kexec_smp_wait) (void *);
 atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
 void (*_crash_smp_send_stop)(void) = NULL;
+
+void kexec_smp_reboot(void)
+{
+	if (smp_processor_id() > 0) {
+		/*
+		 * Instead of cpu_relax() or wait, this is needed for kexec
+		 * smp reboot. Kdump usually doesn't require an smp new
+		 * kernel, but kexec may do.
+		 */
+		play_dead(true);
+	} else
+		((noretfun_t) reboot_code_buffer)();
+}
 #endif
 
 static void kexec_image_info(const struct kimage *kimage)
@@ -79,12 +96,9 @@ machine_crash_shutdown(struct pt_regs *regs)
 		default_machine_crash_shutdown(regs);
 }
 
-typedef void (*noretfun_t)(void) __noreturn;
-
 void
 machine_kexec(struct kimage *image)
 {
-	unsigned long reboot_code_buffer;
 	unsigned long entry;
 	unsigned long *ptr;
 
@@ -132,6 +146,11 @@ machine_kexec(struct kimage *image)
 		(void *)(kexec_smp_wait - relocate_new_kernel);
 	smp_wmb();
 	atomic_set(&kexec_ready_to_reboot, 1);
-#endif
+
+	kexec_smp_reboot();
+
+	/* NOT REACHED */
+#else
 	((noretfun_t) reboot_code_buffer)();
+#endif
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/6] MIPS: kexec: Deprecate (relocated_)kexec_smp_wait
  2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 1/6] MIPS: Make play_dead() work for kexec Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 2/6] MIPS: kexec: Let the new kernel handle all CPUs Dengcheng Zhu
@ 2018-07-12  1:27 ` Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 4/6] MIPS: kexec: Do not flush system wide caches in machine_kexec() Dengcheng Zhu
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

Since we've changed the SMP boot mechanism (by having the new kernel handle
all CPUs), now remove (relocated_)kexec_smp_wait.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
---
 arch/mips/include/asm/kexec.h      |  2 --
 arch/mips/kernel/machine_kexec.c   |  5 -----
 arch/mips/kernel/relocate_kernel.S | 39 --------------------------------------
 3 files changed, 46 deletions(-)

diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index 8f1d0ef..9618e2e 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -41,9 +41,7 @@ extern void (*_machine_kexec_shutdown)(void);
 extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
 extern void default_machine_crash_shutdown(struct pt_regs *regs);
 #ifdef CONFIG_SMP
-extern const unsigned char kexec_smp_wait[];
 extern unsigned long secondary_kexec_args[4];
-extern void (*relocated_kexec_smp_wait) (void *);
 extern atomic_t kexec_ready_to_reboot;
 extern void kexec_smp_reboot(void);
 extern void (*_crash_smp_send_stop)(void);
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 7111fa8..31da6f2 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -27,7 +27,6 @@ int (*_machine_kexec_prepare)(struct kimage *) = NULL;
 void (*_machine_kexec_shutdown)(void) = NULL;
 void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
 #ifdef CONFIG_SMP
-void (*relocated_kexec_smp_wait) (void *);
 atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
 void (*_crash_smp_send_stop)(void) = NULL;
 
@@ -141,10 +140,6 @@ machine_kexec(struct kimage *image)
 	printk("Bye ...\n");
 	__flush_cache_all();
 #ifdef CONFIG_SMP
-	/* All secondary cpus now may jump to kexec_wait cycle */
-	relocated_kexec_smp_wait = reboot_code_buffer +
-		(void *)(kexec_smp_wait - relocate_new_kernel);
-	smp_wmb();
 	atomic_set(&kexec_ready_to_reboot, 1);
 
 	kexec_smp_reboot();
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index c6bbf21..14e0eaf 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -100,45 +100,6 @@ done:
 	j		s1
 	END(relocate_new_kernel)
 
-#ifdef CONFIG_SMP
-/*
- * Other CPUs should wait until code is relocated and
- * then start at entry (?) point.
- */
-LEAF(kexec_smp_wait)
-	PTR_L		a0, s_arg0
-	PTR_L		a1, s_arg1
-	PTR_L		a2, s_arg2
-	PTR_L		a3, s_arg3
-	PTR_L		s1, kexec_start_address
-
-	/* Non-relocated address works for args and kexec_start_address ( old
-	 * kernel is not overwritten). But we need relocated address of
-	 * kexec_flag.
-	 */
-
-	bal		1f
-1:	move		t1,ra;
-	PTR_LA		t2,1b
-	PTR_LA		t0,kexec_flag
-	PTR_SUB		t0,t0,t2;
-	PTR_ADD		t0,t1,t0;
-
-1:	LONG_L		s0, (t0)
-	bne		s0, zero,1b
-
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-	.set push
-	.set noreorder
-	synci		0($0)
-	.set pop
-#else
-	sync
-#endif
-	j		s1
-	END(kexec_smp_wait)
-#endif
-
 #ifdef __mips64
        /* all PTR's must be aligned to 8 byte in 64-bit mode */
        .align  3
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/6] MIPS: kexec: Do not flush system wide caches in machine_kexec()
  2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
                   ` (2 preceding siblings ...)
  2018-07-12  1:27 ` [PATCH v2 3/6] MIPS: kexec: Deprecate (relocated_)kexec_smp_wait Dengcheng Zhu
@ 2018-07-12  1:27 ` Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 5/6] MIPS: kexec: Relax memory restriction Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 6/6] MIPS: kexec: Use prepare method from generic platform as default option Dengcheng Zhu
  5 siblings, 0 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

Instead of __flush_cache_all(), simply flush local icache range. In systems
without IOCU, flushing system wide caches require sending IPIs. But other
CPUs have disabled local IRQs waiting for the reboot signal. It will then
cause system hang.

This patch fixes this problem.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
---
 arch/mips/kernel/machine_kexec.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 31da6f2..3ba9d96 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -138,7 +138,16 @@ machine_kexec(struct kimage *image)
 
 	printk("Will call new kernel at %08lx\n", image->start);
 	printk("Bye ...\n");
-	__flush_cache_all();
+	/*
+	 * __flush_cache_all() is expensive but unnecessary. More
+	 * importantly, it could freeze the system as it may need to send
+	 * IPIs, whereas other CPUs have been waiting for the reboot signal
+	 * (kexec_ready_to_reboot) with local irqs disabled, because
+	 * machine_crash_shutdown() has been called prior to entering
+	 * this function - machine_kexec().
+	 */
+	local_flush_icache_range(reboot_code_buffer,
+		reboot_code_buffer + relocate_new_kernel_size);
 #ifdef CONFIG_SMP
 	atomic_set(&kexec_ready_to_reboot, 1);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/6] MIPS: kexec: Relax memory restriction
  2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
                   ` (3 preceding siblings ...)
  2018-07-12  1:27 ` [PATCH v2 4/6] MIPS: kexec: Do not flush system wide caches in machine_kexec() Dengcheng Zhu
@ 2018-07-12  1:27 ` Dengcheng Zhu
  2018-07-12  1:27 ` [PATCH v2 6/6] MIPS: kexec: Use prepare method from generic platform as default option Dengcheng Zhu
  5 siblings, 0 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

We can rely on the system kernel and the dump capture kernel themselves in
memory usage.

Being restrictive with 512MB limit may cause kexec tool failure on some
platforms.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
---
 arch/mips/include/asm/kexec.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index 9618e2e..97c548c 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -12,11 +12,11 @@
 #include <asm/stacktrace.h>
 
 /* Maximum physical address we can use pages from */
-#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
 /* Maximum address we can reach in physical address mode */
-#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
  /* Maximum address we can use for the control code buffer */
-#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
 /* Reserve 3*4096 bytes for board-specific info */
 #define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 6/6] MIPS: kexec: Use prepare method from generic platform as default option
  2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
                   ` (4 preceding siblings ...)
  2018-07-12  1:27 ` [PATCH v2 5/6] MIPS: kexec: Relax memory restriction Dengcheng Zhu
@ 2018-07-12  1:27 ` Dengcheng Zhu
  5 siblings, 0 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-07-12  1:27 UTC (permalink / raw)
  To: pburton, ralf; +Cc: linux-mips, Dengcheng Zhu

The kexec_prepare method for the generic platform should be applicable to
other platforms. For those otherwise, like Octeon, they will use their own
_machine_kexec_prepare().

Without the default prepare work, platforms other than the generic one will
not be able to automatically set up command line correctly for the new
kernel.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
---
 arch/mips/generic/Makefile       |  1 -
 arch/mips/generic/kexec.c        | 44 ----------------------------------------
 arch/mips/kernel/machine_kexec.c | 34 ++++++++++++++++++++++++++++++-
 3 files changed, 33 insertions(+), 46 deletions(-)
 delete mode 100644 arch/mips/generic/kexec.c

diff --git a/arch/mips/generic/Makefile b/arch/mips/generic/Makefile
index d03a36f..181aa13 100644
--- a/arch/mips/generic/Makefile
+++ b/arch/mips/generic/Makefile
@@ -15,5 +15,4 @@ obj-y += proc.o
 obj-$(CONFIG_YAMON_DT_SHIM)		+= yamon-dt.o
 obj-$(CONFIG_LEGACY_BOARD_SEAD3)	+= board-sead3.o
 obj-$(CONFIG_LEGACY_BOARD_OCELOT)	+= board-ocelot.o
-obj-$(CONFIG_KEXEC)			+= kexec.o
 obj-$(CONFIG_VIRT_BOARD_RANCHU)		+= board-ranchu.o
diff --git a/arch/mips/generic/kexec.c b/arch/mips/generic/kexec.c
deleted file mode 100644
index 1ca409f..0000000
--- a/arch/mips/generic/kexec.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2016 Imagination Technologies
- * Author: Marcin Nowakowski <marcin.nowakowski@mips.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kexec.h>
-#include <linux/libfdt.h>
-#include <linux/uaccess.h>
-
-static int generic_kexec_prepare(struct kimage *image)
-{
-	int i;
-
-	for (i = 0; i < image->nr_segments; i++) {
-		struct fdt_header fdt;
-
-		if (image->segment[i].memsz <= sizeof(fdt))
-			continue;
-
-		if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt)))
-			continue;
-
-		if (fdt_check_header(&fdt))
-			continue;
-
-		kexec_args[0] = -2;
-		kexec_args[1] = (unsigned long)
-			phys_to_virt((unsigned long)image->segment[i].mem);
-		break;
-	}
-	return 0;
-}
-
-static int __init register_generic_kexec(void)
-{
-	_machine_kexec_prepare = generic_kexec_prepare;
-	return 0;
-}
-arch_initcall(register_generic_kexec);
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 3ba9d96..f39f424 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -9,6 +9,7 @@
 #include <linux/kexec.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/libfdt.h>
 
 #include <asm/cacheflush.h>
 #include <asm/page.h>
@@ -64,6 +65,36 @@ static void kexec_image_info(const struct kimage *kimage)
 	}
 }
 
+static int default_machine_kexec_prepare(struct kimage *kimage)
+{
+	int i;
+
+	/*
+	 * In case DTB file is not passed to the new kernel, a flat device
+	 * tree will be created by kexec tool. It holds modified command
+	 * line for the new kernel.
+	 */
+	for (i = 0; i < kimage->nr_segments; i++) {
+		struct fdt_header fdt;
+
+		if (kimage->segment[i].memsz <= sizeof(fdt))
+			continue;
+
+		if (copy_from_user(&fdt, kimage->segment[i].buf, sizeof(fdt)))
+			continue;
+
+		if (fdt_check_header(&fdt))
+			continue;
+
+		kexec_args[0] = -2;
+		kexec_args[1] = (unsigned long)
+			phys_to_virt((unsigned long)kimage->segment[i].mem);
+		break;
+	}
+
+	return 0;
+}
+
 int
 machine_kexec_prepare(struct kimage *kimage)
 {
@@ -71,7 +102,8 @@ machine_kexec_prepare(struct kimage *kimage)
 
 	if (_machine_kexec_prepare)
 		return _machine_kexec_prepare(kimage);
-	return 0;
+	else
+		return default_machine_kexec_prepare(kimage);
 }
 
 void
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/6] MIPS: Make play_dead() work for kexec
  2018-07-12  1:27 ` [PATCH v2 1/6] MIPS: Make play_dead() work for kexec Dengcheng Zhu
@ 2018-08-30 23:20   ` Paul Burton
  2018-08-31 16:58     ` Dengcheng Zhu
  0 siblings, 1 reply; 9+ messages in thread
From: Paul Burton @ 2018-08-30 23:20 UTC (permalink / raw)
  To: Dengcheng Zhu; +Cc: pburton, ralf, linux-mips

Hi Dengcheng,

On Wed, Jul 11, 2018 at 06:27:43PM -0700, Dengcheng Zhu wrote:
> diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
> index 03f1026..4615702 100644
> --- a/arch/mips/kernel/smp-cps.c
> +++ b/arch/mips/kernel/smp-cps.c
> @@ -426,12 +406,18 @@ static enum {
>  	CPU_DEATH_POWER,
>  } cpu_death;
>  
> -void play_dead(void)
> +void play_dead(bool kexec)
>  {
>  	unsigned int cpu, core, vpe_id;
>  
>  	local_irq_disable();
> -	idle_task_exit();
> +	/*
> +	 * Don't bother dealing with idle task's mm as we are executing the
> +	 * new kernel.
> +	 */
> +	if (!kexec)
> +		idle_task_exit();
> +
>  	cpu = smp_processor_id();
>  	core = cpu_core(&cpu_data[cpu]);
>  	cpu_death = CPU_DEATH_POWER;
> @@ -454,7 +440,8 @@ void play_dead(void)
>  	}
>  
>  	/* This CPU has chosen its way out */
> -	(void)cpu_report_death();
> +	if (!kexec)
> +		(void)cpu_report_death();

Is it a problem if we just call cpu_report_death() unconditionally? At a
glance it looks like we'd just change cpu_hotplug_state for the CPU, but
since it's going to either power down or hang anyway that seems fine.

If we could do that, then the only other thing the added kexec argument
is used for is preventing us from calling idle_task_exit(). We could
instead move that to arch_cpu_idle_dead() and not need to add the extra
argument to each implementation of play_dead(), which should make this
patch a little cleaner.

Thanks,
    Paul

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/6] MIPS: Make play_dead() work for kexec
  2018-08-30 23:20   ` Paul Burton
@ 2018-08-31 16:58     ` Dengcheng Zhu
  0 siblings, 0 replies; 9+ messages in thread
From: Dengcheng Zhu @ 2018-08-31 16:58 UTC (permalink / raw)
  To: Paul Burton; +Cc: pburton, ralf, linux-mips

Hi Paul,


On 08/30/2018 04:20 PM, Paul Burton wrote:
> Hi Dengcheng,
>
> On Wed, Jul 11, 2018 at 06:27:43PM -0700, Dengcheng Zhu wrote:
>> diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
>> index 03f1026..4615702 100644
>> --- a/arch/mips/kernel/smp-cps.c
>> +++ b/arch/mips/kernel/smp-cps.c
>> @@ -426,12 +406,18 @@ static enum {
>>   	CPU_DEATH_POWER,
>>   } cpu_death;
>>   
>> -void play_dead(void)
>> +void play_dead(bool kexec)
>>   {
>>   	unsigned int cpu, core, vpe_id;
>>   
>>   	local_irq_disable();
>> -	idle_task_exit();
>> +	/*
>> +	 * Don't bother dealing with idle task's mm as we are executing the
>> +	 * new kernel.
>> +	 */
>> +	if (!kexec)
>> +		idle_task_exit();
>> +
>>   	cpu = smp_processor_id();
>>   	core = cpu_core(&cpu_data[cpu]);
>>   	cpu_death = CPU_DEATH_POWER;
>> @@ -454,7 +440,8 @@ void play_dead(void)
>>   	}
>>   
>>   	/* This CPU has chosen its way out */
>> -	(void)cpu_report_death();
>> +	if (!kexec)
>> +		(void)cpu_report_death();
> Is it a problem if we just call cpu_report_death() unconditionally? At a
> glance it looks like we'd just change cpu_hotplug_state for the CPU, but
> since it's going to either power down or hang anyway that seems fine.
>
> If we could do that, then the only other thing the added kexec argument
> is used for is preventing us from calling idle_task_exit(). We could
> instead move that to arch_cpu_idle_dead() and not need to add the extra
> argument to each implementation of play_dead(), which should make this
> patch a little cleaner.

Agreed. Thanks!



Dengcheng

---------------------------------------------------------------------------

*From:* Paul Burton <mailto:paul.burton@mips.com>
*Sent:* Thursday, August 30, 2018 4:20PM
*To:* Dengcheng Zhu <mailto:dzhu@wavecomp.com>
*Cc:* Pburton <mailto:pburton@wavecomp.com>, Ralf 
<mailto:ralf@linux-mips.org>, Linux-mips <mailto:linux-mips@linux-mips.org>
*Subject:* Re: [PATCH v2 1/6] MIPS: Make play_dead() work for kexec

Hi Dengcheng,

On Wed, Jul 11, 2018 at 06:27:43PM -0700, Dengcheng Zhu wrote:

> diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
> index 03f1026..4615702 100644
> --- a/arch/mips/kernel/smp-cps.c
> +++ b/arch/mips/kernel/smp-cps.c
> @@ -426,12 +406,18 @@ static enum {
>   	CPU_DEATH_POWER,
>   } cpu_death;
>   
> -void play_dead(void)
> +void play_dead(bool kexec)
>   {
>   	unsigned int cpu, core, vpe_id;
>   
>   	local_irq_disable();
> -	idle_task_exit();
> +	/*
> +	 * Don't bother dealing with idle task's mm as we are executing the
> +	 * new kernel.
> +	 */
> +	if (!kexec)
> +		idle_task_exit();
> +
>   	cpu = smp_processor_id();
>   	core = cpu_core(&cpu_data[cpu]);
>   	cpu_death = CPU_DEATH_POWER;
> @@ -454,7 +440,8 @@ void play_dead(void)
>   	}
>   
>   	/* This CPU has chosen its way out */
> -	(void)cpu_report_death();
> +	if (!kexec)
> +		(void)cpu_report_death();

Is it a problem if we just call cpu_report_death() unconditionally? At a
glance it looks like we'd just change cpu_hotplug_state for the CPU, but
since it's going to either power down or hang anyway that seems fine.

If we could do that, then the only other thing the added kexec argument
is used for is preventing us from calling idle_task_exit(). We could
instead move that to arch_cpu_idle_dead() and not need to add the extra
argument to each implementation of play_dead(), which should make this
patch a little cleaner.

Thanks,
     Paul

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-08-31 16:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-12  1:27 [PATCH v2 0/6] MIPS: kexec/kdump: Fix smp reboot and other issues Dengcheng Zhu
2018-07-12  1:27 ` [PATCH v2 1/6] MIPS: Make play_dead() work for kexec Dengcheng Zhu
2018-08-30 23:20   ` Paul Burton
2018-08-31 16:58     ` Dengcheng Zhu
2018-07-12  1:27 ` [PATCH v2 2/6] MIPS: kexec: Let the new kernel handle all CPUs Dengcheng Zhu
2018-07-12  1:27 ` [PATCH v2 3/6] MIPS: kexec: Deprecate (relocated_)kexec_smp_wait Dengcheng Zhu
2018-07-12  1:27 ` [PATCH v2 4/6] MIPS: kexec: Do not flush system wide caches in machine_kexec() Dengcheng Zhu
2018-07-12  1:27 ` [PATCH v2 5/6] MIPS: kexec: Relax memory restriction Dengcheng Zhu
2018-07-12  1:27 ` [PATCH v2 6/6] MIPS: kexec: Use prepare method from generic platform as default option Dengcheng Zhu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.