diff options
author | Peter Griffin <peter.griffin@linaro.org> | 2016-05-05 17:14:22 +0100 |
---|---|---|
committer | Peter Griffin <peter.griffin@linaro.org> | 2016-05-05 17:17:37 +0100 |
commit | 1bef29e65d4ecc8dc667eabea6f4301bbc34f596 (patch) | |
tree | e128adbfe6df09f44efe0b02e96b76b9bbd8fa27 | |
parent | fde7fcff2121c67dd502dbca5751c743c52cfbef (diff) | |
parent | cff086663391fc1360027025d34f2a34951ef8bb (diff) |
Merge tag 'refs/tags/armv8_fix_low_level_access' into armv8armv8
Pull armv8 OpenOCD fixes from Daniel Thompson:
I've been raking through a large work-in-progress patch from Philip
Attfield, dividing it into atomic changes and adding commit
documentation. Philip's work was a mixture of important bug fixes and
WIP to try and get gdb working better. Unfortunately some of the WIP
changes caused regressions.
This pull request includes only those changes that I am confident will
not cause regressions. In particular it includes an number of important
patches to fix acidental 64-bit to 32-bit truncations in the register
handling code.
For the full patch set, see:
https://git.linaro.org/people/daniel.thompson/openocd.git/shortlog/refs/heads/hacking/armv8_gdb_support
-rw-r--r-- | src/server/gdb_server.c | 20 | ||||
-rw-r--r-- | src/target/aarch64.c | 48 | ||||
-rw-r--r-- | src/target/armv8.c | 4 | ||||
-rw-r--r-- | src/target/armv8_dpm.c | 40 | ||||
-rw-r--r-- | src/target/armv8_dpm.h | 11 |
5 files changed, 79 insertions, 44 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 86c7e1c7..90c4c991 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1421,7 +1421,7 @@ static int gdb_write_memory_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; uint8_t *buffer; @@ -1430,7 +1430,7 @@ static int gdb_write_memory_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory packet received, dropping connection"); @@ -1446,7 +1446,7 @@ static int gdb_write_memory_packet(struct connection *connection, buffer = malloc(len); - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); if (unhexify((char *)buffer, separator, len) != (int)len) LOG_ERROR("unable to decode memory packet"); @@ -1468,7 +1468,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; int retval = ERROR_OK; @@ -1476,7 +1476,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory binary packet received, dropping connection"); @@ -1510,7 +1510,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, } if (len) { - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_write_buffer(target, addr, len, (uint8_t *)separator); if (retval != ERROR_OK) @@ -1525,13 +1525,13 @@ static int gdb_step_continue_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); int current = 0; - uint32_t address = 0x0; + uint64_t address = 0x0; int retval = ERROR_OK; LOG_DEBUG("-"); if (packet_size > 1) - address = strtoul(packet + 1, NULL, 16); + address = strtoull(packet + 1, NULL, 16); else current = 1; @@ -1555,7 +1555,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, int type; enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */; enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */; - uint32_t address; + uint64_t address; uint32_t size; char *separator; int retval; @@ -1587,7 +1587,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - address = strtoul(separator + 1, &separator, 16); + address = strtoull(separator + 1, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection"); diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 4e638cb4..13d07ead 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -90,7 +90,7 @@ static int aarch64_restore_system_control_reg(struct target *target) return retval; break; default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state); } } return retval; @@ -115,7 +115,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) if (enable) { /* if mmu enabled at target stop and mmu not enable */ if (!(aarch64->system_control_reg & 0x1U)) { - LOG_ERROR("trying to enable mmu on target stopped with mmu disable"); + LOG_ERROR("trying to enable mmu on stopped target with mmu disabled"); return ERROR_FAIL; } if (!(aarch64->system_control_reg_curr & 0x1U)) { @@ -150,7 +150,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) return retval; break; default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state); } } } else { @@ -193,7 +193,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) return retval; break; default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state); break; } } @@ -339,7 +339,7 @@ static int aarch64_write_dcc(struct aarch64_common *a8, uint32_t data) static int aarch64_write_dcc_64(struct aarch64_common *a8, uint64_t data) { int ret; - LOG_DEBUG("write DCC Low word0x%08" PRIx32, (unsigned)data); + LOG_DEBUG("write DCC Low word 0x%08" PRIx32, (unsigned)data); LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32)); ret = mem_ap_sel_write_u32(a8->armv8_common.arm.dap, a8->armv8_common.debug_ap, a8->armv8_common.debug_base + CPUV8_DBG_DTRRX, data); @@ -898,7 +898,7 @@ static int aarch64_halt(struct target *target) struct armv8_common *armv8 = target_to_armv8(target); struct adiv5_dap *swjdp = armv8->arm.dap; - /* enable CTI*/ + /* enable CTI */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, armv8->cti_base + CTI_CTR, 1); if (retval != ERROR_OK) @@ -1251,7 +1251,7 @@ static int aarch64_post_debug_entry(struct target *target) return retval; break; default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state); } LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; @@ -1288,7 +1288,8 @@ static int aarch64_step(struct target *target, int current, uint32_t address, return retval; retval = mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDECR, (tmp|0x4)); + armv8->debug_base + CPUV8_DBG_EDECR, + (tmp | EDECR_SS_HALTING_STEP_ENABLE)); if (retval != ERROR_OK) return retval; @@ -1308,8 +1309,9 @@ static int aarch64_step(struct target *target, int current, uint32_t address, } target->debug_reason = DBG_REASON_BREAKPOINT; - retval = mem_ap_sel_write_atomic_u32(swjdp, armv8->debug_ap, - armv8->debug_base + 0x24, (tmp&(~0x4))); + retval = mem_ap_sel_write_atomic_u32( + swjdp, armv8->debug_ap, armv8->debug_base + CPUV8_DBG_EDECR, + (tmp & (~EDECR_SS_HALTING_STEP_ENABLE))); if (retval != ERROR_OK) return retval; @@ -1812,7 +1814,7 @@ static int aarch64_write_apb_ab_memory(struct target *target, uint32_t dscr; uint8_t *tmp_buff = NULL; - LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count%" PRIu32, + LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -2069,7 +2071,7 @@ static int aarch64_read_apb_ab_memory(struct target *target, uint8_t *tmp_buff = NULL; uint8_t *u8buf_ptr; - LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count%" PRIu32, + LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -2819,6 +2821,17 @@ COMMAND_HANDLER(aarch64_handle_dbginit_command) return aarch64_init_debug_access(target); } + +COMMAND_HANDLER(aarch64_handle_mmu_info_command) +{ + struct target *target = get_current_target(CMD_CTX); + int ret_value; + + ret_value = armv8_arch_state(target); + + return ret_value; +} + COMMAND_HANDLER(aarch64_handle_smp_off_command) { struct target *target = get_current_target(CMD_CTX); @@ -2892,6 +2905,13 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "Initialize core debug", .usage = "", }, + { + .name = "mmu_info", + .handler = aarch64_handle_mmu_info_command, + .mode = COMMAND_EXEC, + .help = "MMU and cache summary", + .usage = "", + }, { .name = "smp_off", .handler = aarch64_handle_smp_off_command, .mode = COMMAND_EXEC, @@ -2923,9 +2943,9 @@ static const struct command_registration aarch64_command_handlers[] = { .chain = armv8_command_handlers, }, { - .name = "cortex_a", + .name = "aarch64", .mode = COMMAND_ANY, - .help = "Cortex-A command group", + .help = "aarch64 command group", .usage = "", .chain = aarch64_exec_command_handlers, }, diff --git a/src/target/armv8.c b/src/target/armv8.c index 20cec80a..4d147274 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -312,7 +312,7 @@ static int armv8_read_ttbcr(struct target *target) if (retval != ERROR_OK) goto done; - /* claaer ttrr1_used and ttbr0_mask */ + /* clear ttrr1_used and ttbr0_mask */ memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used)); memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask)); @@ -944,7 +944,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) reg_list[i].name = armv8_regs[i].name; reg_list[i].size = armv8_regs[i].bits; - reg_list[i].value = calloc(1, 4); + reg_list[i].value = calloc(1, 8); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &armv8_reg_type; diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index ec33e908..c6b4ad39 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -211,30 +211,33 @@ int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) /* just read the register -- rely on the core mode being right */ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { - uint32_t value; - uint64_t value_64; + union { + uint64_t u64; + uint32_t u32; + } value; int retval = ERROR_FAIL; switch (regnum) { case 0 ... 30: retval = dpm->instr_read_data_dcc_64(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum), - &value_64); + &value.u64); break; - case 31: + case 31: /* SP */ retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MOVFSP_64(0), - &value_64); + &value.u64); break; - case 32: + case 32: /* PC */ retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS_DLR(0), - &value_64); + &value.u64); break; - case 33: + case 33: /* CPSR */ retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS_DSPSR(0), - &value); + &value.u32); + break; default: LOG_DEBUG("READ: %s fail", r->name); break; @@ -243,11 +246,14 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) if (retval == ERROR_OK) { r->valid = true; r->dirty = false; - buf_set_u64(r->value, 0, 32, value_64); - if (r->size == 64) - LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64); - else - LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); + if (r->size == 64) { + buf_set_u64(r->value, 0, 64, value.u64); + LOG_DEBUG("READ: %s, %16.16" PRIx64, r->name, + value.u64); + } else { + buf_set_u32(r->value, 0, 32, value.u32); + LOG_DEBUG("READ: %s, %8.8" PRIx32, r->name, value.u32); + } } return retval; } @@ -624,10 +630,8 @@ static int armv8_dpm_full_context(struct target *target) if (r->mode != mode) continue; - /* CPSR was read, so "R16" must mean SPSR */ retval = dpmv8_read_reg(dpm, - &cache->reg_list[i], - (r->num == 16) ? 17 : r->num); + &cache->reg_list[i], r->num); if (retval != ERROR_OK) goto done; } @@ -847,7 +851,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr) /* ?? */ break; default: - LOG_DEBUG("Unknow core_state"); + LOG_DEBUG("Unknown core_state"); break; } dpm->wp_pc = addr; diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h index e667b431..4d11e16b 100644 --- a/src/target/armv8_dpm.h +++ b/src/target/armv8_dpm.h @@ -160,11 +160,17 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); /* DSCR bits; see ARMv7a arch spec section C10.3.1. * Not all v7 bits are valid in v6. */ +#define DSCR_CORE_HALTED (0x1 << 0) +#define DSCR_CORE_RESTARTED (0x1 << 1) + #define DSCR_DEBUG_STATUS_MASK (0x1F << 0) #define DSCR_ERR (0x1 << 6) +#define DSCR_STICKY_ABORT_PRECISE (0x1 << 6) #define DSCR_SYS_ERROR_PEND (0x1 << 7) +#define DSCR_STICKY_ABORT_IMPRECISE (0x1 << 7) #define DSCR_CUR_EL (0x3 << 8) #define DSCR_EL_STATUS_MASK (0xF << 10) +#define DSCR_ITR_EN (0x1 << 13) #define DSCR_HDE (0x1 << 14) #define DSCR_SDD (0x1 << 16) #define DSCR_NON_SECURE (0x1 << 18) @@ -172,6 +178,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); #define DSCR_TDA (0x1 << 21) #define DSCR_INTDIS_MASK (0x3 << 22) #define DSCR_ITE (0x1 << 24) +#define DSCR_INSTR_COMP (0x1 << 24) #define DSCR_PIPE_ADVANCE (0x1 << 25) #define DSCR_TXU (0x1 << 26) #define DSCR_RTO (0x1 << 27) /* bit 28 is reserved */ @@ -205,17 +212,21 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); #define DRCR_CSPA (1 << 3) #define DRCR_CBRRQ (1 << 4) +/* EDECR value */ +# define EDECR_SS_HALTING_STEP_ENABLE (1 << 2) /* DTR modes */ #define DSCR_EXT_DCC_NON_BLOCKING (0x0 << 20) #define DSCR_EXT_DCC_STALL_MODE (0x1 << 20) #define DSCR_EXT_DCC_FAST_MODE (0x2 << 20) /* bits 22, 23 are reserved */ +#define DSCR_EXT_DCC_MASK (0x3 << 20) /* DTR mode */ /* bits 22, 23 are reserved */ /* DRCR (debug run control register) bits */ #define DRCR_HALT (1 << 0) #define DRCR_RESTART (1 << 1) #define DRCR_CLEAR_EXCEPTIONS (1 << 2) +#define DRCR_CLEAR_SPA (1 << 3) /* PRCR (processor debug status register) bits */ #define PRSR_PU (1 << 0) |