summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--target/arm/cpu.h6
-rw-r--r--target/arm/translate-a64.c6
-rw-r--r--target/arm/translate.c7
3 files changed, 18 insertions, 1 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0981303170..297ad5e47a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2212,6 +2212,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
@@ -2230,10 +2233,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/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 9183f89ba3..4d09ae6f42 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1714,6 +1714,12 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
tcg_temp_free_ptr(tmpptr);
tcg_temp_free_i32(tcg_syn);
tcg_temp_free_i32(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->pc_curr);
}
/* Handle special cases first */
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 66311580c0..78d93f63ca 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7191,6 +7191,13 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
tcg_temp_free_ptr(tmpptr);
tcg_temp_free_i32(tcg_syn);
tcg_temp_free_i32(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 */