From 22ebb693b62fd05bcbe2c0101e180b92ca5b11f3 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 28 Apr 2022 03:46:35 +0100 Subject: cortex_m: add detection of MVE feature for Armv8.1-M cores For Armv8.1-M based cores, detect if the core implements the optional M-profile vector extension (MVE), using MVFR1 register. While at there rework armv7m->fp_feature detection based on MVFR0 and MVFR1 registers. Change-Id: I92d5b1759aea9f7561d285f46acdec51d6efb7b4 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6950 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv7m.h | 2 ++ src/target/cortex_m.c | 51 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 19 deletions(-) (limited to 'src/target') diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 8693404..2878dd1 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -211,6 +211,8 @@ enum { FPV4_SP, FPV5_SP, FPV5_DP, + FPV5_MVE_I, + FPV5_MVE_F, }; #define ARMV7M_NUM_CORE_REGS (ARMV7M_CORE_LAST_REG - ARMV7M_CORE_FIRST_REG + 1) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index d9e8b53..6a29a5f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2486,16 +2486,17 @@ static bool cortex_m_has_tz(struct target *target) return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0; } -#define MVFR0 0xe000ef40 -#define MVFR1 0xe000ef44 -#define MVFR0_DEFAULT_M4 0x10110021 -#define MVFR1_DEFAULT_M4 0x11000011 +#define MVFR0 0xE000EF40 +#define MVFR0_SP_MASK 0x000000F0 +#define MVFR0_SP 0x00000020 +#define MVFR0_DP_MASK 0x00000F00 +#define MVFR0_DP 0x00000200 -#define MVFR0_DEFAULT_M7_SP 0x10110021 -#define MVFR0_DEFAULT_M7_DP 0x10110221 -#define MVFR1_DEFAULT_M7_SP 0x11000011 -#define MVFR1_DEFAULT_M7_DP 0x12000011 +#define MVFR1 0xE000EF44 +#define MVFR1_MVE_MASK 0x00000F00 +#define MVFR1_MVE_I 0x00000100 +#define MVFR1_MVE_F 0x00000200 static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp, struct adiv5_ap **debug_ap) @@ -2509,7 +2510,7 @@ static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp, int cortex_m_examine(struct target *target) { int retval; - uint32_t cpuid, fpcr, mvfr0, mvfr1; + uint32_t cpuid, fpcr; struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; struct armv7m_common *armv7m = target_to_armv7m(target); @@ -2584,25 +2585,37 @@ int cortex_m_examine(struct target *target) LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid); if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) { + uint32_t mvfr0; target_read_u32(target, MVFR0, &mvfr0); - target_read_u32(target, MVFR1, &mvfr1); - /* test for floating point feature on Cortex-M4 */ - if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { - LOG_TARGET_DEBUG(target, "%s floating point feature FPv4_SP found", cortex_m->core_info->name); + if ((mvfr0 & MVFR0_SP_MASK) == MVFR0_SP) { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv4_SP found", + cortex_m->core_info->name); armv7m->fp_feature = FPV4_SP; } } else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) { + uint32_t mvfr0, mvfr1; target_read_u32(target, MVFR0, &mvfr0); target_read_u32(target, MVFR1, &mvfr1); - /* test for floating point features on Cortex-M7 */ - if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { - LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_SP found", cortex_m->core_info->name); + if ((mvfr0 & MVFR0_DP_MASK) == MVFR0_DP) { + if ((mvfr1 & MVFR1_MVE_MASK) == MVFR1_MVE_F) { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP + MVE-F found", + cortex_m->core_info->name); + armv7m->fp_feature = FPV5_MVE_F; + } else { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP found", + cortex_m->core_info->name); + armv7m->fp_feature = FPV5_DP; + } + } else if ((mvfr0 & MVFR0_SP_MASK) == MVFR0_SP) { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_SP found", + cortex_m->core_info->name); armv7m->fp_feature = FPV5_SP; - } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { - LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP found", cortex_m->core_info->name); - armv7m->fp_feature = FPV5_DP; + } else if ((mvfr1 & MVFR1_MVE_MASK) == MVFR1_MVE_I) { + LOG_TARGET_DEBUG(target, "%s floating point feature MVE-I found", + cortex_m->core_info->name); + armv7m->fp_feature = FPV5_MVE_I; } } -- cgit v1.1 From 04eda372634f995c732bed4f67855be258ab0e41 Mon Sep 17 00:00:00 2001 From: ianst Date: Wed, 6 Dec 2023 14:34:09 -0800 Subject: target/xtensa: extra debug info for "xtensa exe" failures - Read and display EXCCAUSE on exe error - Clean up error messages - Clarify "xtensa exe" documentation Signed-off-by: ianst Change-Id: I90ed39f6afb6543c0c873301501435384b4dccbe Reviewed-on: https://review.openocd.org/c/openocd/+/7982 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/xtensa/xtensa.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/target') diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index d2ca32c..ab3bfbb 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3483,15 +3483,21 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) LOG_TARGET_DEBUG(target, "execute stub: %s", CMD_ARGV[0]); xtensa_queue_exec_ins_wide(xtensa, ops, oplen); /* Handles endian-swap */ status = xtensa_dm_queue_execute(&xtensa->dbg_mod); - if (status != ERROR_OK) - LOG_TARGET_ERROR(target, "TIE queue execute: %d\n", status); - status = xtensa_core_status_check(target); - if (status != ERROR_OK) - LOG_TARGET_ERROR(target, "TIE instr execute: %d\n", status); + if (status != ERROR_OK) { + LOG_TARGET_ERROR(target, "exec: queue error %d", status); + } else { + status = xtensa_core_status_check(target); + if (status != ERROR_OK) + LOG_TARGET_ERROR(target, "exec: status error %d", status); + } /* Reread register cache and restore saved regs after instruction execution */ if (xtensa_fetch_all_regs(target) != ERROR_OK) - LOG_TARGET_ERROR(target, "%s: Failed to fetch register cache (post-exec).", target_name(target)); + LOG_TARGET_ERROR(target, "post-exec: register fetch error"); + if (status != ERROR_OK) { + LOG_TARGET_ERROR(target, "post-exec: EXCCAUSE 0x%02" PRIx32, + xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE)); + } xtensa_reg_set(target, XT_REG_IDX_EXCCAUSE, exccause); xtensa_reg_set(target, XT_REG_IDX_CPENABLE, cpenable); return status; -- cgit v1.1 From 2c10e3e2577604f5ec75b7f688f53fa2b3cbb0e7 Mon Sep 17 00:00:00 2001 From: Evgeniy Didin Date: Fri, 31 Jul 2020 00:13:12 +0300 Subject: target/arc: restore breakpoints in arc_resume() Presently, we rely on gdb to restore break/watchpoints upon resuming execution in arc_resume(). To match this behavior in absence of gdb (more specifically, when handle_breakpoints is true), this patch explicitly re-enables all breakpoints and watchpoints in arc_resume(). This has previously been committed to the Zephyr project's openocd repo (see https://github.com/zephyrproject-rtos/openocd/pull/31). Change-Id: I59e9c91270ef0b5fd19cfc570663dc67a6022dbd Signed-off-by: Evgeniy Didin Signed-off-by: Stephanos Ioannidis Signed-off-by: Artemiy Volkov Reviewed-on: https://review.openocd.org/c/openocd/+/7816 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- src/target/arc.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/target') diff --git a/src/target/arc.c b/src/target/arc.c index 0f7b110..f3449aa 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -50,6 +50,8 @@ static int arc_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); +static int arc_enable_watchpoints(struct target *target); +static int arc_enable_breakpoints(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) @@ -1262,6 +1264,13 @@ static int arc_resume(struct target *target, int current, target_addr_t address, return ERROR_TARGET_NOT_HALTED; } + if (!debug_execution) { + /* (gdb) continue = execute until we hit break/watch-point */ + target_free_all_working_areas(target); + CHECK_RETVAL(arc_enable_breakpoints(target)); + CHECK_RETVAL(arc_enable_watchpoints(target)); + } + /* current = 1: continue on current PC, otherwise continue at
*/ if (!current) { target_buffer_set_u32(target, pc->value, address); @@ -1658,6 +1667,19 @@ static int arc_unset_breakpoint(struct target *target, return retval; } +static int arc_enable_breakpoints(struct target *target) +{ + struct breakpoint *breakpoint = target->breakpoints; + + /* set any pending breakpoints */ + while (breakpoint) { + if (!breakpoint->is_set) + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + breakpoint = breakpoint->next; + } + + return ERROR_OK; +} static int arc_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { @@ -1895,6 +1917,20 @@ static int arc_unset_watchpoint(struct target *target, return retval; } +static int arc_enable_watchpoints(struct target *target) +{ + struct watchpoint *watchpoint = target->watchpoints; + + /* set any pending watchpoints */ + while (watchpoint) { + if (!watchpoint->is_set) + CHECK_RETVAL(arc_set_watchpoint(target, watchpoint)); + watchpoint = watchpoint->next; + } + + return ERROR_OK; +} + static int arc_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { -- cgit v1.1 From 0de852f56130bfffa427bbc04bcea0370eecb0f3 Mon Sep 17 00:00:00 2001 From: Evgeniy Didin Date: Fri, 31 Jul 2020 00:13:12 +0300 Subject: target/arc: skip over breakpoints in arc_resume() When requested by the core code (handle_breakpoints = true), arc_resume() should be able to advance over a potential breakpoint set at the resume address instead of getting stuck in one place. This is achieved by removing the breakpoint, executing one instruction, resetting the breakpoint, then proceeding forward as normal. With this patch applied, openocd is now able to resume from a breakpoint halt when debugging ARCv2 targets via telnet. This has previously been committed to the Zephyr project's openocd repo (see https://github.com/zephyrproject-rtos/openocd/pull/31). Change-Id: I17dba0dcea311d394b303c587bc2dfaa99d67859 Signed-off-by: Evgeniy Didin Signed-off-by: Stephanos Ioannidis Signed-off-by: Artemiy Volkov Reviewed-on: https://review.openocd.org/c/openocd/+/7817 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/arc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'src/target') diff --git a/src/target/arc.c b/src/target/arc.c index f3449aa..72e4d91 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -52,6 +52,11 @@ static int arc_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); static int arc_enable_watchpoints(struct target *target); static int arc_enable_breakpoints(struct target *target); +static int arc_unset_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int arc_set_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int arc_single_step_core(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) @@ -750,6 +755,29 @@ static int arc_examine(struct target *target) return ERROR_OK; } +static int arc_exit_debug(struct target *target) +{ + uint32_t value; + struct arc_common *arc = target_to_arc(target); + + /* Do read-modify-write sequence, or DEBUG.UB will be reset unintentionally. */ + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, &value)); + value |= SET_CORE_FORCE_HALT; /* set the HALT bit */ + CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); + alive_sleep(1); + + target->state = TARGET_HALTED; + CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); + + if (debug_level >= LOG_LVL_DEBUG) { + LOG_DEBUG("core stopped (halted) debug-reg: 0x%08" PRIx32, value); + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); + LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + } + + return ERROR_OK; +} + static int arc_halt(struct target *target) { uint32_t value, irq_state; @@ -1251,7 +1279,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, uint32_t value; struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]; - LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints(not supported yet):%i," + LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," " debug_execution:%i", current, address, handle_breakpoints, debug_execution); /* We need to reset ARC cache variables so caches @@ -1296,6 +1324,19 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value)); } + /* the front-end may request us not to handle breakpoints here */ + if (handle_breakpoints) { + /* Single step past breakpoint at current address */ + struct breakpoint *breakpoint = breakpoint_find(target, resume_pc); + if (breakpoint) { + LOG_DEBUG("skipping past breakpoint at 0x%08" TARGET_PRIxADDR, + breakpoint->address); + CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); + CHECK_RETVAL(arc_single_step_core(target)); + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + } + } + /* Restore IRQ state if not in debug_execution*/ if (!debug_execution) CHECK_RETVAL(arc_enable_interrupts(target, arc->irq_state)); @@ -2027,6 +2068,22 @@ static int arc_config_step(struct target *target, int enable_step) return ERROR_OK; } +static int arc_single_step_core(struct target *target) +{ + CHECK_RETVAL(arc_debug_entry(target)); + + /* disable interrupts while stepping */ + CHECK_RETVAL(arc_enable_interrupts(target, 0)); + + /* configure single step mode */ + CHECK_RETVAL(arc_config_step(target, 1)); + + /* exit debug mode */ + CHECK_RETVAL(arc_exit_debug(target)); + + return ERROR_OK; +} + static int arc_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { -- cgit v1.1 From 305f293201a1d75f24eaa188294b78b284c8185b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 4 Jan 2024 22:26:38 +0100 Subject: LICENSES: drop SPDX tag 'GPL-2.0' and use 'GPL-2.0-only' The SPDX tag 'GPL-2.0' has been deprecated in https://spdx.org/licenses/GPL-2.0.html and the preferred tag is now 'GPL-2.0-only' https://spdx.org/licenses/GPL-2.0-only.html Update the LICENSES documents and the SPDX of the only file that reports the deprecated tag. Change-Id: I3c3215438bc4378ff470bb9fa8fa962505a9ae50 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8064 Tested-by: jenkins --- src/target/mips_cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/target') diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h index 2f31dbd..c3b7b54 100644 --- a/src/target/mips_cpu.h +++ b/src/target/mips_cpu.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef OPENOCD_TARGET_MIPS_CPU_H #define OPENOCD_TARGET_MIPS_CPU_H -- cgit v1.1 From 6e6d486de2c668e14f9534fab820eea305826753 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Dec 2023 18:10:45 +0100 Subject: target: drop deprecated code for mem2array and array2mem Commit e370e06b724f ("target: Deprecate 'array2mem' and 'mem2array''") has already replaced the deprecated root versions of commands mem2array and array2mem with TCL proc's that use 'read_memory' and 'write_memory'. It has left the deprecated code of the target's version of the commands because the effort to code the TCL replacement was not considered valuable. To drop the last jim_handler commands, I consider much easier and less error-prone to code them in TCL instead of converting the deprecated code to COMMAND_HANDLER. Drop the code in target.c and extend the TCL proc's. While there, add the TCL procs to _telnet_autocomplete_skip. Change-Id: I97d2370d8af479434ddf5af68541f90913982bc0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8052 Tested-by: jenkins --- src/target/startup.tcl | 57 ++++--- src/target/target.c | 419 ------------------------------------------------- 2 files changed, 35 insertions(+), 441 deletions(-) (limited to 'src/target') diff --git a/src/target/startup.tcl b/src/target/startup.tcl index 35492a6..75e0edc 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -219,31 +219,44 @@ proc init_target_events {} { proc init_board {} { } -proc mem2array {arrayname bitwidth address count {phys ""}} { - echo "DEPRECATED! use 'read_memory' not 'mem2array'" - - upvar $arrayname $arrayname - set $arrayname "" - set i 0 - - foreach elem [read_memory $address $bitwidth $count {*}$phys] { - set ${arrayname}($i) $elem - incr i - } -} - -proc array2mem {arrayname bitwidth address count {phys ""}} { - echo "DEPRECATED! use 'write_memory' not 'array2mem'" - - upvar $arrayname $arrayname - set data "" +lappend _telnet_autocomplete_skip _post_init_target_array_mem +proc _post_init_target_array_mem {} { + set targets [target names] + lappend targets "" - for {set i 0} {$i < $count} {incr i} { - lappend data [expr $${arrayname}($i)] + foreach t $targets { + if {$t != ""} { + set t "$t " + } + eval [format {lappend ::_telnet_autocomplete_skip "%smem2array"} $t] + eval [format {proc {%smem2array} {arrayname bitwidth address count {phys ""}} { + echo "DEPRECATED! use 'read_memory' not 'mem2array'" + + upvar $arrayname $arrayname + set $arrayname "" + set i 0 + + foreach elem [%sread_memory $address $bitwidth $count {*}$phys] { + set ${arrayname}($i) $elem + incr i + } + }} $t $t] + eval [format {lappend ::_telnet_autocomplete_skip "%sarray2mem"} $t] + eval [format {proc {%sarray2mem} {arrayname bitwidth address count {phys ""}} { + echo "DEPRECATED! use 'write_memory' not 'array2mem'" + + upvar $arrayname $arrayname + set data "" + + for {set i 0} {$i < $count} {incr i} { + lappend data [expr $${arrayname}($i)] + } + + %swrite_memory $address $bitwidth $data {*}$phys + }} $t $t] } - - write_memory $address $bitwidth $data {*}$phys } +lappend post_init_commands _post_init_target_array_mem # smp_on/smp_off were already DEPRECATED in v0.11.0 through http://openocd.zylin.com/4615 lappend _telnet_autocomplete_skip "aarch64 smp_on" diff --git a/src/target/target.c b/src/target/target.c index 61890aa..920511e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -56,10 +56,6 @@ static int target_read_buffer_default(struct target *target, target_addr_t addre uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); -static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj * const *argv); -static int target_mem2array(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj * const *argv); static int target_register_user_commands(struct command_context *cmd_ctx); static int target_get_gdb_fileio_info_default(struct target *target, struct gdb_fileio_info *fileio_info); @@ -4397,192 +4393,6 @@ COMMAND_HANDLER(handle_profile_command) return retval; } -static int new_u64_array_element(Jim_Interp *interp, const char *varname, int idx, uint64_t val) -{ - char *namebuf; - Jim_Obj *obj_name, *obj_val; - int result; - - namebuf = alloc_printf("%s(%d)", varname, idx); - if (!namebuf) - return JIM_ERR; - - obj_name = Jim_NewStringObj(interp, namebuf, -1); - jim_wide wide_val = val; - obj_val = Jim_NewWideObj(interp, wide_val); - if (!obj_name || !obj_val) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(obj_name); - Jim_IncrRefCount(obj_val); - result = Jim_SetVariable(interp, obj_name, obj_val); - Jim_DecrRefCount(interp, obj_name); - Jim_DecrRefCount(interp, obj_val); - free(namebuf); - /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ - return result; -} - -static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) -{ - int e; - - LOG_WARNING("DEPRECATED! use 'read_memory' not 'mem2array'"); - - /* argv[0] = name of array to receive the data - * argv[1] = desired element width in bits - * argv[2] = memory address - * argv[3] = count of times to read - * argv[4] = optional "phys" - */ - if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); - return JIM_ERR; - } - - /* Arg 0: Name of the array variable */ - const char *varname = Jim_GetString(argv[0], NULL); - - /* Arg 1: Bit width of one element */ - long l; - e = Jim_GetLong(interp, argv[1], &l); - if (e != JIM_OK) - return e; - const unsigned int width_bits = l; - - if (width_bits != 8 && - width_bits != 16 && - width_bits != 32 && - width_bits != 64) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "Invalid width param. Must be one of: 8, 16, 32 or 64.", NULL); - return JIM_ERR; - } - const unsigned int width = width_bits / 8; - - /* Arg 2: Memory address */ - jim_wide wide_addr; - e = Jim_GetWide(interp, argv[2], &wide_addr); - if (e != JIM_OK) - return e; - target_addr_t addr = (target_addr_t)wide_addr; - - /* Arg 3: Number of elements to read */ - e = Jim_GetLong(interp, argv[3], &l); - if (e != JIM_OK) - return e; - size_t len = l; - - /* Arg 4: phys */ - bool is_phys = false; - if (argc > 4) { - int str_len = 0; - const char *phys = Jim_GetString(argv[4], &str_len); - if (!strncmp(phys, "phys", str_len)) - is_phys = true; - else - return JIM_ERR; - } - - /* Argument checks */ - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); - return JIM_ERR; - } - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "mem2array: too large read request, exceeds 64K items", NULL); - return JIM_ERR; - } - - if ((width == 1) || - ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0)) || - ((width == 8) && ((addr & 7) == 0))) { - /* alignment correct */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "mem2array address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* index counter */ - size_t idx = 0; - - const size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - if (!buffer) - return JIM_ERR; - - /* assume ok */ - e = JIM_OK; - while (len) { - /* Slurp... in buffer size chunks */ - const unsigned int max_chunk_len = buffersize / width; - const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - - int retval; - if (is_phys) - retval = target_read_phys_memory(target, addr, width, chunk_len, buffer); - else - retval = target_read_memory(target, addr, width, chunk_len, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("mem2array: Read @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", - addr, - width, - chunk_len); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); - e = JIM_ERR; - break; - } else { - for (size_t i = 0; i < chunk_len ; i++, idx++) { - uint64_t v = 0; - switch (width) { - case 8: - v = target_buffer_get_u64(target, &buffer[i*width]); - break; - case 4: - v = target_buffer_get_u32(target, &buffer[i*width]); - break; - case 2: - v = target_buffer_get_u16(target, &buffer[i*width]); - break; - case 1: - v = buffer[i] & 0x0ff; - break; - } - new_u64_array_element(interp, varname, idx, v); - } - len -= chunk_len; - addr += chunk_len * width; - } - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; -} - COMMAND_HANDLER(handle_target_read_memory) { /* @@ -4706,201 +4516,6 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_OK; } -static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val) -{ - char *namebuf = alloc_printf("%s(%zu)", varname, idx); - if (!namebuf) - return JIM_ERR; - - Jim_Obj *obj_name = Jim_NewStringObj(interp, namebuf, -1); - if (!obj_name) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(obj_name); - Jim_Obj *obj_val = Jim_GetVariable(interp, obj_name, JIM_ERRMSG); - Jim_DecrRefCount(interp, obj_name); - free(namebuf); - if (!obj_val) - return JIM_ERR; - - jim_wide wide_val; - int result = Jim_GetWide(interp, obj_val, &wide_val); - *val = wide_val; - return result; -} - -static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj *const *argv) -{ - int e; - - LOG_WARNING("DEPRECATED! use 'write_memory' not 'array2mem'"); - - /* argv[0] = name of array from which to read the data - * argv[1] = desired element width in bits - * argv[2] = memory address - * argv[3] = number of elements to write - * argv[4] = optional "phys" - */ - if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); - return JIM_ERR; - } - - /* Arg 0: Name of the array variable */ - const char *varname = Jim_GetString(argv[0], NULL); - - /* Arg 1: Bit width of one element */ - long l; - e = Jim_GetLong(interp, argv[1], &l); - if (e != JIM_OK) - return e; - const unsigned int width_bits = l; - - if (width_bits != 8 && - width_bits != 16 && - width_bits != 32 && - width_bits != 64) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "Invalid width param. Must be one of: 8, 16, 32 or 64.", NULL); - return JIM_ERR; - } - const unsigned int width = width_bits / 8; - - /* Arg 2: Memory address */ - jim_wide wide_addr; - e = Jim_GetWide(interp, argv[2], &wide_addr); - if (e != JIM_OK) - return e; - target_addr_t addr = (target_addr_t)wide_addr; - - /* Arg 3: Number of elements to write */ - e = Jim_GetLong(interp, argv[3], &l); - if (e != JIM_OK) - return e; - size_t len = l; - - /* Arg 4: Phys */ - bool is_phys = false; - if (argc > 4) { - int str_len = 0; - const char *phys = Jim_GetString(argv[4], &str_len); - if (!strncmp(phys, "phys", str_len)) - is_phys = true; - else - return JIM_ERR; - } - - /* Argument checks */ - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: zero width read?", NULL); - return JIM_ERR; - } - - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: too large memory write request, exceeds 64K items", NULL); - return JIM_ERR; - } - - if ((width == 1) || - ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0)) || - ((width == 8) && ((addr & 7) == 0))) { - /* alignment correct */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* assume ok */ - e = JIM_OK; - - const size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - if (!buffer) - return JIM_ERR; - - /* index counter */ - size_t idx = 0; - - while (len) { - /* Slurp... in buffer size chunks */ - const unsigned int max_chunk_len = buffersize / width; - - const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - - /* Fill the buffer */ - for (size_t i = 0; i < chunk_len; i++, idx++) { - uint64_t v = 0; - if (get_u64_array_element(interp, varname, idx, &v) != JIM_OK) { - free(buffer); - return JIM_ERR; - } - switch (width) { - case 8: - target_buffer_set_u64(target, &buffer[i * width], v); - break; - case 4: - target_buffer_set_u32(target, &buffer[i * width], v); - break; - case 2: - target_buffer_set_u16(target, &buffer[i * width], v); - break; - case 1: - buffer[i] = v & 0x0ff; - break; - } - } - len -= chunk_len; - - /* Write the buffer to memory */ - int retval; - if (is_phys) - retval = target_write_phys_memory(target, addr, width, chunk_len, buffer); - else - retval = target_write_memory(target, addr, width, chunk_len, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("array2mem: Write @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", - addr, - width, - chunk_len); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); - e = JIM_ERR; - break; - } - addr += chunk_len * width; - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; -} - static int target_jim_write_memory(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { @@ -5637,24 +5252,6 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a return target_configure(&goi, target); } -static int jim_target_mem2array(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); - return target_mem2array(interp, target, argc - 1, argv + 1); -} - -static int jim_target_array2mem(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); - return target_array2mem(interp, target, argc - 1, argv + 1); -} - COMMAND_HANDLER(handle_target_examine) { bool allow_defer = false; @@ -5977,22 +5574,6 @@ static const struct command_registration target_instance_command_handlers[] = { .usage = "address [count]", }, { - .name = "array2mem", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_array2mem, - .help = "Writes Tcl array of 8/16/32 bit numbers " - "to target memory", - .usage = "arrayname bitwidth address count", - }, - { - .name = "mem2array", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mem2array, - .help = "Loads Tcl array of 8/16/32 bit numbers " - "from target memory", - .usage = "arrayname bitwidth address count", - }, - { .name = "get_reg", .mode = COMMAND_EXEC, .jim_handler = target_jim_get_reg, -- cgit v1.1 From 53811fc584dc8837546be9ac17b77fdf8ad1e8bd Mon Sep 17 00:00:00 2001 From: ianst Date: Wed, 1 Nov 2023 16:41:43 -0700 Subject: target/xtensa: enable xtensa algo support - Add extra error checking - Cache PS; lower PS.INTLEVEL to allow breakpoint trigger (LX) - Xtensa algo support functional on LX per functional flash driver - Test on NX via manual algo validation Change-Id: Ie7cff4933979a0551308b382fa33c33c66376f25 Signed-off-by: ianst Reviewed-on: https://review.openocd.org/c/openocd/+/8075 Reviewed-by: Antonio Borneo Reviewed-by: Erhan Kurubas Tested-by: jenkins --- src/target/xtensa/xtensa.c | 20 +++++++++++++++++--- src/target/xtensa/xtensa.h | 3 ++- src/target/xtensa/xtensa_chip.c | 4 ++++ 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'src/target') diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index ab3bfbb..1ec091c 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -2646,6 +2646,7 @@ int xtensa_start_algorithm(struct target *target, struct xtensa_algorithm *algorithm_info = arch_info; int retval = ERROR_OK; bool usr_ps = false; + uint32_t newps; /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint * at the exit point */ @@ -2660,7 +2661,17 @@ int xtensa_start_algorithm(struct target *target, buf_cpy(reg->value, xtensa->algo_context_backup[i], reg->size); } /* save debug reason, it will be changed */ + if (!algorithm_info) { + LOG_ERROR("BUG: arch_info not specified"); + return ERROR_FAIL; + } algorithm_info->ctx_debug_reason = target->debug_reason; + if (xtensa->core_config->core_type == XT_LX) { + /* save PS and set to debug_level - 1 */ + algorithm_info->ctx_ps = xtensa_reg_get(target, xtensa->eps_dbglevel_idx); + newps = (algorithm_info->ctx_ps & ~0xf) | (xtensa->core_config->debug.irq_level - 1); + xtensa_reg_set(target, xtensa->eps_dbglevel_idx, newps); + } /* write mem params */ for (int i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_IN) { @@ -2688,7 +2699,7 @@ int xtensa_start_algorithm(struct target *target, } if (memcmp(reg_params[i].reg_name, "ps", 3)) { usr_ps = true; - } else { + } else if (xtensa->core_config->core_type == XT_LX) { unsigned int reg_id = xtensa->eps_dbglevel_idx; assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!"); reg = &xtensa->core_cache->reg_list[reg_id]; @@ -2697,7 +2708,7 @@ int xtensa_start_algorithm(struct target *target, reg->valid = 1; } /* ignore custom core mode if custom PS value is specified */ - if (!usr_ps) { + if (!usr_ps && xtensa->core_config->core_type == XT_LX) { unsigned int eps_reg_idx = xtensa->eps_dbglevel_idx; xtensa_reg_val_t ps = xtensa_reg_get(target, eps_reg_idx); enum xtensa_mode core_mode = XT_PS_RING_GET(ps); @@ -2741,7 +2752,8 @@ int xtensa_wait_algorithm(struct target *target, return retval; LOG_TARGET_ERROR(target, "not halted %d, pc 0x%" PRIx32 ", ps 0x%" PRIx32, retval, xtensa_reg_get(target, XT_REG_IDX_PC), - xtensa_reg_get(target, xtensa->eps_dbglevel_idx)); + xtensa_reg_get(target, (xtensa->core_config->core_type == XT_LX) ? + xtensa->eps_dbglevel_idx : XT_REG_IDX_PS)); return ERROR_TARGET_TIMEOUT; } pc = xtensa_reg_get(target, XT_REG_IDX_PC); @@ -2813,6 +2825,8 @@ int xtensa_wait_algorithm(struct target *target, } } target->debug_reason = algorithm_info->ctx_debug_reason; + if (xtensa->core_config->core_type == XT_LX) + xtensa_reg_set(target, xtensa->eps_dbglevel_idx, algorithm_info->ctx_ps); retval = xtensa_write_dirty_registers(target); if (retval != ERROR_OK) diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 3b37122..f799208 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -228,8 +228,9 @@ struct xtensa_sw_breakpoint { struct xtensa_algorithm { /** User can set this to specify which core mode algorithm should be run in. */ enum xtensa_mode core_mode; - /** Used internally to backup and restore debug_reason. */ + /** Used internally to backup and restore core state. */ enum target_debug_reason ctx_debug_reason; + xtensa_reg_val_t ctx_ps; }; #define XTENSA_COMMON_MAGIC 0x54E4E555U diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index 668aa3a..ac758ed 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -184,6 +184,10 @@ struct target_type xtensa_chip_target = { .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = xtensa_breakpoint_add, .remove_breakpoint = xtensa_breakpoint_remove, -- cgit v1.1 From c47d77780cdaeac241e3be5d4433c7e4c8b475b9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 6 Jan 2024 17:54:24 +0100 Subject: target/mips32: fix false positive from clang clang build triggers an error for an uninitialized value of the variable 'instr'. This is a false positive, as the macro #define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT) guarantees the switch/case already covers all the possible values with cases 0, 1, 2 and 3. Silent clang by adding a useless default case to the switch. While there, fix the indentation of the switch/case accordingly to OpenOCD coding style. Change-Id: I0ae316754ce7d091dd8366bf314b8e6ee780e313 Signed-off-by: Antonio Borneo Fixes: 7de4b1202d50 ("target/mips32: add cpu info detection") Reviewed-on: https://review.openocd.org/c/openocd/+/8065 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/target/mips32.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/target') diff --git a/src/target/mips32.c b/src/target/mips32.c index 8a3ddbf..5b94e6c 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -1607,17 +1607,18 @@ COMMAND_HANDLER(mips32_handle_cpuinfo_command) char *instr; switch ((config3 & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT) { - case 0: - instr = "MIPS32"; + case 0: + instr = "MIPS32"; break; - case 1: - instr = "microMIPS"; + case 1: + instr = "microMIPS"; break; - case 2: - instr = "MIPS32 (at reset) and microMIPS"; + case 2: + instr = "MIPS32 (at reset) and microMIPS"; break; - case 3: - instr = "microMIPS (at reset) and MIPS32"; + case 3: + default: + instr = "microMIPS (at reset) and MIPS32"; break; } -- cgit v1.1 From ea2e26f7d521f5755b4bfda7bf12d99650277421 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 23:14:15 +0200 Subject: jtag: rewrite jim_jtag_configure() as COMMAND_HANDLER The function is used for commands: - jtag configure - jtag cget While there, add the missing .usage field. Change-Id: I97ddc4898259ddb7fd2d057a997f33a6f4b0e2a8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8058 Tested-by: jenkins --- src/target/adi_v5_dapdirect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/target') diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c index f3a90c0..d198dac 100644 --- a/src/target/adi_v5_dapdirect.c +++ b/src/target/adi_v5_dapdirect.c @@ -118,7 +118,8 @@ static const struct command_registration dapdirect_jtag_subcommand_handlers[] = { .name = "cget", .mode = COMMAND_EXEC, - .jim_handler = jim_jtag_configure, + .handler = handle_jtag_configure, + .usage = "", }, { .name = "names", -- cgit v1.1 From 987a274a85732e5b23c58456287982260a5959b2 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Mon, 8 Jan 2024 10:43:05 -0800 Subject: target/xtensa: update COMMAND_HELPER output to use command_print() API - Change LOG_ERROR() and LOG_INFO() output, but keep DEBUG and WARNING levels for verbosity - Update command error code return values and remove unnecessary output. Signed-off-by: Ian Thompson Change-Id: I4ef0753b3a56be02716f2db43a7d4370a1917237 Reviewed-on: https://review.openocd.org/c/openocd/+/8076 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/xtensa/xtensa.c | 86 ++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 48 deletions(-) (limited to 'src/target') diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 1ec091c..b516c17 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3459,8 +3459,8 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) const char *parm = CMD_ARGV[0]; unsigned int parm_len = strlen(parm); if ((parm_len >= 64) || (parm_len & 1)) { - LOG_ERROR("Invalid parameter length (%d): must be even, < 64 characters", parm_len); - return ERROR_FAIL; + command_print(CMD, "Invalid parameter length (%d): must be even, < 64 characters", parm_len); + return ERROR_COMMAND_ARGUMENT_INVALID; } uint8_t ops[32]; @@ -3480,7 +3480,7 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) */ int status = xtensa_write_dirty_registers(target); if (status != ERROR_OK) { - LOG_ERROR("%s: Failed to write back register cache.", target_name(target)); + command_print(CMD, "%s: Failed to write back register cache.", target_name(target)); return ERROR_FAIL; } xtensa_reg_val_t exccause = xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE); @@ -3498,18 +3498,18 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) xtensa_queue_exec_ins_wide(xtensa, ops, oplen); /* Handles endian-swap */ status = xtensa_dm_queue_execute(&xtensa->dbg_mod); if (status != ERROR_OK) { - LOG_TARGET_ERROR(target, "exec: queue error %d", status); + command_print(CMD, "exec: queue error %d", status); } else { status = xtensa_core_status_check(target); if (status != ERROR_OK) - LOG_TARGET_ERROR(target, "exec: status error %d", status); + command_print(CMD, "exec: status error %d", status); } /* Reread register cache and restore saved regs after instruction execution */ if (xtensa_fetch_all_regs(target) != ERROR_OK) - LOG_TARGET_ERROR(target, "post-exec: register fetch error"); + command_print(CMD, "post-exec: register fetch error"); if (status != ERROR_OK) { - LOG_TARGET_ERROR(target, "post-exec: EXCCAUSE 0x%02" PRIx32, + command_print(CMD, "post-exec: EXCCAUSE 0x%02" PRIx32, xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE)); } xtensa_reg_set(target, XT_REG_IDX_EXCCAUSE, exccause); @@ -3534,8 +3534,8 @@ COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa) } else if (strcasecmp(core_name, "NX") == 0) { xtensa->core_config->core_type = XT_NX; } else { - LOG_ERROR("xtdef [LX|NX]\n"); - return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "xtdef [LX|NX]\n"); + return ERROR_COMMAND_ARGUMENT_INVALID; } return ERROR_OK; } @@ -3592,7 +3592,7 @@ COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa) if (!xtensa_cmd_xtopt_legal_val("excmlevel", opt_val, 1, 6)) return ERROR_COMMAND_ARGUMENT_INVALID; if (!xtensa->core_config->high_irq.enabled) { - LOG_ERROR("xtopt excmlevel requires hipriints\n"); + command_print(CMD, "xtopt excmlevel requires hipriints\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->core_config->high_irq.excm_level = opt_val; @@ -3605,7 +3605,7 @@ COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa) return ERROR_COMMAND_ARGUMENT_INVALID; } if (!xtensa->core_config->high_irq.enabled) { - LOG_ERROR("xtopt intlevels requires hipriints\n"); + command_print(CMD, "xtopt intlevels requires hipriints\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->core_config->high_irq.level_num = opt_val; @@ -3662,10 +3662,8 @@ COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa) int mem_access = 0; bool is_dcache = false; - if (CMD_ARGC == 0) { - LOG_ERROR("xtmem [parameters]\n"); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } const char *mem_name = CMD_ARGV[0]; if (strcasecmp(mem_name, "icache") == 0) { @@ -3696,25 +3694,21 @@ COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa) memp = &xtensa->core_config->srom; mem_access = XT_MEM_ACCESS_READ; } else { - LOG_ERROR("xtmem types: \n"); + command_print(CMD, "xtmem types: \n"); return ERROR_COMMAND_ARGUMENT_INVALID; } if (cachep) { - if ((CMD_ARGC != 4) && (CMD_ARGC != 5)) { - LOG_ERROR("xtmem [writeback]\n"); + if (CMD_ARGC != 4 && CMD_ARGC != 5) return ERROR_COMMAND_SYNTAX_ERROR; - } cachep->line_size = strtoul(CMD_ARGV[1], NULL, 0); cachep->size = strtoul(CMD_ARGV[2], NULL, 0); cachep->way_count = strtoul(CMD_ARGV[3], NULL, 0); cachep->writeback = ((CMD_ARGC == 5) && is_dcache) ? strtoul(CMD_ARGV[4], NULL, 0) : 0; } else if (memp) { - if (CMD_ARGC != 3) { - LOG_ERROR("xtmem \n"); + if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; - } struct xtensa_local_mem_region_config *memcfgp = &memp->regions[memp->count]; memcfgp->base = strtoul(CMD_ARGV[1], NULL, 0); memcfgp->size = strtoul(CMD_ARGV[2], NULL, 0); @@ -3734,10 +3728,8 @@ COMMAND_HANDLER(xtensa_cmd_xtmem) /* xtmpu */ COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa) { - if (CMD_ARGC != 4) { - LOG_ERROR("xtmpu \n"); + if (CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; - } unsigned int nfgseg = strtoul(CMD_ARGV[0], NULL, 0); unsigned int minsegsize = strtoul(CMD_ARGV[1], NULL, 0); @@ -3745,16 +3737,16 @@ COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa) unsigned int execonly = strtoul(CMD_ARGV[3], NULL, 0); if ((nfgseg > 32)) { - LOG_ERROR(" must be within [0..32]\n"); + command_print(CMD, " must be within [0..32]\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if (minsegsize & (minsegsize - 1)) { - LOG_ERROR(" must be a power of 2 >= 32\n"); + command_print(CMD, " must be a power of 2 >= 32\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if (lockable > 1) { - LOG_ERROR(" must be 0 or 1\n"); + command_print(CMD, " must be 0 or 1\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if (execonly > 1) { - LOG_ERROR(" must be 0 or 1\n"); + command_print(CMD, " must be 0 or 1\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -3775,18 +3767,16 @@ COMMAND_HANDLER(xtensa_cmd_xtmpu) /* xtmmu */ COMMAND_HELPER(xtensa_cmd_xtmmu_do, struct xtensa *xtensa) { - if (CMD_ARGC != 2) { - LOG_ERROR("xtmmu \n"); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } unsigned int nirefillentries = strtoul(CMD_ARGV[0], NULL, 0); unsigned int ndrefillentries = strtoul(CMD_ARGV[1], NULL, 0); if ((nirefillentries != 16) && (nirefillentries != 32)) { - LOG_ERROR(" must be 16 or 32\n"); + command_print(CMD, " must be 16 or 32\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if ((ndrefillentries != 16) && (ndrefillentries != 32)) { - LOG_ERROR(" must be 16 or 32\n"); + command_print(CMD, " must be 16 or 32\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -3809,13 +3799,13 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) if (CMD_ARGC == 1) { int32_t numregs = strtoul(CMD_ARGV[0], NULL, 0); if ((numregs <= 0) || (numregs > UINT16_MAX)) { - LOG_ERROR("xtreg : Invalid 'numregs' (%d)", numregs); - return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "xtreg : Invalid 'numregs' (%d)", numregs); + return ERROR_COMMAND_ARGUMENT_INVALID; } if ((xtensa->genpkt_regs_num > 0) && (numregs < (int32_t)xtensa->genpkt_regs_num)) { - LOG_ERROR("xtregs (%d) must be larger than numgenregs (%d) (if xtregfmt specified)", + command_print(CMD, "xtregs (%d) must be larger than numgenregs (%d) (if xtregfmt specified)", numregs, xtensa->genpkt_regs_num); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->total_regs_num = numregs; xtensa->core_regs_num = 0; @@ -3844,17 +3834,17 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) const char *regname = CMD_ARGV[0]; unsigned int regnum = strtoul(CMD_ARGV[1], NULL, 0); if (regnum > UINT16_MAX) { - LOG_ERROR(" must be a 16-bit number"); + command_print(CMD, " must be a 16-bit number"); return ERROR_COMMAND_ARGUMENT_INVALID; } if ((xtensa->num_optregs + xtensa->core_regs_num) >= xtensa->total_regs_num) { if (xtensa->total_regs_num) - LOG_ERROR("'xtreg %s 0x%04x': Too many registers (%d expected, %d core %d extended)", + command_print(CMD, "'xtreg %s 0x%04x': Too many registers (%d expected, %d core %d extended)", regname, regnum, xtensa->total_regs_num, xtensa->core_regs_num, xtensa->num_optregs); else - LOG_ERROR("'xtreg %s 0x%04x': Number of registers unspecified", + command_print(CMD, "'xtreg %s 0x%04x': Number of registers unspecified", regname, regnum); return ERROR_FAIL; } @@ -3934,7 +3924,7 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) idx = XT_NX_REG_IDX_MESRCLR; if (idx < XT_NX_REG_IDX_NUM) { if (xtensa->nx_reg_idx[idx] != 0) { - LOG_ERROR("nx_reg_idx[%d] previously set to %d", + command_print(CMD, "nx_reg_idx[%d] previously set to %d", idx, xtensa->nx_reg_idx[idx]); return ERROR_FAIL; } @@ -3981,9 +3971,9 @@ COMMAND_HELPER(xtensa_cmd_xtregfmt_do, struct xtensa *xtensa) if ((numgregs <= 0) || ((numgregs > xtensa->total_regs_num) && (xtensa->total_regs_num > 0))) { - LOG_ERROR("xtregfmt: if specified, numgregs (%d) must be <= numregs (%d)", + command_print(CMD, "xtregfmt: if specified, numgregs (%d) must be <= numregs (%d)", numgregs, xtensa->total_regs_num); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->genpkt_regs_num = numgregs; } @@ -4099,7 +4089,7 @@ COMMAND_HELPER(xtensa_cmd_perfmon_dump_do, struct xtensa *xtensa) "%-12" PRIu64 "%s", result.value, result.overflow ? " (overflow)" : ""); - LOG_INFO("%s", result_buf); + command_print(CMD, "%s", result_buf); } return ERROR_OK; @@ -4349,21 +4339,21 @@ COMMAND_HELPER(xtensa_cmd_tracedump_do, struct xtensa *xtensa, const char *fname } memsz = trace_config.memaddr_end - trace_config.memaddr_start + 1; - LOG_INFO("Total trace memory: %d words", memsz); + command_print(CMD, "Total trace memory: %d words", memsz); if ((trace_config.addr & ((TRAXADDR_TWRAP_MASK << TRAXADDR_TWRAP_SHIFT) | TRAXADDR_TWSAT)) == 0) { /*Memory hasn't overwritten itself yet. */ wmem = trace_config.addr & TRAXADDR_TADDR_MASK; - LOG_INFO("...but trace is only %d words", wmem); + command_print(CMD, "...but trace is only %d words", wmem); if (wmem < memsz) memsz = wmem; } else { if (trace_config.addr & TRAXADDR_TWSAT) { - LOG_INFO("Real trace is many times longer than that (overflow)"); + command_print(CMD, "Real trace is many times longer than that (overflow)"); } else { uint32_t trc_sz = (trace_config.addr >> TRAXADDR_TWRAP_SHIFT) & TRAXADDR_TWRAP_MASK; trc_sz = (trc_sz * memsz) + (trace_config.addr & TRAXADDR_TADDR_MASK); - LOG_INFO("Real trace is %d words, but the start has been truncated.", trc_sz); + command_print(CMD, "Real trace is %d words, but the start has been truncated.", trc_sz); } } -- cgit v1.1 From 67675323e1ea09b5d1a4250bf58163103c85b844 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Thu, 11 Jan 2024 14:02:28 +0300 Subject: target: pass target to observers via const pointer There are quite a lot of "getters" in target interface. They do not change target structure, nevertheless the structure is passed to these functions via a plain pointer. The intention is to clarify the purpouse of these functions by passing the `target` structure as a pointer to constant data. Change-Id: Ida4a798da94938753b86a293a308d93b091d1bf3 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8092 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 10 +++++----- src/target/target.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/target') diff --git a/src/target/target.c b/src/target/target.c index 920511e..a411270 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -244,7 +244,7 @@ static const struct nvp nvp_reset_modes[] = { { .name = NULL, .value = -1 }, }; -const char *debug_reason_name(struct target *t) +const char *debug_reason_name(const struct target *t) { const char *cp; @@ -257,7 +257,7 @@ const char *debug_reason_name(struct target *t) return cp; } -const char *target_state_name(struct target *t) +const char *target_state_name(const struct target *t) { const char *cp; cp = nvp_value2name(nvp_target_state, t->state)->name; @@ -733,7 +733,7 @@ int target_examine(void) return retval; } -const char *target_type_name(struct target *target) +const char *target_type_name(const struct target *target) { return target->type->name; } @@ -1398,7 +1398,7 @@ int target_get_gdb_reg_list_noread(struct target *target, return target_get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } -bool target_supports_gdb_connection(struct target *target) +bool target_supports_gdb_connection(const struct target *target) { /* * exclude all the targets that don't provide get_gdb_reg_list @@ -4851,7 +4851,7 @@ static int target_jim_set_reg(Jim_Interp *interp, int argc, /** * Returns true only if the target has a handler for the specified event. */ -bool target_has_event_action(struct target *target, enum target_event event) +bool target_has_event_action(const struct target *target, enum target_event event) { struct target_event_action *teap; diff --git a/src/target/target.h b/src/target/target.h index f69ee77..bd01f5e 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -222,19 +222,19 @@ struct gdb_fileio_info { }; /** Returns a description of the endianness for the specified target. */ -static inline const char *target_endianness(struct target *target) +static inline const char *target_endianness(const struct target *target) { return (target->endianness == TARGET_ENDIAN_UNKNOWN) ? "unknown" : (target->endianness == TARGET_BIG_ENDIAN) ? "big endian" : "little endian"; } /** Returns the instance-specific name of the specified target. */ -static inline const char *target_name(struct target *target) +static inline const char *target_name(const struct target *target) { return target->cmd_name; } -const char *debug_reason_name(struct target *t); +const char *debug_reason_name(const struct target *t); enum target_event { @@ -301,7 +301,7 @@ struct target_event_action { struct target_event_action *next; }; -bool target_has_event_action(struct target *target, enum target_event event); +bool target_has_event_action(const struct target *target, enum target_event event); struct target_event_callback { int (*callback)(struct target *target, enum target_event event, void *priv); @@ -421,7 +421,7 @@ struct target *get_target(const char *id); * This routine is a wrapper for the target->type->name field. * Note that this is not an instance-specific name for his target. */ -const char *target_type_name(struct target *target); +const char *target_type_name(const struct target *target); /** * Examine the specified @a target, letting it perform any @@ -432,7 +432,7 @@ const char *target_type_name(struct target *target); int target_examine_one(struct target *target); /** @returns @c true if target_set_examined() has been called. */ -static inline bool target_was_examined(struct target *target) +static inline bool target_was_examined(const struct target *target) { return target->examined; } @@ -527,7 +527,7 @@ int target_get_gdb_reg_list_noread(struct target *target, * * Some target do not implement the necessary code required by GDB. */ -bool target_supports_gdb_connection(struct target *target); +bool target_supports_gdb_connection(const struct target *target); /** * Step the target. @@ -694,7 +694,7 @@ unsigned target_address_bits(struct target *target); unsigned int target_data_bits(struct target *target); /** Return the *name* of this targets current state */ -const char *target_state_name(struct target *target); +const char *target_state_name(const struct target *target); /** Return the *name* of a target event enumeration value */ const char *target_event_name(enum target_event event); -- cgit v1.1 From 1b0ffa97ea90c09e96b068450644e462102c10ae Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 12 Jan 2024 16:29:32 +0300 Subject: target: get_gdb_arch() accepts target via const pointer The function in question does not need to change target state. It is a target-type-dependant function, however, IMHO, it is safe to assume that any target type would not need to change type-independant state of a target to figure out the arch. Change-Id: I607cb3aee6529cd5a97bc1200a0226cf6ef43caf Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8093 Tested-by: jenkins Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo --- src/target/arm.h | 6 +++--- src/target/armv4_5.c | 2 +- src/target/armv8.c | 2 +- src/target/esirisc.c | 2 +- src/target/esirisc.h | 2 +- src/target/mem_ap.c | 2 +- src/target/riscv/riscv.c | 2 +- src/target/stm8.c | 2 +- src/target/target.c | 2 +- src/target/target.h | 2 +- src/target/target_type.h | 2 +- src/target/xtensa/xtensa.c | 2 +- src/target/xtensa/xtensa.h | 2 +- 13 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/target') diff --git a/src/target/arm.h b/src/target/arm.h index d5053af..486666b 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -257,7 +257,7 @@ struct arm { }; /** Convert target handle to generic ARM target state handle. */ -static inline struct arm *target_to_arm(struct target *target) +static inline struct arm *target_to_arm(const struct target *target) { assert(target); return target->arch_info; @@ -293,11 +293,11 @@ extern const struct command_registration arm_command_handlers[]; extern const struct command_registration arm_all_profiles_command_handlers[]; int arm_arch_state(struct target *target); -const char *arm_get_gdb_arch(struct target *target); +const char *arm_get_gdb_arch(const struct target *target); int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); -const char *armv8_get_gdb_arch(struct target *target); +const char *armv8_get_gdb_arch(const struct target *target); int armv8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 7debb94..1886d5e 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1264,7 +1264,7 @@ const struct command_registration arm_command_handlers[] = { * same way as a gdb for arm. This can be changed later on. User can still * set the specific architecture variant with the gdb command. */ -const char *arm_get_gdb_arch(struct target *target) +const char *arm_get_gdb_arch(const struct target *target) { return "arm"; } diff --git a/src/target/armv8.c b/src/target/armv8.c index daf1ffc..bf582ff 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1865,7 +1865,7 @@ const struct command_registration armv8_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -const char *armv8_get_gdb_arch(struct target *target) +const char *armv8_get_gdb_arch(const struct target *target) { struct arm *arm = target_to_arm(target); return arm->core_state == ARM_STATE_AARCH64 ? "aarch64" : "arm"; diff --git a/src/target/esirisc.c b/src/target/esirisc.c index 561edb2..c9ac1d6 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -1248,7 +1248,7 @@ static int esirisc_arch_state(struct target *target) return ERROR_OK; } -static const char *esirisc_get_gdb_arch(struct target *target) +static const char *esirisc_get_gdb_arch(const struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); diff --git a/src/target/esirisc.h b/src/target/esirisc.h index 7496b1e..6f8cd14 100644 --- a/src/target/esirisc.h +++ b/src/target/esirisc.h @@ -106,7 +106,7 @@ struct esirisc_reg { int (*write)(struct reg *reg); }; -static inline struct esirisc_common *target_to_esirisc(struct target *target) +static inline struct esirisc_common *target_to_esirisc(const struct target *target) { return (struct esirisc_common *)target->arch_info; } diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 50dc91c..5c81e3a 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -182,7 +182,7 @@ static struct reg_arch_type mem_ap_reg_arch_type = { .set = mem_ap_reg_set, }; -static const char *mem_ap_get_gdb_arch(struct target *target) +static const char *mem_ap_get_gdb_arch(const struct target *target) { return "arm"; } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index cb8d04f..d895ca3 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1744,7 +1744,7 @@ static int riscv_write_memory(struct target *target, target_addr_t address, return tt->write_memory(target, address, size, count, buffer); } -static const char *riscv_get_gdb_arch(struct target *target) +static const char *riscv_get_gdb_arch(const struct target *target) { switch (riscv_xlen(target)) { case 32: diff --git a/src/target/stm8.c b/src/target/stm8.c index ad4a452..227101b 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -1158,7 +1158,7 @@ static int stm8_write_core_reg(struct target *target, unsigned int num) return ERROR_OK; } -static const char *stm8_get_gdb_arch(struct target *target) +static const char *stm8_get_gdb_arch(const struct target *target) { return "stm8"; } diff --git a/src/target/target.c b/src/target/target.c index a411270..45698a6 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1358,7 +1358,7 @@ int target_hit_watchpoint(struct target *target, return target->type->hit_watchpoint(target, hit_watchpoint); } -const char *target_get_gdb_arch(struct target *target) +const char *target_get_gdb_arch(const struct target *target) { if (!target->type->get_gdb_arch) return NULL; diff --git a/src/target/target.h b/src/target/target.h index bd01f5e..1713448 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -501,7 +501,7 @@ int target_hit_watchpoint(struct target *target, * * This routine is a wrapper for target->type->get_gdb_arch. */ -const char *target_get_gdb_arch(struct target *target); +const char *target_get_gdb_arch(const struct target *target); /** * Obtain the registers for GDB. diff --git a/src/target/target_type.h b/src/target/target_type.h index 678ce0f..bc42c2d 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -83,7 +83,7 @@ struct target_type { * if dynamic allocation is used for this value, it must be managed by * the target, ideally by caching the result for subsequent calls. */ - const char *(*get_gdb_arch)(struct target *target); + const char *(*get_gdb_arch)(const struct target *target); /** * Target register access for GDB. Do @b not call this function diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index b516c17..fb7748a 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3442,7 +3442,7 @@ void xtensa_target_deinit(struct target *target) free(xtensa->core_config); } -const char *xtensa_get_gdb_arch(struct target *target) +const char *xtensa_get_gdb_arch(const struct target *target) { return "xtensa"; } diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index f799208..a220021 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -422,7 +422,7 @@ int xtensa_run_algorithm(struct target *target, target_addr_t entry_point, target_addr_t exit_point, unsigned int timeout_ms, void *arch_info); void xtensa_set_permissive_mode(struct target *target, bool state); -const char *xtensa_get_gdb_arch(struct target *target); +const char *xtensa_get_gdb_arch(const struct target *target); int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p); COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa); -- cgit v1.1 From 9659a9b5e28dc615dfb508d301fdd8fa426c191b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jan 2024 17:51:41 +0100 Subject: target/esirisc: free memory at OpenOCD exit The target esirisc does not free the allocated memory resources, causing memory leaks at OpenOCD exit. Add esirisc_free_reg_cache() and esirisc_deinit_target() and use them to free all the allocated resources. Change-Id: I17b8ebff54906fa25a37f2d96c01d010a98cffbd Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8094 Tested-by: jenkins Reviewed-by: Steven Stallion --- src/target/esirisc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src/target') diff --git a/src/target/esirisc.c b/src/target/esirisc.c index c9ac1d6..0f76b59 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -1486,6 +1486,32 @@ static struct reg_cache *esirisc_build_reg_cache(struct target *target) return cache; } +static void esirisc_free_reg_cache(struct target *target) +{ + struct esirisc_common *esirisc = target_to_esirisc(target); + struct reg_cache *cache = esirisc->reg_cache; + struct reg *reg_list = cache->reg_list; + + for (int i = 0; i < esirisc->num_regs; ++i) { + struct reg *reg = reg_list + esirisc_regs[i].number; + + free(reg->arch_info); + free(reg->value); + free(reg->reg_data_type); + } + + for (size_t i = 0; i < ARRAY_SIZE(esirisc_csrs); ++i) { + struct reg *reg = reg_list + esirisc_csrs[i].number; + + free(reg->arch_info); + free(reg->value); + free(reg->reg_data_type); + } + + free(reg_list); + free(cache); +} + static int esirisc_identify(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); @@ -1584,6 +1610,19 @@ static int esirisc_init_target(struct command_context *cmd_ctx, struct target *t return ERROR_OK; } +static void esirisc_deinit_target(struct target *target) +{ + struct esirisc_common *esirisc = target_to_esirisc(target); + + if (!target_was_examined(target)) + return; + + esirisc_free_reg_cache(target); + + free(esirisc->gdb_arch); + free(esirisc); +} + static int esirisc_examine(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); @@ -1822,5 +1861,6 @@ struct target_type esirisc_target = { .target_create = esirisc_target_create, .init_target = esirisc_init_target, + .deinit_target = esirisc_deinit_target, .examine = esirisc_examine, }; -- cgit v1.1