Skip to content

Commit 881db17

Browse files
committed
target/riscv: Introduce riscv set_group command
Add support for associating a halt group with current target or an external trigger via a newly exposed configuration option "riscv set_group". Original merge request: #1179 Original author: Rob Bradford rbradford@rivosinc.com https://github.com/rbradford
1 parent d3267c1 commit 881db17

File tree

4 files changed

+149
-11
lines changed

4 files changed

+149
-11
lines changed

doc/openocd.texi

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11673,6 +11673,20 @@ The second argument configures how OpenOCD should use the selected trigger featu
1167311673
With no parameters, prints current trigger features configuration.
1167411674
@end deffn
1167511675

11676+
@deffn {Command} {riscv set_group} grouptype group ['trigger' triggernum]
11677+
OpenOCD assigns a hart or a given external trigger into a RISC-V halt group. This command
11678+
associates the the current target or supplied external trigger(s) with this halt group.
11679+
11680+
@option{trigger} and @var{triggernum} Specify the index of the external trigger.
11681+
When an external input trigger fires, the harts in the halt group will get halted.
11682+
Similarly, all external output triggers will be notified when a hart in the halt group halts.
11683+
11684+
The only supported value of @var{grouptype} is @option{halt_group}. RISC-V resume groups
11685+
are not allowed because the concept of a target resuming due to a different reason than
11686+
user's resume request is not supported by OpenOCD and GDB.
11687+
@end deffn
11688+
11689+
1167611690
@subsection RISC-V Authentication Commands
1167711691

1167811692
The following commands can be used to authenticate to a RISC-V system. Eg. a

src/target/riscv/riscv-013.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,8 @@ static int riscv013_access_memory(struct target *target, const riscv_mem_access_
6868
static bool riscv013_get_impebreak(const struct target *target);
6969
static unsigned int riscv013_get_progbufsize(const struct target *target);
7070

71-
typedef enum {
72-
HALT_GROUP,
73-
RESUME_GROUP
74-
} grouptype_t;
7571
static int set_group(struct target *target, bool *supported, unsigned int group,
76-
grouptype_t grouptype);
72+
enum grouptype grouptype, bool is_trigger, unsigned int trigger_num);
7773

7874
/**
7975
* Since almost everything can be accomplish by scanning the dbus register, all
@@ -138,6 +134,8 @@ typedef struct {
138134
* abstractcs.busy may have remained set. In that case we may need to
139135
* re-check the busy state before executing these operations. */
140136
bool abstract_cmd_maybe_busy;
137+
138+
struct riscv_ext_trigger external_triggers[RISCV_MAX_EXTTRIGGERS];
141139
} dm013_info_t;
142140

