diff --git a/qemu/header_gen.py b/qemu/header_gen.py index cc106996..a6246ecf 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -5467,6 +5467,7 @@ riscv_symbols = ( 'pmpaddr_csr_write', 'pmpcfg_csr_read', 'pmpcfg_csr_write', + 'riscv_cpu_claim_interrupts', 'riscv_cpu_do_interrupt', 'riscv_cpu_do_unaligned_access', 'riscv_cpu_exec_interrupt', diff --git a/qemu/riscv32.h b/qemu/riscv32.h index bb203163..01e1b951 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -3388,6 +3388,7 @@ #define pmpaddr_csr_write pmpaddr_csr_write_riscv32 #define pmpcfg_csr_read pmpcfg_csr_read_riscv32 #define pmpcfg_csr_write pmpcfg_csr_write_riscv32 +#define riscv_cpu_claim_interrupts riscv_cpu_claim_interrupts_riscv32 #define riscv_cpu_do_interrupt riscv_cpu_do_interrupt_riscv32 #define riscv_cpu_do_unaligned_access riscv_cpu_do_unaligned_access_riscv32 #define riscv_cpu_exec_interrupt riscv_cpu_exec_interrupt_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index 4245fa30..27530506 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -3388,6 +3388,7 @@ #define pmpaddr_csr_write pmpaddr_csr_write_riscv64 #define pmpcfg_csr_read pmpcfg_csr_read_riscv64 #define pmpcfg_csr_write pmpcfg_csr_write_riscv64 +#define riscv_cpu_claim_interrupts riscv_cpu_claim_interrupts_riscv64 #define riscv_cpu_do_interrupt riscv_cpu_do_interrupt_riscv64 #define riscv_cpu_do_unaligned_access riscv_cpu_do_unaligned_access_riscv64 #define riscv_cpu_exec_interrupt riscv_cpu_exec_interrupt_riscv64 diff --git a/qemu/target/riscv/cpu.h b/qemu/target/riscv/cpu.h index ddc2d54f..45a3721f 100644 --- a/qemu/target/riscv/cpu.h +++ b/qemu/target/riscv/cpu.h @@ -142,6 +142,7 @@ struct CPURISCVState { * mip is 32-bits to allow atomic_read on 32-bit hosts. */ uint32_t mip; + uint32_t miclaim; target_ulong mie; target_ulong mideleg; @@ -271,6 +272,7 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf); #define cpu_mmu_index riscv_cpu_mmu_index #ifndef CONFIG_USER_ONLY +int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts); uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ #endif diff --git a/qemu/target/riscv/cpu_helper.c b/qemu/target/riscv/cpu_helper.c index d86de54a..d4fb93fc 100644 --- a/qemu/target/riscv/cpu_helper.c +++ b/qemu/target/riscv/cpu_helper.c @@ -72,6 +72,17 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request) #if !defined(CONFIG_USER_ONLY) +int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts) +{ + CPURISCVState *env = &cpu->env; + if (env->miclaim & interrupts) { + return -1; + } else { + env->miclaim |= interrupts; + return 0; + } +} + /* iothread_mutex must be held */ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value) { diff --git a/qemu/target/riscv/csr.c b/qemu/target/riscv/csr.c index dd5c0124..d7048631 100644 --- a/qemu/target/riscv/csr.c +++ b/qemu/target/riscv/csr.c @@ -557,16 +557,10 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value, target_ulong new_value, target_ulong write_mask) { RISCVCPU *cpu = riscv_env_get_cpu(env); - target_ulong mask = write_mask & delegable_ints; + /* Allow software control of delegable interrupts not claimed by hardware */ + target_ulong mask = write_mask & delegable_ints & ~env->miclaim; uint32_t old_mip; - /* We can't allow the supervisor to control SEIP as this would allow the - * supervisor to clear a pending external interrupt which will result in - * lost a interrupt in the case a PLIC is attached. The SEIP bit must be - * hardware controlled when a PLIC is attached. This should be an option - * for CPUs with software-delegated Supervisor External Interrupts. */ - mask &= ~MIP_SEIP; - if (mask) { // Unicorn: commented out //qemu_mutex_lock_iothread();