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 "sysemu/kvm.h"
|
||||||
#include "migration/cpu.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 = {
|
const VMStateDescription vmstate_riscv_cpu = {
|
||||||
.name = "cpu",
|
.name = "cpu",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
@ -70,5 +116,9 @@ const VMStateDescription vmstate_riscv_cpu = {
|
||||||
VMSTATE_UINT64(env.timecmp, RISCVCPU),
|
VMSTATE_UINT64(env.timecmp, RISCVCPU),
|
||||||
|
|
||||||
VMSTATE_END_OF_LIST()
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pmp_update_rule_addr(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)
|
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
env->pmp_state.num_rules = 0;
|
|
||||||
|
|
||||||
uint8_t this_cfg = env->pmp_state.pmp[pmp_index].cfg_reg;
|
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 this_addr = env->pmp_state.pmp[pmp_index].addr_reg;
|
||||||
target_ulong prev_addr = 0u;
|
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].sa = sa;
|
||||||
env->pmp_state.addr[pmp_index].ea = ea;
|
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++) {
|
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||||
const uint8_t a_field =
|
const uint8_t a_field =
|
||||||
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
|
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)
|
static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr)
|
||||||
{
|
{
|
||||||
int result = 0;
|
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);
|
target_ulong size, pmp_priv_t priv, target_ulong mode);
|
||||||
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
||||||
target_ulong *tlb_size);
|
target_ulong *tlb_size);
|
||||||
|
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
|
||||||
|
void pmp_update_rule_nums(CPURISCVState *env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue