diff mbox series

[RFC,v3,6/6,TEMP] demonstrate hole protection using reserved PMP

Message ID 20251130111643.1291462-7-peter.lin@sifive.com
State New
Headers show
Series Extend the reserved PMP entries | expand

Commit Message

Yu-Chien Peter Lin Nov. 30, 2025, 11:16 a.m. UTC
This implementation shows how platforms can use the reserved PMP
allocator to protect critical memory regions during early boot.

Benefits of using reserved PMPs:
1) Reserved PMPs are not managed by domains - platforms have full control
   over them. Since reserved entries won't be freed, they can safely set
   lock bits (pmpcfg.L), unlike domain entries which must allow being
   temporarily revoked during context switches.
2) One can allocate 2 consecutive entries to create ToR mode regions to
   save PMP usage
3) The reserved PMPs have higher priority so their permissions are less
   likely to be overwritten by other entries

Note: This is a demonstration patch and should not be merged.

Signed-off-by: Yu-Chien Peter Lin <peter.lin@sifive.com>
---
 platform/generic/sifive/fu540.c | 56 +++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
diff mbox series

Patch

diff --git a/platform/generic/sifive/fu540.c b/platform/generic/sifive/fu540.c
index 83e57145..3f0fd032 100644
--- a/platform/generic/sifive/fu540.c
+++ b/platform/generic/sifive/fu540.c
@@ -8,6 +8,10 @@ 
  */
 
 #include <platform_override.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_types.h>
 #include <sbi_utils/fdt/fdt_helper.h>
 #include <sbi_utils/fdt/fdt_fixup.h>
 
@@ -20,9 +24,61 @@  static u64 sifive_fu540_tlbr_flush_limit(void)
 	return 0;
 }
 
+static u32 sifive_fu540_get_reserved_pmp_count(void)
+{
+	/*
+	 * Reserve an entry for demonstrating hole protection
+	 * on SiFive FU540.
+	 */
+	return 1;
+}
+
+// This is a demonstration of PMP-based memory protection rather
+// than protecting an actual memory hole.
+static int sifive_fu540_hole_protection(void)
+{
+	int rc;
+	unsigned int pmp_id;
+
+	rc = reserved_pmp_alloc(&pmp_id);
+	if (rc)
+		return rc;
+
+	/*
+	 * Protect the memory hole at 0x0 - 0x1000 by setting
+	 * it as inaccessible (no R/W/X) with the lock bit set.
+	 * This prevents any access to this region in all modes.
+	 */
+	rc = pmp_set(pmp_id, PMP_L, 0x0, 12);
+	if (rc) {
+		reserved_pmp_free(pmp_id);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int sifive_fu540_early_init(bool cold_boot)
+{
+	int rc;
+
+	/* Set up memory hole protection */
+	rc = sifive_fu540_hole_protection();
+	if (rc)
+		return rc;
+
+	rc = generic_early_init(cold_boot);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
 static int sifive_fu540_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
 {
 	generic_platform_ops.get_tlbr_flush_limit = sifive_fu540_tlbr_flush_limit;
+	generic_platform_ops.get_reserved_pmp_count = sifive_fu540_get_reserved_pmp_count;
+	generic_platform_ops.early_init = sifive_fu540_early_init;
 
 	return 0;
 }