From 6e44ef686a9b329d837c61d7f121541abfcfed90 Mon Sep 17 00:00:00 2001 From: Himanshu Chauhan Date: Wed, 12 Jul 2023 10:04:35 +0530 Subject: [PATCH] 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 Reviewed-by: Anup Patel --- include/sbi/sbi_hart.h | 2 ++ lib/sbi/sbi_hart.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index 1b78343..c150b7e 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 12f9c7e..7b5f380 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;