From a01b079440f5ec7880fd072a40f04be0b80acccf Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 16:16:51 +0100 Subject: [PATCH 01/18] rtos/hwthread: add hardware-thread pseudo rtos This patch adds "hwthread", a pseudo rtos that represents cpu cores in an SMP system as threads to gdb. This allows to debug SMP system kernels in a more sensible manner and removes the current atrocities of switching gdb manually between CPU cores to update the context. Change-Id: Ib781c6c34097689d21d9e02011e4d74a4a742379 Signed-off-by: Matthias Welwarsky Source: http://openocd.zylin.com/#/c/3999 --- doc/openocd.texi | 118 +++++++------ src/rtos/Makefile.am | 1 + src/rtos/hwthread.c | 394 +++++++++++++++++++++++++++++++++++++++++++ src/rtos/rtos.c | 2 + 4 files changed, 464 insertions(+), 51 deletions(-) create mode 100644 src/rtos/hwthread.c diff --git a/doc/openocd.texi b/doc/openocd.texi index 59923204a..d79664fe9 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9858,55 +9858,6 @@ and GDB would require stopping the target to get the prompt back. Do not use this mode under an IDE like Eclipse as it caches values of previously shown varibles. -@anchor{usingopenocdsmpwithgdb} -@section Using OpenOCD SMP with GDB -@cindex SMP -For SMP support following GDB serial protocol packet have been defined : -@itemize @bullet -@item j - smp status request -@item J - smp set request -@end itemize - -OpenOCD implements : -@itemize @bullet -@item @option{jc} packet for reading core id displayed by -GDB connection. Reply is @option{XXXXXXXX} (8 hex digits giving core id) or - @option{E01} for target not smp. -@item @option{JcXXXXXXXX} (8 hex digits) packet for setting core id displayed at next GDB continue -(core id -1 is reserved for returning to normal resume mode). Reply @option{E01} -for target not smp or @option{OK} on success. -@end itemize - -Handling of this packet within GDB can be done : -@itemize @bullet -@item by the creation of an internal variable (i.e @option{_core}) by mean -of function allocate_computed_value allowing following GDB command. -@example -set $_core 1 -#Jc01 packet is sent -print $_core -#jc packet is sent and result is affected in $ -@end example - -@item by the usage of GDB maintenance command as described in following example (2 cpus in SMP with -core id 0 and 1 @pxref{definecputargetsworkinginsmp,,Define CPU targets working in SMP}). - -@example -# toggle0 : force display of coreid 0 -define toggle0 -maint packet Jc0 -continue -main packet Jc-1 -end -# toggle1 : force display of coreid 1 -define toggle1 -maint packet Jc1 -continue -main packet Jc-1 -end -@end example -@end itemize - @section RTOS Support @cindex RTOS Support @anchor{gdbrtossupport} @@ -9937,12 +9888,11 @@ Currently supported rtos's include: @item @option{mqx} @item @option{uCOS-III} @item @option{nuttx} +@item @option{hwthread} (This is not an actual RTOS. @xref{usingopenocdsmpwithgdb,,Using OpenOCD SMP with GDB}.) @end itemize -@quotation Note Before an RTOS can be detected, it must export certain symbols; otherwise, it cannot be used by OpenOCD. Below is a list of the required symbols for each supported RTOS. -@end quotation @table @code @item eCos symbols @@ -9989,6 +9939,72 @@ contrib/rtos-helpers/FreeRTOS-openocd.c contrib/rtos-helpers/uCOS-III-openocd.c @end table +@anchor{usingopenocdsmpwithgdb} +@section Using OpenOCD SMP with GDB +@cindex SMP +@cindex RTOS +@cindex hwthread +OpenOCD includes a pseudo RTOS called @emph{hwthread} that presents CPU cores +("hardware threads") in an SMP system as threads to GDB. With this extension, +GDB can be used to inspect the state of an SMP system in a natural way. +After halting the system, using the GDB command @command{info threads} will +list the context of each active CPU core in the system. GDB's @command{thread} +command can be used to switch the view to a different CPU core. +The @command{step} and @command{stepi} commands can be used to step a specific core +while other cores are free-running or remain halted, depending on the +scheduler-locking mode configured in GDB. + +@section Legacy SMP core switching support +@quotation Note +This method is deprecated in favor of the @emph{hwthread} pseudo RTOS. +@end quotation + +For SMP support following GDB serial protocol packet have been defined : +@itemize @bullet +@item j - smp status request +@item J - smp set request +@end itemize + +OpenOCD implements : +@itemize @bullet +@item @option{jc} packet for reading core id displayed by +GDB connection. Reply is @option{XXXXXXXX} (8 hex digits giving core id) or + @option{E01} for target not smp. +@item @option{JcXXXXXXXX} (8 hex digits) packet for setting core id displayed at next GDB continue +(core id -1 is reserved for returning to normal resume mode). Reply @option{E01} +for target not smp or @option{OK} on success. +@end itemize + +Handling of this packet within GDB can be done : +@itemize @bullet +@item by the creation of an internal variable (i.e @option{_core}) by mean +of function allocate_computed_value allowing following GDB command. +@example +set $_core 1 +#Jc01 packet is sent +print $_core +#jc packet is sent and result is affected in $ +@end example + +@item by the usage of GDB maintenance command as described in following example (2 cpus in SMP with +core id 0 and 1 @pxref{definecputargetsworkinginsmp,,Define CPU targets working in SMP}). + +@example +# toggle0 : force display of coreid 0 +define toggle0 +maint packet Jc0 +continue +main packet Jc-1 +end +# toggle1 : force display of coreid 1 +define toggle1 +maint packet Jc1 +continue +main packet Jc-1 +end +@end example +@end itemize + @node Tcl Scripting API @chapter Tcl Scripting API @cindex Tcl Scripting API diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index 6f14b427a..5e188540f 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -17,6 +17,7 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/riscv_debug.c \ %D%/uCOS-III.c \ %D%/nuttx.c \ + %D%/hwthread.c \ %D%/rtos.h \ %D%/rtos_standard_stackings.h \ %D%/rtos_ecos_stackings.h \ diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c new file mode 100644 index 000000000..a1134c89c --- /dev/null +++ b/src/rtos/hwthread.c @@ -0,0 +1,394 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "target/target.h" +#include "target/target_type.h" +#include "target/register.h" +#include "rtos.h" +#include "helper/log.h" +#include "helper/types.h" +#include "server/gdb_server.h" + +static bool hwthread_detect_rtos(struct target *target); +static int hwthread_create(struct target *target); +static int hwthread_update_threads(struct rtos *rtos); +static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); +static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); +static int hwthread_smp_init(struct target *target); + +#define HW_THREAD_NAME_STR_SIZE (32) + +extern int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size); + +static inline threadid_t threadid_from_target(const struct target *target) +{ + return target->coreid + 1; +} + +const struct rtos_type hwthread_rtos = { + .name = "hwthread", + .detect_rtos = hwthread_detect_rtos, + .create = hwthread_create, + .update_threads = hwthread_update_threads, + .get_thread_reg_list = hwthread_get_thread_reg_list, + .get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup, + .smp_init = hwthread_smp_init, +}; + +struct hwthread_params { + int dummy_param; +}; + +static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num) +{ + char tmp_str[HW_THREAD_NAME_STR_SIZE]; + threadid_t tid = threadid_from_target(curr); + + memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE); + + /* thread-id is the core-id of this core inside the SMP group plus 1 */ + rtos->thread_details[thread_num].threadid = tid; + /* create the thread name */ + rtos->thread_details[thread_num].exists = true; + rtos->thread_details[thread_num].thread_name_str = strdup(target_name(curr)); + snprintf(tmp_str, HW_THREAD_NAME_STR_SIZE-1, "state: %s", debug_reason_name(curr)); + rtos->thread_details[thread_num].extra_info_str = strdup(tmp_str); + + return ERROR_OK; +} + +static int hwthread_update_threads(struct rtos *rtos) +{ + int threads_found = 0; + int thread_list_size = 0; + struct target_list *head; + struct target *target; + int64_t current_thread = 0; + enum target_debug_reason current_reason = DBG_REASON_UNDEFINED; + + if (rtos == NULL) + return -1; + + target = rtos->target; + + /* wipe out previous thread details if any */ + rtos_free_threadlist(rtos); + + /* determine the number of "threads" */ + if (target->smp) { + for (head = target->head; head != NULL; head = head->next) { + struct target *curr = head->target; + + if (!target_was_examined(curr)) + continue; + + ++thread_list_size; + } + } else + thread_list_size = 1; + + /* create space for new thread details */ + rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size); + + if (target->smp) { + /* loop over all threads */ + for (head = target->head; head != NULL; head = head->next) { + struct target *curr = head->target; + + if (!target_was_examined(curr)) + continue; + + threadid_t tid = threadid_from_target(curr); + + hwthread_fill_thread(rtos, curr, threads_found); + + /* find an interesting thread to set as current */ + switch (current_reason) { + case DBG_REASON_UNDEFINED: + current_reason = curr->debug_reason; + current_thread = tid; + break; + case DBG_REASON_SINGLESTEP: + /* single-step can only be overridden by itself */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP) { + if (tid == rtos->current_threadid) + current_thread = tid; + } + break; + case DBG_REASON_BREAKPOINT: + /* single-step overrides breakpoint */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP) { + current_reason = curr->debug_reason; + current_thread = tid; + } else + /* multiple breakpoints, prefer gdbs' threadid */ + if (curr->debug_reason == DBG_REASON_BREAKPOINT) { + if (tid == rtos->current_threadid) + current_thread = tid; + } + break; + case DBG_REASON_WATCHPOINT: + /* breakpoint and single-step override watchpoint */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP || + curr->debug_reason == DBG_REASON_BREAKPOINT) { + current_reason = curr->debug_reason; + current_thread = tid; + } + break; + case DBG_REASON_DBGRQ: + /* all other reasons override debug-request */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP || + curr->debug_reason == DBG_REASON_WATCHPOINT || + curr->debug_reason == DBG_REASON_BREAKPOINT) { + current_reason = curr->debug_reason; + current_thread = tid; + } else + if (curr->debug_reason == DBG_REASON_DBGRQ) { + if (tid == rtos->current_threadid) + current_thread = tid; + } + + break; + + default: + break; + } + + threads_found++; + } + } else { + hwthread_fill_thread(rtos, target, threads_found); + current_thread = threadid_from_target(target); + threads_found++; + } + + rtos->thread_count = threads_found; + + /* we found an interesting thread, set it as current */ + if (current_thread != 0) + rtos->current_thread = current_thread; + else if (rtos->current_threadid != 0) + rtos->current_thread = rtos->current_threadid; + else + rtos->current_thread = threadid_from_target(target); + + LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread); + return 0; +} + +static int hwthread_smp_init(struct target *target) +{ + return hwthread_update_threads(target->rtos); +} + +static inline int gdb_reg_pos(struct target *target, int pos, int len) +{ + if (target->endianness == TARGET_LITTLE_ENDIAN) + return pos; + else + return len - 1 - pos; +} + +/* Convert register to string of bytes. NB! The # of bits in the + * register might be non-divisible by 8(a byte), in which + * case an entire byte is shown. + * + * NB! the format on the wire is the target endianness + * + * The format of reg->value is little endian + * + */ +static void gdb_str_to_target(struct target *target, + char *tstr, struct reg *reg) +{ + int i; + + uint8_t *buf; + int buf_len; + buf = reg->value; + buf_len = DIV_ROUND_UP(reg->size, 8); + + for (i = 0; i < buf_len; i++) { + int j = gdb_reg_pos(target, i, buf_len); + tstr += sprintf(tstr, "%02x", buf[j]); + } +} + + +static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) +{ + struct target_list *head; + struct target *target; + struct target *curr; + struct reg **reg_list; + int reg_list_size; + int reg_packet_size = 0; + char *reg_packet; + char *reg_packet_p; + int i; + + int retval; + + *hex_reg_list = NULL; + + if (rtos == NULL) + return ERROR_FAIL; + + target = rtos->target; + + /* Find the thread with that thread_id */ + if (target->smp) { + curr = NULL; + for (head = target->head; head != NULL; head = head->next) { + curr = head->target; + + if (thread_id == threadid_from_target(curr)) + break; + } + + if (head == NULL) + return ERROR_FAIL; + } else { + curr = target; + if (thread_id != threadid_from_target(curr)) + return ERROR_FAIL; + + } + + if (!target_was_examined(curr)) + return ERROR_FAIL; + + retval = target_get_gdb_reg_list(curr, ®_list, ®_list_size, + REG_CLASS_GENERAL); + if (retval != ERROR_OK) + return retval; + + for (i = 0; i < reg_list_size; i++) + reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; + + if (reg_packet_size == 0) + return ERROR_FAIL; + + reg_packet = malloc(reg_packet_size + 1); /* plus one for string termination null */ + if (reg_packet == NULL) + return ERROR_FAIL; + + reg_packet_p = reg_packet; + + for (i = 0; i < reg_list_size; i++) { + if (!reg_list[i]->valid) + reg_list[i]->type->get(reg_list[i]); + gdb_str_to_target(target, reg_packet_p, reg_list[i]); + reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; + } + + *hex_reg_list = reg_packet; + free(reg_list); + + return ERROR_OK; + +} + +static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) +{ + /* return an empty list, we don't have any symbols to look up */ + *symbol_list = calloc(1, sizeof(symbol_table_elem_t)); + (*symbol_list)[0].symbol_name = NULL; + return 0; +} + +static int hwthread_target_for_threadid(struct connection *connection, int64_t thread_id, struct target **p_target) +{ + struct target *target = get_target_from_connection(connection); + struct target_list *head; + struct target *curr; + + if (target->smp) { + /* Find the thread with that thread_id */ + curr = NULL; + for (head = target->head; head != NULL; head = head->next) { + curr = head->target; + + if (thread_id == threadid_from_target(curr)) + break; + } + + if (head == NULL) + return ERROR_FAIL; + } else { + curr = target; + if (thread_id != threadid_from_target(curr)) + return ERROR_FAIL; + } + + *p_target = curr; + + return ERROR_OK; +} + +static bool hwthread_detect_rtos(struct target *target) +{ + /* always return 0, avoid auto-detection */ + return false; +} + +static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size) +{ + struct target *target = get_target_from_connection(connection); + + struct target *curr = NULL; + int64_t current_threadid; + + if (packet[0] == 'H' && packet[1] == 'g') { + sscanf(packet, "Hg%16" SCNx64, ¤t_threadid); + + if (current_threadid > 0) { + if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) { + LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid); + gdb_put_packet(connection, "E01", 3); + return ERROR_FAIL; + } + target->rtos->current_thread = current_threadid; + } else + if (current_threadid == 0 || current_threadid == -1) + target->rtos->current_thread = threadid_from_target(target); + + target->rtos->current_threadid = current_threadid; + + gdb_put_packet(connection, "OK", 2); + return ERROR_OK; + } + + return rtos_thread_packet(connection, packet, packet_size); +} + +static int hwthread_create(struct target *target) +{ + LOG_INFO("Hardware thread awareness created"); + + target->rtos->rtos_specific_params = NULL; + target->rtos->current_thread = 0; + target->rtos->thread_details = NULL; + target->rtos->gdb_target_for_threadid = hwthread_target_for_threadid; + target->rtos->gdb_thread_packet = hwthread_thread_packet; + return 0; +} diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 9b05ab5c4..9032f8180 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -36,6 +36,7 @@ extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; extern struct rtos_type uCOS_III_rtos; extern struct rtos_type nuttx_rtos; +extern struct rtos_type hwthread_rtos; extern struct rtos_type riscv_rtos; static struct rtos_type *rtos_types[] = { @@ -48,6 +49,7 @@ static struct rtos_type *rtos_types[] = { &mqx_rtos, &uCOS_III_rtos, &nuttx_rtos, + &hwthread_rtos, &riscv_rtos, NULL }; From 07369295127cf93af062ed48242d8267a931e771 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 3 Jan 2019 12:47:14 -0800 Subject: [PATCH 02/18] Neuter hwthread_get_thread_reg_list so it builds Change-Id: I07cf72ea1874ca7cb5557677ecb751c931174419 --- src/rtos/hwthread.c | 72 ++++----------------------------------------- 1 file changed, 6 insertions(+), 66 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index a1134c89c..8f826a7ab 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -31,7 +31,8 @@ static bool hwthread_detect_rtos(struct target *target); static int hwthread_create(struct target *target); static int hwthread_update_threads(struct rtos *rtos); -static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); +static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, + struct rtos_reg **reg_list, int *num_regs); static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); static int hwthread_smp_init(struct target *target); @@ -208,47 +209,13 @@ static inline int gdb_reg_pos(struct target *target, int pos, int len) return len - 1 - pos; } -/* Convert register to string of bytes. NB! The # of bits in the - * register might be non-divisible by 8(a byte), in which - * case an entire byte is shown. - * - * NB! the format on the wire is the target endianness - * - * The format of reg->value is little endian - * - */ -static void gdb_str_to_target(struct target *target, - char *tstr, struct reg *reg) -{ - int i; - uint8_t *buf; - int buf_len; - buf = reg->value; - buf_len = DIV_ROUND_UP(reg->size, 8); - - for (i = 0; i < buf_len; i++) { - int j = gdb_reg_pos(target, i, buf_len); - tstr += sprintf(tstr, "%02x", buf[j]); - } -} - - -static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) +static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, + struct rtos_reg **reg_list, int *num_regs) { struct target_list *head; struct target *target; struct target *curr; - struct reg **reg_list; - int reg_list_size; - int reg_packet_size = 0; - char *reg_packet; - char *reg_packet_p; - int i; - - int retval; - - *hex_reg_list = NULL; if (rtos == NULL) return ERROR_FAIL; @@ -277,35 +244,8 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, ch if (!target_was_examined(curr)) return ERROR_FAIL; - retval = target_get_gdb_reg_list(curr, ®_list, ®_list_size, - REG_CLASS_GENERAL); - if (retval != ERROR_OK) - return retval; - - for (i = 0; i < reg_list_size; i++) - reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; - - if (reg_packet_size == 0) - return ERROR_FAIL; - - reg_packet = malloc(reg_packet_size + 1); /* plus one for string termination null */ - if (reg_packet == NULL) - return ERROR_FAIL; - - reg_packet_p = reg_packet; - - for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i]->valid) - reg_list[i]->type->get(reg_list[i]); - gdb_str_to_target(target, reg_packet_p, reg_list[i]); - reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; - } - - *hex_reg_list = reg_packet; - free(reg_list); - - return ERROR_OK; - + LOG_ERROR("TODO: not implemented"); + return ERROR_FAIL; } static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) From a9d436e77fd3945643c4fb1eee4f22c310e94b26 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 3 Jan 2019 15:06:35 -0800 Subject: [PATCH 03/18] WIP make riscv work with -rtos hwthread. Change-Id: I37bb16291fa87a83f21e5fd8bad53492a4d69425 --- src/target/riscv/riscv.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 1c89e6de4..0ec204922 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -856,8 +856,28 @@ static int old_or_new_riscv_resume( int handle_breakpoints, int debug_execution ){ - RISCV_INFO(r); LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints); + if (target->smp) { + struct target_list *targets = target->head; + int result = ERROR_OK; + while (targets) { + struct target *t = targets->target; + riscv_info_t *r = riscv_info(t); + if (r->is_halted == NULL) { + if (oldriscv_resume(t, current, address, handle_breakpoints, + debug_execution) != ERROR_OK) + result = ERROR_FAIL; + } else { + if (riscv_openocd_resume(t, current, address, + handle_breakpoints, debug_execution) != ERROR_OK) + result = ERROR_FAIL; + } + targets = targets->next; + } + return result; + } + + RISCV_INFO(r); if (r->is_halted == NULL) return oldriscv_resume(target, current, address, handle_breakpoints, debug_execution); else @@ -1938,9 +1958,10 @@ int riscv_xlen_of_hart(const struct target *target, int hartid) return r->xlen[hartid]; } +extern struct rtos_type riscv_rtos; bool riscv_rtos_enabled(const struct target *target) { - return target->rtos != NULL; + return target->rtos && target->rtos->type == &riscv_rtos; } int riscv_set_current_hartid(struct target *target, int hartid) From 4bb8bd005c27c3ee7ac0ee3adb0046428e3f1868 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 7 Jan 2019 08:48:49 -0800 Subject: [PATCH 04/18] Implement hwthread_get_thread_reg_list. MulticoreRegTest now gets past the first check on all GPRs. Change-Id: I35f3c51273542668985f7a86965c1e947fc12194 --- src/rtos/hwthread.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 8f826a7ab..7050ba35b 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -211,7 +211,7 @@ static inline int gdb_reg_pos(struct target *target, int pos, int len) static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, - struct rtos_reg **reg_list, int *num_regs) + struct rtos_reg **rtos_reg_list, int *rtos_reg_list_size) { struct target_list *head; struct target *target; @@ -238,14 +238,32 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, curr = target; if (thread_id != threadid_from_target(curr)) return ERROR_FAIL; - } if (!target_was_examined(curr)) return ERROR_FAIL; - LOG_ERROR("TODO: not implemented"); - return ERROR_FAIL; + struct reg **reg_list; + int retval = target_get_gdb_reg_list(curr, ®_list, rtos_reg_list_size, + REG_CLASS_GENERAL); + if (retval != ERROR_OK) + return retval; + + *rtos_reg_list = calloc(*rtos_reg_list_size, sizeof(struct rtos_reg)); + if (*rtos_reg_list == NULL) { + free(reg_list); + return ERROR_FAIL; + } + + for (int i = 0; i < *rtos_reg_list_size; i++) { + (*rtos_reg_list)[i].number = (*reg_list)[i].number; + (*rtos_reg_list)[i].size = (*reg_list)[i].size; + memcpy((*rtos_reg_list)[i].value, (*reg_list)[i].value, + ((*reg_list)[i].size + 7) / 8); + } + free(reg_list); + + return ERROR_OK; } static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) From f9af0b6cca392116d15cb0b3f48cd7ba55420131 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 7 Jan 2019 12:15:18 -0800 Subject: [PATCH 05/18] Handler target_get_gdb_reg_list() better. That function might change from NULL reg_list but then return failure. In that case reg_list shouldn't be freed. Change-Id: I5380630c871d056fb52e25bda16836e346bd74b2 --- src/server/gdb_server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 3548f166c..b95c1ecea 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2399,6 +2399,7 @@ static int gdb_target_description_supported(struct target *target, int *supporte ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK) { LOG_ERROR("get register list failed"); + reg_list = NULL; goto error; } From 6faa9ded26d49bf7d989dfa190a2231b2159c301 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 7 Jan 2019 12:16:51 -0800 Subject: [PATCH 06/18] Clean up debug printf. I only need to see 64 bits of PC if the high bits are non-zero. Change-Id: I29397791da1e3f1705e573b2eaafc3eac202e178 --- src/target/riscv/riscv-013.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index b73410467..75224e925 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2798,7 +2798,7 @@ static int riscv013_get_register(struct target *target, int result = ERROR_OK; if (rid == GDB_REGNO_PC) { result = register_read(target, value, GDB_REGNO_DPC); - LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value); + LOG_DEBUG("read PC from DPC: 0x%" PRIx64, *value); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; result = register_read(target, &dcsr, GDB_REGNO_DCSR); @@ -2822,7 +2822,7 @@ static int riscv013_set_register(struct target *target, int hid, int rid, uint64 if (rid <= GDB_REGNO_XPR31) { return register_write_direct(target, rid, value); } else if (rid == GDB_REGNO_PC) { - LOG_DEBUG("writing PC to DPC: 0x%016" PRIx64, value); + LOG_DEBUG("writing PC to DPC: 0x%" PRIx64, value); register_write_direct(target, GDB_REGNO_DPC, value); uint64_t actual_value; register_read_direct(target, &actual_value, GDB_REGNO_DPC); From fd49f5e96778239d5c9ed172239a6857aa60cbea Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 7 Jan 2019 12:17:41 -0800 Subject: [PATCH 07/18] Make riscv_get_gdb_reg_list read the registers. This may not be the correct behavior, but it gets me further through the tests. Change-Id: I6e9b77e927700de706b6ece723f4d530fa566761 --- src/target/riscv/riscv.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 0ec204922..d786d56be 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -945,10 +945,23 @@ static int riscv_get_gdb_reg_list(struct target *target, if (!*reg_list) return ERROR_FAIL; + bool read = true; for (int i = 0; i < *reg_list_size; i++) { assert(!target->reg_cache->reg_list[i].valid || target->reg_cache->reg_list[i].size > 0); (*reg_list)[i] = &target->reg_cache->reg_list[i]; + if (read && !target->reg_cache->reg_list[i].valid) { + // TODO: Confirm that this function is supposed to actually read + // registers. I'm just adding this because maybe + // hwthread_get_thread_reg_list() expects it. + + // This function gets called from + // gdb_target_description_supported(), and we end up failing in + // that case. Allow failures for now. + if (target->reg_cache->reg_list[i].type->get( + &target->reg_cache->reg_list[i]) != ERROR_OK) + read = false; + } } return ERROR_OK; From 02ece46105ec7d5fe7144adec071ac75706234fe Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 10 Jan 2019 12:32:03 -0800 Subject: [PATCH 08/18] Clean up register caching a little. Change-Id: Id039aedac44d9c206ac4bd30eb3ef754e190c3fe --- src/target/riscv/riscv-013.c | 14 -------------- src/target/riscv/riscv.c | 34 +++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 75224e925..0d74d5cae 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1127,7 +1127,6 @@ static int register_write_direct(struct target *target, unsigned number, if (result == ERROR_OK && target->reg_cache) { struct reg *reg = &target->reg_cache->reg_list[number]; buf_set_u64(reg->value, 0, reg->size, value); - reg->valid = true; } if (result == ERROR_OK || info->progbufsize + r->impebreak < 2 || !riscv_is_halted(target)) @@ -1186,7 +1185,6 @@ static int register_write_direct(struct target *target, unsigned number, if (exec_out == ERROR_OK && target->reg_cache) { struct reg *reg = &target->reg_cache->reg_list[number]; buf_set_u64(reg->value, 0, reg->size, value); - reg->valid = true; } if (use_scratch) @@ -1206,24 +1204,12 @@ static int register_read(struct target *target, uint64_t *value, uint32_t number *value = 0; return ERROR_OK; } - if (target->reg_cache && - (number <= GDB_REGNO_XPR31 || - (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31))) { - /* Only check the cache for registers that we know won't spontaneously - * change. */ - struct reg *reg = &target->reg_cache->reg_list[number]; - if (reg && reg->valid) { - *value = buf_get_u64(reg->value, 0, reg->size); - return ERROR_OK; - } - } int result = register_read_direct(target, value, number); if (result != ERROR_OK) return ERROR_FAIL; if (target->reg_cache) { struct reg *reg = &target->reg_cache->reg_list[number]; buf_set_u64(reg->value, 0, reg->size, *value); - reg->valid = true; } return ERROR_OK; } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index d786d56be..65e019938 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1992,10 +1992,10 @@ int riscv_set_current_hartid(struct target *target, int hartid) /* This might get called during init, in which case we shouldn't be * setting up the register cache. */ - if (!target_was_examined(target)) - return ERROR_OK; + //if (target_was_examined(target) && hartid != previous_hartid) + if (target_was_examined(target) && riscv_rtos_enabled(target)) + riscv_invalidate_register_cache(target); - riscv_invalidate_register_cache(target); return ERROR_OK; } @@ -2003,6 +2003,8 @@ void riscv_invalidate_register_cache(struct target *target) { RISCV_INFO(r); + LOG_DEBUG(">>>"); + register_cache_invalidate(target->reg_cache); for (size_t i = 0; i < target->reg_cache->num_regs; ++i) { struct reg *reg = &target->reg_cache->reg_list[i]; @@ -2079,6 +2081,12 @@ int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value, if (hartid != riscv_current_hartid(target)) riscv_invalidate_register_cache(target); + struct reg *reg = &target->reg_cache->reg_list[regid]; + if (reg && reg->valid) { + *value = buf_get_u64(reg->value, 0, reg->size); + return ERROR_OK; + } + int result = r->get_register(target, value, hartid, regid); if (hartid != riscv_current_hartid(target)) @@ -2292,6 +2300,15 @@ static int register_get(struct reg *reg) if (result != ERROR_OK) return result; buf_set_u64(reg->value, 0, reg->size, value); + /* CSRs (and possibly other extension) registers may change value at any + * time. */ + if (reg->number <= GDB_REGNO_XPR31 || + (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) || + reg->number == GDB_REGNO_PC) + reg->valid = true; + LOG_DEBUG("[%d,%d] read 0x%" PRIx64 " from %s (valid=%d)", + target->coreid, riscv_current_hartid(target), value, reg->name, + reg->valid); return ERROR_OK; } @@ -2302,9 +2319,16 @@ static int register_set(struct reg *reg, uint8_t *buf) uint64_t value = buf_get_u64(buf, 0, reg->size); - LOG_DEBUG("write 0x%" PRIx64 " to %s", value, reg->name); + LOG_DEBUG("[%d,%d] write 0x%" PRIx64 " to %s (valid=%d)", + target->coreid, riscv_current_hartid(target), value, reg->name, + reg->valid); struct reg *r = &target->reg_cache->reg_list[reg->number]; - r->valid = true; + /* CSRs (and possibly other extension) registers may change value at any + * time. */ + if (reg->number <= GDB_REGNO_XPR31 || + (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) || + reg->number == GDB_REGNO_PC) + r->valid = true; memcpy(r->value, buf, (r->size + 7) / 8); riscv_set_register(target, reg->number, value); From c84d56debcc3b7263bc66234164e249b9b1ad737 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 11 Jan 2019 13:53:53 -0800 Subject: [PATCH 09/18] rtos support to write registers on current thread I don't understand how it was ever possible to change the registers on a thread that's not the current active one when a halt happened. Really instead of the RTOS tracking what the currently selected thread is, it would make more sense to have gdb_server do that and simply pass it along in every call to the RTOS layer. Now MulticoreRegTest passes. Change-Id: I399b9b2b05a147aa6b41463714ed3a39534b1fc8 --- src/rtos/hwthread.c | 96 +++++++++++++++++++++-------------------- src/rtos/rtos.c | 15 +++++++ src/rtos/rtos.h | 3 ++ src/server/gdb_server.c | 48 +++++++++++++-------- 4 files changed, 97 insertions(+), 65 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 7050ba35b..a9fc1d9d5 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -35,6 +35,7 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs); static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); static int hwthread_smp_init(struct target *target); +int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value); #define HW_THREAD_NAME_STR_SIZE (32) @@ -53,6 +54,7 @@ const struct rtos_type hwthread_rtos = { .get_thread_reg_list = hwthread_get_thread_reg_list, .get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup, .smp_init = hwthread_smp_init, + .set_reg = hwthread_set_reg, }; struct hwthread_params { @@ -201,44 +203,33 @@ static int hwthread_smp_init(struct target *target) return hwthread_update_threads(target->rtos); } -static inline int gdb_reg_pos(struct target *target, int pos, int len) +static struct target *find_thread(struct target *target, int64_t thread_id) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - return pos; - else - return len - 1 - pos; + /* Find the thread with that thread_id */ + if (target == NULL) + return NULL; + if (target->smp) { + for (struct target_list *head = target->head; head != NULL; head = head->next) { + if (thread_id == threadid_from_target(head->target)) + return head->target; + } + } else if (thread_id == threadid_from_target(target)) { + return target; + } + return NULL; } - static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **rtos_reg_list, int *rtos_reg_list_size) { - struct target_list *head; - struct target *target; - struct target *curr; - if (rtos == NULL) return ERROR_FAIL; - target = rtos->target; + struct target *target = rtos->target; - /* Find the thread with that thread_id */ - if (target->smp) { - curr = NULL; - for (head = target->head; head != NULL; head = head->next) { - curr = head->target; - - if (thread_id == threadid_from_target(curr)) - break; - } - - if (head == NULL) - return ERROR_FAIL; - } else { - curr = target; - if (thread_id != threadid_from_target(curr)) - return ERROR_FAIL; - } + struct target *curr = find_thread(target, thread_id); + if (curr == NULL) + return ERROR_FAIL; if (!target_was_examined(curr)) return ERROR_FAIL; @@ -266,6 +257,32 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, return ERROR_OK; } +int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value) +{ + if (rtos == NULL) + return ERROR_FAIL; + + struct target *target = rtos->target; + + struct target *curr = find_thread(target, rtos->current_thread); + LOG_DEBUG(">>> found %ld: %p", rtos->current_thread, curr); + if (curr == NULL) + return ERROR_FAIL; + + struct reg **reg_list; + int reg_list_size; + if (target_get_gdb_reg_list(curr, ®_list, ®_list_size, + REG_CLASS_ALL) != ERROR_OK) + return ERROR_FAIL; + + if (reg_list_size <= reg_num) { + LOG_ERROR("Register %d requested, but only %d registers exist.", + reg_num, reg_list_size); + return ERROR_FAIL; + } + return reg_list[reg_num]->type->set(reg_list[reg_num], reg_value); +} + static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { /* return an empty list, we don't have any symbols to look up */ @@ -277,26 +294,10 @@ static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[] static int hwthread_target_for_threadid(struct connection *connection, int64_t thread_id, struct target **p_target) { struct target *target = get_target_from_connection(connection); - struct target_list *head; - struct target *curr; - if (target->smp) { - /* Find the thread with that thread_id */ - curr = NULL; - for (head = target->head; head != NULL; head = head->next) { - curr = head->target; - - if (thread_id == threadid_from_target(curr)) - break; - } - - if (head == NULL) - return ERROR_FAIL; - } else { - curr = target; - if (thread_id != threadid_from_target(curr)) - return ERROR_FAIL; - } + struct target *curr = find_thread(target, thread_id); + if (curr == NULL) + return ERROR_FAIL; *p_target = curr; @@ -331,6 +332,7 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac target->rtos->current_thread = threadid_from_target(target); target->rtos->current_threadid = current_threadid; + LOG_DEBUG(">>> current_threadid=%ld", current_threadid); gdb_put_packet(connection, "OK", 2); return ERROR_OK; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 9032f8180..eb48ab8df 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -535,6 +535,21 @@ int rtos_get_gdb_reg_list(struct connection *connection) return ERROR_FAIL; } +int rtos_set_reg(struct connection *connection, int reg_num, + uint8_t *reg_value) +{ + struct target *target = get_target_from_connection(connection); + int64_t current_threadid = target->rtos->current_threadid; + LOG_DEBUG(">>> reg_num=%d", reg_num); + if ((target->rtos != NULL) && + (target->rtos->type->set_reg != NULL) && + (current_threadid != -1) && + (current_threadid != 0)) { + return target->rtos->type->set_reg(target->rtos, reg_num, reg_value); + } + return ERROR_FAIL; +} + int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 22de33fe2..8574b4a0b 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -76,6 +76,7 @@ struct rtos_type { int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]); int (*clean)(struct target *target); char * (*ps_command)(struct target *target); + int (*set_reg)(struct rtos *rtos, int reg_num, uint8_t *reg_value); }; struct stack_register_offset { @@ -105,6 +106,8 @@ struct rtos_register_stacking { #define GDB_THREAD_PACKET_NOT_CONSUMED (-40) int rtos_create(Jim_GetOptInfo *goi, struct target *target); +int rtos_set_reg(struct connection *connection, int reg_num, + uint8_t *reg_value); int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index b95c1ecea..0b4315566 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1340,37 +1340,49 @@ static int gdb_set_register_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint8_t *bin_buf; int reg_num = strtoul(packet + 1, &separator, 16); struct reg **reg_list; int reg_list_size; int retval; +#ifdef _DEBUG_GDB_IO_ LOG_DEBUG("-"); - - retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, - REG_CLASS_ALL); - if (retval != ERROR_OK) - return gdb_error(connection, retval); - - if (reg_list_size <= reg_num) { - LOG_ERROR("gdb requested a non-existing register"); - return ERROR_SERVER_REMOTE_CLOSED; - } +#endif if (*separator != '=') { LOG_ERROR("GDB 'set register packet', but no '=' following the register number"); return ERROR_SERVER_REMOTE_CLOSED; } + size_t chars = strlen(separator + 1); + uint8_t *bin_buf = malloc(chars / 2); + gdb_target_to_reg(target, separator + 1, chars, bin_buf); - /* convert from GDB-string (target-endian) to hex-string (big-endian) */ - bin_buf = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8)); - int chars = (DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2); - - if ((unsigned int)chars != strlen(separator + 1)) { - LOG_ERROR("gdb sent %zu bits for a %d-bit register (%s)", - strlen(separator + 1) * 4, chars * 4, reg_list[reg_num]->name); + if ((target->rtos != NULL) && + (ERROR_OK == rtos_set_reg(connection, reg_num, bin_buf))) { free(bin_buf); + gdb_put_packet(connection, "OK", 2); + return ERROR_OK; + } + + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, + REG_CLASS_ALL); + if (retval != ERROR_OK) { + free(bin_buf); + return gdb_error(connection, retval); + } + + if (reg_list_size <= reg_num) { + LOG_ERROR("gdb requested a non-existing register"); + free(bin_buf); + free(reg_list); + return ERROR_SERVER_REMOTE_CLOSED; + } + + if (chars != (DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2)) { + LOG_ERROR("gdb sent %d bits for a %d-bit register (%s)", + (int) chars * 4, reg_list[reg_num]->size, reg_list[reg_num]->name); + free(bin_buf); + free(reg_list); return ERROR_SERVER_REMOTE_CLOSED; } From c1ef5f61c3b9b59e1a410badb90e485a98cdedb4 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 17 Jan 2019 12:46:20 -0800 Subject: [PATCH 10/18] Fix reading of non-general registers for hwthread Previously the code made the assumption (which is valid for conventional RTOSs) that special registers (e.g. CSRs) are the same across threads. 26/45 tests pass. Change-Id: Ibb3398790d7354a995d506772375d869f608f1f0 --- src/rtos/hwthread.c | 39 ++++++++++++++++++++++++++++++++++++--- src/rtos/rtos.c | 20 +++++++++++++++----- src/rtos/rtos.h | 5 +++++ src/server/gdb_server.c | 2 +- src/target/register.c | 23 +++++++++++++++++++++++ src/target/register.h | 2 ++ src/target/riscv/riscv.c | 18 +++++++++++++++++- src/target/target.c | 5 +++-- 8 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index a9fc1d9d5..da5d2eb0c 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -31,6 +31,8 @@ static bool hwthread_detect_rtos(struct target *target); static int hwthread_create(struct target *target); static int hwthread_update_threads(struct rtos *rtos); +static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, + uint32_t reg_num, struct rtos_reg *rtos_reg); static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs); static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); @@ -52,6 +54,7 @@ const struct rtos_type hwthread_rtos = { .create = hwthread_create, .update_threads = hwthread_update_threads, .get_thread_reg_list = hwthread_get_thread_reg_list, + .get_thread_reg = hwthread_get_thread_reg, .get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup, .smp_init = hwthread_smp_init, .set_reg = hwthread_set_reg, @@ -257,6 +260,38 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, return ERROR_OK; } +static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, + uint32_t reg_num, struct rtos_reg *rtos_reg) +{ + LOG_DEBUG(">>> thread %ld, reg %d", thread_id, reg_num); + if (rtos == NULL) + return ERROR_FAIL; + + struct target *target = rtos->target; + + struct target *curr = find_thread(target, thread_id); + if (curr == NULL) + return ERROR_FAIL; + + if (!target_was_examined(curr)) + return ERROR_FAIL; + + struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true); + if (!reg) + return ERROR_FAIL; + + if (reg->type->get(reg) != ERROR_OK) + return ERROR_FAIL; + + rtos_reg->number = reg->number; + rtos_reg->size = reg->size; + unsigned bytes = (reg->size + 7) / 8; + assert(bytes <= sizeof(rtos_reg->value)); + memcpy(rtos_reg->value, reg->value, bytes); + + return ERROR_OK; +} + int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value) { if (rtos == NULL) @@ -265,14 +300,13 @@ int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value) struct target *target = rtos->target; struct target *curr = find_thread(target, rtos->current_thread); - LOG_DEBUG(">>> found %ld: %p", rtos->current_thread, curr); if (curr == NULL) return ERROR_FAIL; struct reg **reg_list; int reg_list_size; if (target_get_gdb_reg_list(curr, ®_list, ®_list_size, - REG_CLASS_ALL) != ERROR_OK) + REG_CLASS_GENERAL) != ERROR_OK) return ERROR_FAIL; if (reg_list_size <= reg_num) { @@ -332,7 +366,6 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac target->rtos->current_thread = threadid_from_target(target); target->rtos->current_threadid = current_threadid; - LOG_DEBUG(">>> current_threadid=%ld", current_threadid); gdb_put_packet(connection, "OK", 2); return ERROR_OK; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index eb48ab8df..549600870 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -463,6 +463,7 @@ static int rtos_put_gdb_reg_list(struct connection *connection, return ERROR_OK; } +/** Look through all registers to find this register. */ int rtos_get_gdb_reg(struct connection *connection, int reg_num) { struct target *target = get_target_from_connection(connection); @@ -480,10 +481,18 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num) current_threadid, target->rtos->current_thread); - int retval = target->rtos->type->get_thread_reg_list(target->rtos, - current_threadid, - ®_list, - &num_regs); + int retval; + if (target->rtos->type->get_thread_reg) { + reg_list = calloc(1, sizeof(*reg_list)); + num_regs = 1; + retval = target->rtos->type->get_thread_reg(target->rtos, + current_threadid, reg_num, ®_list[0]); + } else { + retval = target->rtos->type->get_thread_reg_list(target->rtos, + current_threadid, + ®_list, + &num_regs); + } if (retval != ERROR_OK) { LOG_ERROR("RTOS: failed to get register list"); return retval; @@ -502,6 +511,7 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num) return ERROR_FAIL; } +/** Return a list of general registers. */ int rtos_get_gdb_reg_list(struct connection *connection) { struct target *target = get_target_from_connection(connection); @@ -540,7 +550,7 @@ int rtos_set_reg(struct connection *connection, int reg_num, { struct target *target = get_target_from_connection(connection); int64_t current_threadid = target->rtos->current_threadid; - LOG_DEBUG(">>> reg_num=%d", reg_num); + LOG_DEBUG(">>> thread %ld, reg %d", current_threadid, reg_num); if ((target->rtos != NULL) && (target->rtos->type->set_reg != NULL) && (current_threadid != -1) && diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 8574b4a0b..e5a7e13fa 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -20,6 +20,7 @@ #define OPENOCD_RTOS_RTOS_H #include "server/server.h" +#include "target/target.h" #include typedef int64_t threadid_t; @@ -71,11 +72,15 @@ struct rtos_type { int (*create)(struct target *target); int (*smp_init)(struct target *target); int (*update_threads)(struct rtos *rtos); + /** Return a list of general registers, with their values filled out. */ int (*get_thread_reg_list)(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs); + int (*get_thread_reg)(struct rtos *rtos, int64_t thread_id, + uint32_t reg_num, struct rtos_reg *reg); int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]); int (*clean)(struct target *target); char * (*ps_command)(struct target *target); + // TODO: int or uint32_t for reg_num? int (*set_reg)(struct rtos *rtos, int reg_num, uint8_t *reg_value); }; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 0b4315566..4631ffb3d 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -96,7 +96,7 @@ struct gdb_connection { char *thread_list; }; -#if 0 +#if 1 #define _DEBUG_GDB_IO_ #endif diff --git a/src/target/register.c b/src/target/register.c index 850641448..dee25b2ee 100644 --- a/src/target/register.c +++ b/src/target/register.c @@ -36,6 +36,29 @@ * may be separate registers associated with debug or trace modules. */ +struct reg *register_get_by_number(struct reg_cache *first, + uint32_t reg_num, bool search_all) +{ + unsigned i; + struct reg_cache *cache = first; + + while (cache) { + for (i = 0; i < cache->num_regs; i++) { + if (cache->reg_list[i].exist == false) + continue; + if (cache->reg_list[i].number == reg_num) + return &(cache->reg_list[i]); + } + + if (search_all) + cache = cache->next; + else + break; + } + + return NULL; +} + struct reg *register_get_by_name(struct reg_cache *first, const char *name, bool search_all) { diff --git a/src/target/register.h b/src/target/register.h index 32c1f39ac..7c53d6e16 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -159,6 +159,8 @@ struct reg_arch_type { int (*set)(struct reg *reg, uint8_t *buf); }; +struct reg *register_get_by_number(struct reg_cache *first, + uint32_t reg_num, bool search_all); struct reg *register_get_by_name(struct reg_cache *first, const char *name, bool search_all); struct reg_cache **register_get_last_cache_p(struct reg_cache **first); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 65e019938..3571e13f2 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -931,7 +931,7 @@ static int riscv_get_gdb_reg_list(struct target *target, switch (reg_class) { case REG_CLASS_GENERAL: - *reg_list_size = 32; + *reg_list_size = 33; break; case REG_CLASS_ALL: *reg_list_size = target->reg_cache->num_regs; @@ -1218,6 +1218,22 @@ int riscv_openocd_poll(struct target *target) target->state = TARGET_HALTED; + if (target->smp) { + LOG_DEBUG("Halt other targets in this SMP group."); + struct target_list *targets = target->head; + int result = ERROR_OK; + while (targets) { + struct target *t = targets->target; + targets = targets->next; + if (t->state != TARGET_HALTED) { + if (old_or_new_riscv_halt(t) != ERROR_OK) + result = ERROR_FAIL; + } + } + if (result != ERROR_OK) + return result; + } + if (target->debug_reason == DBG_REASON_BREAKPOINT) { int retval; if (riscv_semihosting(target, &retval) != 0) diff --git a/src/target/target.c b/src/target/target.c index 7de3e7615..ffd82fb59 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1575,8 +1575,9 @@ int target_call_event_callbacks(struct target *target, enum target_event event) target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } - LOG_DEBUG("target event %i (%s)", event, - Jim_Nvp_value2name_simple(nvp_target_event, event)->name); + LOG_DEBUG("target event %i (%s) for core %d", event, + Jim_Nvp_value2name_simple(nvp_target_event, event)->name, + target->coreid); target_handle_event(target, event); From 348f15315e7670fccdc152545399f3d44a24bf7d Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 18 Jan 2019 11:34:26 -0800 Subject: [PATCH 11/18] Don't reset current thread id on single step. Now passing 36/45 tests. Change-Id: I244b045f84397b058cf526e3bff238cb05d8ad06 --- src/rtos/hwthread.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index da5d2eb0c..bfd299a0e 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -96,9 +96,6 @@ static int hwthread_update_threads(struct rtos *rtos) target = rtos->target; - /* wipe out previous thread details if any */ - rtos_free_threadlist(rtos); - /* determine the number of "threads" */ if (target->smp) { for (head = target->head; head != NULL; head = head->next) { @@ -112,6 +109,23 @@ static int hwthread_update_threads(struct rtos *rtos) } else thread_list_size = 1; + if (thread_list_size == rtos->thread_count) { + /* Nothing changed. Exit early. + * This is important because if we do recreate the data, we potentially + * change what the current thread is, which can lead to trouble because + * this function is sometimes called when single stepping + * (gdb_handle_vcont_packet), and the current thread should not be + * changed as part of that. */ + /* TODO: Do we need to confirm that all the "threads" are really the + * same? Is it even possible to change the number of configured + * targets and SMP groups after this function is called the first time? + */ + return ERROR_OK; + } + + /* wipe out previous thread details if any */ + rtos_free_threadlist(rtos); + /* create space for new thread details */ rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size); @@ -303,18 +317,11 @@ int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value) if (curr == NULL) return ERROR_FAIL; - struct reg **reg_list; - int reg_list_size; - if (target_get_gdb_reg_list(curr, ®_list, ®_list_size, - REG_CLASS_GENERAL) != ERROR_OK) + struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true); + if (!reg) return ERROR_FAIL; - if (reg_list_size <= reg_num) { - LOG_ERROR("Register %d requested, but only %d registers exist.", - reg_num, reg_list_size); - return ERROR_FAIL; - } - return reg_list[reg_num]->type->set(reg_list[reg_num], reg_value); + return reg->type->set(reg, reg_value); } static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) From c296c625214c74e25744ed8c2c0b62b65c90532d Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 18 Jan 2019 12:44:42 -0800 Subject: [PATCH 12/18] Halt all SMP harts on halt request. 38/45 tests pass. Change-Id: Ia4fd523139c197020d9277be4bf5f92079520068 --- src/target/riscv/riscv.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 3571e13f2..4ef417e65 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1226,7 +1226,7 @@ int riscv_openocd_poll(struct target *target) struct target *t = targets->target; targets = targets->next; if (t->state != TARGET_HALTED) { - if (old_or_new_riscv_halt(t) != ERROR_OK) + if (riscv_halt_all_harts(t) != ERROR_OK) result = ERROR_FAIL; } } @@ -1247,16 +1247,26 @@ int riscv_openocd_poll(struct target *target) int riscv_openocd_halt(struct target *target) { RISCV_INFO(r); + int result; LOG_DEBUG("halting all harts"); - int out = riscv_halt_all_harts(target); - if (out != ERROR_OK) { - LOG_ERROR("Unable to halt all harts"); - return out; + if (target->smp) { + LOG_DEBUG("Halt other targets in this SMP group."); + struct target_list *targets = target->head; + result = ERROR_OK; + while (targets) { + struct target *t = targets->target; + targets = targets->next; + if (t->state != TARGET_HALTED) { + if (riscv_halt_all_harts(t) != ERROR_OK) + result = ERROR_FAIL; + } + } + } else { + result = riscv_halt_all_harts(target); } - register_cache_invalidate(target->reg_cache); if (riscv_rtos_enabled(target)) { if (r->rtos_hartid != -1) { LOG_DEBUG("halt requested on RTOS hartid %d", r->rtos_hartid); @@ -1269,7 +1279,7 @@ int riscv_openocd_halt(struct target *target) target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; target_call_event_callbacks(target, TARGET_EVENT_HALTED); - return out; + return result; } int riscv_openocd_resume( @@ -1899,7 +1909,9 @@ int riscv_halt_one_hart(struct target *target, int hartid) return ERROR_OK; } - return r->halt_current_hart(target); + int result = r->halt_current_hart(target); + register_cache_invalidate(target->reg_cache); + return result; } int riscv_resume_all_harts(struct target *target) From afedcb337a79517462765aa62b1988c8857cc724 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 24 Jan 2019 15:15:18 -0800 Subject: [PATCH 13/18] WIP on hardware breakpoints. This is messy, but contains at least some bugfixes. 39/43 tests pass now. Change-Id: Ic9e8dad2a0ceb237e28c93906d1cd60876a5766d --- src/rtos/hwthread.c | 20 +++- src/rtos/rtos.c | 2 + src/rtos/rtos.h | 2 + src/server/gdb_server.c | 30 +++--- src/target/breakpoints.c | 33 ++++++- src/target/riscv/riscv-013.c | 1 + src/target/riscv/riscv.c | 178 ++++++++++++++++++++++++++--------- src/target/target.c | 2 + 8 files changed, 207 insertions(+), 61 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index bfd299a0e..caa3f7289 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -91,8 +91,11 @@ static int hwthread_update_threads(struct rtos *rtos) int64_t current_thread = 0; enum target_debug_reason current_reason = DBG_REASON_UNDEFINED; + LOG_DEBUG("current_thread=%i", (int)rtos->current_thread); + LOG_DEBUG("current_threadid=%i", (int)rtos->current_threadid); + if (rtos == NULL) - return -1; + return ERROR_FAIL; target = rtos->target; @@ -109,6 +112,7 @@ static int hwthread_update_threads(struct rtos *rtos) } else thread_list_size = 1; +#if 0 if (thread_list_size == rtos->thread_count) { /* Nothing changed. Exit early. * This is important because if we do recreate the data, we potentially @@ -122,9 +126,12 @@ static int hwthread_update_threads(struct rtos *rtos) */ return ERROR_OK; } +#endif - /* wipe out previous thread details if any */ + /* Wipe out previous thread details if any, but preserve threadid. */ + int64_t current_threadid = rtos->current_threadid; rtos_free_threadlist(rtos); + rtos->current_threadid = current_threadid; /* create space for new thread details */ rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size); @@ -194,6 +201,8 @@ static int hwthread_update_threads(struct rtos *rtos) } threads_found++; + LOG_DEBUG(">>> tid=%ld, debug_reason=%d, current_thread=%ld, current_reason=%d", + tid, curr->debug_reason, current_thread, current_reason); } } else { hwthread_fill_thread(rtos, target, threads_found); @@ -211,7 +220,8 @@ static int hwthread_update_threads(struct rtos *rtos) else rtos->current_thread = threadid_from_target(target); - LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread); + LOG_DEBUG("current_thread=%i", (int)rtos->current_thread); + LOG_DEBUG("current_threadid=%i", (int)rtos->current_threadid); return 0; } @@ -358,7 +368,10 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac struct target *curr = NULL; int64_t current_threadid; + LOG_DEBUG(">>> %s", packet); + if (packet[0] == 'H' && packet[1] == 'g') { + /* Never reached, because this case is handled by rtos_thread_packet(). */ sscanf(packet, "Hg%16" SCNx64, ¤t_threadid); if (current_threadid > 0) { @@ -373,6 +386,7 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac target->rtos->current_thread = threadid_from_target(target); target->rtos->current_threadid = current_threadid; + LOG_DEBUG("current_threadid=%ld", current_threadid); gdb_put_packet(connection, "OK", 2); return ERROR_OK; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 549600870..a5b7fdb6c 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -432,6 +432,7 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa target->rtos->current_threadid = target->rtos->current_thread; else target->rtos->current_threadid = threadid; + LOG_DEBUG("current_threadid=%ld", target->rtos->current_threadid); } gdb_put_packet(connection, "OK", 2); return ERROR_OK; @@ -516,6 +517,7 @@ int rtos_get_gdb_reg_list(struct connection *connection) { struct target *target = get_target_from_connection(connection); int64_t current_threadid = target->rtos->current_threadid; + LOG_DEBUG("current_threadid=%ld", target->rtos->current_threadid); if ((target->rtos != NULL) && (current_threadid != -1) && (current_threadid != 0) && ((current_threadid != target->rtos->current_thread) || diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index e5a7e13fa..001837fe8 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -50,7 +50,9 @@ struct rtos { symbol_table_elem_t *symbols; struct target *target; /* add a context variable instead of global variable */ + /* The thread currently selected by gdb. */ int64_t current_threadid; + /* The currently selected thread according to the target. */ threadid_t current_thread; struct thread_detail *thread_details; int thread_count; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 4631ffb3d..2772e7a79 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -144,6 +144,7 @@ static char gdb_running_type; static int gdb_last_signal(struct target *target) { + LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); switch (target->debug_reason) { case DBG_REASON_DBGRQ: return 0x2; /* SIGINT */ @@ -733,17 +734,28 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio if (target->debug_reason == DBG_REASON_EXIT) { sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "W00"); } else { + struct target *ct; + if (target->rtos != NULL) { + target->rtos->current_threadid = target->rtos->current_thread; + LOG_DEBUG("current_threadid=%ld", target->rtos->current_threadid); + target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &ct); + } else { + ct = target; + } + if (gdb_connection->ctrl_c) { signal_var = 0x2; } else - signal_var = gdb_last_signal(target); + signal_var = gdb_last_signal(ct); + LOG_DEBUG(">>> ctrl_c=%d, signal_var=%d", gdb_connection->ctrl_c, + signal_var); stop_reason[0] = '\0'; - if (target->debug_reason == DBG_REASON_WATCHPOINT) { + if (ct->debug_reason == DBG_REASON_WATCHPOINT) { enum watchpoint_rw hit_wp_type; target_addr_t hit_wp_address; - if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) { + if (watchpoint_hit(ct, &hit_wp_type, &hit_wp_address) == ERROR_OK) { switch (hit_wp_type) { case WPT_WRITE: @@ -765,15 +777,10 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio } current_thread[0] = '\0'; - if (target->rtos != NULL) { - struct target *ct; + if (target->rtos != NULL) snprintf(current_thread, sizeof(current_thread), "thread:%" PRIx64 ";", target->rtos->current_thread); - target->rtos->current_threadid = target->rtos->current_thread; - target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &ct); - if (!gdb_connection->ctrl_c) - signal_var = gdb_last_signal(ct); - } + LOG_DEBUG(">>> signal_var=%d", signal_var); sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s%s", signal_var, stop_reason, current_thread); @@ -1652,7 +1659,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, char *separator; int retval; - LOG_DEBUG("-"); + LOG_DEBUG("[%d]", target->coreid); type = strtoul(packet + 1, &separator, 16); @@ -3178,6 +3185,7 @@ static int gdb_input_inner(struct connection *connection) } if (packet_size > 0) { + LOG_DEBUG(">>> current_threadid=%ld", target->rtos ? target->rtos->current_threadid : 1234); retval = ERROR_OK; switch (packet[0]) { case 'T': /* Is thread alive? */ diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 58bcc8615..9645f84b4 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -98,7 +98,9 @@ fail: return retval; } - LOG_DEBUG("added %s breakpoint at " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", + LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT + " of length 0x%8.8x, (BPID: %" PRIu32 ")", + target->coreid, breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); @@ -385,8 +387,8 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) return NULL; } -int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, - enum watchpoint_rw rw, uint32_t value, uint32_t mask) +int watchpoint_add_internal(struct target *target, target_addr_t address, + uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; @@ -451,6 +453,29 @@ bye: return ERROR_OK; } +int watchpoint_add(struct target *target, target_addr_t address, + uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) +{ + int retval = ERROR_OK; + if (target->smp) { + struct target_list *head; + struct target *curr; + head = target->head; + + while (head != (struct target_list *)NULL) { + curr = head->target; + retval = watchpoint_add_internal(curr, address, length, rw, value, + mask); + if (retval != ERROR_OK) + return retval; + head = head->next; + } + return retval; + } else + return watchpoint_add_internal(target, address, length, rw, value, + mask); +} + static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove) { struct watchpoint *watchpoint = target->watchpoints; @@ -502,6 +527,8 @@ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, int retval; struct watchpoint *hit_watchpoint; + LOG_DEBUG("[%d]", target->coreid); + retval = target_hit_watchpoint(target, &hit_watchpoint); if (retval != ERROR_OK) return ERROR_FAIL; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 0d74d5cae..2a7917d91 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2952,6 +2952,7 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target) * already set when we connected. Force enumeration now, which has the * side effect of clearing any triggers we did not set. */ riscv_enumerate_triggers(target); + LOG_DEBUG("[%d] halted because of trigger", target->coreid); return RISCV_HALT_TRIGGER; case CSR_DCSR_CAUSE_STEP: return RISCV_HALT_SINGLESTEP; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 4ef417e65..aa871e9b1 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -267,6 +267,7 @@ static int riscv_init_target(struct command_context *cmd_ctx, riscv_semihosting_init(target); target->debug_reason = DBG_REASON_DBGRQ; + LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); return ERROR_OK; } @@ -489,8 +490,8 @@ static int add_trigger(struct target *target, struct trigger *trigger) if (result != ERROR_OK) continue; - LOG_DEBUG("Using trigger %d (type %d) for bp %d", i, type, - trigger->unique_id); + LOG_DEBUG("[%d] Using trigger %d (type %d) for bp %d", target->coreid, + i, type, trigger->unique_id); r->trigger_unique_id[i] = trigger->unique_id; break; } @@ -512,6 +513,7 @@ static int add_trigger(struct target *target, struct trigger *trigger) int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { + LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, breakpoint->address); assert(breakpoint); if (breakpoint->type == BKPT_SOFT) { /** @todo check RVC for size/alignment */ @@ -585,7 +587,8 @@ static int remove_trigger(struct target *target, struct trigger *trigger) "trigger."); return ERROR_FAIL; } - LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id); + LOG_DEBUG("[%d] Stop using resource %d for bp %d", target->coreid, i, + trigger->unique_id); for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; @@ -646,12 +649,33 @@ static void trigger_from_watchpoint(struct trigger *trigger, int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { + LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, watchpoint->address); struct trigger trigger; trigger_from_watchpoint(&trigger, watchpoint); - int result = add_trigger(target, &trigger); - if (result != ERROR_OK) - return result; + if (target->smp) { + struct target *failed = NULL; + for (struct target_list *list = target->head; list != NULL; + list = list->next) { + struct target *t = list->target; + if (add_trigger(t, &trigger) != ERROR_OK) { + failed = t; + break; + } + } + if (failed) { + for (struct target_list *list = target->head; + list->target != failed; list = list->next) { + struct target *t = list->target; + remove_trigger(t, &trigger); + } + return ERROR_FAIL; + } + } else { + int result = add_trigger(target, &trigger); + if (result != ERROR_OK) + return result; + } watchpoint->set = true; return ERROR_OK; @@ -660,12 +684,26 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint) int riscv_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { + LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, watchpoint->address); + struct trigger trigger; trigger_from_watchpoint(&trigger, watchpoint); - int result = remove_trigger(target, &trigger); - if (result != ERROR_OK) - return result; + if (target->smp) { + bool failed = false; + for (struct target_list *list = target->head; list != NULL; + list = list->next) { + struct target *t = list->target; + if (remove_trigger(t, &trigger) != ERROR_OK) + failed = true; + } + if (failed) + return ERROR_FAIL; + } else { + int result = remove_trigger(target, &trigger); + if (result != ERROR_OK) + return result; + } watchpoint->set = false; return ERROR_OK; @@ -1143,6 +1181,31 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid) return RPH_NO_CHANGE; } +int set_debug_reason(struct target *target, int hartid) +{ + switch (riscv_halt_reason(target, hartid)) { + case RISCV_HALT_BREAKPOINT: + target->debug_reason = DBG_REASON_BREAKPOINT; + break; + case RISCV_HALT_TRIGGER: + target->debug_reason = DBG_REASON_WATCHPOINT; + break; + case RISCV_HALT_INTERRUPT: + target->debug_reason = DBG_REASON_DBGRQ; + break; + case RISCV_HALT_SINGLESTEP: + target->debug_reason = DBG_REASON_SINGLESTEP; + break; + case RISCV_HALT_UNKNOWN: + target->debug_reason = DBG_REASON_UNDEFINED; + break; + case RISCV_HALT_ERROR: + return ERROR_FAIL; + } + LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); + return ERROR_OK; +} + /*** OpenOCD Interface ***/ int riscv_openocd_poll(struct target *target) { @@ -1177,6 +1240,64 @@ int riscv_openocd_poll(struct target *target) * harts. */ for (int i = 0; i < riscv_count_harts(target); ++i) riscv_halt_one_hart(target, i); + + } else if (target->smp) { + bool halt_discovered = false; + bool newly_halted[128] = {0}; + unsigned i = 0; + for (struct target_list *list = target->head; list != NULL; + list = list->next, i++) { + struct target *t = list->target; + riscv_info_t *r = riscv_info(t); + assert(i < DIM(newly_halted)); + enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid); + switch (out) { + case RPH_NO_CHANGE: + break; + case RPH_DISCOVERED_RUNNING: + t->state = TARGET_RUNNING; + break; + case RPH_DISCOVERED_HALTED: + halt_discovered = true; + newly_halted[i] = true; + t->state = TARGET_HALTED; + if (set_debug_reason(t, r->current_hartid) != ERROR_OK) + return ERROR_FAIL; + break; + case RPH_ERROR: + return ERROR_FAIL; + } + } + + if (halt_discovered) { + LOG_DEBUG("Halt other targets in this SMP group."); + i = 0; + for (struct target_list *list = target->head; list != NULL; + list = list->next, i++) { + struct target *t = list->target; + riscv_info_t *r = riscv_info(t); + if (t->state != TARGET_HALTED) { + if (riscv_halt_one_hart(t, r->current_hartid) != ERROR_OK) + return ERROR_FAIL; + t->state = TARGET_HALTED; + if (set_debug_reason(t, r->current_hartid) != ERROR_OK) + return ERROR_FAIL; + newly_halted[i] = true; + } + } + + /* Now that we have all our ducks in a row, tell the higher layers + * what just happened. */ + i = 0; + for (struct target_list *list = target->head; list != NULL; + list = list->next, i++) { + struct target *t = list->target; + if (newly_halted[i]) + target_call_event_callbacks(t, TARGET_EVENT_HALTED); + } + } + return ERROR_OK; + } else { enum riscv_poll_hart out = riscv_poll_hart(target, riscv_current_hartid(target)); @@ -1190,25 +1311,8 @@ int riscv_openocd_poll(struct target *target) } target->state = TARGET_HALTED; - switch (riscv_halt_reason(target, halted_hart)) { - case RISCV_HALT_BREAKPOINT: - target->debug_reason = DBG_REASON_BREAKPOINT; - break; - case RISCV_HALT_TRIGGER: - target->debug_reason = DBG_REASON_WATCHPOINT; - break; - case RISCV_HALT_INTERRUPT: - target->debug_reason = DBG_REASON_DBGRQ; - break; - case RISCV_HALT_SINGLESTEP: - target->debug_reason = DBG_REASON_SINGLESTEP; - break; - case RISCV_HALT_UNKNOWN: - target->debug_reason = DBG_REASON_UNDEFINED; - break; - case RISCV_HALT_ERROR: + if (set_debug_reason(target, halted_hart) != ERROR_OK) return ERROR_FAIL; - } if (riscv_rtos_enabled(target)) { target->rtos->current_threadid = halted_hart + 1; @@ -1218,22 +1322,6 @@ int riscv_openocd_poll(struct target *target) target->state = TARGET_HALTED; - if (target->smp) { - LOG_DEBUG("Halt other targets in this SMP group."); - struct target_list *targets = target->head; - int result = ERROR_OK; - while (targets) { - struct target *t = targets->target; - targets = targets->next; - if (t->state != TARGET_HALTED) { - if (riscv_halt_all_harts(t) != ERROR_OK) - result = ERROR_FAIL; - } - } - if (result != ERROR_OK) - return result; - } - if (target->debug_reason == DBG_REASON_BREAKPOINT) { int retval; if (riscv_semihosting(target, &retval) != 0) @@ -1249,7 +1337,7 @@ int riscv_openocd_halt(struct target *target) RISCV_INFO(r); int result; - LOG_DEBUG("halting all harts"); + LOG_DEBUG("[%d] halting all harts", target->coreid); if (target->smp) { LOG_DEBUG("Halt other targets in this SMP group."); @@ -1278,6 +1366,7 @@ int riscv_openocd_halt(struct target *target) target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; + LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return result; } @@ -1366,6 +1455,7 @@ int riscv_openocd_step( target_call_event_callbacks(target, TARGET_EVENT_RESUMED); target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_SINGLESTEP; + LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return out; } diff --git a/src/target/target.c b/src/target/target.c index ffd82fb59..8b94fc9ff 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1206,6 +1206,8 @@ int target_hit_watchpoint(struct target *target, return ERROR_FAIL; } + LOG_DEBUG("[%d]", target->coreid); + return target->type->hit_watchpoint(target, hit_watchpoint); } From b29215735cf150266f3b9928276fe3fc48d2fa1e Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 25 Jan 2019 09:19:33 -0800 Subject: [PATCH 14/18] Properly clean up SMP watchpoints. 42/43 tests pass. Change-Id: Ia800ffacf914742e8b9bdb1799ca3817856448a4 --- src/target/breakpoints.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 9645f84b4..f76c3187d 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -497,7 +497,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint free(watchpoint); } -void watchpoint_remove(struct target *target, target_addr_t address) +int watchpoint_remove_internal(struct target *target, target_addr_t address) { struct watchpoint *watchpoint = target->watchpoints; @@ -507,10 +507,32 @@ void watchpoint_remove(struct target *target, target_addr_t address) watchpoint = watchpoint->next; } - if (watchpoint) + if (watchpoint) { watchpoint_free(target, watchpoint); - else - LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); + return 1; + } else { + if (!target->smp) + LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); + return 0; + } +} + +void watchpoint_remove(struct target *target, target_addr_t address) +{ + int found = 0; + if (target->smp) { + struct target_list *head; + struct target *curr; + head = target->head; + while (head != (struct target_list *)NULL) { + curr = head->target; + found += watchpoint_remove_internal(curr, address); + head = head->next; + } + if (found == 0) + LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); + } else + watchpoint_remove_internal(target, address); } void watchpoint_clear_target(struct target *target) From 82cf37d36c6b91b1fd5f27fe4df7f80928153c8c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 25 Jan 2019 13:11:06 -0800 Subject: [PATCH 15/18] Invalidate register cache on reset. All tests pass with `-rtos hwthread` against spike32! Change-Id: I9051259d2702c76b7c35aeffeac020a773e0597a --- src/target/riscv/riscv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index aa871e9b1..d05b9c787 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -867,13 +867,15 @@ static int old_or_new_riscv_halt(struct target *target) static int riscv_assert_reset(struct target *target) { + LOG_DEBUG("[%d]", target->coreid); struct target_type *tt = get_target_type(target); + riscv_invalidate_register_cache(target); return tt->assert_reset(target); } static int riscv_deassert_reset(struct target *target) { - LOG_DEBUG("RISCV DEASSERT RESET"); + LOG_DEBUG("[%d]", target->coreid); struct target_type *tt = get_target_type(target); return tt->deassert_reset(target); } From 96df1db7b17b5a2298150f21c1c1bee00ffbe0f9 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 25 Jan 2019 14:34:01 -0800 Subject: [PATCH 16/18] Remove debug statements. Change-Id: If37bc883fea0b83740bfd6a7fcb2091db0ac61f0 --- src/rtos/hwthread.c | 30 ++---------------------------- src/rtos/rtos.c | 1 - src/rtos/rtos.h | 3 +-- src/server/gdb_server.c | 5 ----- src/target/riscv/riscv.c | 17 +++-------------- 5 files changed, 6 insertions(+), 50 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index caa3f7289..cb8fb2069 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -37,7 +37,7 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs); static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); static int hwthread_smp_init(struct target *target); -int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value); +int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value); #define HW_THREAD_NAME_STR_SIZE (32) @@ -91,9 +91,6 @@ static int hwthread_update_threads(struct rtos *rtos) int64_t current_thread = 0; enum target_debug_reason current_reason = DBG_REASON_UNDEFINED; - LOG_DEBUG("current_thread=%i", (int)rtos->current_thread); - LOG_DEBUG("current_threadid=%i", (int)rtos->current_threadid); - if (rtos == NULL) return ERROR_FAIL; @@ -112,22 +109,6 @@ static int hwthread_update_threads(struct rtos *rtos) } else thread_list_size = 1; -#if 0 - if (thread_list_size == rtos->thread_count) { - /* Nothing changed. Exit early. - * This is important because if we do recreate the data, we potentially - * change what the current thread is, which can lead to trouble because - * this function is sometimes called when single stepping - * (gdb_handle_vcont_packet), and the current thread should not be - * changed as part of that. */ - /* TODO: Do we need to confirm that all the "threads" are really the - * same? Is it even possible to change the number of configured - * targets and SMP groups after this function is called the first time? - */ - return ERROR_OK; - } -#endif - /* Wipe out previous thread details if any, but preserve threadid. */ int64_t current_threadid = rtos->current_threadid; rtos_free_threadlist(rtos); @@ -201,8 +182,6 @@ static int hwthread_update_threads(struct rtos *rtos) } threads_found++; - LOG_DEBUG(">>> tid=%ld, debug_reason=%d, current_thread=%ld, current_reason=%d", - tid, curr->debug_reason, current_thread, current_reason); } } else { hwthread_fill_thread(rtos, target, threads_found); @@ -220,8 +199,6 @@ static int hwthread_update_threads(struct rtos *rtos) else rtos->current_thread = threadid_from_target(target); - LOG_DEBUG("current_thread=%i", (int)rtos->current_thread); - LOG_DEBUG("current_threadid=%i", (int)rtos->current_threadid); return 0; } @@ -287,7 +264,6 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, uint32_t reg_num, struct rtos_reg *rtos_reg) { - LOG_DEBUG(">>> thread %ld, reg %d", thread_id, reg_num); if (rtos == NULL) return ERROR_FAIL; @@ -316,7 +292,7 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, return ERROR_OK; } -int hwthread_set_reg(struct rtos *rtos, int reg_num, uint8_t *reg_value) +int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value) { if (rtos == NULL) return ERROR_FAIL; @@ -368,8 +344,6 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac struct target *curr = NULL; int64_t current_threadid; - LOG_DEBUG(">>> %s", packet); - if (packet[0] == 'H' && packet[1] == 'g') { /* Never reached, because this case is handled by rtos_thread_packet(). */ sscanf(packet, "Hg%16" SCNx64, ¤t_threadid); diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index a5b7fdb6c..8b9eb4c2a 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -552,7 +552,6 @@ int rtos_set_reg(struct connection *connection, int reg_num, { struct target *target = get_target_from_connection(connection); int64_t current_threadid = target->rtos->current_threadid; - LOG_DEBUG(">>> thread %ld, reg %d", current_threadid, reg_num); if ((target->rtos != NULL) && (target->rtos->type->set_reg != NULL) && (current_threadid != -1) && diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 001837fe8..81829b1c5 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -82,8 +82,7 @@ struct rtos_type { int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]); int (*clean)(struct target *target); char * (*ps_command)(struct target *target); - // TODO: int or uint32_t for reg_num? - int (*set_reg)(struct rtos *rtos, int reg_num, uint8_t *reg_value); + int (*set_reg)(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value); }; struct stack_register_offset { diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 2772e7a79..503a435df 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -144,7 +144,6 @@ static char gdb_running_type; static int gdb_last_signal(struct target *target) { - LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); switch (target->debug_reason) { case DBG_REASON_DBGRQ: return 0x2; /* SIGINT */ @@ -747,8 +746,6 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio signal_var = 0x2; } else signal_var = gdb_last_signal(ct); - LOG_DEBUG(">>> ctrl_c=%d, signal_var=%d", gdb_connection->ctrl_c, - signal_var); stop_reason[0] = '\0'; if (ct->debug_reason == DBG_REASON_WATCHPOINT) { @@ -780,7 +777,6 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio if (target->rtos != NULL) snprintf(current_thread, sizeof(current_thread), "thread:%" PRIx64 ";", target->rtos->current_thread); - LOG_DEBUG(">>> signal_var=%d", signal_var); sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s%s", signal_var, stop_reason, current_thread); @@ -3185,7 +3181,6 @@ static int gdb_input_inner(struct connection *connection) } if (packet_size > 0) { - LOG_DEBUG(">>> current_threadid=%ld", target->rtos ? target->rtos->current_threadid : 1234); retval = ERROR_OK; switch (packet[0]) { case 'T': /* Is thread alive? */ diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index f4a37ad32..6ba61273c 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -267,7 +267,6 @@ static int riscv_init_target(struct command_context *cmd_ctx, riscv_semihosting_init(target); target->debug_reason = DBG_REASON_DBGRQ; - LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); return ERROR_OK; } @@ -991,13 +990,9 @@ static int riscv_get_gdb_reg_list(struct target *target, target->reg_cache->reg_list[i].size > 0); (*reg_list)[i] = &target->reg_cache->reg_list[i]; if (read && !target->reg_cache->reg_list[i].valid) { - // TODO: Confirm that this function is supposed to actually read - // registers. I'm just adding this because maybe - // hwthread_get_thread_reg_list() expects it. - - // This function gets called from - // gdb_target_description_supported(), and we end up failing in - // that case. Allow failures for now. + /* This function gets called from + * gdb_target_description_supported(), and we end up failing in + * that case. Allow failures for now. */ if (target->reg_cache->reg_list[i].type->get( &target->reg_cache->reg_list[i]) != ERROR_OK) read = false; @@ -1204,7 +1199,6 @@ int set_debug_reason(struct target *target, int hartid) case RISCV_HALT_ERROR: return ERROR_FAIL; } - LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); return ERROR_OK; } @@ -1368,7 +1362,6 @@ int riscv_openocd_halt(struct target *target) target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; - LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return result; } @@ -1457,7 +1450,6 @@ int riscv_openocd_step( target_call_event_callbacks(target, TARGET_EVENT_RESUMED); target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_SINGLESTEP; - LOG_DEBUG(">>> [%d] debug_reason=%d", target->coreid, target->debug_reason); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return out; } @@ -2171,7 +2163,6 @@ int riscv_set_current_hartid(struct target *target, int hartid) /* This might get called during init, in which case we shouldn't be * setting up the register cache. */ - //if (target_was_examined(target) && hartid != previous_hartid) if (target_was_examined(target) && riscv_rtos_enabled(target)) riscv_invalidate_register_cache(target); @@ -2182,8 +2173,6 @@ void riscv_invalidate_register_cache(struct target *target) { RISCV_INFO(r); - LOG_DEBUG(">>>"); - register_cache_invalidate(target->reg_cache); for (size_t i = 0; i < target->reg_cache->num_regs; ++i) { struct reg *reg = &target->reg_cache->reg_list[i]; From e186f62962673a3bfdee151693521d46f2adcefb Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 25 Jan 2019 15:31:42 -0800 Subject: [PATCH 17/18] More cleanup. Change-Id: I804bdcec23b69d77dfc376e23c6d1f29f99e7335 --- src/rtos/rtos.c | 2 -- src/server/gdb_server.c | 4 ++-- src/target/breakpoints.c | 2 -- src/target/riscv/riscv.c | 45 ++++++---------------------------------- src/target/target.c | 2 -- 5 files changed, 8 insertions(+), 47 deletions(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 8b9eb4c2a..b055f91de 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -432,7 +432,6 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa target->rtos->current_threadid = target->rtos->current_thread; else target->rtos->current_threadid = threadid; - LOG_DEBUG("current_threadid=%ld", target->rtos->current_threadid); } gdb_put_packet(connection, "OK", 2); return ERROR_OK; @@ -517,7 +516,6 @@ int rtos_get_gdb_reg_list(struct connection *connection) { struct target *target = get_target_from_connection(connection); int64_t current_threadid = target->rtos->current_threadid; - LOG_DEBUG("current_threadid=%ld", target->rtos->current_threadid); if ((target->rtos != NULL) && (current_threadid != -1) && (current_threadid != 0) && ((current_threadid != target->rtos->current_thread) || diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 503a435df..0cfe0ecc4 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -96,7 +96,7 @@ struct gdb_connection { char *thread_list; }; -#if 1 +#if 0 #define _DEBUG_GDB_IO_ #endif @@ -736,7 +736,7 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio struct target *ct; if (target->rtos != NULL) { target->rtos->current_threadid = target->rtos->current_thread; - LOG_DEBUG("current_threadid=%ld", target->rtos->current_threadid); + LOG_DEBUG("current_threadid=%" PRId64, target->rtos->current_threadid); target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &ct); } else { ct = target; diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index f76c3187d..58e4f6139 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -549,8 +549,6 @@ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, int retval; struct watchpoint *hit_watchpoint; - LOG_DEBUG("[%d]", target->coreid); - retval = target_hit_watchpoint(target, &hit_watchpoint); if (retval != ERROR_OK) return ERROR_FAIL; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 6ba61273c..01b84bfda 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -648,33 +648,12 @@ static void trigger_from_watchpoint(struct trigger *trigger, int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { - LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, watchpoint->address); struct trigger trigger; trigger_from_watchpoint(&trigger, watchpoint); - if (target->smp) { - struct target *failed = NULL; - for (struct target_list *list = target->head; list != NULL; - list = list->next) { - struct target *t = list->target; - if (add_trigger(t, &trigger) != ERROR_OK) { - failed = t; - break; - } - } - if (failed) { - for (struct target_list *list = target->head; - list->target != failed; list = list->next) { - struct target *t = list->target; - remove_trigger(t, &trigger); - } - return ERROR_FAIL; - } - } else { - int result = add_trigger(target, &trigger); - if (result != ERROR_OK) - return result; - } + int result = add_trigger(target, &trigger); + if (result != ERROR_OK) + return result; watchpoint->set = true; return ERROR_OK; @@ -688,21 +667,9 @@ int riscv_remove_watchpoint(struct target *target, struct trigger trigger; trigger_from_watchpoint(&trigger, watchpoint); - if (target->smp) { - bool failed = false; - for (struct target_list *list = target->head; list != NULL; - list = list->next) { - struct target *t = list->target; - if (remove_trigger(t, &trigger) != ERROR_OK) - failed = true; - } - if (failed) - return ERROR_FAIL; - } else { - int result = remove_trigger(target, &trigger); - if (result != ERROR_OK) - return result; - } + int result = remove_trigger(target, &trigger); + if (result != ERROR_OK) + return result; watchpoint->set = false; return ERROR_OK; diff --git a/src/target/target.c b/src/target/target.c index 8b94fc9ff..ffd82fb59 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1206,8 +1206,6 @@ int target_hit_watchpoint(struct target *target, return ERROR_FAIL; } - LOG_DEBUG("[%d]", target->coreid); - return target->type->hit_watchpoint(target, hit_watchpoint); } From 220a97979fa0f4253325d482b287a90851d5b95c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 25 Jan 2019 15:56:26 -0800 Subject: [PATCH 18/18] Use more compatible printf formatting. Change-Id: I5d5b46f3e6c4f5abff1c0efa3ea8b4f589c1e635 --- src/rtos/hwthread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index cb8fb2069..8a271fb54 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -360,7 +360,7 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac target->rtos->current_thread = threadid_from_target(target); target->rtos->current_threadid = current_threadid; - LOG_DEBUG("current_threadid=%ld", current_threadid); + LOG_DEBUG("current_threadid=%" PRId64, current_threadid); gdb_put_packet(connection, "OK", 2); return ERROR_OK;