target/riscv: Add ePMP CSR access functions
Signed-off-by: Hongzheng-Li <Ethan.Lee.QNL@gmail.com> Signed-off-by: Hou Weiying <weiying_hou@outlook.com> Signed-off-by: Myriad-Dreamin <camiyoru@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Message-id: 270762cb2507fba6a9eeb99a774cf49f7da9cc32.1618812899.git.alistair.francis@wdc.com [ Changes by AF: - Rebase on master - Fix build errors - Fix some style issues ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
4a345b2a83
commit
2582a95c3c
@ -230,6 +230,7 @@ struct CPURISCVState {
|
|||||||
|
|
||||||
/* physical memory protection */
|
/* physical memory protection */
|
||||||
pmp_table_t pmp_state;
|
pmp_table_t pmp_state;
|
||||||
|
target_ulong mseccfg;
|
||||||
|
|
||||||
/* machine specific rdtime callback */
|
/* machine specific rdtime callback */
|
||||||
uint64_t (*rdtime_fn)(uint32_t);
|
uint64_t (*rdtime_fn)(uint32_t);
|
||||||
|
@ -200,6 +200,15 @@ static RISCVException pmp(CPURISCVState *env, int csrno)
|
|||||||
|
|
||||||
return RISCV_EXCP_ILLEGAL_INST;
|
return RISCV_EXCP_ILLEGAL_INST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RISCVException epmp(CPURISCVState *env, int csrno)
|
||||||
|
{
|
||||||
|
if (env->priv == PRV_M && riscv_feature(env, RISCV_FEATURE_EPMP)) {
|
||||||
|
return RISCV_EXCP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RISCV_EXCP_ILLEGAL_INST;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* User Floating-Point CSRs */
|
/* User Floating-Point CSRs */
|
||||||
@ -1343,6 +1352,20 @@ static RISCVException write_mtinst(CPURISCVState *env, int csrno,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Physical Memory Protection */
|
/* Physical Memory Protection */
|
||||||
|
static RISCVException read_mseccfg(CPURISCVState *env, int csrno,
|
||||||
|
target_ulong *val)
|
||||||
|
{
|
||||||
|
*val = mseccfg_csr_read(env);
|
||||||
|
return RISCV_EXCP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RISCVException write_mseccfg(CPURISCVState *env, int csrno,
|
||||||
|
target_ulong val)
|
||||||
|
{
|
||||||
|
mseccfg_csr_write(env, val);
|
||||||
|
return RISCV_EXCP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static RISCVException read_pmpcfg(CPURISCVState *env, int csrno,
|
static RISCVException read_pmpcfg(CPURISCVState *env, int csrno,
|
||||||
target_ulong *val)
|
target_ulong *val)
|
||||||
{
|
{
|
||||||
@ -1581,6 +1604,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
|||||||
[CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst },
|
[CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst },
|
||||||
|
|
||||||
/* Physical Memory Protection */
|
/* Physical Memory Protection */
|
||||||
|
[CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg },
|
||||||
[CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg },
|
[CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg },
|
||||||
[CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg },
|
[CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg },
|
||||||
[CSR_PMPCFG2] = { "pmpcfg2", pmp, read_pmpcfg, write_pmpcfg },
|
[CSR_PMPCFG2] = { "pmpcfg2", pmp, read_pmpcfg, write_pmpcfg },
|
||||||
|
@ -419,6 +419,40 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle a write to a mseccfg CSR
|
||||||
|
*/
|
||||||
|
void mseccfg_csr_write(CPURISCVState *env, target_ulong val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
trace_mseccfg_csr_write(env->mhartid, val);
|
||||||
|
|
||||||
|
/* RLB cannot be enabled if it's already 0 and if any regions are locked */
|
||||||
|
if (!MSECCFG_RLB_ISSET(env)) {
|
||||||
|
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||||
|
if (pmp_is_locked(env, i)) {
|
||||||
|
val &= ~MSECCFG_RLB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sticky bits */
|
||||||
|
val |= (env->mseccfg & (MSECCFG_MMWP | MSECCFG_MML));
|
||||||
|
|
||||||
|
env->mseccfg = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle a read from a mseccfg CSR
|
||||||
|
*/
|
||||||
|
target_ulong mseccfg_csr_read(CPURISCVState *env)
|
||||||
|
{
|
||||||
|
trace_mseccfg_csr_read(env->mhartid, env->mseccfg);
|
||||||
|
return env->mseccfg;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the TLB size if the start address or the end address of
|
* Calculate the TLB size if the start address or the end address of
|
||||||
* PMP entry is presented in thie TLB page.
|
* PMP entry is presented in thie TLB page.
|
||||||
|
@ -36,6 +36,12 @@ typedef enum {
|
|||||||
PMP_AMATCH_NAPOT /* Naturally aligned power-of-two region */
|
PMP_AMATCH_NAPOT /* Naturally aligned power-of-two region */
|
||||||
} pmp_am_t;
|
} pmp_am_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MSECCFG_MML = 1 << 0,
|
||||||
|
MSECCFG_MMWP = 1 << 1,
|
||||||
|
MSECCFG_RLB = 1 << 2
|
||||||
|
} mseccfg_field_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
target_ulong addr_reg;
|
target_ulong addr_reg;
|
||||||
uint8_t cfg_reg;
|
uint8_t cfg_reg;
|
||||||
@ -55,6 +61,10 @@ typedef struct {
|
|||||||
void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
|
void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
|
||||||
target_ulong val);
|
target_ulong val);
|
||||||
target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index);
|
target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index);
|
||||||
|
|
||||||
|
void mseccfg_csr_write(CPURISCVState *env, target_ulong val);
|
||||||
|
target_ulong mseccfg_csr_read(CPURISCVState *env);
|
||||||
|
|
||||||
void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
||||||
target_ulong val);
|
target_ulong val);
|
||||||
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
|
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
|
||||||
@ -68,4 +78,8 @@ void pmp_update_rule_nums(CPURISCVState *env);
|
|||||||
uint32_t pmp_get_num_rules(CPURISCVState *env);
|
uint32_t pmp_get_num_rules(CPURISCVState *env);
|
||||||
int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
|
int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
|
||||||
|
|
||||||
|
#define MSECCFG_MML_ISSET(env) get_field(env->mseccfg, MSECCFG_MML)
|
||||||
|
#define MSECCFG_MMWP_ISSET(env) get_field(env->mseccfg, MSECCFG_MMWP)
|
||||||
|
#define MSECCFG_RLB_ISSET(env) get_field(env->mseccfg, MSECCFG_RLB)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,3 +6,6 @@ pmpcfg_csr_read(uint64_t mhartid, uint32_t reg_index, uint64_t val) "hart %" PRI
|
|||||||
pmpcfg_csr_write(uint64_t mhartid, uint32_t reg_index, uint64_t val) "hart %" PRIu64 ": write reg%" PRIu32", val: 0x%" PRIx64
|
pmpcfg_csr_write(uint64_t mhartid, uint32_t reg_index, uint64_t val) "hart %" PRIu64 ": write reg%" PRIu32", val: 0x%" PRIx64
|
||||||
pmpaddr_csr_read(uint64_t mhartid, uint32_t addr_index, uint64_t val) "hart %" PRIu64 ": read addr%" PRIu32", val: 0x%" PRIx64
|
pmpaddr_csr_read(uint64_t mhartid, uint32_t addr_index, uint64_t val) "hart %" PRIu64 ": read addr%" PRIu32", val: 0x%" PRIx64
|
||||||
pmpaddr_csr_write(uint64_t mhartid, uint32_t addr_index, uint64_t val) "hart %" PRIu64 ": write addr%" PRIu32", val: 0x%" PRIx64
|
pmpaddr_csr_write(uint64_t mhartid, uint32_t addr_index, uint64_t val) "hart %" PRIu64 ": write addr%" PRIu32", val: 0x%" PRIx64
|
||||||
|
|
||||||
|
mseccfg_csr_read(uint64_t mhartid, uint64_t val) "hart %" PRIu64 ": read mseccfg, val: 0x%" PRIx64
|
||||||
|
mseccfg_csr_write(uint64_t mhartid, uint64_t val) "hart %" PRIu64 ": write mseccfg, val: 0x%" PRIx64
|
||||||
|
Loading…
Reference in New Issue
Block a user