lib: sbi: Add functions to manipulate PMP entries
authorHimanshu Chauhan <hchauhan@ventanamicro.com>
Wed, 12 Jul 2023 04:34:28 +0000 (10:04 +0530)
committerAnup Patel <anup@brainfault.org>
Thu, 13 Jul 2023 06:40:39 +0000 (12:10 +0530)
- Add a function to disable a given PMP entry.
- Add a function to check if a given entry is disabled.

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
include/sbi/riscv_asm.h
lib/sbi/riscv_asm.c

index 1ff36de76e3bef59a3c9395f8785486056e0ddb0..2c34635a3936ac28447a6901010866a8d2838591 100644 (file)
@@ -181,6 +181,12 @@ int misa_xlen(void);
 /* Get RISC-V ISA string representation */
 void misa_string(int xlen, char *out, unsigned int out_sz);
 
+/* Disable pmp entry at a given index */
+int pmp_disable(unsigned int n);
+
+/* Check if the matching field is set */
+int is_pmp_entry_mapped(unsigned long entry);
+
 int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
            unsigned long log2len);
 
index cd565534ca1e856a055d73734247ede4614d2817..881dea3e54aa0b7c78ba0ea4919d04913e140ba2 100644 (file)
@@ -246,6 +246,48 @@ static unsigned long ctz(unsigned long x)
        return ret;
 }
 
+int pmp_disable(unsigned int n)
+{
+       int pmpcfg_csr, pmpcfg_shift;
+       unsigned long cfgmask, pmpcfg;
+
+       if (n >= PMP_COUNT)
+               return SBI_EINVAL;
+
+#if __riscv_xlen == 32
+       pmpcfg_csr   = CSR_PMPCFG0 + (n >> 2);
+       pmpcfg_shift = (n & 3) << 3;
+#elif __riscv_xlen == 64
+       pmpcfg_csr   = (CSR_PMPCFG0 + (n >> 2)) & ~1;
+       pmpcfg_shift = (n & 7) << 3;
+#else
+# error "Unexpected __riscv_xlen"
+#endif
+
+       /* Clear the address matching bits to disable the pmp entry */
+       cfgmask = ~(0xffUL << pmpcfg_shift);
+       pmpcfg  = (csr_read_num(pmpcfg_csr) & cfgmask);
+
+       csr_write_num(pmpcfg_csr, pmpcfg);
+
+       return SBI_OK;
+}
+
+int is_pmp_entry_mapped(unsigned long entry)
+{
+       unsigned long prot;
+       unsigned long addr;
+       unsigned long log2len;
+
+       pmp_get(entry, &prot, &addr, &log2len);
+
+       /* If address matching bits are non-zero, the entry is enable */
+       if (prot & PMP_A)
+               return true;
+
+       return false;
+}
+
 int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
            unsigned long log2len)
 {