diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 1220004ee..110f8dca0 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -663,11 +663,16 @@ static int aarch64_debug_entry(struct target *target) /* make sure to clear all sticky errors */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + + /* discard async exceptions */ + if (retval == ERROR_OK) + retval = dpm->instr_cpsr_sync(dpm); + if (retval != ERROR_OK) return retval; /* Examine debug reason */ - armv8_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); + armv8_dpm_report_dscr(dpm, aarch64->cpudbg_dscr); /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index ee9e1f36b..8caa8b60c 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -360,9 +360,14 @@ static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm, static int dpmv8_instr_cpsr_sync(struct arm_dpm *dpm) { + int retval; struct armv8_common *armv8 = dpm->arm->arch_info; + /* "Prefetch flush" after modifying execution status in CPSR */ - return dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), NULL); + retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), &dpm->dscr); + if (retval == ERROR_OK) + dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_ISB_SY), &dpm->dscr); + return retval; } static int dpmv8_instr_read_data_dcc(struct arm_dpm *dpm, diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 2b42cdf36..779014411 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -37,6 +37,7 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY, [ARMV8_OPC_DCPS] = ARMV8_DCPS(0, 11), [ARMV8_OPC_DRPS] = ARMV8_DRPS, + [ARMV8_OPC_ISB_SY] = ARMV8_ISB, }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { @@ -53,6 +54,7 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY_T1, [ARMV8_OPC_DCPS] = ARMV8_DCPS_T1(0), [ARMV8_OPC_DRPS] = ARMV8_ERET_T1, + [ARMV8_OPC_ISB_SY] = ARMV8_ISB_SY_T1, }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index b489d57df..fe6b28a2c 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -135,6 +135,8 @@ #define ARMV8_DSB_SY 0xd5033F9F #define ARMV8_DSB_SY_T1 0xf3bf8f4f +#define ARMV8_ISB 0xd5033fdf +#define ARMV8_ISB_SY_T1 0xf3bf8f6f #define ARMV8_MRS(System, Rt) (0xd5300000 | ((System) << 5) | (Rt)) /* ARM V8 Move to system register. */ @@ -173,6 +175,7 @@ enum armv8_opcode { ARMV8_OPC_DSB_SY, ARMV8_OPC_DCPS, ARMV8_OPC_DRPS, + ARMV8_OPC_ISB_SY, ARMV8_OPC_NUM, };