[committed,3/3] RISC-V: save and restore ssp on setjmp/longjmp

Message ID 20260622105202.664207-3-kito.cheng@sifive.com
State New
Headers
Series [committed,1/3] RISC-V: introduce ENTRY/END assembler macros for function boilerplate |

Commit Message

Kito Cheng June 22, 2026, 10:52 a.m. UTC
  From: Jesse Huang <jesse.huang@sifive.com>

---
 newlib/libc/include/machine/setjmp.h | 11 +++++--
 newlib/libc/machine/riscv/setjmp.S   | 43 ++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)
  

Patch

diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h
index ab820ed94..4e74bdb0f 100644
--- a/newlib/libc/include/machine/setjmp.h
+++ b/newlib/libc/include/machine/setjmp.h
@@ -431,10 +431,17 @@  _BEGIN_STD_C
    otherwise in rv32imafd, store/restore FPR may mis-align.  */
 #define _JBTYPE long long
 #ifdef __riscv_32e
-#define _JBLEN ((4*sizeof(long))/sizeof(long))
+#define __JBLEN ((4*sizeof(long))/sizeof(long))
 #else
-#define _JBLEN ((14*sizeof(long) + 12*sizeof(double))/sizeof(long))
+#define __JBLEN ((14*sizeof(long) + 12*sizeof(double))/sizeof(long))
 #endif
+
+#ifdef __riscv_shadow_stack
+#define _JBLEN (__JBLEN + 1)
+#else
+#define _JBLEN (__JBLEN)
+#endif
+
 #endif
 
 #ifdef __CSKYABIV2__
diff --git a/newlib/libc/machine/riscv/setjmp.S b/newlib/libc/machine/riscv/setjmp.S
index a29c15f29..336ac5b4e 100644
--- a/newlib/libc/machine/riscv/setjmp.S
+++ b/newlib/libc/machine/riscv/setjmp.S
@@ -60,6 +60,18 @@  ENTRY(setjmp)
 	FREG_S fs11,14*SZREG+11*SZFREG(a0)
 #endif
 
+#ifdef __riscv_shadow_stack
+        /* read ssp into t0  */
+        ssrdp t0
+# ifndef __riscv_float_abi_soft
+	REG_S t0, 14*SZREG+12*SZFREG(a0)
+# elif defined (__riscv_32e)
+	REG_S t0, 4*SZREG(a0)
+# else
+	REG_S t0, 14*SZREG(a0)
+# endif
+#endif
+
 	li    a0, 0
 	ret
 END(setjmp)
@@ -110,6 +122,37 @@  ENTRY(longjmp)
 	FREG_L fs9, 14*SZREG+ 9*SZFREG(a0)
 	FREG_L fs10,14*SZREG+10*SZFREG(a0)
 	FREG_L fs11,14*SZREG+11*SZFREG(a0)
+#endif
+#ifdef __riscv_shadow_stack
+        /* read ssp into t0  */
+        ssrdp t0
+        /* skip unwinding if ss is not enabled  */
+        beqz  t0, .Lunwind_fin
+# ifndef __riscv_float_abi_soft
+	REG_L t1, 14*SZREG+12*SZFREG(a0)
+# elif defined (__riscv_32e)
+	REG_L t0, 4*SZREG(a0)
+# else
+	REG_L t1, 14*SZREG(a0)
+# endif
+.Lunwind:
+        /* should not be taken in normal condition  */
+        bleu  t1, t0, .Lunwind_fin
+        /* The unwinding algorithm came from the zicfiss spec, increase ssp
+           by at most a page size to ensure always run into a guard page
+           before accidentally point to another legal shadow stack page  */
+        /* t0 = (t1 - t0 >= 4096) ? t0 + 4096 : t1  */
+        lui   a0, 1
+        add   t0, t0, a0
+        bleu  t0, t1, 1f
+        mv    t0, t1
+1:
+        csrw  ssp, t0
+        /* Test if the location pointed by ssp is legal  */
+        sspush x5
+        sspopchk x5
+        j .Lunwind
+.Lunwind_fin:
 #endif
 
 	seqz a0, a1