From 6030644a9d3683f357ec17d929204266d26162ff Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 26 Jan 2018 15:10:54 -0800 Subject: [PATCH] Track misa per-hart even in -rtos mode This works around some side effects of the -rtos hack, namely that we were unable to set hardware breakpoints on harts whose misa differed from the first one. There may be other bugs like this one lurking elsewhere. The only proper solution is for gdb to have a better user interface when talking to a server that exposes multiple targets, but that's a very big project. This fixes #194. Change-Id: I81aedddeaa922d220e936730e9c731545953ae21 --- src/target/riscv/riscv-011.c | 6 +++--- src/target/riscv/riscv-013.c | 18 ++++++++++-------- src/target/riscv/riscv.c | 35 +++++++++++++++++++++-------------- src/target/riscv/riscv.h | 5 ++--- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 632567f35..b450d2b0f 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -1572,11 +1572,11 @@ static int examine(struct target *target) } LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target)); - if (read_csr(target, &r->misa, CSR_MISA) != ERROR_OK) { + if (read_csr(target, &r->misa[0], CSR_MISA) != ERROR_OK) { const unsigned old_csr_misa = 0xf10; LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA, old_csr_misa); - if (read_csr(target, &r->misa, old_csr_misa) != ERROR_OK) { + if (read_csr(target, &r->misa[0], old_csr_misa) != ERROR_OK) { /* Maybe this is an old core that still has $misa at the old * address. */ LOG_ERROR("Failed to read misa at 0x%x.", old_csr_misa); @@ -1598,7 +1598,7 @@ static int examine(struct target *target) for (size_t i = 0; i < 32; ++i) reg_cache_set(target, i, -1); LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64, - riscv_xlen(target), r->misa); + riscv_xlen(target), r->misa[0]); return ERROR_OK; } diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index a66d0bf17..894694896 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1072,7 +1072,7 @@ static int register_write_direct(struct target *target, unsigned number, return ERROR_FAIL; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 && - riscv_supports_extension(target, 'D') && + riscv_supports_extension(target, riscv_current_hartid(target), 'D') && riscv_xlen(target) < 64) { /* There are no instructions to move all the bits from a register, so * we need to use some scratch RAM. */ @@ -1094,7 +1094,7 @@ static int register_write_direct(struct target *target, unsigned number, return ERROR_FAIL; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - if (riscv_supports_extension(target, 'D')) + if (riscv_supports_extension(target, riscv_current_hartid(target), 'D')) riscv_program_insert(&program, fmv_d_x(number - GDB_REGNO_FPR0, S0)); else riscv_program_insert(&program, fmv_w_x(number - GDB_REGNO_FPR0, S0)); @@ -1150,7 +1150,8 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t set_field(mstatus, MSTATUS_FS, 1)) != ERROR_OK) return ERROR_FAIL; - if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) { + if (riscv_supports_extension(target, riscv_current_hartid(target), 'D') + && riscv_xlen(target) < 64) { /* There are no instructions to move all the bits from a * register, so we need to use some scratch RAM. */ riscv_program_insert(&program, fsd(number - GDB_REGNO_FPR0, S0, @@ -1163,7 +1164,8 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t if (register_write_direct(target, GDB_REGNO_S0, scratch.hart_address) != ERROR_OK) return ERROR_FAIL; - } else if (riscv_supports_extension(target, 'D')) { + } else if (riscv_supports_extension(target, + riscv_current_hartid(target), 'D')) { riscv_program_insert(&program, fmv_x_d(S0, number - GDB_REGNO_FPR0)); } else { riscv_program_insert(&program, fmv_x_w(S0, number - GDB_REGNO_FPR0)); @@ -1378,7 +1380,7 @@ static int examine(struct target *target) else r->xlen[i] = 32; - if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) { + if (register_read_direct(target, &r->misa[i], GDB_REGNO_MISA)) { LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i); return ERROR_FAIL; } @@ -1390,7 +1392,7 @@ static int examine(struct target *target) /* Display this as early as possible to help people who are using * really slow simulators. */ LOG_DEBUG(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i], - r->misa); + r->misa[i]); } LOG_DEBUG("Enumerated %d harts", r->hart_count); @@ -1420,8 +1422,8 @@ static int examine(struct target *target) riscv_count_harts(target)); for (int i = 0; i < riscv_count_harts(target); ++i) { if (riscv_hart_enabled(target, i)) { - LOG_INFO(" hart %d: XLEN=%d, %d triggers", i, r->xlen[i], - r->trigger_count[i]); + LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64 ", %d triggers", i, + r->xlen[i], r->misa[i], r->trigger_count[i]); } else { LOG_INFO(" hart %d: currently disabled", i); } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 2e980dcb4..aea6d7a94 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -313,9 +313,12 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid, tdata1 = set_field(tdata1, bpcontrol_r, trigger->read); tdata1 = set_field(tdata1, bpcontrol_w, trigger->write); tdata1 = set_field(tdata1, bpcontrol_x, trigger->execute); - tdata1 = set_field(tdata1, bpcontrol_u, !!(r->misa & (1 << ('U' - 'A')))); - tdata1 = set_field(tdata1, bpcontrol_s, !!(r->misa & (1 << ('S' - 'A')))); - tdata1 = set_field(tdata1, bpcontrol_h, !!(r->misa & (1 << ('H' - 'A')))); + tdata1 = set_field(tdata1, bpcontrol_u, + !!(r->misa[hartid] & (1 << ('U' - 'A')))); + tdata1 = set_field(tdata1, bpcontrol_s, + !!(r->misa[hartid] & (1 << ('S' - 'A')))); + tdata1 = set_field(tdata1, bpcontrol_h, + !!(r->misa[hartid] & (1 << ('H' - 'A')))); tdata1 |= bpcontrol_m; tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */ tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */ @@ -358,11 +361,11 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid, MCONTROL_ACTION_DEBUG_MODE); tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL); tdata1 |= MCONTROL_M; - if (r->misa & (1 << ('H' - 'A'))) + if (r->misa[hartid] & (1 << ('H' - 'A'))) tdata1 |= MCONTROL_H; - if (r->misa & (1 << ('S' - 'A'))) + if (r->misa[hartid] & (1 << ('S' - 'A'))) tdata1 |= MCONTROL_S; - if (r->misa & (1 << ('U' - 'A'))) + if (r->misa[hartid] & (1 << ('U' - 'A'))) tdata1 |= MCONTROL_U; if (trigger->execute) @@ -1648,7 +1651,7 @@ int riscv_step_rtos_hart(struct target *target) return ERROR_OK; } -bool riscv_supports_extension(struct target *target, char letter) +bool riscv_supports_extension(struct target *target, int hartid, char letter) { RISCV_INFO(r); unsigned num; @@ -1658,7 +1661,7 @@ bool riscv_supports_extension(struct target *target, char letter) num = letter - 'A'; else return false; - return r->misa & (1 << num); + return r->misa[hartid] & (1 << num); } int riscv_xlen(const struct target *target) @@ -2192,10 +2195,12 @@ int riscv_init_registers(struct target *target) r->feature = &feature_cpu; } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { r->caller_save = true; - if (riscv_supports_extension(target, 'D')) { + if (riscv_supports_extension(target, riscv_current_hartid(target), + 'D')) { r->reg_data_type = &type_ieee_double; r->size = 64; - } else if (riscv_supports_extension(target, 'F')) { + } else if (riscv_supports_extension(target, + riscv_current_hartid(target), 'F')) { r->reg_data_type = &type_ieee_single; r->size = 32; } else { @@ -2326,7 +2331,8 @@ int riscv_init_registers(struct target *target) case CSR_FFLAGS: case CSR_FRM: case CSR_FCSR: - r->exist = riscv_supports_extension(target, 'F'); + r->exist = riscv_supports_extension(target, + riscv_current_hartid(target), 'F'); r->group = "float"; r->feature = &feature_fpu; break; @@ -2340,15 +2346,16 @@ int riscv_init_registers(struct target *target) case CSR_SCAUSE: case CSR_STVAL: case CSR_SATP: - r->exist = riscv_supports_extension(target, 'S'); + r->exist = riscv_supports_extension(target, + riscv_current_hartid(target), 'S'); break; case CSR_MEDELEG: case CSR_MIDELEG: /* "In systems with only M-mode, or with both M-mode and * U-mode but without U-mode trap support, the medeleg and * mideleg registers should not exist." */ - r->exist = riscv_supports_extension(target, 'S') || - riscv_supports_extension(target, 'N'); + r->exist = riscv_supports_extension(target, riscv_current_hartid(target), 'S') || + riscv_supports_extension(target, riscv_current_hartid(target), 'N'); break; } diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index ad70f4caa..8e06bd5fd 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -37,8 +37,6 @@ enum riscv_halt_reason { typedef struct { unsigned dtm_version; - riscv_reg_t misa; - struct command_context *cmd_ctx; void *version_specific; @@ -68,6 +66,7 @@ typedef struct { /* It's possible that each core has a different supported ISA set. */ int xlen[RISCV_MAX_HARTS]; + riscv_reg_t misa[RISCV_MAX_HARTS]; /* The number of triggers per hart. */ unsigned trigger_count[RISCV_MAX_HARTS]; @@ -183,7 +182,7 @@ int riscv_resume_one_hart(struct target *target, int hartid); * then the only hart. */ int riscv_step_rtos_hart(struct target *target); -bool riscv_supports_extension(struct target *target, char letter); +bool riscv_supports_extension(struct target *target, int hartid, char letter); /* Returns XLEN for the given (or current) hart. */ int riscv_xlen(const struct target *target);