Set up halt groups for SMP groups. (#353)

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
reverse-resume-order
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_AUTHENTICATED, "authenticated" },
{ 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_ABSTRACTCS, DMI_ABSTRACTCS_PROGBUFSIZE, "progbufsize" },
@ -663,12 +664,12 @@ uint32_t abstract_register_size(unsigned width)
{
switch (width) {
case 32:
return set_field(0, AC_ACCESS_REGISTER_SIZE, 2);
return set_field(0, AC_ACCESS_REGISTER_AARSIZE, 2);
case 64:
return set_field(0, AC_ACCESS_REGISTER_SIZE, 3);
return set_field(0, AC_ACCESS_REGISTER_AARSIZE, 3);
break;
case 128:
return set_field(0, AC_ACCESS_REGISTER_SIZE, 4);
return set_field(0, AC_ACCESS_REGISTER_AARSIZE, 4);
break;
default:
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, "
"transfer=%d, write=%d, regno=0x%x",
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_TRANSFER),
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);
switch (size) {
case 32:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2);
command = set_field(command, AC_ACCESS_REGISTER_AARSIZE, 2);
break;
case 64:
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
command = set_field(command, AC_ACCESS_REGISTER_AARSIZE, 3);
break;
default:
assert(0);
@ -1362,6 +1363,18 @@ static void deinit_target(struct target *target)
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)
{
/* 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);

View File

@ -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);