143141
typedef struct {
@@ -1732,7 +1730,7 @@ static int halt_set_dcsr_ebreak(struct target *target)
17321730

17331731
if (info->haltgroup_supported) {
17341732
bool supported;
1735-
if (set_group(target, &supported, 0, HALT_GROUP) != ERROR_OK)
1733+
if (set_group(target, &supported, 0, HALT_GROUP, false, 0) != ERROR_OK)
17361734
return ERROR_FAIL;
17371735
if (!supported)
17381736
LOG_TARGET_ERROR(target, "Couldn't place hart in halt group 0. "
@@ -1754,7 +1752,7 @@ static int halt_set_dcsr_ebreak(struct target *target)
17541752
/* Add it back to the halt group. */
17551753
if (info->haltgroup_supported) {
17561754
bool supported;
1757-
if (set_group(target, &supported, target->smp, HALT_GROUP) != ERROR_OK)
1755+
if (set_group(target, &supported, target->smp, HALT_GROUP, false, 0) != ERROR_OK)
17581756
return ERROR_FAIL;
17591757
if (!supported)
17601758
LOG_TARGET_ERROR(target, "Couldn't place hart back in halt group %d. "
@@ -1785,19 +1783,46 @@ static void deinit_target(struct target *target)
17851783
}
17861784

17871785
static int set_group(struct target *target, bool *supported, unsigned int group,
1788-
grouptype_t grouptype)
1786+
enum grouptype grouptype, bool is_trigger, unsigned int trigger_num)
17891787
{
1790-
uint32_t write_val = DM_DMCS2_HGWRITE;
17911788
assert(group <= 31);
1789+
assert(trigger_num < 16);
1790+
1791+
if (!is_trigger && dm013_select_target(target) != ERROR_OK)
1792+
return ERROR_FAIL;
1793+
1794+
dm013_info_t *dm = get_dm(target);
1795+
if (!dm)
1796+
return ERROR_FAIL;
1797+
if (is_trigger && dm->external_triggers[trigger_num].haltgroup_was_set &&
1798+
dm->external_triggers[trigger_num].haltgroup_num == group) {
1799+
LOG_TARGET_WARNING(target, "External trigger %d (at address dbgbase=0x%" PRIx32 ") for halt group %d has been set.",
1800+
trigger_num, dm->base, group);
1801+
return ERROR_OK;
1802+
}
1803+
1804+
uint32_t write_val = DM_DMCS2_HGWRITE;
17921805
write_val = set_field(write_val, DM_DMCS2_GROUP, group);
17931806
write_val = set_field(write_val, DM_DMCS2_GROUPTYPE, (grouptype == HALT_GROUP) ? 0 : 1);
1807+
write_val = set_field(write_val, DM_DMCS2_DMEXTTRIGGER, trigger_num);
1808+
write_val = set_field(write_val, DM_DMCS2_HGSELECT,
1809+
is_trigger ? DM_DMCS2_HGSELECT_TRIGGERS : DM_DMCS2_HGSELECT_HARTS);
17941810
if (dm_write(target, DM_DMCS2, write_val) != ERROR_OK)
17951811
return ERROR_FAIL;
17961812
uint32_t read_val;
17971813
if (dm_read(target, &read_val, DM_DMCS2) != ERROR_OK)
17981814
return ERROR_FAIL;
17991815
if (supported)
1800-
*supported = (get_field(read_val, DM_DMCS2_GROUP) == group);
1816+
*supported = (get_field(read_val, DM_DMCS2_GROUP) == group &&
1817+
get_field(read_val, DM_DMCS2_GROUPTYPE) == ((grouptype == HALT_GROUP) ? 0 : 1) &&
1818+
get_field(read_val, DM_DMCS2_HGSELECT) ==
1819+
(is_trigger ? DM_DMCS2_HGSELECT_TRIGGERS : DM_DMCS2_HGSELECT_HARTS) &&
1820+
get_field(read_val, DM_DMCS2_DMEXTTRIGGER) == trigger_num);
1821+
if (is_trigger && *supported) {
1822+
dm->external_triggers[trigger_num].haltgroup_was_set = true;
1823+
dm->external_triggers[trigger_num].haltgroup_num = group;
1824+
}
1825+
18011826
return ERROR_OK;
18021827
}
18031828

@@ -2145,8 +2170,9 @@ static int examine(struct target *target)
21452170
}
21462171

21472172
if (target->smp) {
2148-
if (set_group(target, &info->haltgroup_supported, target->smp, HALT_GROUP) != ERROR_OK)
2173+
if (set_group(target, &info->haltgroup_supported, target->smp, HALT_GROUP, false, 0) != ERROR_OK)
21492174
return ERROR_FAIL;
2175+
21502176
if (info->haltgroup_supported)
21512177
LOG_TARGET_INFO(target, "Core %d made part of halt group %d.", info->index,
21522178
target->smp);
@@ -2881,6 +2907,8 @@ static int init_target(struct command_context *cmd_ctx,
28812907
generic_info->handle_became_unavailable = &handle_became_unavailable;
28822908
generic_info->tick = &tick;
28832909

2910+
generic_info->set_group = &set_group;
2911+
28842912
if (!generic_info->version_specific) {
28852913
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
28862914
if (!generic_info->version_specific)

src/target/riscv/riscv.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5588,6 +5588,75 @@ COMMAND_HANDLER(handle_riscv_virt2phys_mode)
55885588
return ERROR_OK;
55895589
}
55905590

5591+
COMMAND_HANDLER(riscv_set_group)
5592+
{
5593+
struct target *target = get_current_target(CMD_CTX);
5594+
RISCV_INFO(r);
5595+
5596+
if (CMD_ARGC < 2) {
5597+
return ERROR_COMMAND_SYNTAX_ERROR;
5598+
}
5599+
5600+
enum grouptype grouptype;
5601+
if (!strcmp("halt_group", CMD_ARGV[0])) {
5602+
grouptype = HALT_GROUP;
5603+
} else {
5604+
/* Ext. triggers for resume groups are not supported: neither OpenOCD nor GDB
5605+
* have a concept of hart resuming on its own due to an external reason, without
5606+
* an explicit resume request. */
5607+
LOG_ERROR("%s is not a valid argument. "
5608+
"The only supported group type is 'halt_group'.", CMD_ARGV[1]);
5609+
return ERROR_COMMAND_ARGUMENT_INVALID;
5610+
}
5611+
5612+
unsigned int group;
5613+
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], group);
5614+
if (group > 31) {
5615+
LOG_ERROR("%d is not a valid group number - expecting a number in range 0..31.",
5616+
group);
5617+
return ERROR_COMMAND_ARGUMENT_INVALID;
5618+
}
5619+
5620+
if (!r->set_group) {
5621+
LOG_TARGET_ERROR(target, "set_group is not implemented for this target.");
5622+
return ERROR_FAIL;
5623+
}
5624+
5625+
bool is_trigger = false;
5626+
unsigned int trigger_num = 0;
5627+
switch (CMD_ARGC) {
5628+
case 2:
5629+
break;
5630+
case 4:
5631+
if (strcmp("trigger", CMD_ARGV[2]))
5632+
return ERROR_COMMAND_SYNTAX_ERROR;
5633+
is_trigger = true;
5634+
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[3], trigger_num);
5635+
if (trigger_num > 15) {
5636+
LOG_ERROR("%d is not a valid external trigger number - expecting a number in range 0..15.",
5637+
trigger_num);
5638+
return ERROR_COMMAND_ARGUMENT_INVALID;
5639+
}
5640+
break;
5641+
default:
5642+
return ERROR_COMMAND_SYNTAX_ERROR;
5643+
}
5644+
5645+
bool supported;
5646+
if (r->set_group(target, &supported, group, grouptype, is_trigger, trigger_num) != ERROR_OK)
5647+
return ERROR_FAIL;
5648+
5649+
if (supported)
5650+
LOG_TARGET_INFO(target, "%s %d made part of halt group %d.",
5651+
(is_trigger ? "External trigger" : "Core") , (is_trigger ? trigger_num : (unsigned int)target->coreid), group);
5652+
else
5653+
LOG_TARGET_WARNING(target, "%s %d could not be made part of halt group %d.",
5654+
(is_trigger ? "External trigger" : "Core") , (is_trigger ? trigger_num : (unsigned int)target->coreid), group);
5655+
5656+
return ERROR_OK;
5657+
}
5658+
5659+
55915660
static const struct command_registration riscv_exec_command_handlers[] = {
55925661
{
55935662
.name = "dump_sample_buf",
@@ -5850,6 +5919,13 @@ static const struct command_registration riscv_exec_command_handlers[] = {
58505919
"When off, users need to take care of memory coherency themselves, for example by using "
58515920
"`riscv exec_progbuf` to execute fence or CMO instructions."
58525921
},
5922+
{
5923+
.name = "set_group",
5924+
.handler = riscv_set_group,
5925+
.mode = COMMAND_ANY,
5926+
.usage = "grouptype group ['trigger' triggernum]",
5927+
.help = "Set a hart or a given external trigger to the halt group."
5928+
},
58535929
COMMAND_REGISTRATION_DONE
58545930
};
58555931

src/target/riscv/riscv.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct riscv_program;
2121
#define RISCV_MAX_TRIGGERS 32
2222
#define RISCV_MAX_HWBPS 16
2323
#define RISCV_MAX_DMS 100
24+
#define RISCV_MAX_EXTTRIGGERS 16
2425

2526
#define DEFAULT_COMMAND_TIMEOUT_SEC 5
2627

@@ -122,6 +123,11 @@ typedef struct {
122123
char *name;
123124
} range_list_t;
124125

126+
enum grouptype {
127+
HALT_GROUP,
128+
RESUME_GROUP
129+
};
130+
125131
#define DTM_DTMCS_VERSION_UNKNOWN ((unsigned int)-1)
126132
#define RISCV_TINFO_VERSION_UNKNOWN (-1)
127133

@@ -144,6 +150,17 @@ typedef struct riscv_mem_access_args {
144150
uint32_t increment;
145151
} riscv_mem_access_args_t;
146152

153+
struct riscv_ext_trigger {
154+
bool haltgroup_was_set;
155+
unsigned int haltgroup_num;
156+
/*
157+
In future, this can be added:
158+
159+
bool resumegroup_was_set;
160+
unsigned int resumegroup_num;
161+
*/
162+
};
163+
147164
static inline bool
148165
riscv_mem_access_is_valid(const riscv_mem_access_args_t args)
149166
{
@@ -307,6 +324,9 @@ struct riscv_info {
307324

308325
unsigned int (*data_bits)(struct target *target);
309326

327+
int (*set_group)(struct target *target, bool *supported, unsigned int group,
328+
enum grouptype grouptype, bool is_trigger, unsigned int trigger_num);
329+
310330
COMMAND_HELPER((*print_info), struct target *target);
311331

312332
/* Storage for arch_info of non-custom registers. */

0 commit comments

Comments
 (0)