mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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

* [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 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 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 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

* 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®