X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_a.c;h=6eb6aa933836fd6bf510ccc4c422bc4f78d46366;hp=62ac361e6374e0a4a5a07637261d0e096719356e;hb=84a2cab596a0621fab3424c72b43280ccdc240c2;hpb=47b8cf84202bf792cf66fbfa01169e9592236b8a diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 62ac361e63..6eb6aa9338 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -50,11 +50,13 @@ #include "breakpoints.h" #include "cortex_a.h" #include "register.h" +#include "armv7a_mmu.h" #include "target_request.h" #include "target_type.h" #include "arm_opcodes.h" #include "arm_semihosting.h" -#include "jtag/swd.h" +#include "transport/transport.h" +#include "smp.h" #include static int cortex_a_poll(struct target *target); @@ -68,10 +70,6 @@ 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, @@ -110,7 +108,7 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access) 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); @@ -145,7 +143,7 @@ static int cortex_a_post_memaccess(struct target *target, int phys_access) 0, 0, 3, 0, cortex_a->cp15_dacr_reg); } - dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); } else { int mmu_enabled = 0; cortex_a_mmu(target, &mmu_enabled); @@ -202,31 +200,46 @@ static int cortex_a_mmu_modify(struct target *target, int enable) static int cortex_a_init_debug_access(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); + uint32_t dscr; int retval; /* lock memory-mapped access to debug registers to prevent * software interference */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + 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_write_atomic_u32(armv7a->debug_ap, + 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_write_atomic_u32(armv7a->debug_ap, + 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 */ + /* Enable halt for breakpoint, watchpoint and vector catch */ + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + 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; + /* Since this is likely called from init or reset, update target state information*/ return cortex_a_poll(target); } @@ -300,172 +313,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); - - 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_read_buf(armv7a->memory_ap, - (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); - - 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 */ - int64_t then = timeval_ms(); - while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - 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_read_atomic_u32(armv7a->debug_ap, - 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); - - LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value); - - /* Check that DCCRX is not full */ - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - 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_write_u32(armv7a->debug_ap, - 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, @@ -802,12 +649,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; } @@ -845,46 +723,29 @@ static int cortex_a_poll(struct target *target) /* We have a halting debug event */ LOG_DEBUG("Target halted"); target->state = TARGET_HALTED; - if ((prev_target_state == TARGET_RUNNING) - || (prev_target_state == TARGET_UNKNOWN) - || (prev_target_state == TARGET_RESET)) { - retval = cortex_a_debug_entry(target); + + retval = cortex_a_debug_entry(target); + if (retval != ERROR_OK) + return retval; + + if (target->smp) { + retval = update_halt_gdb(target); if (retval != ERROR_OK) return retval; - if (target->smp) { - retval = update_halt_gdb(target); - if (retval != ERROR_OK) - return retval; - } + } + if (prev_target_state == TARGET_DEBUG_RUNNING) { + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); + } else { /* prev_target_state is RUNNING, UNKNOWN or RESET */ if (arm_semihosting(target, &retval) != 0) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); } - if (prev_target_state == TARGET_DEBUG_RUNNING) { - LOG_DEBUG(" "); - - retval = cortex_a_debug_entry(target); - if (retval != ERROR_OK) - return retval; - if (target->smp) { - retval = update_halt_gdb(target); - if (retval != ERROR_OK) - return retval; - } - - target_call_event_callbacks(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; } @@ -904,19 +765,6 @@ static int cortex_a_halt(struct target *target) if (retval != ERROR_OK) return retval; - /* - * enter halting debug mode - */ - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - - 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; - int64_t then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv7a->debug_ap, @@ -956,15 +804,15 @@ static int cortex_a_internal_restore(struct target *target, int current, * C_MASKINTS in parallel with disabled interrupts can cause * local faults to not be taken. */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1); - armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1; - armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1; + armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = true; + armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = true; /* Make sure we are in Thumb mode */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24)); - armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1; - armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1; + armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = true; + armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = true; } #endif @@ -992,14 +840,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; + arm->pc->dirty = true; + arm->pc->valid = true; /* 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); @@ -1146,14 +997,11 @@ 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, spsr, 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 reg *reg; LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr); @@ -1190,68 +1038,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; - - /* read Current PSR */ - retval = cortex_a_dap_read_coreregister_u32(target, &cpsr, 16); - /* store current cpsr */ - 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; - } + /* First load register accessible through core debug port */ + retval = arm_dpm_read_current_registers(&armv7a->dpm); + if (retval != ERROR_OK) + return retval; if (arm->spsr) { - /* read Saved PSR */ - retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17); - /* store current spsr */ + /* read SPSR */ + retval = arm_dpm_read_reg(&armv7a->dpm, arm->spsr, 17); if (retval != ERROR_OK) return retval; - - reg = arm->spsr; - buf_set_u32(reg->value, 0, 32, spsr); - reg->valid = 1; - reg->dirty = 0; } #if 0 @@ -1294,6 +1090,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); @@ -1310,7 +1109,7 @@ static int cortex_a_post_debug_entry(struct target *target) cortex_a->curr_mode = armv7a->arm.core_mode; /* switch to SVC mode to read DACR */ - dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); armv7a->arm.mrc(target, 15, 0, 0, 3, 0, &cortex_a->cp15_dacr_reg); @@ -1318,7 +1117,7 @@ static int cortex_a_post_debug_entry(struct target *target) LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32, cortex_a->cp15_dacr_reg); - dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); return ERROR_OK; } @@ -1380,6 +1179,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre /* Setup single step breakpoint */ stepbreakpoint.address = address; + stepbreakpoint.asid = 0; stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB) ? 2 : 4; stepbreakpoint.type = BKPT_HARD; @@ -1497,10 +1297,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, @@ -2642,9 +2454,6 @@ static int cortex_a_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; int retval; if (!count || !buffer) @@ -2653,9 +2462,6 @@ static int cortex_a_read_phys_memory(struct target *target, LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) - return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address); - /* read memory through the CPU */ cortex_a_prep_memaccess(target, 1); retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); @@ -2680,57 +2486,10 @@ static int cortex_a_read_memory(struct target *target, target_addr_t address, return retval; } -static int cortex_a_read_memory_ahb(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer) -{ - int mmu_enabled = 0; - target_addr_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 " TARGET_ADDR_FMT "; 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:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, - virt, phys); - address = phys; - } - - if (!count || !buffer) - return ERROR_COMMAND_SYNTAX_ERROR; - - retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address); - - return retval; -} - static int cortex_a_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; int retval; if (!count || !buffer) @@ -2739,9 +2498,6 @@ static int cortex_a_write_phys_memory(struct target *target, LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) - return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address); - /* write memory through the CPU */ cortex_a_prep_memaccess(target, 1); retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); @@ -2768,51 +2524,6 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address, return retval; } -static int cortex_a_write_memory_ahb(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) -{ - int mmu_enabled = 0; - target_addr_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 " TARGET_ADDR_FMT "; 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:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, - virt, - phys); - address = phys; - } - - if (!count || !buffer) - return ERROR_COMMAND_SYNTAX_ERROR; - - retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address); - - return retval; -} - static int cortex_a_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { @@ -2822,7 +2533,7 @@ static int cortex_a_read_buffer(struct target *target, target_addr_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; @@ -2835,7 +2546,7 @@ static int cortex_a_read_buffer(struct target *target, target_addr_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; @@ -2856,7 +2567,7 @@ static int cortex_a_write_buffer(struct target *target, target_addr_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; @@ -2869,7 +2580,7 @@ static int cortex_a_write_buffer(struct target *target, target_addr_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; @@ -2932,12 +2643,6 @@ static int cortex_a_examine_first(struct target *target) int retval = ERROR_OK; uint32_t didr, cpuid, dbg_osreg; - retval = dap_dp_init(swjdp); - if (retval != ERROR_OK) { - LOG_ERROR("Could not initialize the debug port"); - return retval; - } - /* 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) { @@ -2953,21 +2658,6 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_ap->memaccess_tck = 80; - /* Search for the AHB-AB. - * REVISIT: We should search for AXI-AP as well and make sure the AP's MEMTYPE says it - * can access system memory. */ - armv7a->memory_ap_available = false; - retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap); - if (retval == ERROR_OK) { - retval = mem_ap_init(armv7a->memory_ap); - if (retval == ERROR_OK) - armv7a->memory_ap_available = true; - } - if (retval != ERROR_OK) { - /* AHB-AP not found or unavailable - use the CPU */ - LOG_DEBUG("No AHB-AP available for memory access"); - } - if (!target->dbgbase_set) { uint32_t dbgbase; /* Get ROM Table base */ @@ -3119,24 +2809,13 @@ static int cortex_a_init_target(struct command_context *cmd_ctx, } 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; - } - - armv7a->arm.dap = tap->dap; - - cortex_a->fast_reg_read = 0; + armv7a->arm.dap = dap; /* register arch-specific functions */ armv7a->examine_debug_reason = NULL; @@ -3152,37 +2831,76 @@ static int cortex_a_init_arch_info(struct target *target, /* REVISIT v7a setup should be in a v7a-specific routine */ armv7a_init_arch_info(target, armv7a); - target_register_timer_callback(cortex_a_handle_target_request, 1, 1, target); + target_register_timer_callback(cortex_a_handle_target_request, 1, + TARGET_TIMER_TYPE_PERIODIC, target); return ERROR_OK; } 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)); + struct cortex_a_common *cortex_a; + struct adiv5_private_config *pc; + if (target->private_config == NULL) + return ERROR_FAIL; + + pc = (struct adiv5_private_config *)target->private_config; + + cortex_a = calloc(1, sizeof(struct cortex_a_common)); + if (cortex_a == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; cortex_a->armv7a_common.is_armv7r = false; + cortex_a->armv7a_common.arm.arm_vfp_version = ARM_VFP_V3; - return cortex_a_init_arch_info(target, cortex_a, target->tap); + 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)); + struct cortex_a_common *cortex_a; + 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 = calloc(1, sizeof(struct cortex_a_common)); + if (cortex_a == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; 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) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); - struct arm_dpm *dpm = &cortex_a->armv7a_common.dpm; + struct armv7a_common *armv7a = &cortex_a->armv7a_common; + struct arm_dpm *dpm = &armv7a->dpm; + uint32_t dscr; + int retval; + + if (target_was_examined(target)) { + /* Disable halt for breakpoint, watchpoint and vector catch */ + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_DSCR, &dscr); + if (retval == ERROR_OK) + mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_DSCR, + dscr & ~DSCR_HALT_DBG_MODE); + } free(cortex_a->brp_list); free(dpm->dbp); free(dpm->dwp); + free(target->private_config); free(cortex_a); } @@ -3206,27 +2924,27 @@ static int cortex_a_mmu(struct target *target, int *enabled) static int cortex_a_virt2phys(struct target *target, 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, (uint32_t)virt, - (uint32_t *)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) @@ -3249,63 +2967,6 @@ COMMAND_HANDLER(cortex_a_handle_dbginit_command) return cortex_a_init_debug_access(target); } -COMMAND_HANDLER(cortex_a_handle_smp_off_command) -{ - struct target *target = get_current_target(CMD_CTX); - /* check target is an smp target */ - struct target_list *head; - struct target *curr; - head = target->head; - target->smp = 0; - if (head != (struct target_list *)NULL) { - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 0; - head = head->next; - } - /* fixes the target display to the debugger */ - target->gdb_service->target = target; - } - return ERROR_OK; -} - -COMMAND_HANDLER(cortex_a_handle_smp_on_command) -{ - struct target *target = get_current_target(CMD_CTX); - struct target_list *head; - struct target *curr; - head = target->head; - if (head != (struct target_list *)NULL) { - target->smp = 1; - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 1; - head = head->next; - } - } - return ERROR_OK; -} - -COMMAND_HANDLER(cortex_a_handle_smp_gdb_command) -{ - struct target *target = get_current_target(CMD_CTX); - int retval = ERROR_OK; - struct target_list *head; - head = target->head; - if (head != (struct target_list *)NULL) { - if (CMD_ARGC == 1) { - int coreid = 0; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); - if (ERROR_OK != retval) - return retval; - target->gdb_service->core[1] = coreid; - - } - command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] - , target->gdb_service->core[1]); - } - return ERROR_OK; -} COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command) { @@ -3376,25 +3037,6 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { .help = "Initialize core debug", .usage = "", }, - { .name = "smp_off", - .handler = cortex_a_handle_smp_off_command, - .mode = COMMAND_EXEC, - .help = "Stop smp handling", - .usage = "",}, - { - .name = "smp_on", - .handler = cortex_a_handle_smp_on_command, - .mode = COMMAND_EXEC, - .help = "Restart smp handling", - .usage = "", - }, - { - .name = "smp_gdb", - .handler = cortex_a_handle_smp_gdb_command, - .mode = COMMAND_EXEC, - .help = "display/fix current core played to gdb", - .usage = "", - }, { .name = "maskisr", .handler = handle_cortex_a_mask_interrupts_command, @@ -3405,11 +3047,17 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { { .name = "dacrfixup", .handler = handle_cortex_a_dacrfixup_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "set domain access control (DACR) to all-manager " "on memory access", .usage = "['on'|'off']", }, + { + .chain = armv7a_mmu_command_handlers, + }, + { + .chain = smp_command_handlers, + }, COMMAND_REGISTRATION_DONE }; @@ -3445,6 +3093,7 @@ struct target_type cortexa_target = { .deassert_reset = cortex_a_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a_read_memory, @@ -3467,6 +3116,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, @@ -3478,13 +3128,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, @@ -3506,9 +3149,6 @@ static const struct command_registration cortex_r4_command_handlers[] = { { .chain = arm_command_handlers, }, - { - .chain = armv7a_command_handlers, - }, { .name = "cortex_r4", .mode = COMMAND_ANY, @@ -3533,6 +3173,7 @@ struct target_type cortexr4_target = { .deassert_reset = cortex_a_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a_read_phys_memory, @@ -3552,6 +3193,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,