target/riscv: Add PMP state description
In the case of supporting PMP feature, add PMP state description to vmstate_riscv_cpu. 'vmstate_pmp_addr' and 'num_rules' could be regenerated by pmp_update_rule(). But there exists the problem of updating num_rules repeatedly in pmp_update_rule(). So here extracts pmp_update_rule_addr() and pmp_update_rule_nums() to update 'vmstate_pmp_addr' and 'num_rules' respectively. Signed-off-by: Yifei Jiang <jiangyifei@huawei.com> Signed-off-by: Yipeng Yin <yinyipeng1@huawei.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20201026115530.304-4-jiangyifei@huawei.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
f7697f0e62
commit
24beb03e46
@ -22,6 +22,52 @@
|
||||
#include "sysemu/kvm.h"
|
||||
#include "migration/cpu.h"
|
||||
|
||||
static bool pmp_needed(void *opaque)
|
||||
{
|
||||
RISCVCPU *cpu = opaque;
|
||||
CPURISCVState *env = &cpu->env;
|
||||
|
||||
return riscv_feature(env, RISCV_FEATURE_PMP);
|
||||
}
|
||||
|
||||
static int pmp_post_load(void *opaque, int version_id)
|
||||
{
|
||||
RISCVCPU *cpu = opaque;
|
||||
CPURISCVState *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||
pmp_update_rule_addr(env, i);
|
||||
}
|
||||
pmp_update_rule_nums(env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pmp_entry = {
|
||||
.name = "cpu/pmp/entry",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL(addr_reg, pmp_entry_t),
|
||||
VMSTATE_UINT8(cfg_reg, pmp_entry_t),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_pmp = {
|
||||
.name = "cpu/pmp",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pmp_needed,
|
||||
.post_load = pmp_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT_ARRAY(env.pmp_state.pmp, RISCVCPU, MAX_RISCV_PMPS,
|
||||
0, vmstate_pmp_entry, pmp_entry_t),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_riscv_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 1,
|
||||
@ -70,5 +116,9 @@ const VMStateDescription vmstate_riscv_cpu = {
|
||||
VMSTATE_UINT64(env.timecmp, RISCVCPU),
|
||||
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription * []) {
|
||||
&vmstate_pmp,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
@ -136,18 +136,8 @@ static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong *ea)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert cfg/addr reg values here into simple 'sa' --> start address and 'ea'
|
||||
* end address values.
|
||||
* This function is called relatively infrequently whereas the check that
|
||||
* an address is within a pmp rule is called often, so optimise that one
|
||||
*/
|
||||
static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index)
|
||||
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index)
|
||||
{
|
||||
int i;
|
||||
|
||||
env->pmp_state.num_rules = 0;
|
||||
|
||||
uint8_t this_cfg = env->pmp_state.pmp[pmp_index].cfg_reg;
|
||||
target_ulong this_addr = env->pmp_state.pmp[pmp_index].addr_reg;
|
||||
target_ulong prev_addr = 0u;
|
||||
@ -186,7 +176,13 @@ static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index)
|
||||
|
||||
env->pmp_state.addr[pmp_index].sa = sa;
|
||||
env->pmp_state.addr[pmp_index].ea = ea;
|
||||
}
|
||||
|
||||
void pmp_update_rule_nums(CPURISCVState *env)
|
||||
{
|
||||
int i;
|
||||
|
||||
env->pmp_state.num_rules = 0;
|
||||
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||
const uint8_t a_field =
|
||||
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
|
||||
@ -196,6 +192,17 @@ static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index)
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert cfg/addr reg values here into simple 'sa' --> start address and 'ea'
|
||||
* end address values.
|
||||
* This function is called relatively infrequently whereas the check that
|
||||
* an address is within a pmp rule is called often, so optimise that one
|
||||
*/
|
||||
static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index)
|
||||
{
|
||||
pmp_update_rule_addr(env, pmp_index);
|
||||
pmp_update_rule_nums(env);
|
||||
}
|
||||
|
||||
static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr)
|
||||
{
|
||||
int result = 0;
|
||||
|
@ -62,5 +62,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
|
||||
target_ulong size, pmp_priv_t priv, target_ulong mode);
|
||||
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
||||
target_ulong *tlb_size);
|
||||
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
|
||||
void pmp_update_rule_nums(CPURISCVState *env);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user