* [RFC PATCH 0/4] Flush nvdimm/pmem to memory before machine restart
@ 2024-06-18 15:41 Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 1/4] kernel/reboot: Introduce pre_restart notifiers Mathieu Desnoyers
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Mathieu Desnoyers @ 2024-06-18 15:41 UTC (permalink / raw)
To: Dan Williams, Steven Rostedt
Cc: linux-kernel, Mathieu Desnoyers, Vishal Verma, Dave Jiang,
Ira Weiny, nvdimm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Catalin Marinas, Will Deacon,
linux-arm-kernel
Introduce a new pre_restart notifier chain for callbacks that need to
be executed after the system has been made quiescent with
syscore_shutdown(), before machine restart.
Register pre-restart notifiers to flush pmem areas from CPU data cache
to memory on reboot, immediately before restarting the machine. This
ensures all other CPUs are quiescent before the pmem data is flushed to
memory.
The use-case for this new notifier chain is to preserve tracing data
within pmem areas on systems where the BIOS does not clear memory across
warm reboots.
I did an earlier POC that flushed caches on panic/die oops notifiers [1],
but it did not cover the reboot case. I've been made aware that some
distribution vendors have started shipping their own modified version of
my earlier POC patch. This makes a strong argument for upstreaming this
work.
Link: https://lore.kernel.org/linux-kernel/f6067e3e-a2bc-483d-b214-6e3fe6691279@efficios.com/ [1]
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: nvdimm@lists.linux.dev
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Mathieu Desnoyers (4):
kernel/reboot: Introduce pre_restart notifiers
nvdimm/pmem: Flush to memory before machine restart
arm64: Invoke pre_restart notifiers
x86: Invoke pre_restart notifiers
arch/arm64/kernel/process.c | 2 ++
arch/x86/kernel/reboot.c | 7 +++--
drivers/nvdimm/pmem.c | 29 ++++++++++++++++++++-
drivers/nvdimm/pmem.h | 2 ++
include/linux/reboot.h | 4 +++
kernel/reboot.c | 51 +++++++++++++++++++++++++++++++++++++
6 files changed, 92 insertions(+), 3 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 1/4] kernel/reboot: Introduce pre_restart notifiers
2024-06-18 15:41 [RFC PATCH 0/4] Flush nvdimm/pmem to memory before machine restart Mathieu Desnoyers
@ 2024-06-18 15:41 ` Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 2/4] nvdimm/pmem: Flush to memory before machine restart Mathieu Desnoyers
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Mathieu Desnoyers @ 2024-06-18 15:41 UTC (permalink / raw)
To: Dan Williams, Steven Rostedt
Cc: linux-kernel, Mathieu Desnoyers, Vishal Verma, Dave Jiang,
Ira Weiny, nvdimm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Catalin Marinas, Will Deacon,
linux-arm-kernel
Introduce a new pre_restart notifier chain for callbacks that need to
be executed after the system has been made quiescent with
syscore_shutdown(), before machine restart.
This pre_restart notifier chain should be invoked on machine restart and
on emergency machine restart.
The use-case for this new notifier chain is to preserve tracing data
within pmem areas on systems where the BIOS does not clear memory across
warm reboots.
Why do we need a new notifier chain ?
1) The reboot and restart_prepare notifiers are called too early in the
reboot sequence: they are invoked before syscore_shutdown(), which
leaves other CPUs actively running threads while those notifiers are
invoked.
2) The "restart" notifier is meant to trigger the actual machine
restart, and is not meant to be invoked as a last step immediately
before restart. It is also not always used: some architecture code
choose to bypass this restart notifier and reboot directly from the
architecture code.
Wiring up the architecture code to call this notifier chain is left to
follow-up arch-specific patches.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: nvdimm@lists.linux.dev
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
---
include/linux/reboot.h | 4 ++++
kernel/reboot.c | 51 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index abcdde4df697..c7f340e81451 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -50,6 +50,10 @@ extern int register_restart_handler(struct notifier_block *);
extern int unregister_restart_handler(struct notifier_block *);
extern void do_kernel_restart(char *cmd);
+extern int register_pre_restart_handler(struct notifier_block *);
+extern int unregister_pre_restart_handler(struct notifier_block *);
+extern void do_kernel_pre_restart(char *cmd);
+
/*
* Architecture-specific implementations of sys_reboot commands.
*/
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 22c16e2564cc..b7287dd48d35 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -235,6 +235,57 @@ void do_kernel_restart(char *cmd)
atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);
}
+/*
+ * Notifier list for kernel code which wants to be called immediately
+ * before restarting the system.
+ */
+static ATOMIC_NOTIFIER_HEAD(pre_restart_handler_list);
+
+/**
+ * register_pre_restart_handler - Register function to be called in preparation
+ * to reset the system
+ * @nb: Info about handler function to be called
+ *
+ * Registers a function with code to be called in preparation to restart
+ * the system.
+ *
+ * Currently always returns zero, as atomic_notifier_chain_register()
+ * always returns zero.
+ */
+int register_pre_restart_handler(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&pre_restart_handler_list, nb);
+}
+EXPORT_SYMBOL(register_pre_restart_handler);
+
+/**
+ * unregister_pre_restart_handler - Unregister previously registered
+ * pre-restart handler
+ * @nb: Hook to be unregistered
+ *
+ * Unregisters a previously registered pre-restart handler function.
+ *
+ * Returns zero on success, or %-ENOENT on failure.
+ */
+int unregister_pre_restart_handler(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&pre_restart_handler_list, nb);
+}
+EXPORT_SYMBOL(unregister_pre_restart_handler);
+
+/**
+ * do_kernel_pre_restart - Execute kernel pre-restart handler call chain
+ *
+ * Calls functions registered with register_pre_restart_handler.
+ *
+ * Expected to be called from machine_restart and
+ * machine_emergency_restart before invoking the restart handlers.
+ */
+void do_kernel_pre_restart(char *cmd)
+{
+ atomic_notifier_call_chain(&pre_restart_handler_list, reboot_mode, cmd);
+}
+
void migrate_to_reboot_cpu(void)
{
/* The boot cpu is always logical cpu 0 */
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 2/4] nvdimm/pmem: Flush to memory before machine restart
2024-06-18 15:41 [RFC PATCH 0/4] Flush nvdimm/pmem to memory before machine restart Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 1/4] kernel/reboot: Introduce pre_restart notifiers Mathieu Desnoyers
@ 2024-06-18 15:41 ` Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 3/4] arm64: Invoke pre_restart notifiers Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 4/4] x86: " Mathieu Desnoyers
3 siblings, 0 replies; 5+ messages in thread
From: Mathieu Desnoyers @ 2024-06-18 15:41 UTC (permalink / raw)
To: Dan Williams, Steven Rostedt
Cc: linux-kernel, Mathieu Desnoyers, Vishal Verma, Dave Jiang,
Ira Weiny, nvdimm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Catalin Marinas, Will Deacon,
linux-arm-kernel
Register pre-restart notifiers to flush pmem areas from CPU data cache
to memory on reboot, immediately before restarting the machine. This
ensures all other CPUs are quiescent before the pmem data is flushed to
memory.
I did an earlier POC that flushed caches on panic/die oops notifiers [1],
but it did not cover the reboot case. I've been made aware that some
distribution vendors have started shipping their own modified version of
my earlier POC patch. This makes a strong argument for upstreaming this
work.
Use the newly introduced "pre-restart" notifiers to flush pmem data to
memory immediately before machine restart.
Delta from my POC patch [1]:
Looking at the panic() code, it invokes emergency_restart() to restart
the machine, which uses the new pre-restart notifiers. There is
therefore no need to hook into panic handlers explicitly.
Looking at the die notifiers, those don't actually end up triggering
a machine restart, so it does not appear to be relevant to flush pmem
to memory there. I must admit I originally looked at how ftrace hooked
into panic/die-oops handlers for its ring buffers, but the use-case it
different here: we only want to cover machine restart use-cases.
Link: https://lore.kernel.org/linux-kernel/f6067e3e-a2bc-483d-b214-6e3fe6691279@efficios.com/ [1]
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: nvdimm@lists.linux.dev
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
---
drivers/nvdimm/pmem.c | 29 ++++++++++++++++++++++++++++-
drivers/nvdimm/pmem.h | 2 ++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 598fe2e89bda..bf1d187a9dca 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -26,12 +26,16 @@
#include <linux/dax.h>
#include <linux/nd.h>
#include <linux/mm.h>
+#include <linux/reboot.h>
#include <asm/cacheflush.h>
#include "pmem.h"
#include "btt.h"
#include "pfn.h"
#include "nd.h"
+static int pmem_pre_restart_handler(struct notifier_block *self,
+ unsigned long ev, void *unused);
+
static struct device *to_dev(struct pmem_device *pmem)
{
/*
@@ -423,6 +427,7 @@ static void pmem_release_disk(void *__pmem)
{
struct pmem_device *pmem = __pmem;
+ unregister_pre_restart_notifier(&pmem->pre_restart_notifier);
dax_remove_host(pmem->disk);
kill_dax(pmem->dax_dev);
put_dax(pmem->dax_dev);
@@ -575,9 +580,14 @@ static int pmem_attach_disk(struct device *dev,
goto out_cleanup_dax;
dax_write_cache(dax_dev, nvdimm_has_cache(nd_region));
}
- rc = device_add_disk(dev, disk, pmem_attribute_groups);
+ pmem->pre_restart_notifier.notifier_call = pmem_pre_restart_handler;
+ pmem->pre_restart_notifier.priority = 0;
+ rc = register_pre_restart_notifier(&pmem->pre_restart_notifier);
if (rc)
goto out_remove_host;
+ rc = device_add_disk(dev, disk, pmem_attribute_groups);
+ if (rc)
+ goto out_unregister_reboot;
if (devm_add_action_or_reset(dev, pmem_release_disk, pmem))
return -ENOMEM;
@@ -589,6 +599,8 @@ static int pmem_attach_disk(struct device *dev,
dev_warn(dev, "'badblocks' notification disabled\n");
return 0;
+out_unregister_pre_restart:
+ unregister_pre_restart_notifier(&pmem->pre_restart_notifier);
out_remove_host:
dax_remove_host(pmem->disk);
out_cleanup_dax:
@@ -751,6 +763,21 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event)
}
}
+/*
+ * For volatile memory use-cases where explicit flushing of the data cache is
+ * not useful after stores, the pmem reboot notifier is called on preparation
+ * for restart to make sure the content of the pmem memory area is flushed from
+ * data cache to memory, so it can be preserved across warm reboot.
+ */
+static int pmem_pre_restart_handler(struct notifier_block *self,
+ unsigned long ev, void *unused)
+{
+ struct pmem_device *pmem = container_of(self, struct pmem_device, pre_restart_notifier);
+
+ arch_wb_cache_pmem(pmem->virt_addr, pmem->size);
+ return NOTIFY_DONE;
+}
+
MODULE_ALIAS("pmem");
MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_IO);
MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_PMEM);
diff --git a/drivers/nvdimm/pmem.h b/drivers/nvdimm/pmem.h
index 392b0b38acb9..b8a2a518cf82 100644
--- a/drivers/nvdimm/pmem.h
+++ b/drivers/nvdimm/pmem.h
@@ -4,6 +4,7 @@
#include <linux/page-flags.h>
#include <linux/badblocks.h>
#include <linux/memremap.h>
+#include <linux/notifier.h>
#include <linux/types.h>
#include <linux/pfn_t.h>
#include <linux/fs.h>
@@ -27,6 +28,7 @@ struct pmem_device {
struct dax_device *dax_dev;
struct gendisk *disk;
struct dev_pagemap pgmap;
+ struct notifier_block pre_restart_notifier;
};
long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 3/4] arm64: Invoke pre_restart notifiers
2024-06-18 15:41 [RFC PATCH 0/4] Flush nvdimm/pmem to memory before machine restart Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 1/4] kernel/reboot: Introduce pre_restart notifiers Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 2/4] nvdimm/pmem: Flush to memory before machine restart Mathieu Desnoyers
@ 2024-06-18 15:41 ` Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 4/4] x86: " Mathieu Desnoyers
3 siblings, 0 replies; 5+ messages in thread
From: Mathieu Desnoyers @ 2024-06-18 15:41 UTC (permalink / raw)
To: Dan Williams, Steven Rostedt
Cc: linux-kernel, Mathieu Desnoyers, Vishal Verma, Dave Jiang,
Ira Weiny, nvdimm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Catalin Marinas, Will Deacon,
linux-arm-kernel
Invoke the pre_restart notifiers after shutdown, before machine restart.
This allows preserving pmem memory across warm reboots.
Invoke the pre_restart notifiers before emergency machine restart as
well to cover the panic() scenario.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: nvdimm@lists.linux.dev
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
---
arch/arm64/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 4ae31b7af6c3..4a27397617fb 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -129,6 +129,8 @@ void machine_restart(char *cmd)
local_irq_disable();
smp_send_stop();
+ do_kernel_pre_restart(cmd);
+
/*
* UpdateCapsule() depends on the system being reset via
* ResetSystem().
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 4/4] x86: Invoke pre_restart notifiers
2024-06-18 15:41 [RFC PATCH 0/4] Flush nvdimm/pmem to memory before machine restart Mathieu Desnoyers
` (2 preceding siblings ...)
2024-06-18 15:41 ` [RFC PATCH 3/4] arm64: Invoke pre_restart notifiers Mathieu Desnoyers
@ 2024-06-18 15:41 ` Mathieu Desnoyers
3 siblings, 0 replies; 5+ messages in thread
From: Mathieu Desnoyers @ 2024-06-18 15:41 UTC (permalink / raw)
To: Dan Williams, Steven Rostedt
Cc: linux-kernel, Mathieu Desnoyers, Vishal Verma, Dave Jiang,
Ira Weiny, nvdimm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Catalin Marinas, Will Deacon,
linux-arm-kernel
Invoke the pre_restart notifiers after shutdown, before machine restart.
This allows preserving pmem memory across warm reboots.
Invoke the pre_restart notifiers on emergency_machine_restart to cover
the panic() scenario.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: nvdimm@lists.linux.dev
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
---
arch/x86/kernel/reboot.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index f3130f762784..222619fa63c6 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -631,8 +631,10 @@ static void native_machine_emergency_restart(void)
int orig_reboot_type = reboot_type;
unsigned short mode;
- if (reboot_emergency)
+ if (reboot_emergency) {
+ do_kernel_pre_restart(NULL);
emergency_reboot_disable_virtualization();
+ }
tboot_shutdown(TB_SHUTDOWN_REBOOT);
@@ -760,12 +762,13 @@ static void __machine_emergency_restart(int emergency)
machine_ops.emergency_restart();
}
-static void native_machine_restart(char *__unused)
+static void native_machine_restart(char *cmd)
{
pr_notice("machine restart\n");
if (!reboot_force)
machine_shutdown();
+ do_kernel_pre_restart(cmd);
__machine_emergency_restart(0);
}
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-06-18 15:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-18 15:41 [RFC PATCH 0/4] Flush nvdimm/pmem to memory before machine restart Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 1/4] kernel/reboot: Introduce pre_restart notifiers Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 2/4] nvdimm/pmem: Flush to memory before machine restart Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 3/4] arm64: Invoke pre_restart notifiers Mathieu Desnoyers
2024-06-18 15:41 ` [RFC PATCH 4/4] x86: " Mathieu Desnoyers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®