diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 05dcb0b3..957f3eff 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -2169,6 +2169,9 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) * IO indicates that this register does I/O and therefore its accesses * need to be surrounded by gen_io_start()/gen_io_end(). In particular, * registers which implement clocks or timers require this. + * RAISES_EXC is for when the read or write hook might raise an exception; + * the generated code will synchronize the CPU state before calling the hook + * so that it is safe for the hook to call raise_exception(). */ #define ARM_CP_SPECIAL 0x0001 #define ARM_CP_CONST 0x0002 @@ -2187,10 +2190,11 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) #define ARM_CP_FPU 0x1000 #define ARM_CP_SVE 0x2000 #define ARM_CP_NO_GDB 0x4000 +#define ARM_CP_RAISES_EXC 0x8000 /* Used only as a terminator for ARMCPRegInfo lists */ #define ARM_CP_SENTINEL 0xffff /* Mask of only the flag bits in a type field */ -#define ARM_CP_FLAG_MASK 0x70ff +#define ARM_CP_FLAG_MASK 0xf0ff /* Valid values for ARMCPRegInfo state field, indicating which of * the AArch32 and AArch64 execution states this register is visible in. diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 96e46a8d..296942b4 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -1911,6 +1911,12 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, tcg_temp_free_ptr(tcg_ctx, tmpptr); tcg_temp_free_i32(tcg_ctx, tcg_syn); tcg_temp_free_i32(tcg_ctx, tcg_isread); + } else if (ri->type & ARM_CP_RAISES_EXC) { + /* + * The readfn or writefn might raise an exception; + * synchronize the CPU state in case it does. + */ + gen_a64_set_pc_im(s, s->pc_curr); } /* Handle special cases first */ diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 6dca832f..b7a9b03b 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -7352,6 +7352,13 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) tcg_temp_free_ptr(tcg_ctx, tmpptr); tcg_temp_free_i32(tcg_ctx, tcg_syn); tcg_temp_free_i32(tcg_ctx, tcg_isread); + } else if (ri->type & ARM_CP_RAISES_EXC) { + /* + * The readfn or writefn might raise an exception; + * synchronize the CPU state in case it does. + */ + gen_set_condexec(s); + gen_set_pc_im(s, s->pc_curr); } /* Handle special cases first */