From dd4677c3df4eea7917e750b4c380d8fffaee27f5 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 6 Apr 2017 16:02:18 -0700 Subject: [PATCH] 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. --- src/target/riscv/riscv-011.c | 3 +++ src/target/riscv/riscv-013.c | 14 ++++++++++++++ src/target/riscv/riscv.c | 5 ++++- src/target/riscv/riscv.h | 3 +++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index ed2a057ea..10612e22c 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 2eb28bf47..759ac088f 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 13410bdb0..d64115503 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 7ce26228e..3b83a08ad 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. */