X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_a.c;h=73fb8e0f57ebb1ea34147702f995e13d8607347f;hp=61e098956994d4a11d48e9fdbb40a1da111e86c8;hb=29c81a80510aa82b1842b15a9b091a3062cb51dc;hpb=557aa6dc5c596f2475d41c62e5a62c53d17dd421 diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 61e0989569..73fb8e0f57 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -18,7 +18,7 @@ * michel.jaouen@stericsson.com : smp minimum support * * * * Copyright (C) Broadcom 2012 * - * ehunter@broadcom.com : Cortex R4 support * + * ehunter@broadcom.com : Cortex-R4 support * * * * Copyright (C) 2013 Kamal Dasu * * kdasu.kdev@gmail.com * @@ -34,9 +34,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * * * * Cortex-A8(tm) TRM, ARM DDI 0344H * * Cortex-A9(tm) TRM, ARM DDI 0407F * @@ -55,8 +53,13 @@ #include "target_request.h" #include "target_type.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" +#include "transport/transport.h" #include +#define foreach_smp_target(pos, head) \ + for (pos = head; (pos != NULL); pos = pos->next) + static int cortex_a_poll(struct target *target); static int cortex_a_debug_entry(struct target *target); static int cortex_a_restore_context(struct target *target, bool bpwp); @@ -68,15 +71,11 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint); static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); -static int cortex_a_dap_read_coreregister_u32(struct target *target, - uint32_t *value, int regnum); -static int cortex_a_dap_write_coreregister_u32(struct target *target, - uint32_t value, int regnum); static int cortex_a_mmu(struct target *target, int *enabled); static int cortex_a_mmu_modify(struct target *target, int enable); static int cortex_a_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys); -static int cortex_a_read_apb_ab_memory(struct target *target, + target_addr_t virt, target_addr_t *phys); +static int cortex_a_read_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); @@ -106,13 +105,20 @@ static int cortex_a_restore_cp15_control_reg(struct target *target) static int cortex_a_prep_memaccess(struct target *target, int phys_access) { struct armv7a_common *armv7a = target_to_armv7a(target); + struct cortex_a_common *cortex_a = target_to_cortex_a(target); int mmu_enabled = 0; if (phys_access == 0) { - dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); cortex_a_mmu(target, &mmu_enabled); if (mmu_enabled) cortex_a_mmu_modify(target, 1); + if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) { + /* overwrite DACR to all-manager */ + armv7a->arm.mcr(target, 15, + 0, 0, 3, 0, + 0xFFFFFFFF); + } } else { cortex_a_mmu(target, &mmu_enabled); if (mmu_enabled) @@ -129,9 +135,16 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access) static int cortex_a_post_memaccess(struct target *target, int phys_access) { struct armv7a_common *armv7a = target_to_armv7a(target); + struct cortex_a_common *cortex_a = target_to_cortex_a(target); if (phys_access == 0) { - dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); + if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) { + /* restore */ + armv7a->arm.mcr(target, 15, + 0, 0, 3, 0, + cortex_a->cp15_dacr_reg); + } + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); } else { int mmu_enabled = 0; cortex_a_mmu(target, &mmu_enabled); @@ -182,97 +195,37 @@ static int cortex_a_mmu_modify(struct target *target, int enable) return retval; } -/* - * Cortex-A Basic debug access, very low level assumes state is saved - */ -static int cortex_a8_init_debug_access(struct target *target) -{ - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - int retval; - - LOG_DEBUG(" "); - - /* Unlocking the debug registers for modification - * The debugport might be uninitialised so try twice */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); - if (retval != ERROR_OK) { - /* try again */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); - if (retval == ERROR_OK) - LOG_USER( - "Locking debug access failed on first, but succeeded on second try."); - } - - return retval; -} - /* * Cortex-A Basic debug access, very low level assumes state is saved */ static int cortex_a_init_debug_access(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; - uint32_t dbg_osreg; - uint32_t cortex_part_num; - struct cortex_a_common *cortex_a = target_to_cortex_a(target); - - LOG_DEBUG(" "); - cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> - CORTEX_A_MIDR_PARTNUM_SHIFT; - - switch (cortex_part_num) { - case CORTEX_A7_PARTNUM: - case CORTEX_A15_PARTNUM: - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_OSLSR, - &dbg_osreg); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("DBGOSLSR 0x%" PRIx32, dbg_osreg); - - if (dbg_osreg & CPUDBG_OSLAR_LK_MASK) - /* Unlocking the DEBUG OS registers for modification */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - break; - - case CORTEX_A5_PARTNUM: - case CORTEX_A8_PARTNUM: - case CORTEX_A9_PARTNUM: - default: - retval = cortex_a8_init_debug_access(target); - } - - if (retval != ERROR_OK) - return retval; - /* Clear Sticky Power Down status Bit in PRSR to enable access to - the registers in the Core Power Domain */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + /* lock memory-mapped access to debug registers to prevent + * software interference */ + retval = mem_ap_write_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_LOCKACCESS, 0); if (retval != ERROR_OK) return retval; /* Disable cacheline fills and force cache write-through in debug state */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCCR, 0); if (retval != ERROR_OK) return retval; /* Disable TLB lookup and refill/eviction in debug state */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSMCR, 0); if (retval != ERROR_OK) return retval; + retval = dap_run(armv7a->debug_ap->dap); + if (retval != ERROR_OK) + return retval; + /* Enabling of instruction execution in debug mode is done in debug_entry code */ /* Resync breakpoint registers */ @@ -287,11 +240,10 @@ static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool f * Writes final value of DSCR into *dscr. Pass force to force always * reading DSCR at least once. */ struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - long long then = timeval_ms(); + int64_t then = timeval_ms(); while ((*dscr & DSCR_INSTR_COMP) == 0 || force) { force = false; - int retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + int retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) { LOG_ERROR("Could not read DSCR register"); @@ -316,7 +268,6 @@ static int cortex_a_exec_opcode(struct target *target, uint32_t dscr; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; dscr = dscr_p ? *dscr_p : 0; @@ -327,14 +278,14 @@ static int cortex_a_exec_opcode(struct target *target, if (retval != ERROR_OK) return retval; - retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_ITR, opcode); if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); do { - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) { LOG_ERROR("Could not read DSCR register"); @@ -352,175 +303,6 @@ static int cortex_a_exec_opcode(struct target *target, return retval; } -/************************************************************************** -Read core register with very few exec_opcode, fast but needs work_area. -This can cause problems with MMU active. -**************************************************************************/ -static int cortex_a_read_regs_through_mem(struct target *target, uint32_t address, - uint32_t *regfile) -{ - int retval = ERROR_OK; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - - retval = cortex_a_dap_read_coreregister_u32(target, regfile, 0); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_dap_write_coreregister_u32(target, address, 0); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap->ap_num, - (uint8_t *)(®file[1]), 4, 15, address); - - return retval; -} - -static int cortex_a_dap_read_coreregister_u32(struct target *target, - uint32_t *value, int regnum) -{ - int retval = ERROR_OK; - uint8_t reg = regnum&0xFF; - uint32_t dscr = 0; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - - if (reg > 17) - return retval; - - if (reg < 15) { - /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0" 0xEE00nE15 */ - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(14, 0, reg, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } else if (reg == 15) { - /* "MOV r0, r15"; then move r0 to DCCTX */ - retval = cortex_a_exec_opcode(target, 0xE1A0000F, &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } else { - /* "MRS r0, CPSR" or "MRS r0, SPSR" - * then move r0 to DCCTX - */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } - - /* Wait for DTRRXfull then read DTRRTX */ - long long then = timeval_ms(); - while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for cortex_a_exec_opcode"); - return ERROR_FAIL; - } - } - - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_DTRTX, value); - LOG_DEBUG("read DCC 0x%08" PRIx32, *value); - - return retval; -} - -static int cortex_a_dap_write_coreregister_u32(struct target *target, - uint32_t value, int regnum) -{ - int retval = ERROR_OK; - uint8_t Rd = regnum&0xFF; - uint32_t dscr; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - - LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value); - - /* Check that DCCRX is not full */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - if (dscr & DSCR_DTR_RX_FULL) { - LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); - /* Clear DCCRX with MRC(p14, 0, Rd, c0, c5, 0), opcode 0xEE100E15 */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } - - if (Rd > 17) - return retval; - - /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */ - LOG_DEBUG("write DCC 0x%08" PRIx32, value); - retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_DTRRX, value); - if (retval != ERROR_OK) - return retval; - - if (Rd < 15) { - /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0), - &dscr); - - if (retval != ERROR_OK) - return retval; - } else if (Rd == 15) { - /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15 - * then "mov r15, r0" - */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, 0xE1A0F000, &dscr); - if (retval != ERROR_OK) - return retval; - } else { - /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15 - * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields) - */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1), - &dscr); - if (retval != ERROR_OK) - return retval; - - /* "Prefetch flush" after modifying execution status in CPSR */ - if (Rd == 16) { - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(15, 0, 0, 7, 5, 4), - &dscr); - if (retval != ERROR_OK) - return retval; - } - } - - return retval; -} - /* Write to memory mapped registers directly with no cache or mmu handling */ static int cortex_a_dap_write_memap_register_u32(struct target *target, uint32_t address, @@ -528,9 +310,8 @@ static int cortex_a_dap_write_memap_register_u32(struct target *target, { int retval; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, address, value); + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value); return retval; } @@ -554,14 +335,13 @@ static inline struct cortex_a_common *dpm_to_a(struct arm_dpm *dpm) static int cortex_a_write_dcc(struct cortex_a_common *a, uint32_t data) { LOG_DEBUG("write DCC 0x%08" PRIx32, data); - return mem_ap_sel_write_u32(a->armv7a_common.arm.dap, - a->armv7a_common.debug_ap->ap_num, a->armv7a_common.debug_base + CPUDBG_DTRRX, data); + return mem_ap_write_u32(a->armv7a_common.debug_ap, + a->armv7a_common.debug_base + CPUDBG_DTRRX, data); } static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data, uint32_t *dscr_p) { - struct adiv5_dap *swjdp = a->armv7a_common.arm.dap; uint32_t dscr = DSCR_INSTR_COMP; int retval; @@ -569,9 +349,9 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data, dscr = *dscr_p; /* Wait for DTRRXfull */ - long long then = timeval_ms(); + int64_t then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) @@ -582,7 +362,7 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data, } } - retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DTRTX, data); if (retval != ERROR_OK) return retval; @@ -597,14 +377,13 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data, static int cortex_a_dpm_prepare(struct arm_dpm *dpm) { struct cortex_a_common *a = dpm_to_a(dpm); - struct adiv5_dap *swjdp = a->armv7a_common.arm.dap; uint32_t dscr; int retval; /* set up invariant: INSTR_COMP is set after ever DPM operation */ - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;; ) { - retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) @@ -850,7 +629,8 @@ static int cortex_a_halt_smp(struct target *target) head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; - if ((curr != target) && (curr->state != TARGET_HALTED)) + if ((curr != target) && (curr->state != TARGET_HALTED) + && target_was_examined(curr)) retval += cortex_a_halt(curr); head = head->next; } @@ -859,12 +639,43 @@ static int cortex_a_halt_smp(struct target *target) static int update_halt_gdb(struct target *target) { + struct target *gdb_target = NULL; + struct target_list *head; + struct target *curr; int retval = 0; + if (target->gdb_service && target->gdb_service->core[0] == -1) { target->gdb_service->target = target; target->gdb_service->core[0] = target->coreid; retval += cortex_a_halt_smp(target); } + + if (target->gdb_service) + gdb_target = target->gdb_service->target; + + foreach_smp_target(head, target->head) { + curr = head->target; + /* skip calling context */ + if (curr == target) + continue; + if (!target_was_examined(curr)) + continue; + /* skip targets that were already halted */ + if (curr->state == TARGET_HALTED) + continue; + /* Skip gdb_target; it alerts GDB so has to be polled as last one */ + if (curr == gdb_target) + continue; + + /* avoid recursion in cortex_a_poll() */ + curr->smp = 0; + cortex_a_poll(curr); + curr->smp = 1; + } + + /* after all targets were updated, poll the gdb serving target */ + if (gdb_target != NULL && gdb_target != target) + cortex_a_poll(gdb_target); return retval; } @@ -878,7 +689,6 @@ static int cortex_a_poll(struct target *target) uint32_t dscr; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; - struct adiv5_dap *swjdp = armv7a->arm.dap; enum target_state prev_target_state = target->state; /* toggle to another core is done by gdb as follow */ /* maint packet J core_id */ @@ -892,7 +702,7 @@ static int cortex_a_poll(struct target *target) target_call_event_callbacks(target, TARGET_EVENT_HALTED); return retval; } - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -914,6 +724,10 @@ static int cortex_a_poll(struct target *target) if (retval != ERROR_OK) return retval; } + + if (arm_semihosting(target, &retval) != 0) + return retval; + target_call_event_callbacks(target, TARGET_EVENT_HALTED); } @@ -933,12 +747,8 @@ static int cortex_a_poll(struct target *target) TARGET_EVENT_DEBUG_HALTED); } } - } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED) + } else target->state = TARGET_RUNNING; - else { - LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr); - target->state = TARGET_UNKNOWN; - } return retval; } @@ -948,13 +758,12 @@ static int cortex_a_halt(struct target *target) int retval = ERROR_OK; uint32_t dscr; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; /* * Tell the core to be halted by writing DRCR with 0x1 * and then wait for the core to be halted. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT); if (retval != ERROR_OK) return retval; @@ -962,19 +771,19 @@ static int cortex_a_halt(struct target *target) /* * enter halting debug mode */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE); if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;; ) { - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -992,7 +801,7 @@ static int cortex_a_halt(struct target *target) } static int cortex_a_internal_restore(struct target *target, int current, - uint32_t *address, int handle_breakpoints, int debug_execution) + target_addr_t *address, int handle_breakpoints, int debug_execution) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; @@ -1047,13 +856,17 @@ static int cortex_a_internal_restore(struct target *target, int current, case ARM_STATE_JAZELLE: LOG_ERROR("How do I resume into Jazelle state??"); return ERROR_FAIL; + case ARM_STATE_AARCH64: + LOG_ERROR("Shoudn't be in AARCH64 state"); + return ERROR_FAIL; } LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc); buf_set_u32(arm->pc->value, 0, 32, resume_pc); arm->pc->dirty = 1; arm->pc->valid = 1; + /* restore dpm_mode at system halt */ - dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); /* called it now before restoring context because it uses cpu * register r0 for restoring cp15 control register */ retval = cortex_a_restore_cp15_control_reg(target); @@ -1089,7 +902,6 @@ static int cortex_a_internal_restart(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; - struct adiv5_dap *swjdp = arm->dap; int retval; uint32_t dscr; /* @@ -1100,7 +912,7 @@ static int cortex_a_internal_restart(struct target *target) * disable IRQs by default, with optional override... */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -1108,20 +920,20 @@ static int cortex_a_internal_restart(struct target *target) if ((dscr & DSCR_INSTR_COMP) == 0) LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN); if (retval != ERROR_OK) return retval; - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART | DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;; ) { - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -1147,11 +959,12 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) int retval = 0; struct target_list *head; struct target *curr; - uint32_t address; + target_addr_t address; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; - if ((curr != target) && (curr->state != TARGET_RUNNING)) { + if ((curr != target) && (curr->state != TARGET_RUNNING) + && target_was_examined(curr)) { /* resume current address , not in step mode */ retval += cortex_a_internal_restore(curr, 1, &address, handle_breakpoints, 0); @@ -1164,7 +977,7 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) } static int cortex_a_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { int retval = 0; /* dummy resume for smp toggle in order to reduce gdb impact */ @@ -1188,11 +1001,11 @@ static int cortex_a_resume(struct target *target, int current, if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%" PRIx32, address); + LOG_DEBUG("target resumed at " TARGET_ADDR_FMT, address); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%" PRIx32, address); + LOG_DEBUG("target debug resumed at " TARGET_ADDR_FMT, address); } return ERROR_OK; @@ -1200,20 +1013,16 @@ static int cortex_a_resume(struct target *target, int current, static int cortex_a_debug_entry(struct target *target) { - int i; - uint32_t regfile[16], cpsr, dscr; + uint32_t dscr; int retval = ERROR_OK; - struct working_area *regfile_working_area = NULL; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; - struct adiv5_dap *swjdp = armv7a->arm.dap; - struct reg *reg; LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr); /* REVISIT surely we should not re-read DSCR !! */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -1225,7 +1034,7 @@ static int cortex_a_debug_entry(struct target *target) /* Enable the ITR execution once we are in debug mode */ dscr |= DSCR_ITR_EN; - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) return retval; @@ -1237,7 +1046,7 @@ static int cortex_a_debug_entry(struct target *target) if (target->debug_reason == DBG_REASON_WATCHPOINT) { uint32_t wfar; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_WFAR, &wfar); if (retval != ERROR_OK) @@ -1245,54 +1054,16 @@ static int cortex_a_debug_entry(struct target *target) arm_dpm_report_wfar(&armv7a->dpm, wfar); } - /* REVISIT fast_reg_read is never set ... */ - - /* Examine target state and mode */ - if (cortex_a->fast_reg_read) - target_alloc_working_area(target, 64, ®file_working_area); - - /* First load register acessible through core debug port*/ - if (!regfile_working_area) - retval = arm_dpm_read_current_registers(&armv7a->dpm); - else { - retval = cortex_a_read_regs_through_mem(target, - regfile_working_area->address, regfile); - - target_free_working_area(target, regfile_working_area); - if (retval != ERROR_OK) - return retval; + /* First load register accessible through core debug port */ + retval = arm_dpm_read_current_registers(&armv7a->dpm); + if (retval != ERROR_OK) + return retval; - /* read Current PSR */ - retval = cortex_a_dap_read_coreregister_u32(target, &cpsr, 16); - /* store current cpsr */ + if (arm->spsr) { + /* read SPSR */ + retval = arm_dpm_read_reg(&armv7a->dpm, arm->spsr, 17); if (retval != ERROR_OK) return retval; - - LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr); - - arm_set_cpsr(arm, cpsr); - - /* update cache */ - for (i = 0; i <= ARM_PC; i++) { - reg = arm_reg_current(arm, i); - - buf_set_u32(reg->value, 0, 32, regfile[i]); - reg->valid = 1; - reg->dirty = 0; - } - - /* Fixup PC Resume Address */ - if (cpsr & (1 << 5)) { - /* T bit set for Thumb or ThumbEE state */ - regfile[ARM_PC] -= 4; - } else { - /* ARM state */ - regfile[ARM_PC] -= 8; - } - - reg = arm->pc; - buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]); - reg->dirty = reg->valid; } #if 0 @@ -1335,6 +1106,9 @@ static int cortex_a_post_debug_entry(struct target *target) LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg); cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg; + if (!armv7a->is_armv7r) + armv7a_read_ttbcr(target); + if (armv7a->armv7a_mmu.armv7a_cache.info == -1) armv7a_identify_cache(target); @@ -1350,17 +1124,26 @@ static int cortex_a_post_debug_entry(struct target *target) (cortex_a->cp15_control_reg & 0x1000U) ? 1 : 0; cortex_a->curr_mode = armv7a->arm.core_mode; + /* switch to SVC mode to read DACR */ + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); + armv7a->arm.mrc(target, 15, + 0, 0, 3, 0, + &cortex_a->cp15_dacr_reg); + + LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32, + cortex_a->cp15_dacr_reg); + + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); return ERROR_OK; } int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; uint32_t dscr; /* Read DSCR */ - int retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + int retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (ERROR_OK != retval) return retval; @@ -1371,12 +1154,12 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign dscr |= value & bit_mask; /* write new DSCR */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); return retval; } -static int cortex_a_step(struct target *target, int current, uint32_t address, +static int cortex_a_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); @@ -1412,6 +1195,7 @@ static int cortex_a_step(struct target *target, int current, uint32_t address, /* Setup single step breakpoint */ stepbreakpoint.address = address; + stepbreakpoint.asid = 0; stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB) ? 2 : 4; stepbreakpoint.type = BKPT_HARD; @@ -1433,7 +1217,7 @@ static int cortex_a_step(struct target *target, int current, uint32_t address, if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); while (target->state != TARGET_HALTED) { retval = cortex_a_poll(target); if (retval != ERROR_OK) @@ -1529,10 +1313,22 @@ static int cortex_a_set_breakpoint(struct target *target, brp_list[brp_i].value); } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; + /* length == 2: Thumb breakpoint */ if (breakpoint->length == 2) buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); else + /* length == 3: Thumb-2 breakpoint, actual encoding is + * a regular Thumb BKPT instruction but we replace a + * 32bit Thumb-2 instruction, so fix-up the breakpoint + * length + */ + if (breakpoint->length == 3) { + buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); + breakpoint->length = 4; + } else + /* length == 4, normal ARM breakpoint */ buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); + retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, @@ -1893,6 +1689,8 @@ static int cortex_a_assert_reset(struct target *target) /* FIXME when halt is requested, make it work somehow... */ + /* This function can be called in "target not examined" state */ + /* Issue some kind of warm reset. */ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) target_handle_event(target, TARGET_EVENT_RESET_ASSERT); @@ -1900,14 +1698,23 @@ static int cortex_a_assert_reset(struct target *target) /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ - jtag_add_reset(0, 1); + + /* + * FIXME: fix reset when transport is SWD. This is a temporary + * work-around for release v0.10 that is not intended to stay! + */ + if (transport_is_swd() || + (target->reset_halt && (jtag_get_reset_config() & RESET_SRST_NO_GATING))) + jtag_add_reset(0, 1); + } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } /* registers are now invalid */ - register_cache_invalidate(armv7a->arm.core_cache); + if (target_was_examined(target)) + register_cache_invalidate(armv7a->arm.core_cache); target->state = TARGET_RESET; @@ -1923,17 +1730,22 @@ static int cortex_a_deassert_reset(struct target *target) /* be certain SRST is off */ jtag_add_reset(0, 0); - retval = cortex_a_poll(target); - if (retval != ERROR_OK) - return retval; + if (target_was_examined(target)) { + retval = cortex_a_poll(target); + if (retval != ERROR_OK) + return retval; + } if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); - retval = target_halt(target); - if (retval != ERROR_OK) - return retval; + if (target_was_examined(target)) { + retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + } else + target->state = TARGET_UNKNOWN; } } @@ -1952,8 +1764,8 @@ static int cortex_a_set_dcc_mode(struct target *target, uint32_t mode, uint32_t uint32_t new_dscr = (*dscr & ~DSCR_EXT_DCC_MASK) | mode; if (new_dscr != *dscr) { struct armv7a_common *armv7a = target_to_armv7a(target); - int retval = mem_ap_sel_write_atomic_u32(armv7a->arm.dap, - armv7a->debug_ap->ap_num, armv7a->debug_base + CPUDBG_DSCR, new_dscr); + int retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_DSCR, new_dscr); if (retval == ERROR_OK) *dscr = new_dscr; return retval; @@ -1967,12 +1779,11 @@ static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask, { /* Waits until the specified bit(s) of DSCR take on a specified value. */ struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - long long then = timeval_ms(); + int64_t then = timeval_ms(); int retval; while ((*dscr & mask) != value) { - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) return retval; @@ -1989,7 +1800,6 @@ static int cortex_a_read_copro(struct target *target, uint32_t opcode, { int retval; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; /* Move from coprocessor to R0. */ retval = cortex_a_exec_opcode(target, opcode, dscr); @@ -2011,7 +1821,7 @@ static int cortex_a_read_copro(struct target *target, uint32_t opcode, return retval; /* Read the value transferred to DTRTX. */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, data); if (retval != ERROR_OK) return retval; @@ -2044,10 +1854,9 @@ static int cortex_a_write_copro(struct target *target, uint32_t opcode, { int retval; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; /* Write the value into DTRRX. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, data); if (retval != ERROR_OK) return retval; @@ -2116,20 +1925,19 @@ static int cortex_a_dfsr_to_error_code(uint32_t dfsr) } } -static int cortex_a_write_apb_ab_memory_slow(struct target *target, +static int cortex_a_write_cpu_memory_slow(struct target *target, uint32_t size, uint32_t count, const uint8_t *buffer, uint32_t *dscr) { /* Writes count objects of size size from *buffer. Old value of DSCR must * be in *dscr; updated to new value. This is slow because it works for * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and - * the address is aligned, cortex_a_write_apb_ab_memory_fast should be + * the address is aligned, cortex_a_write_cpu_memory_fast should be * preferred. * Preconditions: * - Address is in R0. * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; int retval; @@ -2151,7 +1959,7 @@ static int cortex_a_write_apb_ab_memory_slow(struct target *target, data = target_buffer_get_u16(target, buffer); else data = target_buffer_get_u32(target, buffer); - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, data); if (retval != ERROR_OK) return retval; @@ -2192,7 +2000,7 @@ static int cortex_a_write_apb_ab_memory_slow(struct target *target, return ERROR_OK; } -static int cortex_a_write_apb_ab_memory_fast(struct target *target, +static int cortex_a_write_cpu_memory_fast(struct target *target, uint32_t count, const uint8_t *buffer, uint32_t *dscr) { /* Writes count objects of size 4 from *buffer. Old value of DSCR must be @@ -2203,7 +2011,6 @@ static int cortex_a_write_apb_ab_memory_fast(struct target *target, * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; /* Switch to fast mode if not already in that mode. */ @@ -2212,28 +2019,27 @@ static int cortex_a_write_apb_ab_memory_fast(struct target *target, return retval; /* Latch STC instruction. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_ITR, ARMV4_5_STC(0, 1, 0, 1, 14, 5, 0, 4)); if (retval != ERROR_OK) return retval; /* Transfer all the data and issue all the instructions. */ - return mem_ap_sel_write_buf_noincr(swjdp, armv7a->debug_ap->ap_num, buffer, + return mem_ap_write_buf_noincr(armv7a->debug_ap, buffer, 4, count, armv7a->debug_base + CPUDBG_DTRRX); } -static int cortex_a_write_apb_ab_memory(struct target *target, +static int cortex_a_write_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - /* Write memory through APB-AP. */ + /* Write memory through the CPU. */ int retval, final_retval; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr; - LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, + LOG_DEBUG("Writing CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -2244,13 +2050,13 @@ static int cortex_a_write_apb_ab_memory(struct target *target, return ERROR_OK; /* Clear any abort. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; /* Read DSCR. */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -2269,7 +2075,7 @@ static int cortex_a_write_apb_ab_memory(struct target *target, goto out; /* Get the memory address into R0. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, address); if (retval != ERROR_OK) goto out; @@ -2279,10 +2085,10 @@ static int cortex_a_write_apb_ab_memory(struct target *target, if (size == 4 && (address % 4) == 0) { /* We are doing a word-aligned transfer, so use fast mode. */ - retval = cortex_a_write_apb_ab_memory_fast(target, count, buffer, &dscr); + retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr); } else { /* Use slow path. */ - retval = cortex_a_write_apb_ab_memory_slow(target, size, count, buffer, &dscr); + retval = cortex_a_write_cpu_memory_slow(target, size, count, buffer, &dscr); } out: @@ -2301,7 +2107,7 @@ out: /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also * check RXfull_l). Most of the time this will be free because RXfull_l - * will be cleared immediately and cached in dscr. However, don’t do this + * will be cleared immediately and cached in dscr. However, don't do this * if there is fault, because then the instruction might not have completed * successfully. */ if (!(dscr & DSCR_STICKY_ABORT_PRECISE)) { @@ -2313,7 +2119,7 @@ out: /* If there were any sticky abort flags, clear them. */ if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { fault_dscr = dscr; - mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE); } else { @@ -2347,7 +2153,7 @@ out: /* If the DCC is nonempty, clear it. */ if (dscr & DSCR_DTRTX_FULL_LATCHED) { uint32_t dummy; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &dummy); if (final_retval == ERROR_OK) final_retval = retval; @@ -2362,20 +2168,19 @@ out: return final_retval; } -static int cortex_a_read_apb_ab_memory_slow(struct target *target, +static int cortex_a_read_cpu_memory_slow(struct target *target, uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr) { /* Reads count objects of size size into *buffer. Old value of DSCR must be * in *dscr; updated to new value. This is slow because it works for * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and - * the address is aligned, cortex_a_read_apb_ab_memory_fast should be + * the address is aligned, cortex_a_read_cpu_memory_fast should be * preferred. * Preconditions: * - Address is in R0. * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; int retval; @@ -2420,7 +2225,7 @@ static int cortex_a_read_apb_ab_memory_slow(struct target *target, return retval; /* Read the value transferred to DTRTX into the buffer. */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &data); if (retval != ERROR_OK) return retval; @@ -2439,7 +2244,7 @@ static int cortex_a_read_apb_ab_memory_slow(struct target *target, return ERROR_OK; } -static int cortex_a_read_apb_ab_memory_fast(struct target *target, +static int cortex_a_read_cpu_memory_fast(struct target *target, uint32_t count, uint8_t *buffer, uint32_t *dscr) { /* Reads count objects of size 4 into *buffer. Old value of DSCR must be in @@ -2450,7 +2255,6 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target, * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; uint32_t u32; int retval; @@ -2473,7 +2277,7 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target, return retval; /* Latch LDC instruction. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_ITR, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4)); if (retval != ERROR_OK) return retval; @@ -2484,7 +2288,7 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target, * memory. The last read of DTRTX in this call reads the second-to-last * word from memory and issues the read instruction for the last word. */ - retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap->ap_num, buffer, + retval = mem_ap_read_buf_noincr(armv7a->debug_ap, buffer, 4, count, armv7a->debug_base + CPUDBG_DTRTX); if (retval != ERROR_OK) return retval; @@ -2518,7 +2322,7 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target, /* Read the value transferred to DTRTX into the buffer. This is the last * word. */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &u32); if (retval != ERROR_OK) return retval; @@ -2527,18 +2331,17 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target, return ERROR_OK; } -static int cortex_a_read_apb_ab_memory(struct target *target, +static int cortex_a_read_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - /* Read memory through APB-AP. */ + /* Read memory through the CPU. */ int retval, final_retval; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr; - LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, + LOG_DEBUG("Reading CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -2549,13 +2352,13 @@ static int cortex_a_read_apb_ab_memory(struct target *target, return ERROR_OK; /* Clear any abort. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; /* Read DSCR */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -2574,7 +2377,7 @@ static int cortex_a_read_apb_ab_memory(struct target *target, goto out; /* Get the memory address into R0. */ - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, address); if (retval != ERROR_OK) goto out; @@ -2584,10 +2387,10 @@ static int cortex_a_read_apb_ab_memory(struct target *target, if (size == 4 && (address % 4) == 0) { /* We are doing a word-aligned transfer, so use fast mode. */ - retval = cortex_a_read_apb_ab_memory_fast(target, count, buffer, &dscr); + retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr); } else { /* Use slow path. */ - retval = cortex_a_read_apb_ab_memory_slow(target, size, count, buffer, &dscr); + retval = cortex_a_read_cpu_memory_slow(target, size, count, buffer, &dscr); } out: @@ -2606,7 +2409,7 @@ out: /* If there were any sticky abort flags, clear them. */ if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { fault_dscr = dscr; - mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE); } else { @@ -2640,7 +2443,7 @@ out: /* If the DCC is nonempty, clear it. */ if (dscr & DSCR_DTRTX_FULL_LATCHED) { uint32_t dummy; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &dummy); if (final_retval == ERROR_OK) final_retval = retval; @@ -2659,169 +2462,85 @@ out: /* * Cortex-A Memory access * - * This is same Cortex M3 but we must also use the correct + * This is same Cortex-M3 but we must also use the correct * ap number for every access. */ static int cortex_a_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - int retval = ERROR_COMMAND_SYNTAX_ERROR; + int retval; - LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, + if (!count || !buffer) + return ERROR_COMMAND_SYNTAX_ERROR; + + LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); - if (count && buffer) { - /* read memory through APB-AP */ - cortex_a_prep_memaccess(target, 1); - retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer); - cortex_a_post_memaccess(target, 1); - } + /* read memory through the CPU */ + cortex_a_prep_memaccess(target, 1); + retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); + cortex_a_post_memaccess(target, 1); + return retval; } -static int cortex_a_read_memory(struct target *target, uint32_t address, +static int cortex_a_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); cortex_a_prep_memaccess(target, 0); - retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer); + retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); cortex_a_post_memaccess(target, 0); return retval; } -static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, - uint32_t size, uint32_t count, uint8_t *buffer) +static int cortex_a_write_phys_memory(struct target *target, + target_addr_t address, uint32_t size, + uint32_t count, const uint8_t *buffer) { - int mmu_enabled = 0; - uint32_t virt, phys; int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; - - if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num)) - return target_read_memory(target, address, size, count, buffer); - - /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); - - /* determine if MMU was enabled on target stop */ - if (!armv7a->is_armv7r) { - retval = cortex_a_mmu(target, &mmu_enabled); - if (retval != ERROR_OK) - return retval; - } - - if (mmu_enabled) { - virt = address; - retval = cortex_a_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, - virt, phys); - address = phys; - } if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap->ap_num, buffer, size, count, address); - - return retval; -} - -static int cortex_a_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, - uint32_t count, const uint8_t *buffer) -{ - int retval = ERROR_COMMAND_SYNTAX_ERROR; - - LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); - if (count && buffer) { - /* write memory through APB-AP */ - cortex_a_prep_memaccess(target, 1); - retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); - cortex_a_post_memaccess(target, 1); - } + /* write memory through the CPU */ + cortex_a_prep_memaccess(target, 1); + retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); + cortex_a_post_memaccess(target, 1); return retval; } -static int cortex_a_write_memory(struct target *target, uint32_t address, +static int cortex_a_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* memory writes bypass the caches, must flush before writing */ armv7a_cache_auto_flush_on_write(target, address, size * count); cortex_a_prep_memaccess(target, 0); - retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); + retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); cortex_a_post_memaccess(target, 0); return retval; } -static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) -{ - int mmu_enabled = 0; - uint32_t virt, phys; - int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; - - if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num)) - return target_write_memory(target, address, size, count, buffer); - - /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); - - /* determine if MMU was enabled on target stop */ - if (!armv7a->is_armv7r) { - retval = cortex_a_mmu(target, &mmu_enabled); - if (retval != ERROR_OK) - return retval; - } - - if (mmu_enabled) { - virt = address; - retval = cortex_a_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, - virt, - phys); - address = phys; - } - - if (!count || !buffer) - return ERROR_COMMAND_SYNTAX_ERROR; - - retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap->ap_num, buffer, size, count, address); - - return retval; -} - -static int cortex_a_read_buffer(struct target *target, uint32_t address, +static int cortex_a_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; @@ -2830,7 +2549,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address, * will have something to do with the size we leave to it. */ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { if (address & size) { - int retval = cortex_a_read_memory_ahb(target, address, size, 1, buffer); + int retval = target_read_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; address += size; @@ -2843,7 +2562,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address, for (; size > 0; size /= 2) { uint32_t aligned = count - count % size; if (aligned > 0) { - int retval = cortex_a_read_memory_ahb(target, address, size, aligned / size, buffer); + int retval = target_read_memory(target, address, size, aligned / size, buffer); if (retval != ERROR_OK) return retval; address += aligned; @@ -2855,7 +2574,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address, return ERROR_OK; } -static int cortex_a_write_buffer(struct target *target, uint32_t address, +static int cortex_a_write_buffer(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; @@ -2864,7 +2583,7 @@ static int cortex_a_write_buffer(struct target *target, uint32_t address, * will have something to do with the size we leave to it. */ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { if (address & size) { - int retval = cortex_a_write_memory_ahb(target, address, size, 1, buffer); + int retval = target_write_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; address += size; @@ -2877,7 +2596,7 @@ static int cortex_a_write_buffer(struct target *target, uint32_t address, for (; size > 0; size /= 2) { uint32_t aligned = count - count % size; if (aligned > 0) { - int retval = cortex_a_write_memory_ahb(target, address, size, aligned / size, buffer); + int retval = target_write_memory(target, address, size, aligned / size, buffer); if (retval != ERROR_OK) return retval; address += aligned; @@ -2893,7 +2612,6 @@ static int cortex_a_handle_target_request(void *priv) { struct target *target = priv; struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; if (!target_was_examined(target)) @@ -2904,18 +2622,23 @@ static int cortex_a_handle_target_request(void *priv) if (target->state == TARGET_RUNNING) { uint32_t request; uint32_t dscr; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); /* check if we have data */ + int64_t then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) { - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &request); if (retval == ERROR_OK) { target_request(target, request); - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); } + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for dtr tx full"); + return ERROR_FAIL; + } } } @@ -2931,34 +2654,25 @@ static int cortex_a_examine_first(struct target *target) struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct adiv5_dap *swjdp = armv7a->arm.dap; + int i; int retval = ERROR_OK; - uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg; + uint32_t didr, cpuid, dbg_osreg; - /* Search for the APB-AB - it is needed for access to debug registers */ + /* Search for the APB-AP - it is needed for access to debug registers */ retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); return retval; } - /* We do one extra read to ensure DAP is configured, - * we call ahbap_debugport_init(swjdp) instead - */ - retval = ahbap_debugport_init(swjdp, armv7a->debug_ap->ap_num); - if (retval != ERROR_OK) - return retval; - - /* Search for the AHB-AB */ - retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap); + retval = mem_ap_init(armv7a->debug_ap); if (retval != ERROR_OK) { - /* AHB-AP not found - use APB-AP */ - LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access"); - armv7a->memory_ap_available = false; - } else { - armv7a->memory_ap_available = true; + LOG_ERROR("Could not initialize the APB-AP"); + return retval; } + armv7a->debug_ap->memaccess_tck = 80; if (!target->dbgbase_set) { uint32_t dbgbase; @@ -2967,11 +2681,11 @@ static int cortex_a_examine_first(struct target *target) int32_t coreidx = target->coreid; LOG_DEBUG("%s's dbgbase is not set, trying to detect using the ROM table", target->cmd_name); - retval = dap_get_debugbase(swjdp, 1, &dbgbase, &apid); + retval = dap_get_debugbase(armv7a->debug_ap, &dbgbase, &apid); if (retval != ERROR_OK) return retval; /* Lookup 0x15 -- Processor DAP */ - retval = dap_lookup_cs_component(swjdp, 1, dbgbase, 0x15, + retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, 0x15, &armv7a->debug_base, &coreidx); if (retval != ERROR_OK) { LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.", @@ -2983,80 +2697,70 @@ static int cortex_a_examine_first(struct target *target) } else armv7a->debug_base = target->dbgbase; - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_CPUID, &cpuid); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_CPUID, &cpuid); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CPUID"); - return retval; - } - - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_CTYPR, &ctypr); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CTYPR"); - return retval; - } - - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_TTYPR, &ttypr); + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_DIDR, &didr); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "TTYPR"); + LOG_DEBUG("Examine %s failed", "DIDR"); return retval; } - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_DIDR, &didr); + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_CPUID, &cpuid); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "DIDR"); + LOG_DEBUG("Examine %s failed", "CPUID"); return retval; } - LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr); - LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr); LOG_DEBUG("didr = 0x%08" PRIx32, didr); + LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - cortex_a->cpuid = cpuid; - cortex_a->ctypr = ctypr; - cortex_a->ttypr = ttypr; cortex_a->didr = didr; + cortex_a->cpuid = cpuid; - /* Unlocking the debug registers */ - if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == - CORTEX_A15_PARTNUM) { - - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - - if (retval != ERROR_OK) - return retval; + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) { + LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid); + target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ + return ERROR_TARGET_INIT_FAILED; } - /* Unlocking the debug registers */ - if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == - CORTEX_A7_PARTNUM) { - - retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - - if (retval != ERROR_OK) - return retval; - } - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num, - armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); + if (dbg_osreg & PRSR_STICKY_RESET_STATUS) + LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid); + /* Read DBGOSLSR and check if OSLK is implemented */ + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); if (retval != ERROR_OK) return retval; + LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg); - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + /* check if OS Lock is implemented */ + if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) { + /* check if OS Lock is set */ + if (dbg_osreg & OSLSR_OSLK) { + LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid); + + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLAR, + 0); + if (retval == ERROR_OK) + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); + + /* if we fail to access the register or cannot reset the OSLK bit, bail out */ + if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) { + LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?", + target->coreid); + target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ + return ERROR_TARGET_INIT_FAILED; + } + } + } armv7a->arm.core_type = ARM_MODE_MON; @@ -3087,6 +2791,9 @@ static int cortex_a_examine_first(struct target *target) LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num); + /* select debug_ap as default */ + swjdp->apsel = armv7a->debug_ap->ap_num; + target_set_examined(target); return ERROR_OK; } @@ -3113,29 +2820,18 @@ static int cortex_a_init_target(struct command_context *cmd_ctx, struct target *target) { /* examine_first() does a bunch of this */ + arm_semihosting_init(target); return ERROR_OK; } static int cortex_a_init_arch_info(struct target *target, - struct cortex_a_common *cortex_a, struct jtag_tap *tap) + struct cortex_a_common *cortex_a, struct adiv5_dap *dap) { struct armv7a_common *armv7a = &cortex_a->armv7a_common; /* Setup struct cortex_a_common */ cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; - - /* tap has no dap initialized */ - if (!tap->dap) { - tap->dap = dap_init(); - - /* Leave (only) generic DAP stuff for debugport_init() */ - tap->dap->tap = tap; - } - - tap->dap->ap[dap_ap_get_select(tap->dap)].memaccess_tck = 80; - armv7a->arm.dap = tap->dap; - - cortex_a->fast_reg_read = 0; + armv7a->arm.dap = dap; /* register arch-specific functions */ armv7a->examine_debug_reason = NULL; @@ -3159,19 +2855,34 @@ static int cortex_a_init_arch_info(struct target *target, static int cortex_a_target_create(struct target *target, Jim_Interp *interp) { struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common)); + cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; + struct adiv5_private_config *pc; + + if (target->private_config == NULL) + return ERROR_FAIL; + + pc = (struct adiv5_private_config *)target->private_config; cortex_a->armv7a_common.is_armv7r = false; - return cortex_a_init_arch_info(target, cortex_a, target->tap); + cortex_a->armv7a_common.arm.arm_vfp_version = ARM_VFP_V3; + + return cortex_a_init_arch_info(target, cortex_a, pc->dap); } static int cortex_r4_target_create(struct target *target, Jim_Interp *interp) { struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common)); + cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; + struct adiv5_private_config *pc; + + pc = (struct adiv5_private_config *)target->private_config; + if (adiv5_verify_config(pc) != ERROR_OK) + return ERROR_FAIL; cortex_a->armv7a_common.is_armv7r = true; - return cortex_a_init_arch_info(target, cortex_a, target->tap); + return cortex_a_init_arch_info(target, cortex_a, pc->dap); } static void cortex_a_deinit_target(struct target *target) @@ -3182,6 +2893,7 @@ static void cortex_a_deinit_target(struct target *target) free(cortex_a->brp_list); free(dpm->dbp); free(dpm->dwp); + free(target->private_config); free(cortex_a); } @@ -3203,28 +2915,29 @@ static int cortex_a_mmu(struct target *target, int *enabled) } static int cortex_a_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys) + target_addr_t virt, target_addr_t *phys) { - int retval = ERROR_FAIL; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) { - uint32_t ret; - retval = armv7a_mmu_translate_va(target, - virt, &ret); - if (retval != ERROR_OK) - goto done; - *phys = ret; - } else {/* use this method if armv7a->memory_ap not selected - * mmu must be enable in order to get a correct translation */ - retval = cortex_a_mmu_modify(target, 1); - if (retval != ERROR_OK) - goto done; - retval = armv7a_mmu_translate_va_pa(target, virt, phys, 1); + int retval; + int mmu_enabled = 0; + + /* + * If the MMU was not enabled at debug entry, there is no + * way of knowing if there was ever a valid configuration + * for it and thus it's not safe to enable it. In this case, + * just return the virtual address as physical. + */ + cortex_a_mmu(target, &mmu_enabled); + if (!mmu_enabled) { + *phys = virt; + return ERROR_OK; } -done: - return retval; + + /* mmu must be enable in order to get a correct translation */ + retval = cortex_a_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; + return armv7a_mmu_translate_va_pa(target, (uint32_t)virt, + (uint32_t *)phys, 1); } COMMAND_HANDLER(cortex_a_handle_cache_info_command) @@ -3317,17 +3030,14 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command) }; const Jim_Nvp *n; - if (target->state != TARGET_HALTED) { - command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); - return ERROR_OK; - } - if (CMD_ARGC > 0) { n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]); - if (n->name == NULL) + if (n->name == NULL) { + LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; - cortex_a->isrmasking_mode = n->value; + } + cortex_a->isrmasking_mode = n->value; } n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode); @@ -3336,6 +3046,32 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command) return ERROR_OK; } +COMMAND_HANDLER(handle_cortex_a_dacrfixup_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct cortex_a_common *cortex_a = target_to_cortex_a(target); + + static const Jim_Nvp nvp_dacrfixup_modes[] = { + { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF }, + { .name = "on", .value = CORTEX_A_DACRFIXUP_ON }, + { .name = NULL, .value = -1 }, + }; + const Jim_Nvp *n; + + if (CMD_ARGC > 0) { + n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]); + if (n->name == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + cortex_a->dacrfixup_mode = n->value; + + } + + n = Jim_Nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode); + command_print(CMD_CTX, "cortex_a domain access control fixup %s", n->name); + + return ERROR_OK; +} + static const struct command_registration cortex_a_exec_command_handlers[] = { { .name = "cache_info", @@ -3373,11 +3109,18 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { { .name = "maskisr", .handler = handle_cortex_a_mask_interrupts_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "mask cortex_a interrupts", .usage = "['on'|'off']", }, - + { + .name = "dacrfixup", + .handler = handle_cortex_a_dacrfixup_command, + .mode = COMMAND_ANY, + .help = "set domain access control (DACR) to all-manager " + "on memory access", + .usage = "['on'|'off']", + }, COMMAND_REGISTRATION_DONE }; @@ -3435,6 +3178,7 @@ struct target_type cortexa_target = { .commands = cortex_a_command_handlers, .target_create = cortex_a_target_create, + .target_jim_configure = adiv5_jim_configure, .init_target = cortex_a_init_target, .examine = cortex_a_examine, .deinit_target = cortex_a_deinit_target, @@ -3446,13 +3190,6 @@ struct target_type cortexa_target = { }; static const struct command_registration cortex_r4_exec_command_handlers[] = { - { - .name = "cache_info", - .handler = cortex_a_handle_cache_info_command, - .mode = COMMAND_EXEC, - .help = "display information about target caches", - .usage = "", - }, { .name = "dbginit", .handler = cortex_a_handle_dbginit_command, @@ -3474,9 +3211,6 @@ static const struct command_registration cortex_r4_command_handlers[] = { { .chain = arm_command_handlers, }, - { - .chain = armv7a_command_handlers, - }, { .name = "cortex_r4", .mode = COMMAND_ANY, @@ -3503,8 +3237,8 @@ struct target_type cortexr4_target = { /* REVISIT allow exporting VFP3 registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, - .read_memory = cortex_a_read_memory, - .write_memory = cortex_a_write_memory, + .read_memory = cortex_a_read_phys_memory, + .write_memory = cortex_a_write_phys_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, @@ -3520,6 +3254,7 @@ struct target_type cortexr4_target = { .commands = cortex_r4_command_handlers, .target_create = cortex_r4_target_create, + .target_jim_configure = adiv5_jim_configure, .init_target = cortex_a_init_target, .examine = cortex_a_examine, .deinit_target = cortex_a_deinit_target,