summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshu Chauhan <[email protected]>2023-07-12 10:04:35 +0530
committerAnup Patel <[email protected]>2023-07-13 12:44:02 +0530
commit6e44ef686a9b329d837c61d7f121541abfcfed90 (patch)
treeb42e9899749b974eec6d9ca7193f2c9eaa5e1f77
parent5dd8db5b10fc03aeded76407aecb731a8a9f1cfa (diff)
lib: sbi: Add functions to map/unmap shared memory
When Smepmp is enabled, M-mode will need to map/unmap the shared memory before it can read/write to it. This patch adds functions to create dynamic short-lived mappings. Signed-off-by: Himanshu Chauhan <[email protected]> Reviewed-by: Anup Patel <[email protected]>
-rw-r--r--include/sbi/sbi_hart.h2
-rw-r--r--lib/sbi/sbi_hart.c42
2 files changed, 44 insertions, 0 deletions
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index 1b783436..c150b7e4 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -90,6 +90,8 @@ unsigned long sbi_hart_pmp_granularity(struct sbi_scratch *scratch);
unsigned int sbi_hart_pmp_addrbits(struct sbi_scratch *scratch);
unsigned int sbi_hart_mhpm_bits(struct sbi_scratch *scratch);
int sbi_hart_pmp_configure(struct sbi_scratch *scratch);
+int sbi_hart_map_saddr(unsigned long base, unsigned long size);
+int sbi_hart_unmap_saddr(void);
int sbi_hart_priv_version(struct sbi_scratch *scratch);
void sbi_hart_get_priv_version_str(struct sbi_scratch *scratch,
char *version_str, int nvstr);
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 12f9c7ea..7b5f3801 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -347,6 +347,48 @@ unsigned int sbi_hart_get_smepmp_flags(struct sbi_scratch *scratch,
return pmp_flags;
}
+int sbi_hart_map_saddr(unsigned long addr, unsigned long size)
+{
+ /* shared R/W access for M and S/U mode */
+ unsigned int pmp_flags = (PMP_W | PMP_X);
+ unsigned long order, base = 0;
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+
+ /* If Smepmp is not supported no special mapping is required */
+ if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMEPMP))
+ return SBI_OK;
+
+ if (is_pmp_entry_mapped(SBI_SMEPMP_RESV_ENTRY))
+ return SBI_ENOSPC;
+
+ for (order = log2roundup(size) ; order <= __riscv_xlen; order++) {
+ if (order < __riscv_xlen) {
+ base = addr & ~((1UL << order) - 1UL);
+ if ((base <= addr) &&
+ (addr < (base + (1UL << order))) &&
+ (base <= (addr + size - 1UL)) &&
+ ((addr + size - 1UL) < (base + (1UL << order))))
+ break;
+ } else {
+ return SBI_EFAIL;
+ }
+ }
+
+ pmp_set(SBI_SMEPMP_RESV_ENTRY, pmp_flags, base, order);
+
+ return SBI_OK;
+}
+
+int sbi_hart_unmap_saddr(void)
+{
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+
+ if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMEPMP))
+ return SBI_OK;
+
+ return pmp_disable(SBI_SMEPMP_RESV_ENTRY);
+}
+
int sbi_hart_pmp_configure(struct sbi_scratch *scratch)
{
struct sbi_domain_memregion *reg;