From ab7c1570d8943cccdae593f6962a42578d93b25d Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Sun, 22 Mar 2020 01:16:43 -0400 Subject: [PATCH] target/riscv: Add the force HS exception mode 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. Backports commit c7b1bbc80fc2af17395d3986c346fd2307e57829 from qemu --- qemu/header_gen.py | 2 ++ qemu/target/riscv/cpu.h | 2 ++ qemu/target/riscv/cpu_bits.h | 7 +++++++ qemu/target/riscv/cpu_helper.c | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 1d1f6ace..48007f5f 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -5565,12 +5565,14 @@ riscv_symbols = ( 'riscv_cpu_do_interrupt', 'riscv_cpu_do_unaligned_access', 'riscv_cpu_exec_interrupt', + 'riscv_cpu_force_hs_excep_enabled', 'riscv_cpu_get_fflags', 'riscv_cpu_get_phys_page_debug', 'riscv_cpu_list', 'riscv_cpu_mmu_index', 'riscv_cpu_register_types', 'riscv_cpu_set_fflags', + 'riscv_cpu_set_force_hs_excep', 'riscv_cpu_set_mode', 'riscv_cpu_set_virt_enabled', 'riscv_cpu_tlb_fill', diff --git a/qemu/target/riscv/cpu.h b/qemu/target/riscv/cpu.h index 0cce5c32..8d4bd0ca 100644 --- a/qemu/target/riscv/cpu.h +++ b/qemu/target/riscv/cpu.h @@ -276,6 +276,8 @@ int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request); 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/qemu/target/riscv/cpu_bits.h b/qemu/target/riscv/cpu_bits.h index f3b5697d..27cbadc5 100644 --- a/qemu/target/riscv/cpu_bits.h +++ b/qemu/target/riscv/cpu_bits.h @@ -433,6 +433,13 @@ /* 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/qemu/target/riscv/cpu_helper.c b/qemu/target/riscv/cpu_helper.c index 6191f022..d98cef8e 100644 --- a/qemu/target/riscv/cpu_helper.c +++ b/qemu/target/riscv/cpu_helper.c @@ -90,6 +90,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;