On Fri, 31 Jan 2020 17:01:54 PST (-0800), Alistair Francis wrote:
> Add a FORCE_HS_EXCEP mode to the RISC-V virtulisation status. This bit
> specifies if an exeption should be taken to HS mode no matter the
> current delegation status. This is used when an exeption must be taken
> to HS mode, such as when handling interrupts.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
> target/riscv/cpu.h | 2 ++
> target/riscv/cpu_bits.h | 6 ++++++
> target/riscv/cpu_helper.c | 18 ++++++++++++++++++
> 3 files changed, 26 insertions(+)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index a9cbd8584e..42720d65f9 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -273,6 +273,8 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
> bool riscv_cpu_fp_enabled(CPURISCVState *env);
> bool riscv_cpu_virt_enabled(CPURISCVState *env);
> void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
> +bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
> +void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
> int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
> hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
> void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 2cdb0de4fe..ad6479796c 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -432,6 +432,12 @@
>
> /* Virtulisation Register Fields */
> #define VIRT_ONOFF 1
> +/* This is used to save state for when we take an exception. If this is set
> + * that means that we want to force a HS level exception (no matter what the
> + * delegation is set to). This will occur for things such as a second level
> + * page table fault.
> + */
> +#define FORCE_HS_EXCEP 2
>
> /* RV32 satp CSR field masks */
> #define SATP32_MODE 0x80000000
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 5844e543f3..1e28103500 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -100,6 +100,24 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
> env->virt = set_field(env->virt, VIRT_ONOFF, enable);
> }
>
> +bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env)
> +{
> + if (!riscv_has_ext(env, RVH)) {
> + return false;
> + }
> +
> + return get_field(env->virt, FORCE_HS_EXCEP);
> +}
> +
> +void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable)
> +{
> + if (!riscv_has_ext(env, RVH)) {
> + return;
> + }
> +
> + env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable);
> +}
> +
> int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
> {
> CPURISCVState *env = &cpu->env;
Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>