Set up halt groups for SMP groups. ()

If the hardware supports it, when one hart in an SMP group halts all the
other harts in that same SMP group will automatically, quickly, halt as
well.

Change-Id: Ida81f1309c180674e8c9d8060e3d2a4bbb910a6f
This commit is contained in:
Tim Newsome 2019-03-05 13:05:53 -08:00 committed by GitHub
parent c91ff146d8
commit 9fac2de633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 616 additions and 164 deletions

File diff suppressed because it is too large Load Diff

View File

@ -314,7 +314,8 @@ static void decode_dmi(char *text, unsigned address, unsigned data)
{ DMI_DMSTATUS, DMI_DMSTATUS_ANYHALTED, "anyhalted" }, { DMI_DMSTATUS, DMI_DMSTATUS_ANYHALTED, "anyhalted" },
{ DMI_DMSTATUS, DMI_DMSTATUS_AUTHENTICATED, "authenticated" }, { DMI_DMSTATUS, DMI_DMSTATUS_AUTHENTICATED, "authenticated" },
{ DMI_DMSTATUS, DMI_DMSTATUS_AUTHBUSY, "authbusy" }, { DMI_DMSTATUS, DMI_DMSTATUS_AUTHBUSY, "authbusy" },
{ DMI_DMSTATUS, DMI_DMSTATUS_DEVTREEVALID, "devtreevalid" }, { DMI_DMSTATUS, DMI_DMSTATUS_HASRESETHALTREQ, "hasresethaltreq" },
{ DMI_DMSTATUS, DMI_DMSTATUS_CONFSTRPTRVALID, "confstrptrvalid" },
{ DMI_DMSTATUS, DMI_DMSTATUS_VERSION, "version" }, { DMI_DMSTATUS, DMI_DMSTATUS_VERSION, "version" },
{ DMI_ABSTRACTCS, DMI_ABSTRACTCS_PROGBUFSIZE, "progbufsize" }, { DMI_ABSTRACTCS, DMI_ABSTRACTCS_PROGBUFSIZE, "progbufsize" },
@ -663,12 +664,12 @@ uint32_t abstract_register_size(unsigned width)
{ {
switch (width) { switch (width) {
case 32: case 32:
return set_field(0, AC_ACCESS_REGISTER_SIZE, 2); return set_field(0, AC_ACCESS_REGISTER_AARSIZE, 2);
case 64: case 64:
return set_field(0, AC_ACCESS_REGISTER_SIZE, 3); return set_field(0, AC_ACCESS_REGISTER_AARSIZE, 3);
break; break;
case 128: case 128:
return set_field(0, AC_ACCESS_REGISTER_SIZE, 4); return set_field(0, AC_ACCESS_REGISTER_AARSIZE, 4);
break; break;
default: default:
LOG_ERROR("Unsupported register width: %d", width); LOG_ERROR("Unsupported register width: %d", width);
@ -722,7 +723,7 @@ static int execute_abstract_command(struct target *target, uint32_t command)
LOG_DEBUG("command=0x%x; access register, size=%d, postexec=%d, " LOG_DEBUG("command=0x%x; access register, size=%d, postexec=%d, "
"transfer=%d, write=%d, regno=0x%x", "transfer=%d, write=%d, regno=0x%x",
command, command,
8 << get_field(command, AC_ACCESS_REGISTER_SIZE), 8 << get_field(command, AC_ACCESS_REGISTER_AARSIZE),
get_field(command, AC_ACCESS_REGISTER_POSTEXEC), get_field(command, AC_ACCESS_REGISTER_POSTEXEC),
get_field(command, AC_ACCESS_REGISTER_TRANSFER), get_field(command, AC_ACCESS_REGISTER_TRANSFER),
get_field(command, AC_ACCESS_REGISTER_WRITE), get_field(command, AC_ACCESS_REGISTER_WRITE),
@ -798,10 +799,10 @@ static uint32_t access_register_command(struct target *target, uint32_t number,
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0); uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0);
switch (size) { switch (size) {
case 32: case 32:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2); command = set_field(command, AC_ACCESS_REGISTER_AARSIZE, 2);
break; break;
case 64: case 64:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3); command = set_field(command, AC_ACCESS_REGISTER_AARSIZE, 3);
break; break;
default: default:
assert(0); assert(0);
@ -1362,6 +1363,18 @@ static void deinit_target(struct target *target)
info->version_specific = NULL; info->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) static int examine(struct target *target)
{ {
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */ /* 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) if (target->rtos)
riscv_update_threads(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 /* Some regression suites rely on seeing 'Examined RISC-V core' to know
* when they can connect with gdb/telnet. * when they can connect with gdb/telnet.
* We will need to update those suites if we want to change that text. */ * 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) int riscv013_execute_debug_buffer(struct target *target)
{ {
uint32_t run_program = 0; 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_POSTEXEC, 1);
run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0); run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0);
run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000); run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000);

View File

@ -5839,6 +5839,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int i; int i;
const char *targetname; const char *targetname;
int retval, len; int retval, len;
static int smp_group = 1;
struct target *target = (struct target *) NULL; struct target *target = (struct target *) NULL;
struct target_list *head, *curr, *new; struct target_list *head, *curr, *new;
curr = (struct target_list *) NULL; 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) { while (curr != (struct target_list *)NULL) {
target = curr->target; target = curr->target;
target->smp = 1; target->smp = smp_group;
target->head = head; target->head = head;
curr = curr->next; curr = curr->next;
} }
smp_group++;
if (target && target->rtos) if (target && target->rtos)
retval = rtos_smp_init(head->target); retval = rtos_smp_init(head->target);