[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20240918025926.233858-1-guocai.he.cn@windriver.com>
Date: Wed, 18 Sep 2024 10:59:26 +0800
From: guocai.he.cn@...driver.com
To: tglx@...utronix.de
Cc: bp@...en8.de, guocai.he.cn@...driver.com, henning.schild@...mens.com,
jan.kiszka@...mens.com, linux-kernel@...r.kernel.org,
linux@...ck-us.net, mingo@...hat.com, peterz@...radead.org,
x86@...nel.org, xenomai@...omai.org
Subject: [PATCH] patch for poweroff
From: Guocai He <guocai.he.cn@...driver.com>
My branch is v5.2/standard/preempt-rt/intel-x86 and I make a patch according
to your adviced patch.
But it does not work.
Do you have more advice?
Thanks very much.
The following is my patch on v5.2:
---
arch/x86/include/asm/processor.h | 2 +-
arch/x86/kernel/process.c | 14 +++++++++++++-
arch/x86/kernel/reboot.c | 2 +-
arch/x86/kernel/smp.c | 9 ++++++---
4 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 5f4e79d14613..4c1cf610807a 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -975,7 +975,7 @@ bool xen_set_default_idle(void);
#define xen_set_default_idle 0
#endif
-void stop_this_cpu(void *dummy);
+void stop_this_cpu(bool sync);
void df_debug(struct pt_regs *regs, long error_code);
void microcode_check(void);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 2243af6530f8..35d5cf73716e 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -590,9 +590,21 @@ bool xen_set_default_idle(void)
}
#endif
-void stop_this_cpu(void *dummy)
+atomic_t cpus_stop_in_ipi;
+void stop_this_cpu(bool sync)
{
local_irq_disable();
+
+ /*
+ * Account this cpu and loop until the other cpus reached this
+ * point. If they don't react, the control cpu will raise an NMI.
+ */
+ if(sync) {
+ atomic_dec(&cpus_stop_in_ipi);
+ while (atomic_read(&cpus_stop_in_ipi))
+ cpu_relax();
+ }
+
/*
* Remove this CPU:
*/
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 3f677832fc12..389643727e37 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -742,7 +742,7 @@ static void native_machine_halt(void)
tboot_shutdown(TB_SHUTDOWN_HALT);
- stop_this_cpu(NULL);
+ stop_this_cpu(false);
}
static void native_machine_power_off(void)
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index f2a749586252..9dee65b96115 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -112,6 +112,7 @@
* about nothing of note with C stepping upwards.
*/
+extern atomic_t cpus_stop_in_ipi;
static atomic_t stopping_cpu = ATOMIC_INIT(-1);
static bool smp_no_nmi_ipi = false;
@@ -162,7 +163,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
return NMI_HANDLED;
cpu_emergency_vmxoff();
- stop_this_cpu(NULL);
+ stop_this_cpu(false);
return NMI_HANDLED;
}
@@ -175,7 +176,7 @@ asmlinkage __visible void smp_reboot_interrupt(void)
{
ipi_entering_ack_irq();
cpu_emergency_vmxoff();
- stop_this_cpu(NULL);
+ stop_this_cpu(true);
irq_exit();
}
@@ -192,7 +193,8 @@ static void native_stop_other_cpus(int wait)
if (reboot_force)
return;
-
+
+ atomic_set(&cpus_stop_in_ipi, num_online_cpus() - 1);
/*
* Use an own vector here because smp_call_function
* does lots of things not suitable in a panic situation.
@@ -256,6 +258,7 @@ static void native_stop_other_cpus(int wait)
local_irq_save(flags);
disable_local_APIC();
mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
+ atomic_set(&cpus_stop_in_ipi, 0);
local_irq_restore(flags);
}
--
2.25.1
Powered by blists - more mailing lists