This is an automated email from Gerrit. Alamy Liu ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/3317
-- gerrit commit 636f78d95618b6c0aa36af34d58acf339fb0786c Author: Alamy Liu <[email protected]> Date: Mon Oct 19 13:05:03 2015 -0700 aarch64: rewrite aarch64_read_apb_ab_memory() Problem: > mdw 0xffffffc000097dd0 4 (before: incorrect) 0xFFFFFFC000097DD0: e00314aa 60025fd6 1f2003d5 1f2003d5 > mdw 0xffffffc000097dd0 4 (after : correct) 0xFFFFFFC000097DD0: aa1403e0 d65f0260 d503201f d503201f Investigation: memcpy() will screw up big/little endian order in the case that Target & Debugger have different endians. i.e.: Target: ARM64; Debugger MIPS Fix and Other restriction/enhancement *) Use buf_set_u32/_u64 instead of memcpy() *) 4-byte size access only *) Address must be aligned to 4-byte boundary *) Fast reading Change-Id: I84df36193928053a689a52d857beaf369b887d92 Signed-off-by: Alamy Liu <[email protected]> diff --git a/src/target/aarch64.c b/src/target/aarch64.c index b89dc44..92333af 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -28,6 +28,7 @@ #include "target_type.h" #include "target_type64.h" #include "arm_opcodes.h" +#include "armv8_opcodes.h" #include <helper/time_support.h> static int aarch64_poll(struct target *target); @@ -1872,99 +1873,122 @@ error_free_buff_w: return ERROR_FAIL; } +/* read memory through APB-AP */ static int aarch64_read_apb_ab_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - /* read memory through APB-AP */ - int retval = ERROR_COMMAND_SYNTAX_ERROR; struct armv8_common *armv8 = target_to_armv8(target); struct adiv5_dap *swjdp = armv8->arm.dap; struct arm *arm = &armv8->arm; + struct arm_dpm *dpm = &armv8->dpm; /* or arm->dpm */ struct reg *reg; - uint32_t dscr, val; - uint8_t *tmp_buff = NULL; - uint32_t i = 0; + uint32_t itr, bytes; + uint64_t value; - LOG_DEBUG("WARNING(Alamy): Review this function"); - LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count%" PRIu32, + LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } - /* Mark register X0, X1 as dirty, as it will be used + /* Support 4-byte accessing only (for now?) */ + if (((address & 0x3) != 0) || (size != 4)) { + LOG_WARNING("Unaligned access at 0x%.16" PRIx64, address); + return ERROR_TARGET_UNALIGNED_ACCESS; + } + + /* Mark register X0 and X1 as dirty, as they will be used * for transferring the data. * It will be restored automatically when exiting * debug mode */ - reg = armv8_get_reg_by_num(arm, 1); + reg = armv8_get_reg_by_num(arm, AARCH64_X1); reg->dirty = true; - reg = armv8_get_reg_by_num(arm, 0); + reg = armv8_get_reg_by_num(arm, AARCH64_X0); reg->dirty = true; - /* clear any abort */ + /* Clear any sticky error */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); - if (retval != ERROR_OK) - goto error_free_buff_r; + armv8->debug_base + ARMV8_REG_EDRCR, ARMV8_EDRCR_CSE); + if (retval != ERROR_OK) { + LOG_WARNING("Fail to clear sticky error"); + /* We could keep going, this is not a critical problem */ + } - retval = mem_ap_sel_read_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); - if (retval != ERROR_OK) - goto error_unset_dtr_r; - if (size > 4) { - LOG_WARNING("reading size >4 bytes not yet supported"); - goto error_unset_dtr_r; - } + /* Basic 4-byte alignment reading loop */ + /* while() { + * x1 = addr + * ldr w0, [x1] + * value = w0 + * } + */ - while (i < count * size) { + /* Coding consideration: + * *) We could load addr to X0, then "mov X1, X0" with dpm->arm->msr() + * dpm->arm->msr(target, opcode <mov X1, X0>, address); + * Here we load 'address' into X1 directly, but we need + * dpm->prepare & dpm->finish to encapsulate the operations ourself. + * *) Use X1 as address base and take the advantage of 'LDR' instruction + * to increase the address after loading, only one function call is + * needed in the loop. + * *) Load as many bytes as possible (ldr x0) + * + * Note: + * It still works without dpm->prepare/finish as they don't do much + * at the moment, but it's a bad coding style. Others would not know + * what/how to follow. (Oct-19, 2015) + */ - retval = aarch64_instr_write_data_dcc_64(arm->dpm, 0xd5330400, address+4); - if (retval != ERROR_OK) - goto error_unset_dtr_r; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; - dscr = DSCR_INSTR_COMP; - retval = aarch64_exec_opcode(target, 0xb85fc000, &dscr); - if (retval != ERROR_OK) - goto error_unset_dtr_r; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + /* x1 = addr: addr -> DCC -> X1 */ + retval = aarch64_instr_write_data_dcc_64(dpm, + A64_OPCODE_MRS_DBGDTR_EL0(AARCH64_X1), /* mrs x1, dbgdtr_el0 */ + address); + if (retval != ERROR_OK) + return retval; - retval = aarch64_instr_read_data_dcc(arm->dpm, 0xd5130400, &val); + while (count) { + /* ldr x0/w0, [x1] */ + if (count > 1) { + itr = 0xf8408420; /* ldr x0, [x1],#8 */ + bytes = 8; /* two words */ + } else { + itr = 0xb8404420; /* ldr w0, [x1],#4 */ + bytes = 4; /* one word */ + } + + /* value = X0 */ + retval = aarch64_instr_read_data_x0(dpm, itr, &value); if (retval != ERROR_OK) - goto error_unset_dtr_r; - memcpy(&buffer[i], &val, size); - i += 4; - address += 4; - } + break; - /* Clear any sticky error */ - mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); + if (count > 1) + buf_set_u64(buffer, 0, 64, value); + else + buf_set_u32(buffer, 0, 32, (uint32_t)value); - /* Done */ - return ERROR_OK; + buffer += bytes; + count -= bytes >> 2; -error_unset_dtr_r: - LOG_WARNING("DSCR = 0x%" PRIx32, dscr); - /* Todo: Unset DTR mode */ + } /* End of while(count--) */ + + /* (void) */ dpm->finish(dpm); -error_free_buff_r: - LOG_ERROR("error"); - free(tmp_buff); /* Clear any sticky error */ - mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); + /* (void) */ mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, + armv8->debug_base + ARMV8_REG_EDRCR, ARMV8_EDRCR_CSE); - return ERROR_FAIL; + /* Done */ + return retval; } static int aarch64_read_phys_memory(struct target *target, -- ------------------------------------------------------------------------------ Site24x7 APM Insight: Get Deep Visibility into Application Performance APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month Monitor end-to-end web transactions and take corrective actions now Troubleshoot faster and improve end-user experience. Signup Now! http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140 _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
