* [PATCH 0/2] arm64/suspend: Save more registers over suspend
@ 2026-11-05 16:05 Mark Brown
2026-11-05 16:05 ` [PATCH 1/2] arm64: suspend: Save POR_EL0 " Mark Brown
2026-11-05 16:05 ` [PATCH 2/2] arm64: suspend: Save GCS state " Mark Brown
0 siblings, 2 replies; 7+ messages in thread
From: Mark Brown @ 2026-11-05 16:05 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual,
Joey Gouly
Cc: linux-arm-kernel, linux-kernel, Mark Brown, stable
While reviewing beeec0404622 (arm64: suspend: Save and restore
TPIDR2_EL0 across CPU suspend) I noticed some more registers that we
need to save over suspend, fix this.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Mark Brown (2):
arm64: suspend: Save POR_EL0 over suspend
arm64: suspend: Save GCS state over suspend
arch/arm64/include/asm/suspend.h | 2 +-
arch/arm64/mm/proc.S | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
---
base-commit: b0958b1397fb5ffdb995c0ccc74349841929c08d
base-tree: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
change-id: 20261104-arm64-fix-sysreg-suspend-56624f4a411c
Best regards,
--
Mark Brown <broonie@kernel.org>
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/2] arm64: suspend: Save POR_EL0 over suspend 2026-11-05 16:05 [PATCH 0/2] arm64/suspend: Save more registers over suspend Mark Brown @ 2026-11-05 16:05 ` Mark Brown 2026-11-11 13:33 ` Vladimir Murzin 2026-11-05 16:05 ` [PATCH 2/2] arm64: suspend: Save GCS state " Mark Brown 1 sibling, 1 reply; 7+ messages in thread From: Mark Brown @ 2026-11-05 16:05 UTC (permalink / raw) To: Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual, Joey Gouly Cc: linux-arm-kernel, linux-kernel, Mark Brown, stable POR_EL0 is a live EL0 register on systems with S1POE but it is not saved and restored by cpu_do_suspend()/cpu_do_resume(). This means that the task that initiated suspend can return to userspace with an UNKNOWN value. Fix this by saving and restoring the value over suspend. This increases the size of struct cpu_suspend_ctx. Fixes: bf83dae90fbc ("arm64: enable the Permission Overlay Extension for EL0") Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org --- arch/arm64/include/asm/suspend.h | 2 +- arch/arm64/mm/proc.S | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h index a5abf0615594..eb9ce315f146 100644 --- a/arch/arm64/include/asm/suspend.h +++ b/arch/arm64/include/asm/suspend.h @@ -2,7 +2,7 @@ #ifndef __ASM_SUSPEND_H #define __ASM_SUSPEND_H -#define NR_CTX_REGS 15 +#define NR_CTX_REGS 16 #define NR_CALLEE_SAVED_REGS 12 /* diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index b1516630904d..664ea9e3b9ad 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -117,6 +117,10 @@ alternative_else_nop_endif alternative_if ARM64_SME mrs_s x2, SYS_TPIDR2_EL0 str x2, [x0, #112] +alternative_else_nop_endif +alternative_if ARM64_HAS_S1POE + mrs x2, REG_POR_EL0 + str x2, [x0, #120] alternative_else_nop_endif ret SYM_FUNC_END(cpu_do_suspend) @@ -160,6 +164,10 @@ alternative_if ARM64_SME ldr x2, [x0, #112] msr_s SYS_TPIDR2_EL0, x2 alternative_else_nop_endif +alternative_if ARM64_HAS_S1POE + ldr x2, [x0, #120] + msr REG_POR_EL0, x2 +alternative_else_nop_endif msr sctlr_el1, x12 set_this_cpu_offset x13 -- 2.47.3 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] arm64: suspend: Save POR_EL0 over suspend 2026-11-05 16:05 ` [PATCH 1/2] arm64: suspend: Save POR_EL0 " Mark Brown @ 2026-11-11 13:33 ` Vladimir Murzin 2026-11-11 13:52 ` Mark Brown 0 siblings, 1 reply; 7+ messages in thread From: Vladimir Murzin @ 2026-11-11 13:33 UTC (permalink / raw) To: Mark Brown, Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual, Joey Gouly Cc: linux-arm-kernel, linux-kernel, stable On 11/5/26 16:05, Mark Brown wrote: > POR_EL0 is a live EL0 register on systems with S1POE but it is not saved > and restored by cpu_do_suspend()/cpu_do_resume(). This means that the task > that initiated suspend can return to userspace with an UNKNOWN value. Fix > this by saving and restoring the value over suspend. > > This increases the size of struct cpu_suspend_ctx. This seems to be implied since we need storage to keep register value, no? > > Fixes: bf83dae90fbc ("arm64: enable the Permission Overlay Extension for EL0") > Signed-off-by: Mark Brown <broonie@kernel.org> > Cc: stable@vger.kernel.org > --- > arch/arm64/include/asm/suspend.h | 2 +- > arch/arm64/mm/proc.S | 8 ++++++++ > 2 files changed, 9 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h > index a5abf0615594..eb9ce315f146 100644 > --- a/arch/arm64/include/asm/suspend.h > +++ b/arch/arm64/include/asm/suspend.h > @@ -2,7 +2,7 @@ > #ifndef __ASM_SUSPEND_H > #define __ASM_SUSPEND_H > > -#define NR_CTX_REGS 15 > +#define NR_CTX_REGS 16 > #define NR_CALLEE_SAVED_REGS 12 > > /* > diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S > index b1516630904d..664ea9e3b9ad 100644 > --- a/arch/arm64/mm/proc.S > +++ b/arch/arm64/mm/proc.S > @@ -117,6 +117,10 @@ alternative_else_nop_endif > alternative_if ARM64_SME > mrs_s x2, SYS_TPIDR2_EL0 > str x2, [x0, #112] > +alternative_else_nop_endif > +alternative_if ARM64_HAS_S1POE > + mrs x2, REG_POR_EL0 > + str x2, [x0, #120] > alternative_else_nop_endif > ret > SYM_FUNC_END(cpu_do_suspend) > @@ -160,6 +164,10 @@ alternative_if ARM64_SME > ldr x2, [x0, #112] > msr_s SYS_TPIDR2_EL0, x2 > alternative_else_nop_endif > +alternative_if ARM64_HAS_S1POE > + ldr x2, [x0, #120] > + msr REG_POR_EL0, x2 > +alternative_else_nop_endif > > msr sctlr_el1, x12 > set_this_cpu_offset x13 > > -- 2.47.3 > FWIW, Reviewed-by: Vladimir Murzin <vladimir.murzin@arm.com> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] arm64: suspend: Save POR_EL0 over suspend 2026-11-11 13:33 ` Vladimir Murzin @ 2026-11-11 13:52 ` Mark Brown 0 siblings, 0 replies; 7+ messages in thread From: Mark Brown @ 2026-11-11 13:52 UTC (permalink / raw) To: Vladimir Murzin Cc: Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual, Joey Gouly, linux-arm-kernel, linux-kernel, stable [-- Attachment #1: Type: text/plain, Size: 406 bytes --] On Wed, Nov 11, 2026 at 01:33:27PM +0000, Vladimir Murzin wrote: > On 11/5/26 16:05, Mark Brown wrote: > > This increases the size of struct cpu_suspend_ctx. > This seems to be implied since we need storage to keep register value, no? Yeah, it's just noting that we're not fitting in the existing padding which prior commits seemed to be keeping track of for reasons I'm not 100% specifically clear on. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] arm64: suspend: Save GCS state over suspend 2026-11-05 16:05 [PATCH 0/2] arm64/suspend: Save more registers over suspend Mark Brown 2026-11-05 16:05 ` [PATCH 1/2] arm64: suspend: Save POR_EL0 " Mark Brown @ 2026-11-05 16:05 ` Mark Brown 2026-11-11 13:44 ` Vladimir Murzin 1 sibling, 1 reply; 7+ messages in thread From: Mark Brown @ 2026-11-05 16:05 UTC (permalink / raw) To: Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual, Joey Gouly Cc: linux-arm-kernel, linux-kernel, Mark Brown, stable GCSCRE0_EL1 and GCSPR_EL0 are live registers for EL0 on systems with GCS but are not saved and restored by cpu_do_suspend()/cpu_do_resume(). This means that the task that initiated suspend can return to userspace with UNKNOWN or incorrect values for GCSPR_EL0 and GCSCRE0_EL1 (many fields in GCSCRE0_EL1 reset to 0). This will in turn lead to ongoing corruption, including not restoring mode until a task with a different GCS mode is run. Fix this by saving and restoring the values over suspend. This increases the size of struct cpu_suspend_ctx by 16 bytes. Fixes: 5d8b172e7005 ("arm64: Add Kconfig for Guarded Control Stack (GCS)") Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org --- arch/arm64/include/asm/suspend.h | 2 +- arch/arm64/mm/proc.S | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h index eb9ce315f146..8e9c97aab15a 100644 --- a/arch/arm64/include/asm/suspend.h +++ b/arch/arm64/include/asm/suspend.h @@ -2,7 +2,7 @@ #ifndef __ASM_SUSPEND_H #define __ASM_SUSPEND_H -#define NR_CTX_REGS 16 +#define NR_CTX_REGS 18 #define NR_CALLEE_SAVED_REGS 12 /* diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 664ea9e3b9ad..99aacf03367d 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -121,6 +121,12 @@ alternative_else_nop_endif alternative_if ARM64_HAS_S1POE mrs x2, REG_POR_EL0 str x2, [x0, #120] +alternative_else_nop_endif +alternative_if ARM64_HAS_GCS + mrs x2, REG_GCSPR_EL0 + str x2, [x0, #128] + mrs x2, REG_GCSCRE0_EL1 + str x2, [x0, #136] alternative_else_nop_endif ret SYM_FUNC_END(cpu_do_suspend) @@ -168,6 +174,12 @@ alternative_if ARM64_HAS_S1POE ldr x2, [x0, #120] msr REG_POR_EL0, x2 alternative_else_nop_endif +alternative_if ARM64_HAS_GCS + ldr x2, [x0, #128] + msr REG_GCSPR_EL0, x2 + ldr x2, [x0, #136] + msr REG_GCSCRE0_EL1, x2 +alternative_else_nop_endif msr sctlr_el1, x12 set_this_cpu_offset x13 -- 2.47.3 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] arm64: suspend: Save GCS state over suspend 2026-11-05 16:05 ` [PATCH 2/2] arm64: suspend: Save GCS state " Mark Brown @ 2026-11-11 13:44 ` Vladimir Murzin 2026-11-11 13:55 ` Mark Brown 0 siblings, 1 reply; 7+ messages in thread From: Vladimir Murzin @ 2026-11-11 13:44 UTC (permalink / raw) To: Mark Brown, Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual, Joey Gouly Cc: linux-arm-kernel, linux-kernel, stable On 11/5/26 16:05, Mark Brown wrote: > GCSCRE0_EL1 and GCSPR_EL0 are live registers for EL0 on systems with GCS > but are not saved and restored by cpu_do_suspend()/cpu_do_resume(). This > means that the task that initiated suspend can return to userspace with > UNKNOWN or incorrect values for GCSPR_EL0 and GCSCRE0_EL1 (many fields > in GCSCRE0_EL1 reset to 0). This will in turn lead to ongoing > corruption, including not restoring mode until a task with a different > GCS mode is run. Fix this by saving and restoring the values over > suspend. > > This increases the size of struct cpu_suspend_ctx by 16 bytes. > > Fixes: 5d8b172e7005 ("arm64: Add Kconfig for Guarded Control Stack (GCS)") > Signed-off-by: Mark Brown <broonie@kernel.org> > Cc: stable@vger.kernel.org > --- > arch/arm64/include/asm/suspend.h | 2 +- > arch/arm64/mm/proc.S | 12 ++++++++++++ > 2 files changed, 13 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h > index eb9ce315f146..8e9c97aab15a 100644 > --- a/arch/arm64/include/asm/suspend.h > +++ b/arch/arm64/include/asm/suspend.h > @@ -2,7 +2,7 @@ > #ifndef __ASM_SUSPEND_H > #define __ASM_SUSPEND_H > > -#define NR_CTX_REGS 16 > +#define NR_CTX_REGS 18 > #define NR_CALLEE_SAVED_REGS 12 > > /* > diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S > index 664ea9e3b9ad..99aacf03367d 100644 > --- a/arch/arm64/mm/proc.S > +++ b/arch/arm64/mm/proc.S > @@ -121,6 +121,12 @@ alternative_else_nop_endif > alternative_if ARM64_HAS_S1POE > mrs x2, REG_POR_EL0 > str x2, [x0, #120] > +alternative_else_nop_endif > +alternative_if ARM64_HAS_GCS > + mrs x2, REG_GCSPR_EL0 > + str x2, [x0, #128] > + mrs x2, REG_GCSCRE0_EL1 > + str x2, [x0, #136] Have you considered using stp? > alternative_else_nop_endif > ret > SYM_FUNC_END(cpu_do_suspend) > @@ -168,6 +174,12 @@ alternative_if ARM64_HAS_S1POE > ldr x2, [x0, #120] > msr REG_POR_EL0, x2 > alternative_else_nop_endif > +alternative_if ARM64_HAS_GCS > + ldr x2, [x0, #128] > + msr REG_GCSPR_EL0, x2 > + ldr x2, [x0, #136] > + msr REG_GCSCRE0_EL1, x2 Have you considered using ldp? Cheers Vladimir ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] arm64: suspend: Save GCS state over suspend 2026-11-11 13:44 ` Vladimir Murzin @ 2026-11-11 13:55 ` Mark Brown 0 siblings, 0 replies; 7+ messages in thread From: Mark Brown @ 2026-11-11 13:55 UTC (permalink / raw) To: Vladimir Murzin Cc: Catalin Marinas, Will Deacon, Mark Rutland, Anshuman Khandual, Joey Gouly, linux-arm-kernel, linux-kernel, stable [-- Attachment #1: Type: text/plain, Size: 592 bytes --] On Wed, Nov 11, 2026 at 01:44:40PM +0000, Vladimir Murzin wrote: > On 11/5/26 16:05, Mark Brown wrote: > > GCSCRE0_EL1 and GCSPR_EL0 are live registers for EL0 on systems with GCS > > but are not saved and restored by cpu_do_suspend()/cpu_do_resume(). This > > +alternative_else_nop_endif > > +alternative_if ARM64_HAS_GCS > > + mrs x2, REG_GCSPR_EL0 > > + str x2, [x0, #128] > > + mrs x2, REG_GCSCRE0_EL1 > > + str x2, [x0, #136] > Have you considered using stp? It seemed better to keep the code repetitively simliar to the surrounding code and also avoid using an additional registers. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-11-11 13:55 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-11-05 16:05 [PATCH 0/2] arm64/suspend: Save more registers over suspend Mark Brown 2026-11-05 16:05 ` [PATCH 1/2] arm64: suspend: Save POR_EL0 " Mark Brown 2026-11-11 13:33 ` Vladimir Murzin 2026-11-11 13:52 ` Mark Brown 2026-11-05 16:05 ` [PATCH 2/2] arm64: suspend: Save GCS state " Mark Brown 2026-11-11 13:44 ` Vladimir Murzin 2026-11-11 13:55 ` Mark Brown
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®