+static int aarch64_read_cpu_memory_slow(struct target *target,
+ uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ struct arm_dpm *dpm = &armv8->dpm;
+ struct arm *arm = &armv8->arm;
+ int retval;
+
+ armv8_reg_current(arm, 1)->dirty = true;
+
+ /* change DCC to normal mode (if necessary) */
+ if (*dscr & DSCR_MA) {
+ *dscr &= DSCR_MA;
+ retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ while (count) {
+ uint32_t opcode, data;
+
+ if (size == 1)
+ opcode = armv8_opcode(armv8, ARMV8_OPC_LDRB_IP);
+ else if (size == 2)
+ opcode = armv8_opcode(armv8, ARMV8_OPC_LDRH_IP);
+ else
+ opcode = armv8_opcode(armv8, ARMV8_OPC_LDRW_IP);
+ retval = dpm->instr_execute(dpm, opcode);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (arm->core_state == ARM_STATE_AARCH64)
+ retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1));
+ else
+ retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0));
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRTX, &data);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (size == 1)
+ *buffer = (uint8_t)data;
+ else if (size == 2)
+ target_buffer_set_u16(target, buffer, (uint16_t)data);
+ else
+ target_buffer_set_u32(target, buffer, data);
+
+ /* Advance */
+ buffer += size;
+ --count;
+ }
+
+ return ERROR_OK;
+}
+
+static int aarch64_read_cpu_memory_fast(struct target *target,
+ uint32_t count, uint8_t *buffer, uint32_t *dscr)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ struct arm_dpm *dpm = &armv8->dpm;
+ struct arm *arm = &armv8->arm;
+ int retval;
+ uint32_t value;
+
+ /* Mark X1 as dirty */
+ armv8_reg_current(arm, 1)->dirty = true;
+
+ if (arm->core_state == ARM_STATE_AARCH64) {
+ /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
+ retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0));
+ } else {
+ /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
+ retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
+ }
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Step 1.e - Change DCC to memory mode */
+ *dscr |= DSCR_MA;
+ retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Step 1.f - read DBGDTRTX and discard the value */
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRTX, &value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ count--;
+ /* Read the data - Each read of the DTRTX register causes the instruction to be reissued
+ * Abort flags are sticky, so can be read at end of transactions
+ *
+ * This data is read in aligned to 32 bit boundary.
+ */
+
+ if (count) {
+ /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and
+ * increments X0 by 4. */
+ retval = mem_ap_read_buf_noincr(armv8->debug_ap, buffer, 4, count,
+ armv8->debug_base + CPUV8_DBG_DTRTX);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ /* Step 3.a - set DTR access mode back to Normal mode */
+ *dscr &= ~DSCR_MA;
+ retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Step 3.b - read DBGDTRTX for the final value */
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRTX, &value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ target_buffer_set_u32(target, buffer + count * 4, value);
+ return retval;