X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Faarch64.c;h=d3ed57c5d8a38015cc3792517bc09821ee5ab8e3;hb=9527d1e595e316a4155c808fafa3a0ea6baa72f2;hp=947c1ecfff9e6a3065b7e6c8d13b50a5082c2f12;hpb=05bf20d05afbcbb723c16cfa0e2f3a93edb435f7;p=openocd.git diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 947c1ecfff..d3ed57c5d8 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -49,7 +49,9 @@ static int aarch64_read_apb_ap_memory(struct target *target, static int aarch64_restore_system_control_reg(struct target *target) { + enum arm_mode target_mode = ARM_MODE_ANY; int retval = ERROR_OK; + uint32_t instr; struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = target_to_armv8(target); @@ -59,41 +61,45 @@ static int aarch64_restore_system_control_reg(struct target *target) /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, cortex_v8->cp15_control_reg); */ switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 0, 1, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL0T: + target_mode = ARMV8_64_EL1H; + /* fall through */ + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0); break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 4, 1, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL2, 0); break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 6, 1, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL3, 0); break; - default: - retval = armv8->arm.mcr(target, 15, 0, 0, 1, 0, aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; - break; - } + + case ARM_MODE_SVC: + case ARM_MODE_ABT: + case ARM_MODE_FIQ: + case ARM_MODE_IRQ: + instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0); + break; + + default: + LOG_INFO("cannot read system control register in this mode"); + return ERROR_FAIL; + } + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, target_mode); + + retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); } + return retval; } @@ -112,6 +118,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; int retval = ERROR_OK; + uint32_t instr = 0; if (enable) { /* if mmu enabled at target stop and mmu not enable */ @@ -119,86 +126,42 @@ static int aarch64_mmu_modify(struct target *target, int enable) LOG_ERROR("trying to enable mmu on target stopped with mmu disable"); return ERROR_FAIL; } - if (!(aarch64->system_control_reg_curr & 0x1U)) { + if (!(aarch64->system_control_reg_curr & 0x1U)) aarch64->system_control_reg_curr |= 0x1U; - switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 0, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 4, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 6, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); - } - } } else { if (aarch64->system_control_reg_curr & 0x4U) { /* data cache is active */ aarch64->system_control_reg_curr &= ~0x4U; - /* flush data cache armv7 function to be called */ + /* flush data cache armv8 function to be called */ if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache) armv8->armv8_mmu.armv8_cache.flush_all_data_cache(target); } if ((aarch64->system_control_reg_curr & 0x1U)) { aarch64->system_control_reg_curr &= ~0x1U; - switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 0, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 4, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 6, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); - break; - } } } + + switch (armv8->arm.core_mode) { + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0); + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL2, 0); + break; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL3, 0); + break; + default: + LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state); + break; + } + + retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, + aarch64->system_control_reg_curr); return retval; } @@ -389,7 +352,7 @@ static int aarch64_poll(struct target *target) if (DSCR_RUN_MODE(dscr) == 0x3) { if (prev_target_state != TARGET_HALTED) { /* We have a halting debug event */ - LOG_DEBUG("Target halted"); + LOG_DEBUG("Target %s halted", target_name(target)); target->state = TARGET_HALTED; if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_UNKNOWN) @@ -504,25 +467,16 @@ static int aarch64_internal_restore(struct target *target, int current, LOG_ERROR("How do I resume into Jazelle state??"); return ERROR_FAIL; } - LOG_DEBUG("resume pc = 0x%16" PRIx64, resume_pc); + LOG_DEBUG("resume pc = 0x%016" PRIx64, resume_pc); buf_set_u64(arm->pc->value, 0, 64, resume_pc); arm->pc->dirty = 1; arm->pc->valid = 1; - armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); /* called it now before restoring context because it uses cpu * register r0 for restoring system control register */ retval = aarch64_restore_system_control_reg(target); - if (retval != ERROR_OK) - return retval; - retval = aarch64_restore_context(target, handle_breakpoints); - if (retval != ERROR_OK) - return retval; - target->debug_reason = DBG_REASON_NOTHALTED; - target->state = TARGET_RUNNING; - - /* registers are now invalid */ - register_cache_invalidate(arm->core_cache); + if (retval == ERROR_OK) + retval = aarch64_restore_context(target, handle_breakpoints); return retval; } @@ -547,7 +501,9 @@ static int aarch64_internal_restart(struct target *target, bool slave_pe) return retval; if ((dscr & DSCR_ITE) == 0) - LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); + LOG_ERROR("DSCR.ITE must be set before leaving debug!"); + if ((dscr & DSCR_ERR) != 0) + LOG_ERROR("DSCR.ERR must be cleared before leaving debug!"); /* make sure to acknowledge the halt event before resuming */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, @@ -590,6 +546,7 @@ static int aarch64_internal_restart(struct target *target, bool slave_pe) /* registers are now invalid */ register_cache_invalidate(arm->core_cache); + register_cache_invalidate(arm->core_cache->next); return ERROR_OK; } @@ -630,6 +587,10 @@ static int aarch64_resume(struct target *target, int current, target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return 0; } + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + aarch64_internal_restore(target, current, &addr, handle_breakpoints, debug_execution); if (target->smp) { @@ -671,11 +632,16 @@ static int aarch64_debug_entry(struct target *target) /* make sure to clear all sticky errors */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + + /* discard async exceptions */ + if (retval == ERROR_OK) + retval = dpm->instr_cpsr_sync(dpm); + if (retval != ERROR_OK) return retval; /* Examine debug reason */ - armv8_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); + armv8_dpm_report_dscr(dpm, aarch64->cpudbg_dscr); /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { @@ -711,55 +677,47 @@ static int aarch64_post_debug_entry(struct target *target) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; int retval; - - /* clear sticky errors */ - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + enum arm_mode target_mode = ARM_MODE_ANY; + uint32_t instr; switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - armv8_dpm_modeswitch(&armv8->dpm, ARMV8_64_EL1H); - /* fall through */ - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.mrs(target, 3, /*op 0*/ - 0, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL0T: + target_mode = ARMV8_64_EL1H; + /* fall through */ + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + instr = ARMV8_MRS(SYSTEM_SCTLR_EL1, 0); break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.mrs(target, 3, /*op 0*/ - 4, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + instr = ARMV8_MRS(SYSTEM_SCTLR_EL2, 0); break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.mrs(target, 3, /*op 0*/ - 6, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + instr = ARMV8_MRS(SYSTEM_SCTLR_EL3, 0); break; - case ARM_MODE_SVC: - retval = armv8->arm.mrc(target, 15, 0, 0, 1, 0, &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; - break; + case ARM_MODE_SVC: + case ARM_MODE_ABT: + case ARM_MODE_FIQ: + case ARM_MODE_IRQ: + instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0); + break; - default: - LOG_INFO("cannot read system control register in this mode"); - break; + default: + LOG_INFO("cannot read system control register in this mode"); + return ERROR_FAIL; } - armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, target_mode); + + retval = armv8->dpm.instr_read_data_r0(&armv8->dpm, instr, &aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; @@ -844,13 +802,12 @@ static int aarch64_restore_context(struct target *target, bool bpwp) { struct armv8_common *armv8 = target_to_armv8(target); - LOG_DEBUG(" "); + LOG_DEBUG("%s", target_name(target)); if (armv8->pre_restore_context) armv8->pre_restore_context(target); return armv8_dpm_write_dirty_registers(&armv8->dpm, bpwp); - } /* @@ -917,7 +874,7 @@ static int aarch64_set_breakpoint(struct target *target, } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - buf_set_u32(code, 0, 32, ARMV8_HLT(0x11)); + buf_set_u32(code, 0, 32, armv8_opcode(armv8, ARMV8_OPC_HLT)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, @@ -1322,7 +1279,8 @@ static int aarch64_assert_reset(struct target *target) } /* registers are now invalid */ - register_cache_invalidate(armv8->arm.core_cache); + if (target_was_examined(target)) + register_cache_invalidate(armv8->arm.core_cache); target->state = TARGET_RESET; @@ -1338,6 +1296,9 @@ static int aarch64_deassert_reset(struct target *target) /* be certain SRST is off */ jtag_add_reset(0, 0); + if (!target_was_examined(target)) + return ERROR_OK; + retval = aarch64_poll(target); if (retval != ERROR_OK) return retval; @@ -1372,8 +1333,6 @@ static int aarch64_write_apb_ap_memory(struct target *target, uint32_t dscr; uint8_t *tmp_buff = NULL; - LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count%" PRIu32, - address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1392,13 +1351,6 @@ static int aarch64_write_apb_ap_memory(struct target *target, reg = armv8_reg_current(arm, 0); reg->dirty = true; - /* clear any abort */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - if (retval != ERROR_OK) - return retval; - - /* This algorithm comes from DDI0487A.g, chapter J9.1 */ /* The algorithm only copies 32 bit words, so the buffer @@ -1489,8 +1441,6 @@ static int aarch64_write_apb_ap_memory(struct target *target, if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); armv8_dpm_handle_exception(dpm); goto error_free_buff_w; } @@ -1531,8 +1481,6 @@ static int aarch64_read_apb_ap_memory(struct target *target, uint8_t *u8buf_ptr; uint32_t value; - LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR " size %" PRIu32 " count%" PRIu32, - address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1550,12 +1498,6 @@ static int aarch64_read_apb_ap_memory(struct target *target, reg = armv8_reg_current(arm, 0); reg->dirty = true; - /* clear any abort */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - if (retval != ERROR_OK) - goto error_free_buff_r; - /* Read DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); @@ -1655,8 +1597,6 @@ static int aarch64_read_apb_ap_memory(struct target *target, if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); armv8_dpm_handle_exception(dpm); goto error_free_buff_r; } @@ -1688,8 +1628,6 @@ static int aarch64_read_phys_memory(struct target *target, uint32_t count, uint8_t *buffer) { int retval = ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Reading memory at real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, - address, size, count); if (count && buffer) { /* read memory through APB-AP */ @@ -1707,10 +1645,6 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, int mmu_enabled = 0; int retval; - /* aarch64 handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, - size, count); - /* determine if MMU was enabled on target stop */ retval = aarch64_mmu(target, &mmu_enabled); if (retval != ERROR_OK) @@ -1734,9 +1668,6 @@ static int aarch64_write_phys_memory(struct target *target, { int retval = ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Writing memory to real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, - size, count); - if (count && buffer) { /* write memory through APB-AP */ retval = aarch64_mmu_modify(target, 0); @@ -1754,10 +1685,6 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, int mmu_enabled = 0; int retval; - /* aarch64 handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 - "; count %" PRId32, address, size, count); - /* determine if MMU was enabled on target stop */ retval = aarch64_mmu(target, &mmu_enabled); if (retval != ERROR_OK) @@ -2146,9 +2073,6 @@ static const struct command_registration aarch64_exec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; static const struct command_registration aarch64_command_handlers[] = { - { - .chain = arm_command_handlers, - }, { .chain = armv8_command_handlers, },