aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2023-01-12 13:44:12 +0100
committerPeter Zijlstra <peterz@infradead.org>2023-11-29 09:21:47 +0100
commit1104d6206a2fd888a7f751ed9a7185ee079f44ac (patch)
tree43edd2cc5c023fed6dd685997edc66e82de27839
parent3a2763998da787b0335a971aae6b1294d3676709 (diff)
downloadqueue-x86/call-stuff.tar.gz
PM / hibernate: Add minimal noinstr annotationsx86/call-stuff
When resuming there must not be any code between swsusp_arch_suspend() and restore_processor_state() since the CPU state is ill defined at this point in time. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Joan Bruguera <joanbrugueram@gmail.com>
-rw-r--r--kernel/power/hibernate.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index dee341ae4ace78..97b62773ecfc0c 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -281,6 +281,32 @@ __weak int arch_resume_nosmt(void)
return 0;
}
+static noinstr int suspend_and_restore(void)
+{
+ int error;
+
+ /*
+ * Strictly speaking swsusp_arch_suspend() should be noinstr too but it
+ * is typically written in asm, as such, assume it is good and shut up
+ * the validator.
+ */
+ instrumentation_begin();
+ error = swsusp_arch_suspend();
+ instrumentation_end();
+
+ /*
+ * Architecture resume code 'returns' from the swsusp_arch_suspend()
+ * call and resumes execution here with some very dodgy machine state.
+ *
+ * Compiler instrumentation between these two calls (or in
+ * restore_processor_state() for that matter) will make life *very*
+ * interesting indeed.
+ */
+ restore_processor_state();
+
+ return error;
+}
+
/**
* create_image - Create a hibernation image.
* @platform_mode: Whether or not to use the platform driver.
@@ -324,9 +350,7 @@ static int create_image(int platform_mode)
in_suspend = 1;
save_processor_state();
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
- error = swsusp_arch_suspend();
- /* Restore control flow magically appears here */
- restore_processor_state();
+ error = suspend_and_restore();
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
if (error)
pr_err("Error %d creating image\n", error);