summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBo Gan <ganboing@gmail.com>2025-12-18 02:42:40 -0800
committerAnup Patel <anuppate@hu-anuppate-blr.qualcomm.com>2025-12-21 20:33:23 +0530
commit878c2676e633ff05a8275c2ff76254990e120bed (patch)
tree0a5382a9df2d6a30c4913d0c57eb6edb5d19d190
parented1deab09ef6284d018fbf37ab397dcd4b9f82b8 (diff)
downloadopensbi-878c2676e633ff05a8275c2ff76254990e120bed.tar.gz
opensbi-878c2676e633ff05a8275c2ff76254990e120bed.zip
lib: sbi: give platform choice of using single memregion to cover OpenSBI
By default the OpenSBI itself is covered by 2 memregions for RX/RW sections. This is required by platforms with Smepmp to enforce proper permissions in M mode. Note: M-mode only regions can't have RWX permissions with Smepmp. Platforms with traditional PMPs won't be able to benefit from it, as both regions are effectively RWX in M mode, but usually it's harmless to so. Now we provide these platforms with an option to disable this logic. It saves 1 PMP entry. For platforms really in short of PMPs, it does make a difference. Note: Platform requesting single OpenSBI memregion must be using traditional (old) PMP. We expect the platform code to do the right thing. Signed-off-by: Bo Gan <ganboing@gmail.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20251218104243.562667-5-ganboing@gmail.com Signed-off-by: Anup Patel <anup@brainfault.org>
-rw-r--r--include/sbi/sbi_platform.h21
-rw-r--r--lib/sbi/sbi_domain.c36
2 files changed, 45 insertions, 12 deletions
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index d75c12de..e65d9877 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -76,6 +76,9 @@ struct sbi_platform_operations {
/* Check if specified HART is allowed to do cold boot */
bool (*cold_boot_allowed)(u32 hartid);
+ /* Check if platform requires single firmware region */
+ bool (*single_fw_region)(void);
+
/* Platform nascent initialization */
int (*nascent_init)(void);
@@ -348,6 +351,24 @@ static inline bool sbi_platform_cold_boot_allowed(
}
/**
+ * Check whether platform requires single firmware region
+ *
+ * Note: Single firmware region only works with legacy PMP because with
+ * Smepmp M-mode only regions can't have RWX permissions.
+ *
+ * @param plat pointer to struct sbi_platform
+ *
+ * @return true if single firmware region required and false otherwise
+ */
+static inline bool sbi_platform_single_fw_region(
+ const struct sbi_platform *plat)
+{
+ if (plat && sbi_platform_ops(plat)->single_fw_region)
+ return sbi_platform_ops(plat)->single_fw_region();
+ return false;
+}
+
+/**
* Nascent (very early) initialization for current HART
*
* NOTE: This function can be used to do very early initialization of
diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
index a19bf25b..90cbb540 100644
--- a/lib/sbi/sbi_domain.c
+++ b/lib/sbi/sbi_domain.c
@@ -923,18 +923,30 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
root.possible_harts = root_hmask;
/* Root domain firmware memory region */
- sbi_domain_memregion_init(scratch->fw_start, scratch->fw_rw_offset,
- (SBI_DOMAIN_MEMREGION_M_READABLE |
- SBI_DOMAIN_MEMREGION_M_EXECUTABLE |
- SBI_DOMAIN_MEMREGION_FW),
- &root_memregs[root_memregs_count++]);
-
- sbi_domain_memregion_init((scratch->fw_start + scratch->fw_rw_offset),
- (scratch->fw_size - scratch->fw_rw_offset),
- (SBI_DOMAIN_MEMREGION_M_READABLE |
- SBI_DOMAIN_MEMREGION_M_WRITABLE |
- SBI_DOMAIN_MEMREGION_FW),
- &root_memregs[root_memregs_count++]);
+ if (sbi_platform_single_fw_region(sbi_platform_ptr(scratch))) {
+ sbi_domain_memregion_init(scratch->fw_start, scratch->fw_size,
+ (SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE |
+ SBI_DOMAIN_MEMREGION_M_EXECUTABLE |
+ SBI_DOMAIN_MEMREGION_FW),
+ &root_memregs[root_memregs_count++]);
+ } else {
+ sbi_domain_memregion_init(scratch->fw_start,
+ scratch->fw_rw_offset,
+ (SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_EXECUTABLE |
+ SBI_DOMAIN_MEMREGION_FW),
+ &root_memregs[root_memregs_count++]);
+
+ sbi_domain_memregion_init((scratch->fw_start +
+ scratch->fw_rw_offset),
+ (scratch->fw_size -
+ scratch->fw_rw_offset),
+ (SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE |
+ SBI_DOMAIN_MEMREGION_FW),
+ &root_memregs[root_memregs_count++]);
+ }
root.fw_region_inited = true;