aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPalmer Dabbelt <palmer@dabbelt.com>2017-04-06 16:02:18 -0700
committerPalmer Dabbelt <palmer@dabbelt.com>2017-04-07 15:26:17 -0700
commitdd4677c3df4eea7917e750b4c380d8fffaee27f5 (patch)
treea06e58433dfbfb6646fa3f503bf9e55855f9d8e6
parent74095335dc2a147a75d62e1c55be2c80f16876c7 (diff)
downloadriscv-openocd-dd4677c3df4eea7917e750b4c380d8fffaee27f5.zip
riscv-openocd-dd4677c3df4eea7917e750b4c380d8fffaee27f5.tar.gz
riscv-openocd-dd4677c3df4eea7917e750b4c380d8fffaee27f5.tar.bz2
Determine the hart count dynamically
This assumes that v0.11 targets have one hart, and that v0.13 targets have harts IDs that start at 0 and are concecutive.
-rw-r--r--src/target/riscv/riscv-011.c3
-rw-r--r--src/target/riscv/riscv-013.c14
-rw-r--r--src/target/riscv/riscv.c5
-rw-r--r--src/target/riscv/riscv.h3
4 files changed, 24 insertions, 1 deletions
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index ed2a057..10612e2 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -1810,6 +1810,9 @@ static int examine(struct target *target)
return ERROR_FAIL;
}
+ RISCV_INFO(r);
+ r->hart_count = 1;
+
riscv011_info_t *info = get_info(target);
info->addrbits = get_field(dtmcontrol, DTMCONTROL_ADDRBITS);
info->dtmcontrol_idle = get_field(dtmcontrol, DTMCONTROL_IDLE);
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 2eb28bf..759ac08 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1220,6 +1220,20 @@ static int examine(struct target *target)
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
info->progsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGSIZE);
+ /* Before doing anything else we must first enumerate the harts. */
+ RISCV_INFO(r);
+ for (int i = 0; i < RISCV_MAX_HARTS; ++i) {
+ riscv_set_current_hartid(target, i);
+ uint32_t s = dmi_read(target, DMI_DMSTATUS);
+ if (get_field(s, DMI_DMSTATUS_ANYNONEXISTENT))
+ break;
+ r->hart_count = i + 1;
+ }
+
+ /* FIXME: This is broken. */
+ LOG_ERROR("Enumerated %d harts, but there's an off-by-one error in the hardware", r->hart_count);
+ r->hart_count--;
+
/* Halt every hart so we can probe them. */
riscv_halt_all_harts(target);
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 13410bd..d641155 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -963,7 +963,10 @@ void riscv_set_rtos_hartid(struct target *target, int hartid)
int riscv_count_harts(struct target *target)
{
- return 3;
+ if (target == NULL) return 1;
+ RISCV_INFO(r);
+ if (r == NULL) return 1;
+ return r->hart_count;
}
bool riscv_has_register(struct target *target, int hartid, int regid)
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 7ce2622..3b83a08 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -33,6 +33,9 @@ typedef struct {
struct command_context *cmd_ctx;
void *version_specific;
+ /* The number of harts on this system. */
+ int hart_count;
+
/* When the RTOS is enabled this target is expected to handle all the
* harts in the system. When it's disabled this just uses the regular
* multi-target mode. */