diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h index d6ddd4ff1..e6c2c5d3e 100644 --- a/src/target/riscv/debug_defines.h +++ b/src/target/riscv/debug_defines.h @@ -84,8 +84,7 @@ /* * 0: Version described in spec version 0.11. * -* 1: Version described in spec version 0.13 (and later?), which -* reduces the DMI data width to 32 bits. +* 1: Version described in spec version 0.13. * * 15: Version not described in any available version of this spec. */ @@ -134,7 +133,7 @@ * cleared by writing \Fdmireset in \Rdtmcs. * * This indicates that the DM itself responded with an error. -* Note: there are no specified cases in which the DM would +* There are no specified cases in which the DM would * respond with an error, and DMI is not required to support * returning errors. * @@ -145,11 +144,6 @@ * needs to give the target more TCK edges between Update-DR and * Capture-DR. The simplest way to do that is to add extra transitions * in Run-Test/Idle. -* -* (The DTM, DM, and/or component may be in different clock domains, -* so synchronization may be required. Some relatively fixed number of -* TCK ticks may be needed for the request to reach the DM, complete, -* and for the response to be synchronized back into the TCK domain.) */ #define DTM_DMI_OP_OFFSET 0 #define DTM_DMI_OP_LENGTH 2 @@ -167,20 +161,28 @@ #define CSR_DCSR_XDEBUGVER_LENGTH 4 #define CSR_DCSR_XDEBUGVER (0xfU << CSR_DCSR_XDEBUGVER_OFFSET) /* -* When 1, {\tt ebreak} instructions in Machine Mode enter Debug Mode. +* 0: {\tt ebreak} instructions in M-mode behave as described in the +* Privileged Spec. +* +* 1: {\tt ebreak} instructions in M-mode enter Debug Mode. */ #define CSR_DCSR_EBREAKM_OFFSET 15 #define CSR_DCSR_EBREAKM_LENGTH 1 #define CSR_DCSR_EBREAKM (0x1U << CSR_DCSR_EBREAKM_OFFSET) /* -* When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode. +* 0: {\tt ebreak} instructions in S-mode behave as described in the +* Privileged Spec. +* +* 1: {\tt ebreak} instructions in S-mode enter Debug Mode. */ #define CSR_DCSR_EBREAKS_OFFSET 13 #define CSR_DCSR_EBREAKS_LENGTH 1 #define CSR_DCSR_EBREAKS (0x1U << CSR_DCSR_EBREAKS_OFFSET) /* -* When 1, {\tt ebreak} instructions in User/Application Mode enter -* Debug Mode. +* 0: {\tt ebreak} instructions in U-mode behave as described in the +* Privileged Spec. +* +* 1: {\tt ebreak} instructions in U-mode enter Debug Mode. */ #define CSR_DCSR_EBREAKU_OFFSET 12 #define CSR_DCSR_EBREAKU_LENGTH 1 @@ -191,9 +193,10 @@ * 1: Interrupts are enabled during single stepping. * * Implementations may hard wire this bit to 0. -* The debugger must read back the value it -* writes to check whether the feature is supported. If not -* supported, interrupt behavior can be emulated by the debugger. +* In that case interrupt behavior can be emulated by the debugger. +* +* The debugger must not change the value of this bit while the hart +* is running. */ #define CSR_DCSR_STEPIE_OFFSET 11 #define CSR_DCSR_STEPIE_LENGTH 1 @@ -201,14 +204,13 @@ /* * 0: Increment counters as usual. * -* 1: Don't increment any counters while in Debug Mode or on {\tt -* ebreak} instructions that cause entry into Debug Mode. These -* counters include the {\tt cycle} and {\tt instret} CSRs. This is -* preferred for most debugging scenarios. +* 1: Don't increment any hart-local counters while in Debug Mode or +* on {\tt ebreak} instructions that cause entry into Debug Mode. +* These counters include the {\tt instret} CSR. On single-hart cores +* {\tt cycle} should be stopped, but on multi-hart cores it must keep +* incrementing. * -* An implementation may choose not to support writing to this bit. -* The debugger must read back the value it writes to check whether -* the feature is supported. +* An implementation may hardwire this bit to 0 or 1. */ #define CSR_DCSR_STOPCOUNT_OFFSET 10 #define CSR_DCSR_STOPCOUNT_LENGTH 1 @@ -218,9 +220,7 @@ * * 1: Don't increment any hart-local timers while in Debug Mode. * -* An implementation may choose not to support writing to this bit. -* The debugger must read back the value it writes to check whether -* the feature is supported. +* An implementation may hardwire this bit to 0 or 1. */ #define CSR_DCSR_STOPTIME_OFFSET 9 #define CSR_DCSR_STOPTIME_LENGTH 1 @@ -236,9 +236,16 @@ * * 2: The Trigger Module caused a breakpoint exception. (priority 4) * -* 3: The debugger requested entry to Debug Mode. (priority 2) +* 3: The debugger requested entry to Debug Mode using \Fhaltreq. +* (priority 1) * -* 4: The hart single stepped because \Fstep was set. (priority 1) +* 4: The hart single stepped because \Fstep was set. (priority 0, lowest) +* +* 5: The hart halted directly out of reset due to \Fresethaltreq. It +* is also acceptable to report 3 when this happens. (priority 2) +* +* 6: The hart halted because it's part of a halt group. (priority 5, +* highest) Harts may report 3 for this cause instead. * * Other values are reserved for future use. */ @@ -246,10 +253,11 @@ #define CSR_DCSR_CAUSE_LENGTH 3 #define CSR_DCSR_CAUSE (0x7U << CSR_DCSR_CAUSE_OFFSET) /* -* When 1, \Fmprv in \Rmstatus takes effect during debug mode. -* When 0, it is ignored during debug mode. -* Implementing this bit is optional. -* If not implemented it should be tied to 0. +* 0: \Fmprv in \Rmstatus is ignored in Debug Mode. +* +* 1: \Fmprv in \Rmstatus takes effect in Debug Mode. +* +* Implementing this bit is optional. It may be tied to either 0 or 1. */ #define CSR_DCSR_MPRVEN_OFFSET 4 #define CSR_DCSR_MPRVEN_LENGTH 1 @@ -270,6 +278,9 @@ * If the instruction does not complete due to an exception, * the hart will immediately enter Debug Mode before executing * the trap handler, with appropriate exception registers set. +* +* The debugger must not change the value of this bit while the hart +* is running. */ #define CSR_DCSR_STEP_OFFSET 2 #define CSR_DCSR_STEP_LENGTH 1 @@ -289,14 +300,14 @@ #define CSR_DCSR_PRV (0x3U << CSR_DCSR_PRV_OFFSET) #define CSR_DPC 0x7b1 #define CSR_DPC_DPC_OFFSET 0 -#define CSR_DPC_DPC_LENGTH MXLEN -#define CSR_DPC_DPC (((1L<version_specific = NULL; } +static int set_haltgroup(struct target *target, bool *supported) +{ + uint32_t write = set_field(DMI_DMCS2_HGWRITE, DMI_DMCS2_HALTGROUP, target->smp); + if (dmi_write(target, DMI_DMCS2, write) != ERROR_OK) + return ERROR_FAIL; + uint32_t read; + if (dmi_read(target, &read, DMI_DMCS2) != ERROR_OK) + return ERROR_FAIL; + *supported = get_field(read, DMI_DMCS2_HALTGROUP) == (unsigned) target->smp; + return ERROR_OK; +} + static int examine(struct target *target) { /* Don't need to select dbus, since the first thing we do is read dtmcontrol. */ @@ -1540,6 +1553,18 @@ static int examine(struct target *target) if (target->rtos) riscv_update_threads(target->rtos); + if (target->smp) { + bool haltgroup_supported; + if (set_haltgroup(target, &haltgroup_supported) != ERROR_OK) + return ERROR_FAIL; + if (haltgroup_supported) + LOG_INFO("Core %d made part of halt group %d.", target->coreid, + target->smp); + else + LOG_INFO("Core %d could not be made part of halt group %d.", + target->coreid, target->smp); + } + /* Some regression suites rely on seeing 'Examined RISC-V core' to know * when they can connect with gdb/telnet. * We will need to update those suites if we want to change that text. */ @@ -3017,7 +3042,7 @@ riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned index) int riscv013_execute_debug_buffer(struct target *target) { uint32_t run_program = 0; - run_program = set_field(run_program, AC_ACCESS_REGISTER_SIZE, 2); + run_program = set_field(run_program, AC_ACCESS_REGISTER_AARSIZE, 2); run_program = set_field(run_program, AC_ACCESS_REGISTER_POSTEXEC, 1); run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0); run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000); diff --git a/src/target/target.c b/src/target/target.c index 8857dc44c..036c065d4 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5839,6 +5839,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int i; const char *targetname; int retval, len; + static int smp_group = 1; struct target *target = (struct target *) NULL; struct target_list *head, *curr, *new; curr = (struct target_list *) NULL; @@ -5874,10 +5875,11 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) while (curr != (struct target_list *)NULL) { target = curr->target; - target->smp = 1; + target->smp = smp_group; target->head = head; curr = curr->next; } + smp_group++; if (target && target->rtos) retval = rtos_smp_init(head->target);