Skip to content

Commit af9e4f4

Browse files
committed
target/riscv: Add support for external triggers
Add support for associating a halt group with an external trigger via a newly exposed configuration option "riscv smp_add_ext_triggers". Original merge request: riscv-collab#1179 Original author: Rob Bradford rbradford@rivosinc.com https://github.com/rbradford
1 parent 2605cbd commit af9e4f4

File tree

4 files changed

+111
-6
lines changed

4 files changed

+111
-6
lines changed

doc/openocd.texi

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11616,6 +11616,19 @@ The second argument configures how OpenOCD should use the selected trigger featu
1161611616
With no parameters, prints current trigger features configuration.
1161711617
@end deffn
1161811618

11619+
@deffn {Command} {riscv smp_set_ext_triggers} num1 grouptype1 [num2 grouptype2] ...
11620+
OpenOCD assigns targets of a SMP group into a RISC-V halt group. This command associates the
11621+
supplied external trigger(s) with this halt group.
11622+
11623+
When an external input trigger fires, the harts in the halt group will get halted. Similarly, all
11624+
external output triggers will be notified when a hart in the halt group halts.
11625+
11626+
The only supported value of @var{grouptype} is @option{halt_group}. RISC-V resume groups
11627+
are not allowed because the concept of a target resuming due to a different reason than
11628+
user's resume request is not supported by OpenOCD and GDB.
11629+
@end deffn
11630+
11631+
1161911632
@subsection RISC-V Authentication Commands
1162011633

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

src/target/riscv/riscv-013.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ typedef enum {
7373
RESUME_GROUP
7474
} grouptype_t;
7575
static int set_group(struct target *target, bool *supported, unsigned int group,
76-
grouptype_t grouptype);
76+
grouptype_t grouptype, bool is_trigger, unsigned int trigger_num);
7777

7878
/**
7979
* Since almost everything can be accomplish by scanning the dbus register, all
@@ -1732,7 +1732,7 @@ static int halt_set_dcsr_ebreak(struct target *target)
17321732

17331733
if (info->haltgroup_supported) {
17341734
bool supported;
1735-
if (set_group(target, &supported, 0, HALT_GROUP) != ERROR_OK)
1735+
if (set_group(target, &supported, 0, HALT_GROUP, false, 0) != ERROR_OK)
17361736
return ERROR_FAIL;
17371737
if (!supported)
17381738
LOG_TARGET_ERROR(target, "Couldn't place hart in halt group 0. "
@@ -1754,7 +1754,7 @@ static int halt_set_dcsr_ebreak(struct target *target)
17541754
/* Add it back to the halt group. */
17551755
if (info->haltgroup_supported) {
17561756
bool supported;
1757-
if (set_group(target, &supported, target->smp, HALT_GROUP) != ERROR_OK)
1757+
if (set_group(target, &supported, target->smp, HALT_GROUP, false, 0) != ERROR_OK)
17581758
return ERROR_FAIL;
17591759
if (!supported)
17601760
LOG_TARGET_ERROR(target, "Couldn't place hart back in halt group %d. "
@@ -1785,19 +1785,26 @@ static void deinit_target(struct target *target)
17851785
}
17861786

17871787
static int set_group(struct target *target, bool *supported, unsigned int group,
1788-
grouptype_t grouptype)
1788+
grouptype_t grouptype, bool is_trigger, unsigned int trigger_num)
17891789
{
17901790
uint32_t write_val = DM_DMCS2_HGWRITE;
17911791
assert(group <= 31);
17921792
write_val = set_field(write_val, DM_DMCS2_GROUP, group);
17931793
write_val = set_field(write_val, DM_DMCS2_GROUPTYPE, (grouptype == HALT_GROUP) ? 0 : 1);
1794+
write_val = set_field(write_val, DM_DMCS2_DMEXTTRIGGER, trigger_num);
1795+
write_val = set_field(write_val, DM_DMCS2_HGSELECT,
1796+
is_trigger ? DM_DMCS2_HGSELECT_TRIGGERS : DM_DMCS2_HGSELECT_HARTS);
17941797
if (dm_write(target, DM_DMCS2, write_val) != ERROR_OK)
17951798
return ERROR_FAIL;
17961799
uint32_t read_val;
17971800
if (dm_read(target, &read_val, DM_DMCS2) != ERROR_OK)
17981801
return ERROR_FAIL;
17991802
if (supported)
1800-
*supported = (get_field(read_val, DM_DMCS2_GROUP) == group);
1803+
*supported = (get_field(read_val, DM_DMCS2_GROUP) == group &&
1804+
get_field(read_val, DM_DMCS2_GROUPTYPE) == ((grouptype == HALT_GROUP) ? 0 : 1) &&
1805+
get_field(read_val, DM_DMCS2_HGSELECT) ==
1806+
(is_trigger ? DM_DMCS2_HGSELECT_TRIGGERS : DM_DMCS2_HGSELECT_HARTS) &&
1807+
get_field(read_val, DM_DMCS2_DMEXTTRIGGER) == trigger_num);
18011808
return ERROR_OK;
18021809
}
18031810

@@ -2145,14 +2152,33 @@ static int examine(struct target *target)
21452152
}
21462153

