aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
Diffstat (limited to 'src/target')
-rw-r--r--src/target/aarch64.c2
-rw-r--r--src/target/arm_tpiu_swo.c57
-rw-r--r--src/target/armv7a.c3
-rw-r--r--src/target/armv7a.h2
-rw-r--r--src/target/armv7a_cache.c63
-rw-r--r--src/target/armv7a_cache.h4
-rw-r--r--src/target/cortex_a.c104
-rw-r--r--src/target/cortex_m.c6
-rw-r--r--src/target/semihosting_common.c4
-rw-r--r--src/target/smp.c2
-rw-r--r--src/target/startup.tcl22
-rw-r--r--src/target/target.c11
-rw-r--r--src/target/xtensa/xtensa.c89
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) {