diff options
author | Peter Zijlstra <peterz@infradead.org> | 2023-01-12 13:44:12 +0100 |
---|---|---|
committer | Peter Zijlstra <peterz@infradead.org> | 2023-11-29 09:21:47 +0100 |
commit | 1104d6206a2fd888a7f751ed9a7185ee079f44ac (patch) | |
tree | 43edd2cc5c023fed6dd685997edc66e82de27839 | |
parent | 3a2763998da787b0335a971aae6b1294d3676709 (diff) | |
download | queue-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.c | 30 |
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); |