[PATCH 1/2] lib: sbi: restore platform CSR when suspend

Xiang W wxjstz at 126.com
Thu Dec 4 06:58:51 PST 2025


When HART enters suspend mode, some platforms require specific CSRs
to be saved for recovery. This patch add interface for this.

Signed-off-by: Xiang W <wangxiang at iscas.ac.cn>
---
 include/sbi/sbi_platform.h | 60 ++++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_hsm.c          | 12 +++++++-
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index d75c12de..175ec1e2 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -41,6 +41,9 @@
 #define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x60 + (__SIZEOF_POINTER__ * 2))
 /** Offset of cbom_block_size in struct sbi_platform */
 #define SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET (0x60 + (__SIZEOF_POINTER__ * 3))
+/** Offset of suspend_backup_csr_count in struct sbi_platform */
+#define SBI_PLATFORM_SUSPEND_BACKUP_CSR_COUNT_OFFSET \
+					    (0x60 + (__SIZEOF_POINTER__ * 4))
 
 #define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT		(1UL << 12)
 
@@ -146,6 +149,12 @@ struct sbi_platform_operations {
 			unsigned long log2len);
 	/** platform specific pmp disable on current HART */
 	void (*pmp_disable)(unsigned int n);
+
+	/** Save platform specific CSR before suspend */
+	void (*suspend_non_ret_save)(unsigned long *data);
+
+	/** Restore platform specific CSR after suspend */
+	void (*suspend_non_ret_restore)(unsigned long *data);
 };
 
 /** Platform default per-HART stack size for exception/interrupt handling */
@@ -198,6 +207,13 @@ struct sbi_platform {
 	const u32 *hart_index2id;
 	/** Allocation alignment for Scratch */
 	unsigned long cbom_block_size;
+
+	/**
+	 * When HART enters suspend mode, some platforms require specific CSRs
+	 * to be saved for recovery. This variable tracks how many CSRs need to
+	 *  be backed up for this platform.
+	 */
+	unsigned long suspend_backup_csr_count;
 };
 
 /**
@@ -216,6 +232,8 @@ assert_member_offset(struct sbi_platform, platform_ops_addr, SBI_PLATFORM_OPS_OF
 assert_member_offset(struct sbi_platform, firmware_context, SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET);
 assert_member_offset(struct sbi_platform, hart_index2id, SBI_PLATFORM_HART_INDEX2ID_OFFSET);
 assert_member_offset(struct sbi_platform, cbom_block_size, SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET);
+assert_member_offset(struct sbi_platform, suspend_backup_csr_count, SBI_PLATFORM_SUSPEND_BACKUP_CSR_COUNT_OFFSET);
+
 
 /** Get pointer to sbi_platform for sbi_scratch pointer */
 #define sbi_platform_ptr(__s) \
@@ -666,6 +684,48 @@ static inline void sbi_platform_pmp_disable(const struct sbi_platform *plat,
 		sbi_platform_ops(plat)->pmp_disable(n);
 }
 
+/**
+ * Platform specific CSR count to backup during suspend.
+ *
+ * @param plat pointer to struct sbi_platform
+ *
+ * @return csr count need backup
+ */
+static inline unsigned long sbi_platform_suspend_backup_csr_count(
+					    const struct sbi_platform *plat)
+{
+	if (plat)
+		return plat->suspend_backup_csr_count;
+	return 0;
+}
+
+/**
+ * Save platform specific CSR before suspend
+ *
+ * @param plat pointer to struct sbi_platform
+ * @param data buffer used to save CSR
+ */
+static inline void sbi_platform_suspend_non_ret_save(
+					    const struct sbi_platform *plat,
+					    unsigned long *data)
+{
+	if (plat && sbi_platform_ops(plat)->suspend_non_ret_save)
+		sbi_platform_ops(plat)->suspend_non_ret_save(data);
+}
+
+/**
+ * Restore platform specific CSR after suspend
+ * @param plat pointer to struct sbi_platform
+ * @param data buffer used to restore CSR
+ */
+static inline void sbi_platform_suspend_non_ret_restore(
+					    const struct sbi_platform *plat,
+					    unsigned long *data)
+{
+	if (plat && sbi_platform_ops(plat)->suspend_non_ret_restore)
+		sbi_platform_ops(plat)->suspend_non_ret_restore(data);
+}
+
 #endif
 
 #endif
diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index 0a355f9c..949f7aaf 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -21,6 +21,7 @@
 #include <sbi/sbi_hsm.h>
 #include <sbi/sbi_init.h>
 #include <sbi/sbi_ipi.h>
+#include <sbi/sbi_platform.h>
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_system.h>
 #include <sbi/sbi_timer.h>
@@ -50,6 +51,7 @@ struct sbi_hsm_data {
 	unsigned long saved_mideleg;
 	u64 saved_menvcfg;
 	atomic_t start_ticket;
+	unsigned long platform_saved[0];
 };
 
 bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
@@ -249,9 +251,13 @@ int sbi_hsm_init(struct sbi_scratch *scratch, bool cold_boot)
 {
 	struct sbi_scratch *rscratch;
 	struct sbi_hsm_data *hdata;
+	unsigned long n;
 
 	if (cold_boot) {
-		hart_data_offset = sbi_scratch_alloc_offset(sizeof(*hdata));
+		n = sbi_platform_suspend_backup_csr_count(
+			sbi_platform_ptr(scratch));
+		hart_data_offset = sbi_scratch_alloc_offset(sizeof(*hdata) +
+							    n * sizeof(long));
 		if (!hart_data_offset)
 			return SBI_ENOMEM;
 
@@ -430,6 +436,8 @@ void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch)
 	hdata->saved_mideleg = csr_read(CSR_MIDELEG);
 	if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_12)
 		hdata->saved_menvcfg = csr_read64(CSR_MENVCFG);
+
+	sbi_platform_suspend_non_ret_save(sbi_platform_ptr(scratch), hdata->platform_saved);
 }
 
 static void __sbi_hsm_suspend_non_ret_restore(struct sbi_scratch *scratch)
@@ -443,6 +451,8 @@ static void __sbi_hsm_suspend_non_ret_restore(struct sbi_scratch *scratch)
 	csr_write(CSR_MEDELEG, hdata->saved_medeleg);
 	csr_write(CSR_MIE, hdata->saved_mie);
 	csr_set(CSR_MIP, (hdata->saved_mip & (MIP_SSIP | MIP_STIP)));
+
+	sbi_platform_suspend_non_ret_restore(sbi_platform_ptr(scratch), hdata->platform_saved);
 }
 
 void sbi_hsm_hart_resume_start(struct sbi_scratch *scratch)
-- 
2.47.3




More information about the opensbi mailing list