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/3327
-- gerrit commit 8cf8e2ca2c0f19bdbe89114b3a31cc0d84e6f107 Author: Alamy Liu <[email protected]> Date: Tue Dec 1 10:34:19 2015 -0800 debug: 'aarch64 debug' telnet command Change-Id: Ieb2c94422bb0367bee37135b0da44d86f92062eb Signed-off-by: Alamy Liu <[email protected]> diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 4062798..2b8afb6 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -88,6 +88,7 @@ ARMV7_SRC = \ ARMV8_SRC = \ target64.c \ aarch64.c \ + aarch64_debug.c \ armv8_cti.c \ armv8.c diff --git a/src/target/aarch64_debug.c b/src/target/aarch64_debug.c new file mode 100644 index 0000000..bbc2230 --- /dev/null +++ b/src/target/aarch64_debug.c @@ -0,0 +1,541 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "register.h" +#include "aarch64.h" +#include "target_type64.h" +#include "armv8_opcodes.h" +#include "armv8_cti.h" + + +extern int aarch64_exec_opcode(struct target *target, + uint32_t opcode, uint32_t *edscr_p); + + + + +void print_edscr_detail(struct command_context *cmd_ctx, uint32_t edscr) +{ + struct target *target = get_current_target(cmd_ctx); + + command_print(cmd_ctx, + "EDSCR = 0x%.8"PRIx32 "\n" + "\tRXFull = %d TXFull = %d\n" + "\tITO (ITR Overrun) = %d ITE (ITR empty) = %d\n" + "\tRXO (RX Overrun) = %d TXU (TX Underrun) = %d\n" + "\tTDA (trap dbg reg acc) = %d MA (mem access mode) = %d\n" + "\tNS (Non-Secure) = %d SDD (Secure debug disable) = %d\n" + "\tRW =0x%03x EL = %d\n" + "\tA (sys error) = %d ERR = %d\n" + "\tHDE (halting debug) = %d STATUS = 0x%03x (%s)\n" + "\tPIPEADV (Pipeline advance) = %d\n", + edscr, + (edscr & ARMV8_EDSCR_RXFULL) ? 1 : 0, + (edscr & ARMV8_EDSCR_TXFULL) ? 1 : 0, + (edscr & ARMV8_EDSCR_ITO) ? 1 : 0, + (edscr & ARMV8_EDSCR_ITE) ? 1 : 0, + (edscr & ARMV8_EDSCR_RXO) ? 1 : 0, + (edscr & ARMV8_EDSCR_TXU) ? 1 : 0, + (edscr & ARMV8_EDSCR_TDA) ? 1 : 0, + (edscr & ARMV8_EDSCR_MA) ? 1 : 0, + (edscr & ARMV8_EDSCR_NS) ? 1 : 0, + (edscr & ARMV8_EDSCR_SDD) ? 1 : 0, + EDSCR_RW(edscr), EDSCR_EL(edscr), + (edscr & ARMV8_EDSCR_A) ? 1 : 0, + (edscr & ARMV8_EDSCR_ERR) ? 1 : 0, + (edscr & ARMV8_EDSCR_HDE) ? 1 : 0, EDSCR_STATUS(edscr), debug_reason_name(target), + (edscr & ARMV8_EDSCR_PIPEADV) ? 1: 0 + ); +} + +void print_edesr_detail(struct command_context *cmd_ctx, uint32_t edesr) +{ + command_print(cmd_ctx, + "EDESR = 0x%.8"PRIx32 "\n" + "\tSS (Halting step debug event pending) = %d\n" + "\tRC (Reset catch debug event pending) = %d\n" + "\tOSUC (OS unlock debug event pending) = %d\n", + edesr, + (edesr & ARMV8_EDESR_SS) ? 1 : 0, + (edesr & ARMV8_EDESR_RC) ? 1 : 0, + (edesr & ARMV8_EDESR_OSUC) ? 1 : 0 + ); +} + +void print_edprsr_detail(struct command_context *cmd_ctx, uint32_t edprsr) +{ + command_print(cmd_ctx, + "EDPRSR = 0x%.8"PRIx32 "\n" + "\tHALTED = %d SDR (Sticky debug restart) = %d\n" + "\tSPMAD (Stidky EPMAD err) = %d EPMAD (Ext PM access disable) = %d\n" + "\tSDAD (Sticky EDAD err) = %d EDAD (Ext Debug disable) = %d\n" + "\tDLK (Double lock) = %d OSLK = %d\n" + "\tSR (Sticky reset) = %d R = %d\n" + "\tSPD (Sticky Powerdown) = %d PU = %d\n", + edprsr, + (edprsr & ARMV8_EDPRSR_HALTED) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_SDR) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_SPMAD) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_EPMAD) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_SDAD) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_EDAD) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_DLK) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_OSLK) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_SR) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_R) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_SPD) ? 1 : 0, + (edprsr & ARMV8_EDPRSR_PU) ? 1 : 0 + ); +} + +int print_target_debug_info_cti( + struct command_context *cmd_ctx, + struct target *target) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct adiv5_dap *dap = armv8->arm.dap; + int rc = ERROR_FAIL; + uint32_t cti_base = armv8->debug_base + ARMV8_CTI_BASE_OFST; + uint32_t cti_devid, cti_devtype; + uint32_t cti_control, cti_appset, cti_gate, cti_asicctl; + uint32_t cti_inen[8], cti_outen[8]; + uint32_t cti_triginstatus, cti_trigoutstatus; + uint32_t cti_chinstatus, cti_choutstatus; + /* WO: CTI_INTACK, CTI_APPCLEAR, CTI_APPPULSE + */ + + assert(dap != NULL); +// uint32_t cti_authstatus, /* FB8 */ + + + /* We need at least 3 channels (DEBUG, RESTART, IRQ) to work */ + rc = mem_ap_read_atomic_u32(dap, cti_base + CS_REG_DEVID, &cti_devid); + if (rc == ERROR_OK) { + command_print(cmd_ctx, "CTI DevID = 0x%.8" PRIx32 ", Num Channel=%d, Num Trigger=%d", + cti_devid, + ARMV8_CTIDEVID_NUMCHAN(cti_devid), + ARMV8_CTIDEVID_NUMTRIG(cti_devid) + ); + } + + rc = mem_ap_read_atomic_u32(dap, cti_base + CS_REG_DEVTYPE, &cti_devtype); + if (rc == ERROR_OK) { + command_print(cmd_ctx, "\tCTI type Major/Sub = 0x%x/0x%x", + (cti_devtype & 0xf), + (cti_devtype >> 4) & 0xf + ); + } + + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_CONTROL, &cti_control); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_GATE, &cti_gate); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_ASICCTL, &cti_asicctl); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_APPSET, &cti_appset); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_TRIGINSTATUS, &cti_triginstatus); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_TRIGOUTSTATUS, &cti_trigoutstatus); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_CHINSTATUS, &cti_chinstatus); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_CHOUTSTATUS, &cti_choutstatus); + if (rc != ERROR_OK) goto err; + int i; + for (i = 0; i < 8; i++) { + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_INEN(i), &(cti_inen[i])); + if (rc != ERROR_OK) goto err; + rc = mem_ap_read_u32(dap, cti_base + ARMV8_REG_CTI_OUTEN(i),&(cti_outen[i])); + if (rc != ERROR_OK) goto err; + } + rc = dap_run(dap); + if (rc != ERROR_OK) goto err; + + command_print(cmd_ctx, + "\tcontrol (glben) = %08x gate = %08x\n" + "\tasicctl = %08x appset = %08x\n" + "\ttrig in status = %08x trig out status = %08x\n" + "\t ch in status = %08x ch out status = %08x\n" + "\t in en 0..7 = %08x %08x %08x %08x\n" + "\t %08x %08x %08x %08x\n" + "\tout en 0..7 = %08x %08x %08x %08x\n" + "\t %08x %08x %08x %08x\n", + cti_control, cti_gate, + cti_asicctl, cti_appset, + cti_triginstatus, cti_trigoutstatus, + cti_chinstatus, cti_choutstatus, + cti_inen[0], cti_inen[1], cti_inen[2], cti_inen[3], + cti_inen[4], cti_inen[5], cti_inen[6], cti_inen[7], + cti_outen[0], cti_outen[1], cti_outen[2], cti_outen[3], + cti_outen[4], cti_outen[5], cti_outen[6], cti_outen[7] + ); + +err: + return rc; +} + +void print_target_debug_info(struct command_context *cmd_ctx, struct target *target) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct adiv5_dap *dap = armv8->arm.dap; + int rc = ERROR_FAIL; + uint32_t edprsr, edesr; + + command_print(cmd_ctx, "----- Target %s -----", target_name(target)); + + dap_ap_select(dap, armv8->debug_ap); + + print_edscr_detail(cmd_ctx, aarch64->cpudbg_edscr); + + rc = mem_ap_read_atomic_u32(dap, + armv8->debug_base + ARMV8_REG_EDESR, &edesr); + if (rc == ERROR_OK) { + print_edesr_detail(cmd_ctx, edesr); + } + + rc = mem_ap_read_atomic_u32(dap, + armv8->debug_base + ARMV8_REG_EDPRSR, &edprsr); + if (rc == ERROR_OK) { + print_edprsr_detail(cmd_ctx, edprsr); + } + + rc = print_target_debug_info_cti(cmd_ctx, target); + +} + +COMMAND_HANDLER(aarch64_handle_debug_info_command) +{ + struct target *target = get_current_target(CMD_CTX); + bool opt_smp = false; + + if (CMD_ARGC >= 1) { + opt_smp = (strcmp(CMD_ARGV[0], "smp") == 0); + } + + if (!opt_smp) { + print_target_debug_info(CMD_CTX, target); + return ERROR_OK; + } + + for (target = all_targets; target; target = target->next) { + print_target_debug_info(CMD_CTX, target); + command_print(CMD_CTX, "\n"); + } + + return ERROR_OK; +} + + +/* + d2801543 mov x3, #0xAA + 14000002 b loop + d2800aa3 mov x3, #0x55 +loop: + 14000000 b loop +*/ +static uint32_t opcodes_55aa[] = { + /* loop_00: */ + 0x14000000, /* b loop_00 */ + + 0xd2801543, /* mov x3, #0xAA */ + /* loop_10: */ + 0x14000000, /* b loop_10 */ + + 0xd2800aa3, /* mov x3, #0x55 */ + /* loop_20: */ + 0x14000000 /* b loop_20 */ + }; + +/* + d2800004 mov x4, #0x0 // #0 + d2800025 mov x5, #0x1 // #1 + 8b050086 add x6, x4, x5 + 8b0600a7 add x7, x5, x6 + 8b0700c8 add x8, x6, x7 + 8b0800e9 add x9, x7, x8 + dead_loop: + 14000000 b 18 <dead_loop> +*/ +static uint32_t opcodes_add[] = { + 0xd2800004, /* mov x4, #0x0 */ + 0xd2800025, /* mov x5, #0x1 */ + 0x8b050086, /* add x6, x4, x5 */ + 0x8b0600a7, /* add x7, x5, x6 */ + 0x8b0700c8, /* add x8, x6, x7 */ + 0x8b0800e9, /* add x9, x7, x8 */ + 0x14000000 /* b <dead_loop> */ + }; + +COMMAND_HANDLER(aarch64_handle_debug_codes_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct arm *arm = target->arch_info; + struct reg *r; + uint64_t addr; + int64_t offset; + uint64_t armpc_addr, regpc_addr; + uint32_t *code; + uint32_t code_size; + + armpc_addr = buf_get_u64(arm->pc->value, 0, 64); + + r = armv8_get_reg_by_num(arm, AARCH64_PC); + regpc_addr = buf_get_u64(r->value, 0, 64); + + command_print(CMD_CTX, "armpc=0x%.16" PRIX64 ", regpc=0x%.16" PRIX64, + armpc_addr, + regpc_addr + ); + + /* Parameter 0: code pattern */ + code = NULL; + if (CMD_ARGC >= 1) { + if (strcmp(CMD_ARGV[0], "55aa") == 0) { + code = opcodes_55aa; + code_size = ARRAY_SIZE(opcodes_55aa); + } else if (strcmp(CMD_ARGV[0], "add") == 0) { + code = opcodes_add; + code_size = ARRAY_SIZE(opcodes_add); + } + } + if (code == NULL) { + command_print(CMD_CTX, "No code selected"); + return ERROR_OK; + } + + /* Parameter 1: address/offset */ + addr = regpc_addr; + if (CMD_ARGC >= 2) { + if ((CMD_ARGV[1][0] == '-') || (CMD_ARGV[1][0] == '+')) { + /* relative offset */ + COMMAND_PARSE_NUMBER(s64, CMD_ARGV[1], offset); + addr += offset; + command_print(CMD_CTX, "offset = 0x%"PRIX64 ", addr=0x%.16"PRIX64, + offset, addr); + } else { + /* absoluted address */ + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], addr); + command_print(CMD_CTX, "user pc = 0x%.16" PRIX64, addr); + } + } + +#if 1 + return target->type64->write_memory(target, addr, 4, code_size, (uint8_t *)code); +#else + while (code_size--) { +// aarch64_write_memory(target, addr + i*4, 4, 1, (uint8_t *)(&opcodes[i])); + target->type64->write_memory(target, addr, 4, 1, (uint8_t *)(code++)); + + /* step to next instruction (4-byte) */ + addr += 4; + } /* End of while(code_size) */ + + return ERROR_OK; +#endif +} + +COMMAND_HANDLER(aarch64_handle_debug_cache_ic_command) +{ + struct target *target = get_current_target(CMD_CTX); + bool ialluis; + bool iallu; + uint32_t opcode; + uint32_t edscr; + int retval; + + if (CMD_ARGC == 0) { + iallu = 0; + ialluis = 1; + opcode = 0xd508711f; /* ic ialluis */ + } else if (CMD_ARGC >= 1) { + ialluis = strcmp(CMD_ARGV[0], "ialluis") == 0; + iallu = strcmp(CMD_ARGV[0], "iallu") == 0; + } + + /* IC IALLU and DC ste/way: apply only to the caches of the PE that performs the instruction. + * IC IALLUIS instruction can affect the caches of all PEs in the same Inner Shareable shareability domain */ + + if (iallu) + opcode = 0xd508751f; /* ic iallu */ + if (ialluis) + opcode = 0xd508711f; /* ic ialluis */ + edscr = 0; + retval = aarch64_exec_opcode(target, opcode, &edscr); + + command_print(CMD_CTX, "I-Cahce flushed (ialluis=%d, iallu=%d)", + ialluis, iallu); + + return retval; +} + +/* Kernel: arch/arm64/mm/cache.S + * flush_cache_all + * mov x12, lr + * bl __flush_dcache_all + * mov x0, #0 + * ic ialluis // I+BTB cache invalidate + * ret x12 + */ +COMMAND_HANDLER(aarch64_handle_debug_cache_flushall_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + uint32_t edscr; + uint32_t opcode; + int rc = ERROR_OK; + +#if 0 /* beginning of cache flushing only: doens't work */ + /* DSB SY & ISB: Invalidate entire TLB */ + opcode = A64_OPCODE_DSB_SY; /* d5033f9f dsb sy */ + if (rc == ERROR_OK) + rc = aarch64_exec_opcode(target, opcode, &edscr); + + opcode = A64_OPCODE_ISB; /* d5033fdf isb */ + if (rc == ERROR_OK) + rc = aarch64_exec_opcode(target, opcode, &edscr); +#endif + + /* Flush D-Cache */ + if (armv8->armv8_mmu.armv8_cache.flush_dcache_all) + armv8->armv8_mmu.armv8_cache.flush_dcache_all(target); + + /* Flush I-Cache */ + opcode = 0xd508711f; /* ic ialluis */ + edscr = 0; + rc = aarch64_exec_opcode(target, opcode, &edscr); + +#if 0 + /* DSB SY & ISB: Invalidate entire TLB */ + opcode = A64_OPCODE_DSB_SY; /* d5033f9f dsb sy */ + if (rc == ERROR_OK) + rc = aarch64_exec_opcode(target, opcode, &edscr); + + opcode = A64_OPCODE_ISB; /* d5033fdf isb */ + if (rc == ERROR_OK) + rc = aarch64_exec_opcode(target, opcode, &edscr); +#endif + + if (rc != ERROR_OK) { + command_print(CMD_CTX, "Fail to flushall, rc = %d", rc); + } + + return rc; +} + +COMMAND_HANDLER(aarch64_handle_debug_resume_command) +{ + + return ERROR_OK; +} + +COMMAND_HANDLER(aarch64_handle_debug_step_command) +{ + + return ERROR_OK; +} + +COMMAND_HANDLER(aarch64_handle_debug_test_command) +{ + + return ERROR_OK; +} + +#if 0 +COMMAND_HANDLER(aarch64_handle_debug_command) +{ +// struct target *target = get_current_target(CMD_CTX); + + return ERROR_OK; +} +#endif + + + +static const struct command_registration aarch64_debug_cache_subcommand_handlers[] = { + { + .name = "iallu", /* aarch64 debug cache iallu */ + .handler = aarch64_handle_debug_cache_ic_command, + .mode = COMMAND_EXEC, + .help = "ic iallu", + .usage = "", + }, + { + .name = "ialluis", /* aarch64 debug cache ialluis */ + .handler = aarch64_handle_debug_cache_ic_command, + .mode = COMMAND_EXEC, + .help = "ic ialluis", + .usage = "", + }, + { + .name = "flushall", /* aarch64 debug cache flushall */ + .handler = aarch64_handle_debug_cache_flushall_command, + .mode = COMMAND_EXEC, + .help = "flush I & D caches", + .usage = "", + }, + + COMMAND_REGISTRATION_DONE +}; + +const struct command_registration aarch64_debug_subcommand_handlers[] = { + { + .name = "info", + .handler = aarch64_handle_debug_info_command, + .mode = COMMAND_EXEC, + .help = "debugging information", + .usage = "", + }, + + { + .name = "codes", /* debug codes */ + .mode = COMMAND_ANY, + .handler = aarch64_handle_debug_codes_command, + .help = "replace opcodes around PC", +// .chain = aarch64_debug_codes_subcommand_handlers, + .usage = "", + }, + + { + .name = "resume", /* debug resume */ + .mode = COMMAND_ANY, + .handler = aarch64_handle_debug_resume_command, + .help = "debugging 'resume' command", +// .chain = aarch64_debug_resume_subcommand_handlers, + .usage = "", + }, + + { + .name = "step", /* debug step */ + .mode = COMMAND_ANY, + .handler = aarch64_handle_debug_step_command, + .help = "debugging 'step' command", +// .chain = aarch64_debug_step_subcommand_handlers, + .usage = "", + }, + + { + .name = "cache", /* cache operation */ + .mode = COMMAND_EXEC, +// .handler = aarch64_handle_debug_cache_command, + .help = "cache operation", + .chain = aarch64_debug_cache_subcommand_handlers, + .usage = "", + }, + + { + .name = "test", /* test operation */ + .mode = COMMAND_EXEC, + .handler = aarch64_handle_debug_test_command, + .help = "test something misc", + .usage = "", + }, + + COMMAND_REGISTRATION_DONE +}; + -- ------------------------------------------------------------------------------ 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