21472154
if (target->smp) {
2148-
if (set_group(target, &info->haltgroup_supported, target->smp, HALT_GROUP) != ERROR_OK)
2155+
if (set_group(target, &info->haltgroup_supported, target->smp, HALT_GROUP, false, 0) != ERROR_OK)
21492156
return ERROR_FAIL;
21502157
if (info->haltgroup_supported)
21512158
LOG_TARGET_INFO(target, "Core %d made part of halt group %d.", info->index,
21522159
target->smp);
21532160
else
21542161
LOG_TARGET_INFO(target, "Core %d could not be made part of halt group %d.",
21552162
info->index, target->smp);
2163+
2164+
for (unsigned int i = 0; i < RISCV_MAX_EXTTRIGGERS; i++) {
2165+
if (r->external_triggers[i].haltgroup_num != 0 &&
2166+
!r->external_triggers[i].haltgroup_was_set &&
2167+
info->haltgroup_supported) {
2168+
bool supported;
2169+
if (set_group(target, &supported, target->smp, HALT_GROUP, true, i) != ERROR_OK)
2170+
return ERROR_FAIL;
2171+
if (supported) {
2172+
r->external_triggers[i].haltgroup_was_set = true;
2173+
LOG_TARGET_INFO(target, "External trigger %d made part of halt group %d.",
2174+
i, target->smp);
2175+
} else {
2176+
LOG_TARGET_WARNING(target, "External trigger %d could not be made part of halt group %d.",
2177+
i, target->smp);
2178+
}
2179+
}
2180+
}
2181+
21562182
}
21572183

21582184
/* Some regression suites rely on seeing 'Examined RISC-V core' to know

src/target/riscv/riscv.c

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

5591+
COMMAND_HANDLER(riscv_smp_set_ext_triggers)
5592+
{
5593+
struct target *target = get_current_target(CMD_CTX);
5594+
RISCV_INFO(r);
5595+
5596+
if (!target->smp) {
5597+
LOG_TARGET_ERROR(target, "This target does not belong to any SMP group. "
5598+
"Command 'riscv smp_set_ext_triggers' cannot be used.");
5599+
return ERROR_FAIL;
5600+
}
5601+
5602+
if (CMD_ARGC % 2) {
5603+
LOG_ERROR("Command takes an even number of parameters.");
5604+
return ERROR_COMMAND_SYNTAX_ERROR;
5605+
}
5606+
5607+
if (CMD_ARGC > 2 * RISCV_MAX_EXTTRIGGERS) {
5608+
LOG_ERROR("The number of parameters must not exceed %d.", 2 * RISCV_MAX_EXTTRIGGERS);
5609+
return ERROR_COMMAND_SYNTAX_ERROR;
5610+
}
5611+
5612+
unsigned int trigger_num = 0;
5613+
for (unsigned int i = 0; i < CMD_ARGC - 1; i += 2) {
5614+
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[i], trigger_num);
5615+
if (trigger_num > 15) {
5616+
LOG_ERROR("%s is not a valid external trigger number - expecting a number in range 0..15.",
5617+
CMD_ARGV[i + 1]);
5618+
return ERROR_COMMAND_ARGUMENT_INVALID;
5619+
}
5620+
if (!strcmp("halt_group", CMD_ARGV[i + 1])) {
5621+
r->external_triggers[trigger_num].haltgroup_num = target->smp;
5622+
} else {
5623+
/* Ext. triggers for resume groups are not supported: neither OpenOCD nor GDB
5624+
* have a concept of hart resuming on its own due to an external reason, without
5625+
* an explicit resume request. */
5626+
LOG_ERROR("%s is not a valid argument. "
5627+
"The only supported group type is 'halt_group'.", CMD_ARGV[0]);
5628+
return ERROR_COMMAND_ARGUMENT_INVALID;
5629+
}
5630+
}
5631+
5632+
return ERROR_OK;
5633+
}
5634+
5635+
55915636
static const struct command_registration riscv_exec_command_handlers[] = {
55925637
{
55935638
.name = "dump_sample_buf",
@@ -5850,6 +5895,13 @@ static const struct command_registration riscv_exec_command_handlers[] = {
58505895
"When off, users need to take care of memory coherency themselves, for example by using "
58515896
"`riscv exec_progbuf` to execute fence or CMO instructions."
58525897
},
5898+
{
5899+
.name = "smp_set_ext_triggers",
5900+
.handler = riscv_smp_set_ext_triggers,
5901+
.mode = COMMAND_CONFIG,
5902+
.usage = "num1 grouptype1 [num2 grouptype2]......",
5903+
.help = "Set the given external triggers to the halt group."
5904+
},
58535905
COMMAND_REGISTRATION_DONE
58545906
};
58555907

src/target/riscv/riscv.h

Lines changed: 14 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

@@ -144,6 +145,17 @@ typedef struct riscv_mem_access_args {
144145
uint32_t increment;
145146
} riscv_mem_access_args_t;
146147

148+
struct riscv_ext_trigger {
149+
bool haltgroup_was_set;
150+
unsigned int haltgroup_num;
151+
/*
152+
In future, this can be added:
153+
154+
bool resumegroup_was_set;
155+
unsigned int resumegroup_num;
156+
*/
157+
};
158+
147159
static inline bool
148160
riscv_mem_access_is_valid(const riscv_mem_access_args_t args)
149161
{
@@ -365,6 +377,8 @@ struct riscv_info {
365377
bool wp_allow_ge_lt_trigger;
366378

367379
bool autofence;
380+
381+
struct riscv_ext_trigger external_triggers[RISCV_MAX_EXTTRIGGERS];
368382
};
369383

370384
enum riscv_priv_mode {

0 commit comments

Comments
 (0)