diff options
author | Alistair Francis <alistair.francis@wdc.com> | 2020-08-12 12:13:49 -0700 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2020-08-25 09:11:36 -0700 |
commit | e39a8320b088dd5efc9ebaafe387e52b3d962665 (patch) | |
tree | be1a09e13c4e3d30200146316abb2d847590f8af /target/riscv/op_helper.c | |
parent | 57cb2083e638bb28616c059cbf067d99552a04bb (diff) | |
download | qemu-e39a8320b088dd5efc9ebaafe387e52b3d962665.zip qemu-e39a8320b088dd5efc9ebaafe387e52b3d962665.tar.gz qemu-e39a8320b088dd5efc9ebaafe387e52b3d962665.tar.bz2 |
target/riscv: Support the Virtual Instruction fault
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 4c744dce9b0b057cbb5cc0f4d4ac75cda682a8af.1597259519.git.alistair.francis@wdc.com
Message-Id: <4c744dce9b0b057cbb5cc0f4d4ac75cda682a8af.1597259519.git.alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv/op_helper.c')
-rw-r--r-- | target/riscv/op_helper.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 948d204..9b9ada4 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -94,6 +94,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } + if (riscv_has_ext(env, RVH) && riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_VTSR)) { + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } + mstatus = env->mstatus; if (riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) { @@ -176,7 +181,7 @@ void helper_wfi(CPURISCVState *env) if ((env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TW)) || riscv_cpu_virt_enabled(env)) { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); } else { cs->halted = 1; cs->exception_index = EXCP_HLT; @@ -191,6 +196,9 @@ void helper_tlb_flush(CPURISCVState *env) (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM))) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } else if (riscv_has_ext(env, RVH) && riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_VTVM)) { + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); } else { tlb_flush(cs); } @@ -200,6 +208,10 @@ void helper_hyp_tlb_flush(CPURISCVState *env) { CPUState *cs = env_cpu(env); + if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) { + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } + if (env->priv == PRV_M || (env->priv == PRV_S && !riscv_cpu_virt_enabled(env))) { tlb_flush(cs); @@ -209,6 +221,16 @@ void helper_hyp_tlb_flush(CPURISCVState *env) riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } +void helper_hyp_gvma_tlb_flush(CPURISCVState *env) +{ + if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env) && + get_field(env->mstatus, MSTATUS_TVM)) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + + helper_hyp_tlb_flush(env); +} + target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, target_ulong attrs, target_ulong memop) { @@ -251,7 +273,11 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, return pte; } - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + if (riscv_cpu_virt_enabled(env)) { + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } else { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } return 0; } @@ -289,7 +315,11 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, return; } - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + if (riscv_cpu_virt_enabled(env)) { + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } else { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } } target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, @@ -319,7 +349,11 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, return pte; } - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + if (riscv_cpu_virt_enabled(env)) { + riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } else { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } return 0; } |