Merge patch series "target/riscv: Various fixes to gdbstub and CSR access"
Bin Meng <bmeng@tinylab.org> says: At present gdbstub reports an incorrect / incomplete CSR list in the target description XML, for example: - menvcfg is reported in 'sifive_u' machine - fcsr is missing in a F/D enabled processor The issue is caused by: - priv spec version check is missing when reporting CSRs - CSR predicate() routine is called without turning on the debugger flag * b4-shazam-merge: target/riscv: Group all predicate() routines together target/riscv: Drop priv level check in mseccfg predicate() target/riscv: Allow debugger to access sstc CSRs target/riscv: Allow debugger to access {h, s}stateen CSRs target/riscv: Allow debugger to access seed CSR target/riscv: Allow debugger to access user timer and counter CSRs target/riscv: gdbstub: Drop the vector CSRs in riscv-vector.xml target/riscv: gdbstub: Turn on debugger mode before calling CSR predicate() target/riscv: Avoid reporting odd-numbered pmpcfgX in the CSR XML for RV64 target/riscv: Simplify getting RISCVCPU pointer from env target/riscv: Simplify {read, write}_pmpcfg() a little bit target/riscv: Use 'bool' type for read_only target/riscv: Coding style fixes in csr.c target/riscv: gdbstub: Do not generate CSR XML if Zicsr is disabled target/riscv: gdbstub: Minor change for better readability target/riscv: Use g_assert() for the predicate() NULL check target/riscv: Add some comments to clarify the priority policy of riscv_csrrw_check() target/riscv: gdbstub: Check priv spec version before reporting CSR Message-ID: <20230228104035.1879882-1-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
commit
73b9da4aa3
@ -40,43 +40,6 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
|
||||
csr_ops[csrno & (CSR_TABLE_SIZE - 1)] = *ops;
|
||||
}
|
||||
|
||||
/* Predicates */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static RISCVException smstateen_acc_ok(CPURISCVState *env, int index,
|
||||
uint64_t bit)
|
||||
{
|
||||
bool virt = riscv_cpu_virt_enabled(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
|
||||
if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (!(env->mstateen[index] & bit)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (virt) {
|
||||
if (!(env->hstateen[index] & bit)) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_U && !(env->sstateen[index] & bit)) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if (env->priv == PRV_U && riscv_has_ext(env, RVS)) {
|
||||
if (!(env->sstateen[index] & bit)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static RISCVException fs(CPURISCVState *env, int csrno)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
@ -90,8 +53,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException vs(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (cpu->cfg.ext_zve32f) {
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
@ -107,8 +69,7 @@ static RISCVException vs(CPURISCVState *env, int csrno)
|
||||
static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
int ctr_index;
|
||||
target_ulong ctr_mask;
|
||||
int base_csrno = CSR_CYCLE;
|
||||
@ -133,6 +94,10 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
|
||||
skip_ext_pmu_check:
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv < PRV_M && !get_field(env->mcounteren, ctr_mask)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
@ -165,8 +130,7 @@ static RISCVException ctr32(CPURISCVState *env, int csrno)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static RISCVException mctr(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
int ctr_index;
|
||||
int base_csrno = CSR_MHPMCOUNTER3;
|
||||
|
||||
@ -194,8 +158,7 @@ static RISCVException mctr32(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException sscofpmf(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_sscofpmf) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -320,8 +283,7 @@ static RISCVException umode32(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException mstateen(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -332,20 +294,28 @@ static RISCVException mstateen(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException hstateen_pred(CPURISCVState *env, int csrno, int base)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
RISCVException ret = hmode(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv < PRV_M) {
|
||||
if (!(env->mstateen[csrno - base] & SMSTATEEN_STATEEN)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
}
|
||||
|
||||
return hmode(env, csrno);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException hstateen(CPURISCVState *env, int csrno)
|
||||
@ -362,13 +332,21 @@ static RISCVException sstateen(CPURISCVState *env, int csrno)
|
||||
{
|
||||
bool virt = riscv_cpu_virt_enabled(env);
|
||||
int index = csrno - CSR_SSTATEEN0;
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
RISCVException ret = smode(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv < PRV_M) {
|
||||
if (!(env->mstateen[index] & SMSTATEEN_STATEEN)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -381,7 +359,61 @@ static RISCVException sstateen(CPURISCVState *env, int csrno)
|
||||
}
|
||||
}
|
||||
|
||||
return smode(env, csrno);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException sstc(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
bool hmode_check = false;
|
||||
|
||||
if (!cpu->cfg.ext_sstc || !env->rdtime_fn) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) {
|
||||
hmode_check = true;
|
||||
}
|
||||
|
||||
RISCVException ret = hmode_check ? hmode(env, csrno) : smode(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_M) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need of separate function for rv32 as menvcfg stores both menvcfg
|
||||
* menvcfgh for RV32.
|
||||
*/
|
||||
if (!(get_field(env->mcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->menvcfg, MENVCFG_STCE))) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
if (!(get_field(env->hcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->henvcfg, HENVCFG_STCE))) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException sstc_32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_cpu_mxl(env) != MXL_RV32) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return sstc(env, csrno);
|
||||
}
|
||||
|
||||
/* Checks if PointerMasking registers could be accessed */
|
||||
@ -419,6 +451,15 @@ static int aia_hmode32(CPURISCVState *env, int csrno)
|
||||
static RISCVException pmp(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_cpu_cfg(env)->pmp) {
|
||||
if (csrno <= CSR_PMPCFG3) {
|
||||
uint32_t reg_index = csrno - CSR_PMPCFG0;
|
||||
|
||||
/* TODO: RV128 restriction check */
|
||||
if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -427,7 +468,7 @@ static RISCVException pmp(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException epmp(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (env->priv == PRV_M && riscv_cpu_cfg(env)->epmp) {
|
||||
if (riscv_cpu_cfg(env)->epmp) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -453,6 +494,10 @@ static RISCVException seed(CPURISCVState *env, int csrno)
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* With a CSR read-write instruction:
|
||||
* 1) The seed CSR is always available in machine mode as normal.
|
||||
@ -915,54 +960,8 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException sstc(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
bool hmode_check = false;
|
||||
|
||||
if (!cpu->cfg.ext_sstc || !env->rdtime_fn) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_M) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need of separate function for rv32 as menvcfg stores both menvcfg
|
||||
* menvcfgh for RV32.
|
||||
*/
|
||||
if (!(get_field(env->mcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->menvcfg, MENVCFG_STCE))) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
if (!(get_field(env->hcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->henvcfg, HENVCFG_STCE))) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) {
|
||||
hmode_check = true;
|
||||
}
|
||||
|
||||
return hmode_check ? hmode(env, csrno) : smode(env, csrno);
|
||||
}
|
||||
|
||||
static RISCVException sstc_32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_cpu_mxl(env) != MXL_RV32) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return sstc(env, csrno);
|
||||
}
|
||||
|
||||
static RISCVException read_vstimecmp(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->vstimecmp;
|
||||
|
||||
@ -970,7 +969,7 @@ static RISCVException read_vstimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_vstimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->vstimecmp >> 32;
|
||||
|
||||
@ -978,7 +977,7 @@ static RISCVException read_vstimecmph(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_vstimecmp(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -995,7 +994,7 @@ static RISCVException write_vstimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_vstimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -1019,7 +1018,7 @@ static RISCVException read_stimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_stimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
*val = env->vstimecmp >> 32;
|
||||
@ -1031,7 +1030,7 @@ static RISCVException read_stimecmph(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_stimecmp(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -1054,7 +1053,7 @@ static RISCVException write_stimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_stimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -1151,8 +1150,7 @@ static RISCVException write_ignore(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
*val = cpu->cfg.mvendorid;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1161,8 +1159,7 @@ static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_marchid(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
*val = cpu->cfg.marchid;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1171,8 +1168,7 @@ static RISCVException read_marchid(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_mimpid(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
*val = cpu->cfg.mimpid;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1341,7 +1337,8 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
|
||||
|
||||
/* 'E' excludes all other extensions */
|
||||
if (val & RVE) {
|
||||
/* when we support 'E' we can do "val = RVE;" however
|
||||
/*
|
||||
* when we support 'E' we can do "val = RVE;" however
|
||||
* for now we just drop writes if 'E' is present.
|
||||
*/
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1360,7 +1357,8 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
|
||||
val &= ~RVD;
|
||||
}
|
||||
|
||||
/* Suppress 'C' if next instruction is not aligned
|
||||
/*
|
||||
* Suppress 'C' if next instruction is not aligned
|
||||
* TODO: this should check next_pc
|
||||
*/
|
||||
if ((val & RVC) && (GETPC() & ~3) != 0) {
|
||||
@ -1829,28 +1827,28 @@ static RISCVException write_mscratch(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_mepc(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->mepc;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_mepc(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
env->mepc = val;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException read_mcause(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->mcause;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_mcause(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
env->mcause = val;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1872,14 +1870,14 @@ static RISCVException write_mtval(CPURISCVState *env, int csrno,
|
||||
|
||||
/* Execution environment configuration setup */
|
||||
static RISCVException read_menvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->menvcfg;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE;
|
||||
|
||||
@ -1892,14 +1890,14 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_menvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->menvcfg >> 32;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE;
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
@ -1909,8 +1907,41 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException smstateen_acc_ok(CPURISCVState *env, int index,
|
||||
uint64_t bit)
|
||||
{
|
||||
bool virt = riscv_cpu_virt_enabled(env);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (!(env->mstateen[index] & bit)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (virt) {
|
||||
if (!(env->hstateen[index] & bit)) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_U && !(env->sstateen[index] & bit)) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if (env->priv == PRV_U && riscv_has_ext(env, RVS)) {
|
||||
if (!(env->sstateen[index] & bit)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
RISCVException ret;
|
||||
|
||||
@ -1924,7 +1955,7 @@ static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
|
||||
RISCVException ret;
|
||||
@ -1939,7 +1970,7 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
RISCVException ret;
|
||||
|
||||
@ -1953,7 +1984,7 @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
|
||||
RISCVException ret;
|
||||
@ -1973,7 +2004,7 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
RISCVException ret;
|
||||
|
||||
@ -1987,7 +2018,7 @@ static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
@ -2030,13 +2061,13 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mstateen_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
|
||||
static RISCVException read_mstateenh(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->mstateen[csrno - CSR_MSTATEEN0H] >> 32;
|
||||
|
||||
@ -2057,7 +2088,7 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
|
||||
|
||||
@ -2065,7 +2096,7 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mstateenh_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
@ -2102,7 +2133,7 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_hstateen_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
@ -2141,7 +2172,7 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_hstateenh_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
@ -3334,30 +3365,18 @@ static RISCVException read_mseccfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mseccfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
mseccfg_csr_write(env, val);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static bool check_pmp_reg_index(CPURISCVState *env, uint32_t reg_index)
|
||||
{
|
||||
/* TODO: RV128 restriction check */
|
||||
if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static RISCVException read_pmpcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
uint32_t reg_index = csrno - CSR_PMPCFG0;
|
||||
|
||||
if (!check_pmp_reg_index(env, reg_index)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
*val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
|
||||
*val = pmpcfg_csr_read(env, reg_index);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -3366,10 +3385,7 @@ static RISCVException write_pmpcfg(CPURISCVState *env, int csrno,
|
||||
{
|
||||
uint32_t reg_index = csrno - CSR_PMPCFG0;
|
||||
|
||||
if (!check_pmp_reg_index(env, reg_index)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val);
|
||||
pmpcfg_csr_write(env, reg_index, val);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -3772,27 +3788,32 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
|
||||
RISCVCPU *cpu)
|
||||
{
|
||||
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
|
||||
int read_only = get_field(csrno, 0xC00) == 3;
|
||||
bool read_only = get_field(csrno, 0xC00) == 3;
|
||||
int csr_min_priv = csr_ops[csrno].min_priv_ver;
|
||||
|
||||
/* ensure the CSR extension is enabled. */
|
||||
/* ensure the CSR extension is enabled */
|
||||
if (!cpu->cfg.ext_icsr) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* privileged spec version check */
|
||||
if (env->priv_ver < csr_min_priv) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* check predicate */
|
||||
if (!csr_ops[csrno].predicate) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* read / write check */
|
||||
if (write_mask && read_only) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/*
|
||||
* The predicate() not only does existence check but also does some
|
||||
* access control check which triggers for example virtual instruction
|
||||
* exception in some cases. When writing read-only CSRs in those cases
|
||||
* illegal instruction exception should be triggered instead of virtual
|
||||
* instruction exception. Hence this comes after the read / write check.
|
||||
*/
|
||||
g_assert(csr_ops[csrno].predicate != NULL);
|
||||
RISCVException ret = csr_ops[csrno].predicate(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
|
@ -127,40 +127,6 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert register index number passed by GDB to the correspond
|
||||
* vector CSR number. Vector CSRs are defined after vector registers
|
||||
* in dynamic generated riscv-vector.xml, thus the starting register index
|
||||
* of vector CSRs is 32.
|
||||
* Return 0 if register index number is out of range.
|
||||
*/
|
||||
static int riscv_gdb_vector_csrno(int num_regs)
|
||||
{
|
||||
/*
|
||||
* The order of vector CSRs in the switch case
|
||||
* should match with the order defined in csr_ops[].
|
||||
*/
|
||||
switch (num_regs) {
|
||||
case 32:
|
||||
return CSR_VSTART;
|
||||
case 33:
|
||||
return CSR_VXSAT;
|
||||
case 34:
|
||||
return CSR_VXRM;
|
||||
case 35:
|
||||
return CSR_VCSR;
|
||||
case 36:
|
||||
return CSR_VL;
|
||||
case 37:
|
||||
return CSR_VTYPE;
|
||||
case 38:
|
||||
return CSR_VLENB;
|
||||
default:
|
||||
/* Unknown register. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
|
||||
{
|
||||
uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
@ -174,19 +140,6 @@ static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int csrno = riscv_gdb_vector_csrno(n);
|
||||
|
||||
if (!csrno) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
target_ulong val = 0;
|
||||
int result = riscv_csrrw_debug(env, csrno, &val, 0, 0);
|
||||
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return gdb_get_regl(buf, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -201,19 +154,6 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
return vlenb;
|
||||
}
|
||||
|
||||
int csrno = riscv_gdb_vector_csrno(n);
|
||||
|
||||
if (!csrno) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
target_ulong val = ldtul_p(mem_buf);
|
||||
int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
|
||||
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -280,6 +220,10 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||
int bitsize = 16 << env->misa_mxl_max;
|
||||
int i;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->debugger = true;
|
||||
#endif
|
||||
|
||||
/* Until gdb knows about 128-bit registers */
|
||||
if (bitsize > 64) {
|
||||
bitsize = 64;
|
||||
@ -290,6 +234,9 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||
g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">");
|
||||
|
||||
for (i = 0; i < CSR_TABLE_SIZE; i++) {
|
||||
if (env->priv_ver < csr_ops[i].min_priv_ver) {
|
||||
continue;
|
||||
}
|
||||
predicate = csr_ops[i].predicate;
|
||||
if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
|
||||
if (csr_ops[i].name) {
|
||||
@ -305,6 +252,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||
g_string_append_printf(s, "</feature>");
|
||||
|
||||
cpu->dyn_csr_xml = g_string_free(s, false);
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->debugger = false;
|
||||
#endif
|
||||
|
||||
return CSR_TABLE_SIZE;
|
||||
}
|
||||
|
||||
@ -349,21 +301,6 @@ static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
|
||||
num_regs++;
|
||||
}
|
||||
|
||||
/* Define vector CSRs */
|
||||
const char *vector_csrs[7] = {
|
||||
"vstart", "vxsat", "vxrm", "vcsr",
|
||||
"vl", "vtype", "vlenb"
|
||||
};
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"%s\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"int\"/>",
|
||||
vector_csrs[i], TARGET_LONG_BITS, base_reg++);
|
||||
num_regs++;
|
||||
}
|
||||
|
||||
g_string_append_printf(s, "</feature>");
|
||||
|
||||
cpu->dyn_vreg_xml = g_string_free(s, false);
|
||||
@ -382,9 +319,9 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||
32, "riscv-32bit-fpu.xml", 0);
|
||||
}
|
||||
if (env->misa_ext & RVV) {
|
||||
int base_reg = cs->gdb_num_regs;
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector,
|
||||
ricsv_gen_dynamic_vector_xml(cs,
|
||||
cs->gdb_num_regs),
|
||||
ricsv_gen_dynamic_vector_xml(cs, base_reg),
|
||||
"riscv-vector.xml", 0);
|
||||
}
|
||||
switch (env->misa_mxl_max) {
|
||||
@ -403,7 +340,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
|
||||
riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs),
|
||||
"riscv-csr.xml", 0);
|
||||
if (cpu->cfg.ext_icsr) {
|
||||
int base_reg = cs->gdb_num_regs;
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
|
||||
riscv_gen_dynamic_csr_xml(cs, base_reg),
|
||||
"riscv-csr.xml", 0);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user