diff options
author | Anup Patel <anup.patel@wdc.com> | 2020-09-07 15:50:33 +0530 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2020-09-16 09:05:25 +0530 |
commit | 7ccf6bf54c2d7db6331f3fa319ef4e7019108c28 (patch) | |
tree | 2e54824ef04c5c3dfcfd475e16c24f89e07112f9 /lib/sbi/sbi_hart.c | |
parent | 6734304f8c759c782cab12ecfd6c20fb23b8ee44 (diff) |
lib: sbi: Allow specifying mode in sbi_hart_pmp_check_addr() API
We extend sbi_hart_pmp_check_addr() API so that users can specify
privilege mode of the address for checking PMP access permissions.
To achieve this, we end-up converting "unsigned long *size" parameter
to "unsigned long *log2len" for pmp_get() implementation so that we
can deal with regions of "1UL << __riscv_xlen" size in a special case
in sbi_hart_pmp_check_addr() implementation.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Diffstat (limited to 'lib/sbi/sbi_hart.c')
-rw-r--r-- | lib/sbi/sbi_hart.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index d788918..4cbe8ce 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -156,22 +156,31 @@ int sbi_hart_pmp_get(struct sbi_scratch *scratch, unsigned int n, unsigned long *prot_out, unsigned long *addr_out, unsigned long *size) { + int err; + unsigned long log2size; + if (sbi_hart_pmp_count(scratch) <= n) return SBI_EINVAL; - return pmp_get(n, prot_out, addr_out, size); + err = pmp_get(n, prot_out, addr_out, &log2size); + if (err) + return err; + *size = (log2size < __riscv_xlen) ? 1UL << log2size : 0; + + return 0; } void sbi_hart_pmp_dump(struct sbi_scratch *scratch) { - unsigned long prot, addr, size; + unsigned long prot, addr, size, log2size; unsigned int i, pmp_count; pmp_count = sbi_hart_pmp_count(scratch); for (i = 0; i < pmp_count; i++) { - pmp_get(i, &prot, &addr, &size); + pmp_get(i, &prot, &addr, &log2size); if (!(prot & PMP_A)) continue; + size = (log2size < __riscv_xlen) ? 1UL << log2size : 0; #if __riscv_xlen == 32 sbi_printf("PMP%d : 0x%08lx-0x%08lx (A", #else @@ -190,18 +199,23 @@ void sbi_hart_pmp_dump(struct sbi_scratch *scratch) } } -int sbi_hart_pmp_check_addr(struct sbi_scratch *scratch, unsigned long addr, +int sbi_hart_pmp_check_addr(struct sbi_scratch *scratch, + unsigned long addr, unsigned long mode, unsigned long attr) { - unsigned long prot, size, tempaddr; + unsigned long prot, size, log2size, tempaddr; unsigned int i, pmp_count; pmp_count = sbi_hart_pmp_count(scratch); for (i = 0; i < pmp_count; i++) { - pmp_get(i, &prot, &tempaddr, &size); + pmp_get(i, &prot, &tempaddr, &log2size); if (!(prot & PMP_A)) continue; - if (tempaddr <= addr && addr <= tempaddr + size) + if (mode == PRV_M && !(prot & PMP_L)) + continue; + size = 1UL << log2size; + if ((log2size >= __riscv_xlen) || + ((tempaddr <= addr && addr <= tempaddr + size))) if (!(prot & attr)) return SBI_EINVALID_ADDR; } |