diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2017-12-28 17:36:45 -0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2018-01-30 10:22:26 -0800 |
commit | 4f5f254808e1e317b407275724df7794a270c5c1 (patch) | |
tree | 94c42a5cfc575a8fd47d45e07447f9600d7c3c0b /target/hppa/int_helper.c | |
parent | 650cdb2a2e4936fb66c13793278f4bacf0e5a6f7 (diff) | |
download | qemu-4f5f254808e1e317b407275724df7794a270c5c1.zip |
target/hppa: Implement external interrupts
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/hppa/int_helper.c')
-rw-r--r-- | target/hppa/int_helper.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 3d668a3a4f..c468b12e73 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -24,6 +24,65 @@ #include "exec/helper-proto.h" #include "qom/cpu.h" +#ifndef CONFIG_USER_ONLY +static void eval_interrupt(HPPACPU *cpu) +{ + CPUState *cs = CPU(cpu); + if (cpu->env.cr[CR_EIRR] & cpu->env.cr[CR_EIEM]) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + +/* Each CPU has a word mapped into the GSC bus. Anything on the GSC bus + * can write to this word to raise an external interrupt on the target CPU. + * This includes the system controler (DINO) for regular devices, or + * another CPU for SMP interprocessor interrupts. + */ +static uint64_t io_eir_read(void *opaque, hwaddr addr, unsigned size) +{ + HPPACPU *cpu = opaque; + + /* ??? What does a read of this register over the GSC bus do? */ + return cpu->env.cr[CR_EIRR]; +} + +static void io_eir_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + HPPACPU *cpu = opaque; + int le_bit = ~data & (TARGET_REGISTER_BITS - 1); + + cpu->env.cr[CR_EIRR] |= (target_ureg)1 << le_bit; + eval_interrupt(cpu); +} + +const MemoryRegionOps hppa_io_eir_ops = { + .read = io_eir_read, + .write = io_eir_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .impl.min_access_size = 4, + .impl.max_access_size = 4, +}; + +void HELPER(write_eirr)(CPUHPPAState *env, target_ureg val) +{ + env->cr[CR_EIRR] &= ~val; + qemu_mutex_lock_iothread(); + eval_interrupt(hppa_env_get_cpu(env)); + qemu_mutex_unlock_iothread(); +} + +void HELPER(write_eiem)(CPUHPPAState *env, target_ureg val) +{ + env->cr[CR_EIEM] = val; + qemu_mutex_lock_iothread(); + eval_interrupt(hppa_env_get_cpu(env)); + qemu_mutex_unlock_iothread(); +} +#endif /* !CONFIG_USER_ONLY */ void hppa_cpu_do_interrupt(CPUState *cs) { |