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
This commit is contained in:
parent
c91ff146d8
commit
9fac2de633
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue