mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2026-06-12 22:31:45 +01:00
lib: sbi: Move hart PMP functions to sbi_hart_pmp.c
The sbi_hart_pmp.c looks like a good place for the hart PMP CSR access functions. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260430045528.420437-9-npiggin@gmail.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
committed by
Anup Patel
parent
63350c6ea6
commit
a59c8fb9fb
@@ -81,8 +81,6 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
|
||||||
|
|
||||||
#define csr_swap(csr, val) \
|
#define csr_swap(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
register unsigned long __v = (unsigned long)(val); \
|
register unsigned long __v = (unsigned long)(val); \
|
||||||
@@ -211,18 +209,6 @@ int misa_xlen(void);
|
|||||||
/* Get RISC-V ISA string representation */
|
/* Get RISC-V ISA string representation */
|
||||||
void misa_string(int xlen, char *out, unsigned int out_sz);
|
void misa_string(int xlen, char *out, unsigned int out_sz);
|
||||||
|
|
||||||
/* Disable pmp entry at a given index */
|
|
||||||
int sbi_hart_pmp_disable(unsigned int n);
|
|
||||||
|
|
||||||
/* Check if the matching field is set */
|
|
||||||
bool sbi_hart_is_pmp_enabled(unsigned int n);
|
|
||||||
|
|
||||||
int sbi_hart_pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
|
||||||
unsigned long log2len);
|
|
||||||
|
|
||||||
int sbi_hart_pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
|
||||||
unsigned long *log2len);
|
|
||||||
|
|
||||||
#endif /* !__ASSEMBLER__ */
|
#endif /* !__ASSEMBLER__ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,18 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
/* Disable pmp entry at a given index */
|
||||||
|
int sbi_hart_pmp_disable(unsigned int n);
|
||||||
|
|
||||||
|
/* Check if the matching field is set */
|
||||||
|
bool sbi_hart_is_pmp_enabled(unsigned int n);
|
||||||
|
|
||||||
|
int sbi_hart_pmp_set(unsigned int n, unsigned long prot,
|
||||||
|
unsigned long addr, unsigned long log2len);
|
||||||
|
|
||||||
|
int sbi_hart_pmp_get(unsigned int n, unsigned long *prot_out,
|
||||||
|
unsigned long *addr_out, unsigned long *log2len);
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
|
||||||
unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch);
|
unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch);
|
||||||
|
|||||||
@@ -272,112 +272,3 @@ void csr_write_num(int csr_num, unsigned long val)
|
|||||||
#undef switchcase_csr_write_2
|
#undef switchcase_csr_write_2
|
||||||
#undef switchcase_csr_write
|
#undef switchcase_csr_write
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hart_pmp_read(pmp_t *pmp, unsigned int n)
|
|
||||||
{
|
|
||||||
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
|
|
||||||
unsigned long cfgmask;
|
|
||||||
|
|
||||||
/* check parameters */
|
|
||||||
if (n >= PMP_COUNT)
|
|
||||||
return SBI_EINVAL;
|
|
||||||
|
|
||||||
/* calculate PMP register and offset */
|
|
||||||
#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
|
|
||||||
pmpaddr_csr = CSR_PMPADDR0 + n;
|
|
||||||
|
|
||||||
cfgmask = (0xffUL << pmpcfg_shift);
|
|
||||||
pmp->cfg = (csr_read_num(pmpcfg_csr) & cfgmask) >> pmpcfg_shift;
|
|
||||||
pmp->addr = csr_read_num(pmpaddr_csr);
|
|
||||||
|
|
||||||
return SBI_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hart_pmp_write(pmp_t *pmp, unsigned int n)
|
|
||||||
{
|
|
||||||
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
|
|
||||||
unsigned long cfgmask, pmpcfg;
|
|
||||||
|
|
||||||
/* check parameters */
|
|
||||||
if (n >= PMP_COUNT)
|
|
||||||
return SBI_EINVAL;
|
|
||||||
|
|
||||||
/* calculate PMP register and offset */
|
|
||||||
#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
|
|
||||||
pmpaddr_csr = CSR_PMPADDR0 + n;
|
|
||||||
|
|
||||||
/* write csrs */
|
|
||||||
csr_write_num(pmpaddr_csr, pmp->addr);
|
|
||||||
cfgmask = ~(0xffUL << pmpcfg_shift);
|
|
||||||
pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
|
|
||||||
pmpcfg |= (((unsigned long)pmp->cfg << pmpcfg_shift) & ~cfgmask);
|
|
||||||
csr_write_num(pmpcfg_csr, pmpcfg);
|
|
||||||
|
|
||||||
return SBI_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sbi_hart_pmp_disable(unsigned int n)
|
|
||||||
{
|
|
||||||
pmp_t pmp;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = hart_pmp_read(&pmp, n);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
pmp.cfg = 0;
|
|
||||||
|
|
||||||
return hart_pmp_write(&pmp, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sbi_hart_is_pmp_enabled(unsigned int n)
|
|
||||||
{
|
|
||||||
pmp_t pmp;
|
|
||||||
|
|
||||||
if (hart_pmp_read(&pmp, n) != SBI_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return sbi_pmp_is_enabled(&pmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sbi_hart_pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
|
||||||
unsigned long log2len)
|
|
||||||
{
|
|
||||||
pmp_t pmp;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = sbi_pmp_encode(&pmp, prot, addr, log2len);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return hart_pmp_write(&pmp, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sbi_hart_pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
|
||||||
unsigned long *log2len)
|
|
||||||
{
|
|
||||||
pmp_t pmp;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = hart_pmp_read(&pmp, n);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return sbi_pmp_decode(&pmp, prot_out, addr_out, log2len);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,9 +12,119 @@
|
|||||||
#include <sbi/sbi_hfence.h>
|
#include <sbi/sbi_hfence.h>
|
||||||
#include <sbi/sbi_math.h>
|
#include <sbi/sbi_math.h>
|
||||||
#include <sbi/sbi_platform.h>
|
#include <sbi/sbi_platform.h>
|
||||||
|
#include <sbi/sbi_pmp.h>
|
||||||
#include <sbi/sbi_tlb.h>
|
#include <sbi/sbi_tlb.h>
|
||||||
#include <sbi/riscv_asm.h>
|
#include <sbi/riscv_asm.h>
|
||||||
|
|
||||||
|
static int hart_pmp_read(pmp_t *pmp, unsigned int n)
|
||||||
|
{
|
||||||
|
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
|
||||||
|
unsigned long cfgmask;
|
||||||
|
|
||||||
|
/* check parameters */
|
||||||
|
if (n >= PMP_COUNT)
|
||||||
|
return SBI_EINVAL;
|
||||||
|
|
||||||
|
/* calculate PMP register and offset */
|
||||||
|
#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
|
||||||
|
pmpaddr_csr = CSR_PMPADDR0 + n;
|
||||||
|
|
||||||
|
cfgmask = (0xffUL << pmpcfg_shift);
|
||||||
|
pmp->cfg = (csr_read_num(pmpcfg_csr) & cfgmask) >> pmpcfg_shift;
|
||||||
|
pmp->addr = csr_read_num(pmpaddr_csr);
|
||||||
|
|
||||||
|
return SBI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hart_pmp_write(pmp_t *pmp, unsigned int n)
|
||||||
|
{
|
||||||
|
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
|
||||||
|
unsigned long cfgmask, pmpcfg;
|
||||||
|
|
||||||
|
/* check parameters */
|
||||||
|
if (n >= PMP_COUNT)
|
||||||
|
return SBI_EINVAL;
|
||||||
|
|
||||||
|
/* calculate PMP register and offset */
|
||||||
|
#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
|
||||||
|
pmpaddr_csr = CSR_PMPADDR0 + n;
|
||||||
|
|
||||||
|
/* write csrs */
|
||||||
|
csr_write_num(pmpaddr_csr, pmp->addr);
|
||||||
|
cfgmask = ~(0xffUL << pmpcfg_shift);
|
||||||
|
pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
|
||||||
|
pmpcfg |= (((unsigned long)pmp->cfg << pmpcfg_shift) & ~cfgmask);
|
||||||
|
csr_write_num(pmpcfg_csr, pmpcfg);
|
||||||
|
|
||||||
|
return SBI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_hart_pmp_disable(unsigned int n)
|
||||||
|
{
|
||||||
|
pmp_t pmp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = hart_pmp_read(&pmp, n);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
pmp.cfg = 0;
|
||||||
|
|
||||||
|
return hart_pmp_write(&pmp, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sbi_hart_is_pmp_enabled(unsigned int n)
|
||||||
|
{
|
||||||
|
pmp_t pmp;
|
||||||
|
|
||||||
|
if (hart_pmp_read(&pmp, n) != SBI_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return sbi_pmp_is_enabled(&pmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_hart_pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
||||||
|
unsigned long log2len)
|
||||||
|
{
|
||||||
|
pmp_t pmp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = sbi_pmp_encode(&pmp, prot, addr, log2len);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return hart_pmp_write(&pmp, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_hart_pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
||||||
|
unsigned long *log2len)
|
||||||
|
{
|
||||||
|
pmp_t pmp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = hart_pmp_read(&pmp, n);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return sbi_pmp_decode(&pmp, prot_out, addr_out, log2len);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Smepmp enforces access boundaries between M-mode and
|
* Smepmp enforces access boundaries between M-mode and
|
||||||
* S/U-mode. When it is enabled, the PMPs are programmed
|
* S/U-mode. When it is enabled, the PMPs are programmed
|
||||||
|
|||||||
Reference in New Issue
Block a user