Skip to content

Commit bf7c3ac

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

File tree

4 files changed

+111
-4
lines changed

4 files changed

+111
-4
lines changed

doc/openocd.texi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11616,6 +11616,11 @@ 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_add_ext_triggers} grouptype1 num1 [grouptype2 num2] ...
11620+
Associate the supplied external trigger with the halt group for the harts. When
11621+
the external trigger fires the harts in the halt group will be halted.
11622+
@end deffn
11623+
1161911624
@subsection RISC-V Authentication Commands
1162011625

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

src/target/riscv/riscv-013.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ 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,
7672
grouptype_t grouptype);
7773

@@ -1784,6 +1780,37 @@ static void deinit_target(struct target *target)
17841780
info->version_specific = NULL;
17851781
}
17861782

1783+
static int smp_add_ext_trigger(struct target *target, unsigned int group,
1784+
riscv_ext_trigger_t external_trigger)
1785+
{
1786+
uint32_t write_val = DM_DMCS2_HGSELECT;
1787+
assert(group <= 31);
1788+
assert(external_trigger.dmexttrigger < 16);
1789+
write_val = set_field(write_val, DM_DMCS2_GROUP, group);
1790+
write_val = set_field(write_val, DM_DMCS2_GROUPTYPE, external_trigger.grouptype);
1791+
write_val = set_field(write_val, DM_DMCS2_DMEXTTRIGGER, external_trigger.dmexttrigger);
1792+
if (dm_write(target, DM_DMCS2, write_val) != ERROR_OK)
1793+
return ERROR_FAIL;
1794+
write_val = set_field(write_val, DM_DMCS2_HGWRITE, 1);
1795+
if (dm_write(target, DM_DMCS2, write_val) != ERROR_OK)
1796+
return ERROR_FAIL;
1797+
1798+
uint32_t read_val;
1799+
if (dm_read(target, &read_val, DM_DMCS2) != ERROR_OK)
1800+
return ERROR_FAIL;
1801+
if (get_field(read_val, DM_DMCS2_GROUP) == group &&
1802+
get_field(read_val, DM_DMCS2_DMEXTTRIGGER) == external_trigger.dmexttrigger &&
1803+
get_field(read_val, DM_DMCS2_HGSELECT) == 1) {
1804+
LOG_TARGET_INFO(target, "External trigger %d added to %s group %d", external_trigger.dmexttrigger,
1805+
external_trigger.grouptype ? "resume" : "halt", group);
1806+
} else {
1807+
LOG_TARGET_ERROR(target, "External trigger %d not supported %s group %d", external_trigger.dmexttrigger,
1808+
external_trigger.grouptype ? "resume" : "halt", group);
1809+
}
1810+
1811+
return ERROR_OK;
1812+
}
1813+
17871814
static int set_group(struct target *target, bool *supported, unsigned int group,
17881815
grouptype_t grouptype)
17891816
{
@@ -2153,6 +2180,20 @@ static int examine(struct target *target)
21532180
else
21542181
LOG_TARGET_INFO(target, "Core %d could not be made part of halt group %d.",
21552182
info->index, target->smp);
2183+
2184+
/* TODO: Resume groups with external input triggers look to be very problematic.
2185+
* Neither OpenOCD nor GDB is ready for the case when a target suddenly
2186+
* resumes (due to the trigger), without an explicit resume request and
2187+
* at arbitrary moment in time. */
2188+
2189+
for (unsigned int i = 0; i < RISCV_MAX_EXTTRIGGERS; i++) {
2190+
if (r->external_triggers[i].is_set) {
2191+
if (smp_add_ext_trigger(target, target->smp, r->external_triggers[i]) != ERROR_OK)
2192+
return ERROR_FAIL;
2193+
} else {
2194+
break;
2195+
}
2196+
}
21562197
}
21572198

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

src/target/riscv/riscv.c

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

5591+
COMMAND_HANDLER(riscv_smp_add_ext_triggers)
5592+
{
5593+
struct target *target = get_current_target(CMD_CTX);
5594+
RISCV_INFO(r);
5595+
5596+
if (CMD_ARGC % 2) {
5597+
LOG_ERROR("Command takes an even number of parameters.");
5598+
return ERROR_COMMAND_SYNTAX_ERROR;
5599+
}
5600+
5601+
if (CMD_ARGC > 2 * RISCV_MAX_EXTTRIGGERS) {
5602+
LOG_ERROR("The number of parameters can not exceeds %d.", 2 * RISCV_MAX_EXTTRIGGERS);
5603+
return ERROR_COMMAND_SYNTAX_ERROR;
5604+
}
5605+
5606+
unsigned int index = 0;
5607+
for (unsigned int i = 0; i < CMD_ARGC - 1; i += 2) {
5608+
if (!strcmp("halt_group", CMD_ARGV[i])) {
5609+
r->external_triggers[index].grouptype = HALT_GROUP;
5610+
} else if (!strcmp("resume_group", CMD_ARGV[i])) {
5611+
r->external_triggers[index].grouptype = RESUME_GROUP;
5612+
} else {
5613+
LOG_ERROR("%s is not a valid argument for command,"
5614+
"should be halt_group or resume_group.", CMD_ARGV[0]);
5615+
return ERROR_COMMAND_SYNTAX_ERROR;
5616+
}
5617+
int value = atoi(CMD_ARGV[i + 1]);
5618+
if (value < 0 || value > 16) {
5619+
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[i + 1]);
5620+
return ERROR_FAIL;
5621+
}
5622+
r->external_triggers[index].dmexttrigger = value;
5623+
r->external_triggers[index].is_set = true;
5624+
index++;
5625+
}
5626+
5627+
return ERROR_OK;
5628+
}
5629+
5630+
55915631
static const struct command_registration riscv_exec_command_handlers[] = {
55925632
{
55935633
.name = "dump_sample_buf",
@@ -5850,6 +5890,13 @@ static const struct command_registration riscv_exec_command_handlers[] = {
58505890
"When off, users need to take care of memory coherency themselves, for example by using "
58515891
"`riscv exec_progbuf` to execute fence or CMO instructions."
58525892
},
5893+
{
5894+
.name = "smp_add_ext_triggers",
5895+
.handler = riscv_smp_add_ext_triggers,
5896+
.mode = COMMAND_CONFIG,
5897+
.usage = "grouptype1 num1 [grouptype2 num2]......",
5898+
.help = "Add the given external triggers to the halt/resume group"
5899+
},
58535900
COMMAND_REGISTRATION_DONE
58545901
};
58555902

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 32
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+
typedef enum {
149+
HALT_GROUP,
150+
RESUME_GROUP
151+
} grouptype_t;
152+
153+
typedef struct {
154+
grouptype_t grouptype;
155+
uint32_t dmexttrigger;
156+
bool is_set;
157+
} riscv_ext_trigger_t;
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+
riscv_ext_trigger_t external_triggers[RISCV_MAX_EXTTRIGGERS];
368382
};
369383

370384
enum riscv_priv_mode {

0 commit comments

Comments
 (0)