diff options
Diffstat (limited to 'src/target')
-rw-r--r-- | src/target/aarch64.c | 2 | ||||
-rw-r--r-- | src/target/arm_tpiu_swo.c | 57 | ||||
-rw-r--r-- | src/target/armv7a.c | 3 | ||||
-rw-r--r-- | src/target/armv7a.h | 2 | ||||
-rw-r--r-- | src/target/armv7a_cache.c | 63 | ||||
-rw-r--r-- | src/target/armv7a_cache.h | 4 | ||||
-rw-r--r-- | src/target/cortex_a.c | 104 | ||||
-rw-r--r-- | src/target/cortex_m.c | 6 | ||||
-rw-r--r-- | src/target/semihosting_common.c | 4 | ||||
-rw-r--r-- | src/target/smp.c | 2 | ||||
-rw-r--r-- | src/target/startup.tcl | 22 | ||||
-rw-r--r-- | src/target/target.c | 11 | ||||
-rw-r--r-- | src/target/xtensa/xtensa.c | 89 |
13 files changed, 210 insertions, 159 deletions
diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 2e4d0b5..6a70b2d 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1983,7 +1983,7 @@ static int aarch64_assert_reset(struct target *target) } /* registers are now invalid */ - if (target_was_examined(target)) { + if (armv8->arm.core_cache) { register_cache_invalidate(armv8->arm.core_cache); register_cache_invalidate(armv8->arm.core_cache->next); } diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 5cea682..b5a4882 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -40,7 +40,6 @@ /* START_DEPRECATED_TPIU */ #include <target/cortex_m.h> -#include <target/target_type.h> #define MSG "DEPRECATED \'tpiu config\' command: " /* END_DEPRECATED_TPIU */ @@ -153,7 +152,7 @@ static int arm_tpiu_swo_poll_trace(void *priv) } } - if (obj->out_filename && obj->out_filename[0] == ':') + if (obj->out_filename[0] == ':') list_for_each_entry(c, &obj->connections, lh) if (connection_write(c->connection, buf, size) != (int)size) LOG_ERROR("Error writing to connection"); /* FIXME: which connection? */ @@ -161,7 +160,7 @@ static int arm_tpiu_swo_poll_trace(void *priv) return ERROR_OK; } -static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_tpiu_swo_event event) +static int arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_tpiu_swo_event event) { for (struct arm_tpiu_swo_event_action *ea = obj->event_action; ea; ea = ea->next) { if (ea->event != event) @@ -182,7 +181,7 @@ static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_ if (retval == JIM_RETURN) retval = ea->interp->returnCode; if (retval == JIM_OK || retval == ERROR_COMMAND_CLOSE_CONNECTION) - return; + return ERROR_OK; Jim_MakeErrorMessage(ea->interp); LOG_USER("Error executing event %s on TPIU/SWO %s:\n%s", @@ -191,8 +190,10 @@ static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_ Jim_GetString(Jim_GetResult(ea->interp), NULL)); /* clean both error code and stacktrace before return */ Jim_Eval(ea->interp, "error \"\" \"\""); - return; + return ERROR_FAIL; } + + return ERROR_OK; } static void arm_tpiu_swo_close_output(struct arm_tpiu_swo_object *obj) @@ -201,7 +202,7 @@ static void arm_tpiu_swo_close_output(struct arm_tpiu_swo_object *obj) fclose(obj->file); obj->file = NULL; } - if (obj->out_filename && obj->out_filename[0] == ':') + if (obj->out_filename[0] == ':') remove_service(TCP_SERVICE_NAME, &obj->out_filename[1]); } @@ -475,12 +476,13 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s return JIM_ERR; } } - free(obj->out_filename); - obj->out_filename = strdup(s); - if (!obj->out_filename) { + char *out_filename = strdup(s); + if (!out_filename) { LOG_ERROR("Out of memory"); return JIM_ERR; } + free(obj->out_filename); + obj->out_filename = out_filename; } else { if (goi->argc) goto err_no_params; @@ -625,16 +627,25 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) return ERROR_FAIL; } - if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) - if (!obj->swo_pin_freq) + const bool output_external = !strcmp(obj->out_filename, "external"); + + if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) { + if (!obj->swo_pin_freq) { + if (output_external) { + command_print(CMD, "SWO pin frequency required when using external capturing"); + return ERROR_FAIL; + } + LOG_DEBUG("SWO pin frequency not set, will be autodetected by the adapter"); + } + } struct target *target = get_current_target(CMD_CTX); /* START_DEPRECATED_TPIU */ if (obj->recheck_ap_cur_target) { - if (strcmp(target->type->name, "cortex_m") && - strcmp(target->type->name, "hla_target")) { + if (strcmp(target_type_name(target), "cortex_m") && + strcmp(target_type_name(target), "hla_target")) { LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA"); return ERROR_FAIL; } @@ -664,7 +675,9 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) } /* trigger the event before any attempt to R/W in the TPIU/SWO */ - arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_ENABLE); + retval = arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_ENABLE); + if (retval != ERROR_OK) + return retval; retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_DEVID_OFFSET, &value); if (retval != ERROR_OK) { @@ -705,7 +718,7 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) uint16_t prescaler = 1; /* dummy value */ unsigned int swo_pin_freq = obj->swo_pin_freq; /* could be replaced */ - if (obj->out_filename && strcmp(obj->out_filename, "external") && obj->out_filename[0]) { + if (!output_external) { if (obj->out_filename[0] == ':') { struct arm_tpiu_swo_priv_connection *priv = malloc(sizeof(*priv)); if (!priv) { @@ -790,7 +803,9 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) if (retval != ERROR_OK) goto error_exit; - arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_ENABLE); + retval = arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_ENABLE); + if (retval != ERROR_OK) + goto error_exit; /* START_DEPRECATED_TPIU */ target_handle_event(target, TARGET_EVENT_TRACE_CONFIG); @@ -947,6 +962,12 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const adiv5_mem_ap_spot_init(&obj->spot); obj->spot.base = TPIU_SWO_DEFAULT_BASE; obj->port_width = 1; + obj->out_filename = strdup("external"); + if (!obj->out_filename) { + LOG_ERROR("Out of memory"); + free(obj); + return JIM_ERR; + } Jim_Obj *n; jim_getopt_obj(&goi, &n); @@ -1021,8 +1042,8 @@ COMMAND_HANDLER(handle_tpiu_deprecated_config_command) struct arm_tpiu_swo_object *obj = NULL; int retval; - if (strcmp(target->type->name, "cortex_m") && - strcmp(target->type->name, "hla_target")) { + if (strcmp(target_type_name(target), "cortex_m") && + strcmp(target_type_name(target), "hla_target")) { LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA"); return ERROR_FAIL; } diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 82f4be5..dc3752e 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -473,7 +473,7 @@ int armv7a_identify_cache(struct target *target) /* if no l2 cache initialize l1 data cache flush function function */ if (!armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache) { armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = - armv7a_cache_auto_flush_all_data; + armv7a_cache_flush_all_data; } armv7a->armv7a_mmu.armv7a_cache.info = 1; @@ -525,7 +525,6 @@ int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) armv7a->armv7a_mmu.armv7a_cache.info = -1; armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL; - armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1; return ERROR_OK; } diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 6b9c2a6..8943f1c 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -65,8 +65,6 @@ struct armv7a_cache_common { struct armv7a_arch_cache arch[6]; /* cache info, L1 - L7 */ int i_cache_enabled; int d_u_cache_enabled; - int auto_cache_enabled; /* openocd automatic - * cache handling */ /* outer unified cache if some */ void *outer_cache; int (*flush_all_data_cache)(struct target *target); diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index e1f0dfa..f2f1097 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -118,20 +118,19 @@ done: return retval; } -int armv7a_cache_auto_flush_all_data(struct target *target) +int armv7a_cache_flush_all_data(struct target *target) { int retval = ERROR_FAIL; - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) - return ERROR_OK; if (target->smp) { struct target_list *head; foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - if (curr->state == TARGET_HALTED) - retval = armv7a_l1_d_cache_clean_inval_all(curr); + if (curr->state == TARGET_HALTED) { + int retval1 = armv7a_l1_d_cache_clean_inval_all(curr); + if (retval1 != ERROR_OK) + retval = retval1; + } } } else retval = armv7a_l1_d_cache_clean_inval_all(target); @@ -391,27 +390,6 @@ int armv7a_cache_flush_virt(struct target *target, uint32_t virt, return ERROR_OK; } -/* - * We assume that target core was chosen correctly. It means if same data - * was handled by two cores, other core will loose the changes. Since it - * is impossible to know (FIXME) which core has correct data, keep in mind - * that some kind of data lost or corruption is possible. - * Possible scenario: - * - core1 loaded and changed data on 0x12345678 - * - we halted target and modified same data on core0 - * - data on core1 will be lost. - */ -int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt, - uint32_t size) -{ - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) - return ERROR_OK; - - return armv7a_cache_flush_virt(target, virt, size); -} - COMMAND_HANDLER(arm7a_l1_cache_info_cmd) { struct target *target = get_current_target(CMD_CTX); @@ -493,28 +471,6 @@ COMMAND_HANDLER(arm7a_l1_i_cache_inval_virt_cmd) return armv7a_l1_i_cache_inval_virt(target, virt, size); } -COMMAND_HANDLER(arm7a_cache_disable_auto_cmd) -{ - struct target *target = get_current_target(CMD_CTX); - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (CMD_ARGC == 0) { - command_print(CMD, "auto cache is %s", - armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled ? "enabled" : "disabled"); - return ERROR_OK; - } - - if (CMD_ARGC == 1) { - uint32_t set; - - COMMAND_PARSE_ENABLE(CMD_ARGV[0], set); - armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = !!set; - return ERROR_OK; - } - - return ERROR_COMMAND_SYNTAX_ERROR; -} - static const struct command_registration arm7a_l1_d_cache_commands[] = { { .name = "flush_all", @@ -585,13 +541,6 @@ static const struct command_registration arm7a_l1_di_cache_group_handlers[] = { static const struct command_registration arm7a_cache_group_handlers[] = { { - .name = "auto", - .handler = arm7a_cache_disable_auto_cmd, - .mode = COMMAND_ANY, - .help = "disable or enable automatic cache handling.", - .usage = "(1|0)", - }, - { .name = "l1", .mode = COMMAND_ANY, .help = "l1 cache command group", diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h index 17ec5e6..c4637c5 100644 --- a/src/target/armv7a_cache.h +++ b/src/target/armv7a_cache.h @@ -20,9 +20,7 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, int armv7a_l1_i_cache_inval_all(struct target *target); int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, uint32_t size); -int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt, - uint32_t size); -int armv7a_cache_auto_flush_all_data(struct target *target); +int armv7a_cache_flush_all_data(struct target *target); int armv7a_cache_flush_virt(struct target *target, uint32_t virt, uint32_t size); extern const struct command_registration arm7a_cache_command_handlers[]; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 7fa0c4e..2de77c9 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -314,19 +314,6 @@ static int cortex_a_exec_opcode(struct target *target, 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, - uint32_t value) -{ - int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value); - - return retval; -} - /* * Cortex-A implementation of Debug Programmer's Model * @@ -611,11 +598,11 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, LOG_DEBUG("A: bpwp enable, vr %08x cr %08x", (unsigned) vr, (unsigned) cr); - retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target, + retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, vr, addr); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target, + retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, control); return retval; } @@ -641,7 +628,7 @@ static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); /* clear control register */ - return cortex_a_dap_write_memap_register_u32(dpm->arm->target, cr, 0); + return mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, 0); } static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr) @@ -1323,13 +1310,13 @@ static int cortex_a_set_breakpoint(struct target *target, brp_list[brp_i].used = true; brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_i].control = control; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1362,10 +1349,8 @@ static int cortex_a_set_breakpoint(struct target *target, return retval; /* make sure data cache is cleaned & invalidated down to PoC */ - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) { - armv7a_cache_flush_virt(target, breakpoint->address, + armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length); - } retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, @@ -1417,13 +1402,13 @@ static int cortex_a_set_context_breakpoint(struct target *target, brp_list[brp_i].used = true; brp_list[brp_i].value = (breakpoint->asid); brp_list[brp_i].control = control; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1483,13 +1468,13 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi brp_list[brp_1].used = true; brp_list[brp_1].value = (breakpoint->asid); brp_list[brp_1].control = control_ctx; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn, brp_list[brp_1].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn, brp_list[brp_1].control); if (retval != ERROR_OK) return retval; @@ -1501,13 +1486,13 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi brp_list[brp_2].used = true; brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_2].control = control_iva; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn, brp_list[brp_2].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn, brp_list[brp_2].control); if (retval != ERROR_OK) return retval; @@ -1540,13 +1525,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_i].used = false; brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; @@ -1559,13 +1544,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_j].used = false; brp_list[brp_j].value = 0; brp_list[brp_j].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn, brp_list[brp_j].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn, brp_list[brp_j].value); if (retval != ERROR_OK) return retval; @@ -1584,13 +1569,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_i].used = false; brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; @@ -1600,10 +1585,8 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b } else { /* make sure data cache is cleaned & invalidated down to PoC */ - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) { - armv7a_cache_flush_virt(target, breakpoint->address, + armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length); - } /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { @@ -1787,14 +1770,14 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat wrp_list[wrp_i].value = address; wrp_list[wrp_i].control = control; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].control); if (retval != ERROR_OK) return retval; @@ -1836,13 +1819,13 @@ static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *w wrp_list[wrp_i].used = false; wrp_list[wrp_i].value = 0; wrp_list[wrp_i].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].value); if (retval != ERROR_OK) return retval; @@ -1932,7 +1915,7 @@ static int cortex_a_assert_reset(struct target *target) } /* registers are now invalid */ - if (target_was_examined(target)) + if (armv7a->arm.core_cache) register_cache_invalidate(armv7a->arm.core_cache); target->state = TARGET_RESET; @@ -2791,9 +2774,6 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address, LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32, 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_cpu_memory(target, address, size, count, buffer); cortex_a_post_memaccess(target, 0); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 4894cab..c225b1a 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1109,6 +1109,11 @@ static int cortex_m_halt_one(struct target *target) int retval; LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); + if (!target_was_examined(target)) { + LOG_TARGET_ERROR(target, "target non examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } + if (target->state == TARGET_HALTED) { LOG_TARGET_DEBUG(target, "target was already halted"); return ERROR_OK; @@ -2351,6 +2356,7 @@ static void cortex_m_dwt_addreg(struct target *t, struct reg *r, const struct dw r->value = state->value; r->arch_info = state; r->type = &dwt_reg_type; + r->exist = true; } static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target) diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index f7acc60..1eb1957 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -1802,10 +1802,8 @@ static int semihosting_service_input_handler(struct connection *connection) static int semihosting_service_connection_closed_handler(struct connection *connection) { struct semihosting_tcp_service *service = connection->service->priv; - if (service) { + if (service) free(service->name); - free(service); - } return ERROR_OK; } diff --git a/src/target/smp.c b/src/target/smp.c index 50b19d0..41ca880 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -119,7 +119,7 @@ COMMAND_HANDLER(default_handle_smp_command) head->target->smp = 0; /* fixes the target display to the debugger */ - if (!list_empty(target->smp_targets)) + if (!list_empty(target->smp_targets) && target->gdb_service) target->gdb_service->target = target; return ERROR_OK; diff --git a/src/target/startup.tcl b/src/target/startup.tcl index 75e0edc..e964609 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -294,3 +294,25 @@ proc "mips_m4k smp_off" {args} { echo "DEPRECATED! use 'mips_m4k smp off' not 'mips_m4k smp_off'" eval mips_m4k smp off $args } + +lappend _telnet_autocomplete_skip _post_init_target_cortex_a_cache_auto +proc _post_init_target_cortex_a_cache_auto {} { + set cortex_a_found 0 + + foreach t [target names] { + if { [$t cget -type] != "cortex_a" } { continue } + set cortex_a_found 1 + lappend ::_telnet_autocomplete_skip "$t cache auto" + proc "$t cache auto" { enable } { + echo "DEPRECATED! Don't use anymore '[dict get [info frame 0] proc] $enable' as it's always enabled" + } + } + + if { $cortex_a_found } { + lappend ::_telnet_autocomplete_skip "cache auto" + proc "cache auto" { enable } { + echo "DEPRECATED! Don't use anymore 'cache auto $enable' as it's always enabled" + } + } +} +lappend post_init_commands _post_init_target_cortex_a_cache_auto diff --git a/src/target/target.c b/src/target/target.c index 0c57292..5187006 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1504,7 +1504,7 @@ static int target_init_one(struct command_context *cmd_ctx, */ if (type->mmu) { if (!type->virt2phys) { - LOG_ERROR("type '%s' is missing virt2phys", type->name); + LOG_ERROR("type '%s' is missing virt2phys", target_name(target)); type->virt2phys = identity_virt2phys; } } else { @@ -1513,7 +1513,7 @@ static int target_init_one(struct command_context *cmd_ctx, * ensure that virt2phys() is always an identity mapping. */ if (type->write_phys_memory || type->read_phys_memory || type->virt2phys) - LOG_WARNING("type '%s' has bad MMU hooks", type->name); + LOG_WARNING("type '%s' has bad MMU hooks", target_name(target)); type->mmu = no_mmu; type->write_phys_memory = type->write_memory; @@ -6721,6 +6721,13 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "address width data ['phys']", }, { + .name = "debug_reason", + .mode = COMMAND_EXEC, + .handler = handle_target_debug_reason, + .help = "displays the debug reason of this target", + .usage = "", + }, + { .name = "reset_nag", .handler = handle_target_reset_nag, .mode = COMMAND_ANY, diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index fb7748a..f7c82ef 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -158,6 +158,12 @@ #define XT_INS_RFWU(X) (XT_ISBE(X) ? 0x005300 << 8 : 0x003500) #define XT_INS_RFWO_RFWU_MASK(X) (XT_ISBE(X) ? 0xFFFFFF << 8 : 0xFFFFFF) +/* Read Protection TLB Entry Info */ +#define XT_INS_PPTLB(X, S, T) _XT_INS_FORMAT_RRR(X, 0x500000, ((S) << 4) | (T), 0xD) + +#define XT_TLB1_ACC_SHIFT 8 +#define XT_TLB1_ACC_MSK 0xF + #define XT_WATCHPOINTS_NUM_MAX 2 /* Special register number macro for DDR, PS, WB, A3, A4 registers. @@ -298,6 +304,27 @@ enum xtensa_mem_region_type { XTENSA_MEM_REGS_NUM }; +/** + * Types of access rights for MPU option + * The first block is kernel RWX ARs; the second block is user rwx ARs. + */ +enum xtensa_mpu_access_type { + XTENSA_ACC_00X_000 = 0x2, + XTENSA_ACC_000_00X, + XTENSA_ACC_R00_000, + XTENSA_ACC_R0X_000, + XTENSA_ACC_RW0_000, + XTENSA_ACC_RWX_000, + XTENSA_ACC_0W0_0W0, + XTENSA_ACC_RW0_RWX, + XTENSA_ACC_RW0_R00, + XTENSA_ACC_RWX_R0X, + XTENSA_ACC_R00_R00, + XTENSA_ACC_R0X_R0X, + XTENSA_ACC_RW0_RW0, + XTENSA_ACC_RWX_RWX +}; + /* Register definition as union for list allocation */ union xtensa_reg_val_u { xtensa_reg_val_t val; @@ -521,6 +548,44 @@ static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint } } +/* NOTE: Assumes A3 has already been saved and marked dirty; A3 will be clobbered */ +static inline bool xtensa_region_ar_exec(struct target *target, target_addr_t start, target_addr_t end) +{ + struct xtensa *xtensa = target_to_xtensa(target); + if (xtensa->core_config->mpu.enabled) { + /* For cores with the MPU option, issue PPTLB on start and end addresses. + * Parse access rights field, and confirm both have execute permissions. + */ + for (int i = 0; i <= 1; i++) { + uint32_t at, acc; + uint8_t at_buf[4]; + bool exec_acc; + target_addr_t addr = i ? end : start; + xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, addr); + xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3)); + xtensa_queue_exec_ins(xtensa, XT_INS_PPTLB(xtensa, XT_REG_A3, XT_REG_A3)); + xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A3)); + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, at_buf); + int res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) + LOG_TARGET_ERROR(target, "Error queuing PPTLB: %d", res); + res = xtensa_core_status_check(target); + if (res != ERROR_OK) + LOG_TARGET_ERROR(target, "Error issuing PPTLB: %d", res); + at = buf_get_u32(at_buf, 0, 32); + acc = (at >> XT_TLB1_ACC_SHIFT) & XT_TLB1_ACC_MSK; + exec_acc = ((acc == XTENSA_ACC_00X_000) || (acc == XTENSA_ACC_R0X_000) || + (acc == XTENSA_ACC_RWX_000) || (acc == XTENSA_ACC_RWX_R0X) || + (acc == XTENSA_ACC_R0X_R0X) || (acc == XTENSA_ACC_RWX_RWX)); + LOG_TARGET_DEBUG(target, "PPTLB(" TARGET_ADDR_FMT ") -> 0x%08" PRIx32 " exec_acc %d", + addr, at, exec_acc); + if (!exec_acc) + return false; + } + } + return true; +} + static int xtensa_queue_pwr_reg_write(struct xtensa *xtensa, unsigned int reg, uint32_t data) { struct xtensa_debug_module *dm = &xtensa->dbg_mod; @@ -2176,11 +2241,13 @@ int xtensa_write_memory(struct target *target, } } else { /* Invalidate ICACHE, writeback DCACHE if present */ - uint32_t issue_ihi = xtensa_is_icacheable(xtensa, address); - uint32_t issue_dhwb = xtensa_is_dcacheable(xtensa, address); - if (issue_ihi || issue_dhwb) { + bool issue_ihi = xtensa_is_icacheable(xtensa, address) && + xtensa_region_ar_exec(target, addrstart_al, addrend_al); + bool issue_dhwbi = xtensa_is_dcacheable(xtensa, address); + LOG_TARGET_DEBUG(target, "Cache OPs: IHI %d, DHWBI %d", issue_ihi, issue_dhwbi); + if (issue_ihi || issue_dhwbi) { uint32_t ilinesize = issue_ihi ? xtensa->core_config->icache.line_size : UINT32_MAX; - uint32_t dlinesize = issue_dhwb ? xtensa->core_config->dcache.line_size : UINT32_MAX; + uint32_t dlinesize = issue_dhwbi ? xtensa->core_config->dcache.line_size : UINT32_MAX; uint32_t linesize = MIN(ilinesize, dlinesize); uint32_t off = 0; adr = addrstart_al; @@ -2193,7 +2260,7 @@ int xtensa_write_memory(struct target *target, } if (issue_ihi) xtensa_queue_exec_ins(xtensa, XT_INS_IHI(xtensa, XT_REG_A3, off)); - if (issue_dhwb) + if (issue_dhwbi) xtensa_queue_exec_ins(xtensa, XT_INS_DHWBI(xtensa, XT_REG_A3, off)); off += linesize; if (off > 1020) { @@ -2205,7 +2272,11 @@ int xtensa_write_memory(struct target *target, /* Execute cache WB/INV instructions */ res = xtensa_dm_queue_execute(&xtensa->dbg_mod); - xtensa_core_status_check(target); + if (res != ERROR_OK) + LOG_TARGET_ERROR(target, + "Error queuing cache writeback/invaldate instruction(s): %d", + res); + res = xtensa_core_status_check(target); if (res != ERROR_OK) LOG_TARGET_ERROR(target, "Error issuing cache writeback/invaldate instruction(s): %d", @@ -2367,7 +2438,8 @@ int xtensa_poll(struct target *target) static int xtensa_update_instruction(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { struct xtensa *xtensa = target_to_xtensa(target); - unsigned int issue_ihi = xtensa_is_icacheable(xtensa, address); + unsigned int issue_ihi = xtensa_is_icacheable(xtensa, address) && + xtensa_region_ar_exec(target, address, address + size); unsigned int issue_dhwbi = xtensa_is_dcacheable(xtensa, address); uint32_t icache_line_size = issue_ihi ? xtensa->core_config->icache.line_size : UINT32_MAX; uint32_t dcache_line_size = issue_dhwbi ? xtensa->core_config->dcache.line_size : UINT32_MAX; @@ -2385,7 +2457,8 @@ static int xtensa_update_instruction(struct target *target, target_addr_t addres /* Write start address to A3 and invalidate */ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, address); xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3)); - LOG_TARGET_DEBUG(target, "DHWBI, IHI for address "TARGET_ADDR_FMT, address); + LOG_TARGET_DEBUG(target, "IHI %d, DHWBI %d for address " TARGET_ADDR_FMT, + issue_ihi, issue_dhwbi, address); if (issue_dhwbi) { xtensa_queue_exec_ins(xtensa, XT_INS_DHWBI(xtensa, XT_REG_A3, 0)); if (!same_dc_line) { |