From 5c0a9a9ee40c94714a5061b4df7033d6716985b2 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 5 Apr 2018 17:59:07 -0700 Subject: Just read abstractcs once when executing a command DebugBreakpoint went from 3.41s to 3.05s! Change-Id: Icfc4ad5fb663b3607bf2027fda744b43be662fc5 --- src/target/riscv/riscv-013.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 8946948..26a8c95 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -670,17 +670,12 @@ static int execute_abstract_command(struct target *target, uint32_t command) LOG_DEBUG("command=0x%x", command); dmi_write(target, DMI_COMMAND, command); - { - uint32_t abstractcs = 0; - wait_for_idle(target, &abstractcs); - } + uint32_t abstractcs = 0; + wait_for_idle(target, &abstractcs); - uint32_t cs; - if (dmi_read(target, &cs, DMI_ABSTRACTCS) != ERROR_OK) - return ERROR_FAIL; - info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR); + info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); if (info->cmderr != 0) { - LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs); + LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, abstractcs); /* Clear the error. */ dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR, info->cmderr)); -- cgit v1.1 From 238b1e9f06709ce993f3057b7be54311485b5467 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 6 Apr 2018 15:52:40 -0700 Subject: Cache registers while halted. This saves us from re-reading s0 before doing just about anything program buffer related. Improves DebugBreakpoint from 3.01s to 2.89s. Feels like the improvement should be larger than that. Maybe my metric isn't very good. Change-Id: I85e1a1ddbf09006d76c451a32048be7b773dcfe9 --- src/target/riscv/riscv-013.c | 72 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 26a8c95..d9e2907 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -57,6 +57,7 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a); static int riscv013_dmi_write_u64_bits(struct target *target); static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf); +static int register_read(struct target *target, uint64_t *value, uint32_t number); static int register_read_direct(struct target *target, uint64_t *value, uint32_t number); static int register_write_direct(struct target *target, unsigned number, uint64_t value); @@ -846,7 +847,7 @@ static int examine_progbuf(struct target *target) } uint64_t s0; - if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; struct riscv_program program; @@ -1055,6 +1056,11 @@ static int register_write_direct(struct target *target, unsigned number, int result = register_write_abstract(target, number, value, register_size(target, number)); + if (result == ERROR_OK && target->reg_cache) { + struct reg *reg = &target->reg_cache->reg_list[number]; + buf_set_u64(reg->value, 0, reg->size, value); + reg->valid = true; + } if (result == ERROR_OK || info->progbufsize + r->impebreak < 2 || !riscv_is_halted(target)) return result; @@ -1063,7 +1069,7 @@ static int register_write_direct(struct target *target, unsigned number, riscv_program_init(&program, target); uint64_t s0; - if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 && @@ -1103,6 +1109,11 @@ static int register_write_direct(struct target *target, unsigned number, int exec_out = riscv_program_exec(&program, target); /* Don't message on error. Probably the register doesn't exist. */ + if (exec_out == ERROR_OK && target->reg_cache) { + struct reg *reg = &target->reg_cache->reg_list[number]; + buf_set_u64(reg->value, 0, reg->size, value); + reg->valid = true; + } /* Restore S0. */ if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) @@ -1111,6 +1122,37 @@ static int register_write_direct(struct target *target, unsigned number, return exec_out; } +/** Return the cached value, or read from the target if necessary. */ +static int register_read(struct target *target, uint64_t *value, uint32_t number) +{ + if (number == GDB_REGNO_ZERO) { + *value = 0; + return ERROR_OK; + } + if (target->reg_cache && + (number <= GDB_REGNO_XPR31 || + (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31))) { + /* Only check the cache for registers that we know won't spontaneously + * change. */ + struct reg *reg = &target->reg_cache->reg_list[number]; + if (reg && reg->valid) { + *value = buf_get_u64(reg->value, 0, reg->size); + LOG_INFO(">>> cache hit on %s: 0x%" PRIx64, + gdb_regno_name(number), *value); + return ERROR_OK; + } + } + int result = register_read_direct(target, value, number); + if (result != ERROR_OK) + return ERROR_FAIL; + if (target->reg_cache) { + struct reg *reg = &target->reg_cache->reg_list[number]; + buf_set_u64(reg->value, 0, reg->size, *value); + reg->valid = true; + } + return ERROR_OK; +} + /** Actually read registers from the target right now. */ static int register_read_direct(struct target *target, uint64_t *value, uint32_t number) { @@ -1131,14 +1173,14 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t bool use_scratch = false; uint64_t s0; - if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; /* Write program to move data into s0. */ uint64_t mstatus; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - if (register_read_direct(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) + if (register_read(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) return ERROR_FAIL; if ((mstatus & MSTATUS_FS) == 0) if (register_write_direct(target, GDB_REGNO_MSTATUS, @@ -1375,7 +1417,7 @@ static int examine(struct target *target) else r->xlen[i] = 32; - if (register_read_direct(target, &r->misa[i], GDB_REGNO_MISA)) { + if (register_read(target, &r->misa[i], GDB_REGNO_MISA)) { LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i); return ERROR_FAIL; } @@ -1948,9 +1990,9 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, * s1 holds the next data value to write */ uint64_t s0, s1; - if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; - if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK) + if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) return ERROR_FAIL; if (execute_fence(target) != ERROR_OK) @@ -2381,9 +2423,9 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, int result = ERROR_OK; uint64_t s0, s1; - if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; - if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK) + if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) return ERROR_FAIL; /* Write the program (store, increment) */ @@ -2607,14 +2649,14 @@ static int riscv013_get_register(struct target *target, int result = ERROR_OK; if (rid == GDB_REGNO_PC) { - result = register_read_direct(target, value, GDB_REGNO_DPC); + result = register_read(target, value, GDB_REGNO_DPC); LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR); + result = register_read(target, &dcsr, GDB_REGNO_DCSR); *value = get_field(dcsr, CSR_DCSR_PRV); } else { - result = register_read_direct(target, value, rid); + result = register_read(target, value, rid); if (result != ERROR_OK) *value = -1; } @@ -2644,7 +2686,7 @@ static int riscv013_set_register(struct target *target, int hid, int rid, uint64 } } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - register_read_direct(target, &dcsr, GDB_REGNO_DCSR); + register_read(target, &dcsr, GDB_REGNO_DCSR); dcsr = set_field(dcsr, CSR_DCSR_PRV, value); return register_write_direct(target, GDB_REGNO_DCSR, dcsr); } else { @@ -2740,7 +2782,7 @@ static bool riscv013_is_halted(struct target *target) static enum riscv_halt_reason riscv013_halt_reason(struct target *target) { riscv_reg_t dcsr; - int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR); + int result = register_read(target, &dcsr, GDB_REGNO_DCSR); if (result != ERROR_OK) return RISCV_HALT_UNKNOWN; @@ -2839,7 +2881,7 @@ static int riscv013_on_step_or_resume(struct target *target, bool step) /* We want to twiddle some bits in the debug CSR so debugging works. */ riscv_reg_t dcsr; - int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR); + int result = register_read(target, &dcsr, GDB_REGNO_DCSR); if (result != ERROR_OK) return result; dcsr = set_field(dcsr, CSR_DCSR_STEP, step); -- cgit v1.1 From 1fda89c3cef918a87d2b3bcd1f3158c011ef107e Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 9 Apr 2018 15:12:51 -0700 Subject: Only write hartsel if we're changing it. DebugBreakpoint went from 2.94s to 2.74s. Change-Id: Ia3ab857aea89fb83f0bcdd9a6bb69f256bde13dd --- src/target/riscv/riscv-013.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index d9e2907..4d23cd6 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -144,6 +144,8 @@ typedef struct { bool was_reset; /* Targets that are connected to this DM. */ struct list_head target_list; + /* The currently selected hartid on this DM. */ + int current_hartid; } dm013_info_t; typedef struct { @@ -243,6 +245,7 @@ static dm013_info_t *get_dm(struct target *target) if (!dm) { dm = calloc(1, sizeof(dm013_info_t)); dm->abs_chain_position = abs_chain_position; + dm->current_hartid = -1; INIT_LIST_HEAD(&dm->target_list); list_add(&dm->list, &dm_list); } @@ -1137,8 +1140,6 @@ static int register_read(struct target *target, uint64_t *value, uint32_t number struct reg *reg = &target->reg_cache->reg_list[number]; if (reg && reg->valid) { *value = buf_get_u64(reg->value, 0, reg->size); - LOG_INFO(">>> cache hit on %s: 0x%" PRIx64, - gdb_regno_name(number), *value); return ERROR_OK; } } @@ -2700,10 +2701,19 @@ static void riscv013_select_current_hart(struct target *target) { RISCV_INFO(r); + dm013_info_t *dm = get_dm(target); + if (r->current_hartid == dm->current_hartid) { + LOG_DEBUG(">>> nothing to be done"); + return; + } + + LOG_DEBUG(">>> change it"); + uint32_t dmcontrol; dmi_read(target, &dmcontrol, DMI_DMCONTROL); dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid); dmi_write(target, DMI_DMCONTROL, dmcontrol); + dm->current_hartid = r->current_hartid; } static int riscv013_halt_current_hart(struct target *target) -- cgit v1.1 From 005630d24d94203ccd5fbdcc6fb86118fddee42f Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 18 Apr 2018 14:31:00 -0700 Subject: Use reset timeout to read dmstatus out of reset Change-Id: I74cc6a1e006269270c5197994d21523d01206141 --- src/target/riscv/riscv-013.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 4670569..b7f762f 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -482,8 +482,8 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); } -static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, - uint32_t address, uint32_t data_out) +static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, + uint32_t address, uint32_t data_out, int timeout_sec) { select_dmi(target); @@ -520,11 +520,11 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, LOG_ERROR("failed %s at 0x%x, status=%d", op_name, address, status); return ERROR_FAIL; } - if (time(NULL) - start > riscv_command_timeout_sec) { + if (time(NULL) - start > timeout_sec) { LOG_ERROR("dmi.op is still busy after %d seconds. The target is " "either really slow or broken. You could increase the " "timeout with riscv set_command_timeout_sec.", - riscv_command_timeout_sec); + timeout_sec); return ERROR_FAIL; } } @@ -549,11 +549,11 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, status); return ERROR_FAIL; } - if (time(NULL) - start > riscv_command_timeout_sec) { + if (time(NULL) - start > timeout_sec) { LOG_ERROR("dmi.op is still busy after %d seconds. The target is " "either really slow or broken. You could increase the " "timeout with riscv set_command_timeout_sec.", - riscv_command_timeout_sec); + timeout_sec); return ERROR_FAIL; } } @@ -572,6 +572,13 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, return ERROR_OK; } +static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, + uint32_t address, uint32_t data_out) +{ + return dmi_op_timeout(target, data_in, dmi_op, address, data_out, + riscv_command_timeout_sec); +} + static int dmi_read(struct target *target, uint32_t *value, uint32_t address) { return dmi_op(target, value, DMI_OP_READ, address, 0); @@ -582,10 +589,11 @@ static int dmi_write(struct target *target, uint32_t address, uint32_t value) return dmi_op(target, NULL, DMI_OP_WRITE, address, value); } -int dmstatus_read(struct target *target, uint32_t *dmstatus, - bool authenticated) +int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus, + bool authenticated, unsigned timeout_sec) { - if (dmi_read(target, dmstatus, DMI_DMSTATUS) != ERROR_OK) + if (dmi_op_timeout(target, dmstatus, DMI_OP_READ, DMI_DMSTATUS, 0, + timeout_sec) != ERROR_OK) return ERROR_FAIL; if (authenticated && !get_field(*dmstatus, DMI_DMSTATUS_AUTHENTICATED)) { LOG_ERROR("Debugger is not authenticated to target Debug Module. " @@ -596,6 +604,13 @@ int dmstatus_read(struct target *target, uint32_t *dmstatus, return ERROR_OK; } +int dmstatus_read(struct target *target, uint32_t *dmstatus, + bool authenticated) +{ + return dmstatus_read_timeout(target, dmstatus, authenticated, + riscv_command_timeout_sec); +} + static void increase_ac_busy_delay(struct target *target) { riscv013_info_t *info = get_info(target); @@ -1592,7 +1607,8 @@ static int deassert_reset(struct target *target) if (target->reset_halt) { LOG_DEBUG("Waiting for hart %d to halt out of reset.", index); do { - if (dmstatus_read(target, &dmstatus, true) != ERROR_OK) + if (dmstatus_read_timeout(target, &dmstatus, true, + riscv_reset_timeout_sec) != ERROR_OK) return ERROR_FAIL; if (time(NULL) - start > riscv_reset_timeout_sec) { LOG_ERROR("Hart %d didn't halt coming out of reset in %ds; " @@ -1607,7 +1623,8 @@ static int deassert_reset(struct target *target) } else { LOG_DEBUG("Waiting for hart %d to run out of reset.", index); while (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 0) { - if (dmstatus_read(target, &dmstatus, true) != ERROR_OK) + if (dmstatus_read_timeout(target, &dmstatus, true, + riscv_reset_timeout_sec) != ERROR_OK) return ERROR_FAIL; if (get_field(dmstatus, DMI_DMSTATUS_ANYHALTED) || get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) { -- cgit v1.1 From 5fa6dae9df391c386d729b6461be987504a7eaff Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 18 Apr 2018 15:49:53 -0700 Subject: Disable style check for now. Fixes #242 Change-Id: I4d151350bf26bd3ea7733cb5247e4990fb487194 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2aeed08..f110fe1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,6 +55,6 @@ script: # 50 changes any case. Most merges won't consist of more than 40 changes, # so this should work fine most of the time, and be a lot better than not # checking at all. - - git diff HEAD~40 | ./tools/scripts/checkpatch.pl --no-signoff - + #- git diff HEAD~40 | ./tools/scripts/checkpatch.pl --no-signoff - - ./bootstrap && ./configure --enable-remote-bitbang --enable-jtag_vpi $CONFIGURE_ARGS && make - file src/$EXECUTABLE -- cgit v1.1 From b5dae238a15d1dd964f7a3ecbe55631e5834e883 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 18 Apr 2018 16:01:38 -0700 Subject: Fix comments in encoding.h. This was updated in the source a long time ago: https://github.com/riscv/riscv-opcodes/commit/25881d8a221393cfd996ec074d8003ef31bfc5a6 Change-Id: Ia158205d046522c6802a3a32b330759f5e65566f --- src/target/riscv/encoding.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/target/riscv/encoding.h b/src/target/riscv/encoding.h index c109ce1..dadbbd0 100644 --- a/src/target/riscv/encoding.h +++ b/src/target/riscv/encoding.h @@ -1,4 +1,4 @@ -// See LICENSE for license details. +/* See LICENSE for license details. */ #ifndef RISCV_CSR_ENCODING_H #define RISCV_CSR_ENCODING_H @@ -156,16 +156,16 @@ #define EXT_IO_BASE 0x40000000 #define DRAM_BASE 0x80000000 -// page table entry (PTE) fields -#define PTE_V 0x001 // Valid -#define PTE_R 0x002 // Read -#define PTE_W 0x004 // Write -#define PTE_X 0x008 // Execute -#define PTE_U 0x010 // User -#define PTE_G 0x020 // Global -#define PTE_A 0x040 // Accessed -#define PTE_D 0x080 // Dirty -#define PTE_SOFT 0x300 // Reserved for Software +/* page table entry (PTE) fields */ +#define PTE_V 0x001 /* Valid */ +#define PTE_R 0x002 /* Read */ +#define PTE_W 0x004 /* Write */ +#define PTE_X 0x008 /* Execute */ +#define PTE_U 0x010 /* User */ +#define PTE_G 0x020 /* Global */ +#define PTE_A 0x040 /* Accessed */ +#define PTE_D 0x080 /* Dirty */ +#define PTE_SOFT 0x300 /* Reserved for Software */ #define PTE_PPN_SHIFT 10 -- cgit v1.1 From ba2174249daf80775c7759ab04c7a2d7c9f01378 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 18 Apr 2018 16:10:24 -0700 Subject: Make encoding.h pass style guide. There's a manual step in commenting this out, but this file changes very rarely. Change-Id: I332d6490940ecc81e18c3b112a7ba415331b9c86 --- src/target/riscv/encoding.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/riscv/encoding.h b/src/target/riscv/encoding.h index dadbbd0..e214c0c 100644 --- a/src/target/riscv/encoding.h +++ b/src/target/riscv/encoding.h @@ -191,6 +191,7 @@ #ifdef __GNUC__ +/* #define read_csr(reg) ({ unsigned long __tmp; \ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ __tmp; }) @@ -209,6 +210,7 @@ #define clear_csr(reg, bit) ({ unsigned long __tmp; \ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ __tmp; }) + */ #define rdtime() read_csr(time) #define rdcycle() read_csr(cycle) -- cgit v1.1 From dc8c5eeac9952565fd7133c900229dceb576c29c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 18 Apr 2018 16:19:18 -0700 Subject: Re-enable style check. Tell git to give us 20 lines of context, which hopefully is enough to deal with some spurious warnings. Change-Id: I97cb572f7b89ff305f46290d20ed0b4674af1f5b --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f110fe1..88a6b8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,6 +55,6 @@ script: # 50 changes any case. Most merges won't consist of more than 40 changes, # so this should work fine most of the time, and be a lot better than not # checking at all. - #- git diff HEAD~40 | ./tools/scripts/checkpatch.pl --no-signoff - + - git diff -U20 HEAD~40 | ./tools/scripts/checkpatch.pl --no-signoff - - ./bootstrap && ./configure --enable-remote-bitbang --enable-jtag_vpi $CONFIGURE_ARGS && make - file src/$EXECUTABLE -- cgit v1.1 From 4593659edfb7c3c5c8873a7666a7d4a7ed28c6eb Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 20 Apr 2018 15:10:56 -0700 Subject: Fix error messages for reset dmi timeouts. Change-Id: I00869ba20db6f27415af8e53e7b3e67741bf894d --- src/helper/log.h | 1 + src/target/riscv/riscv-013.c | 104 +++++++++++++++++++++---------------------- 2 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/helper/log.h b/src/helper/log.h index 512bcc5..c2398ca 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -149,6 +149,7 @@ extern int debug_level; */ #define ERROR_FAIL (-4) #define ERROR_WAIT (-5) +#define ERROR_TIMEOUT (-6) #endif /* OPENOCD_HELPER_LOG_H */ diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index b7f762f..116d82a 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -520,13 +520,8 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, LOG_ERROR("failed %s at 0x%x, status=%d", op_name, address, status); return ERROR_FAIL; } - if (time(NULL) - start > timeout_sec) { - LOG_ERROR("dmi.op is still busy after %d seconds. The target is " - "either really slow or broken. You could increase the " - "timeout with riscv set_command_timeout_sec.", - timeout_sec); - return ERROR_FAIL; - } + if (time(NULL) - start > timeout_sec) + return ERROR_TIMEOUT; } if (status != DMI_STATUS_SUCCESS) { @@ -549,13 +544,8 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, status); return ERROR_FAIL; } - if (time(NULL) - start > timeout_sec) { - LOG_ERROR("dmi.op is still busy after %d seconds. The target is " - "either really slow or broken. You could increase the " - "timeout with riscv set_command_timeout_sec.", - timeout_sec); - return ERROR_FAIL; - } + if (time(NULL) - start > timeout_sec) + return ERROR_TIMEOUT; } if (status != DMI_STATUS_SUCCESS) { @@ -575,8 +565,16 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, uint32_t address, uint32_t data_out) { - return dmi_op_timeout(target, data_in, dmi_op, address, data_out, + int result = dmi_op_timeout(target, data_in, dmi_op, address, data_out, riscv_command_timeout_sec); + if (result == ERROR_TIMEOUT) { + LOG_ERROR("DMI operation didn't complete in %d seconds. The target is " + "either really slow or broken. You could increase the " + "timeout with riscv set_command_timeout_sec.", + riscv_command_timeout_sec); + return ERROR_FAIL; + } + return result; } static int dmi_read(struct target *target, uint32_t *value, uint32_t address) @@ -592,9 +590,10 @@ static int dmi_write(struct target *target, uint32_t address, uint32_t value) int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus, bool authenticated, unsigned timeout_sec) { - if (dmi_op_timeout(target, dmstatus, DMI_OP_READ, DMI_DMSTATUS, 0, - timeout_sec) != ERROR_OK) - return ERROR_FAIL; + int result = dmi_op_timeout(target, dmstatus, DMI_OP_READ, DMI_DMSTATUS, 0, + timeout_sec); + if (result != ERROR_OK) + return result; if (authenticated && !get_field(*dmstatus, DMI_DMSTATUS_AUTHENTICATED)) { LOG_ERROR("Debugger is not authenticated to target Debug Module. " "(dmstatus=0x%x). Use `riscv authdata_read` and " @@ -1604,44 +1603,45 @@ static int deassert_reset(struct target *target) index = r->current_hartid; } + char *operation; + uint32_t expected_field; + uint32_t unexpected_field; if (target->reset_halt) { - LOG_DEBUG("Waiting for hart %d to halt out of reset.", index); - do { - if (dmstatus_read_timeout(target, &dmstatus, true, - riscv_reset_timeout_sec) != ERROR_OK) - return ERROR_FAIL; - if (time(NULL) - start > riscv_reset_timeout_sec) { - LOG_ERROR("Hart %d didn't halt coming out of reset in %ds; " - "dmstatus=0x%x; " - "Increase the timeout with riscv set_reset_timeout_sec.", - index, riscv_reset_timeout_sec, dmstatus); - return ERROR_FAIL; - } - } while (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0); - target->state = TARGET_HALTED; - + operation = "halt"; + expected_field = DMI_DMSTATUS_ALLHALTED; + unexpected_field = DMI_DMSTATUS_ANYRUNNING; } else { - LOG_DEBUG("Waiting for hart %d to run out of reset.", index); - while (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 0) { - if (dmstatus_read_timeout(target, &dmstatus, true, - riscv_reset_timeout_sec) != ERROR_OK) - return ERROR_FAIL; - if (get_field(dmstatus, DMI_DMSTATUS_ANYHALTED) || - get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) { - LOG_ERROR("Unexpected hart %d status during reset. dmstatus=0x%x", - index, dmstatus); - return ERROR_FAIL; - } - if (time(NULL) - start > riscv_reset_timeout_sec) { - LOG_ERROR("Hart %d didn't run coming out of reset in %ds; " - "dmstatus=0x%x; " - "Increase the timeout with riscv set_reset_timeout_sec.", - index, riscv_reset_timeout_sec, dmstatus); - return ERROR_FAIL; - } + operation = "run"; + expected_field = DMI_DMSTATUS_ALLRUNNING; + unexpected_field = DMI_DMSTATUS_ANYHALTED; + } + LOG_DEBUG("Waiting for hart %d to %s out of reset.", index, operation); + while (1) { + int result = dmstatus_read_timeout(target, &dmstatus, true, + riscv_reset_timeout_sec); + if (result == ERROR_TIMEOUT) + LOG_ERROR("Hart %d didn't complete a DMI read coming out of " + "reset in %ds; Increase the timeout with riscv " + "set_reset_timeout_sec.", + index, riscv_reset_timeout_sec); + if (result != ERROR_OK) + return result; + if (get_field(dmstatus, unexpected_field)) { + LOG_ERROR("Unexpected hart %d status during reset. dmstatus=0x%x", + index, dmstatus); + return ERROR_FAIL; + } + if (get_field(dmstatus, expected_field)) + break; + if (time(NULL) - start > riscv_reset_timeout_sec) { + LOG_ERROR("Hart %d didn't %s coming out of reset in %ds; " + "dmstatus=0x%x; " + "Increase the timeout with riscv set_reset_timeout_sec.", + index, operation, riscv_reset_timeout_sec, dmstatus); + return ERROR_FAIL; } - target->state = TARGET_RUNNING; } + target->state = TARGET_HALTED; if (get_field(dmstatus, DMI_DMSTATUS_ALLHAVERESET)) { /* Ack reset. */ -- cgit v1.1 From 9a69c1c096a5498900c997daa17f23fbc5d7b87d Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 20 Apr 2018 16:28:24 -0700 Subject: Fix mingw32 build. Change-Id: If7a57749ba8c49385a4020ce8d2d8dbb94242122 --- src/helper/log.h | 3 ++- src/target/riscv/riscv-013.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/helper/log.h b/src/helper/log.h index c2398ca..d60587f 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -149,7 +149,8 @@ extern int debug_level; */ #define ERROR_FAIL (-4) #define ERROR_WAIT (-5) -#define ERROR_TIMEOUT (-6) +/* ERROR_TIMEOUT is already taken by winerror.h. */ +#define ERROR_TIMEOUT_REACHED (-6) #endif /* OPENOCD_HELPER_LOG_H */ diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 116d82a..9a628bb 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -521,7 +521,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, return ERROR_FAIL; } if (time(NULL) - start > timeout_sec) - return ERROR_TIMEOUT; + return ERROR_TIMEOUT_REACHED; } if (status != DMI_STATUS_SUCCESS) { @@ -545,7 +545,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, return ERROR_FAIL; } if (time(NULL) - start > timeout_sec) - return ERROR_TIMEOUT; + return ERROR_TIMEOUT_REACHED; } if (status != DMI_STATUS_SUCCESS) { @@ -567,7 +567,7 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, { int result = dmi_op_timeout(target, data_in, dmi_op, address, data_out, riscv_command_timeout_sec); - if (result == ERROR_TIMEOUT) { + if (result == ERROR_TIMEOUT_REACHED) { LOG_ERROR("DMI operation didn't complete in %d seconds. The target is " "either really slow or broken. You could increase the " "timeout with riscv set_command_timeout_sec.", @@ -1619,7 +1619,7 @@ static int deassert_reset(struct target *target) while (1) { int result = dmstatus_read_timeout(target, &dmstatus, true, riscv_reset_timeout_sec); - if (result == ERROR_TIMEOUT) + if (result == ERROR_TIMEOUT_REACHED) LOG_ERROR("Hart %d didn't complete a DMI read coming out of " "reset in %ds; Increase the timeout with riscv " "set_reset_timeout_sec.", -- cgit v1.1 From 3715f207c0c16fcdbaf01a36dd085423a19d24f2 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Tue, 24 Apr 2018 09:49:06 -0700 Subject: fespi: flag an error if offset can't be handled in 3B mode --- src/flash/nor/fespi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index f6827e3..6df0d38 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -436,6 +436,12 @@ static int slow_fespi_write_buffer(struct flash_bank *bank, uint32_t ctrl_base = fespi_info->ctrl_base; uint32_t ii; + if (offset & 0xFF000000) { + LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x", + offset); + return ERROR_FAIL; + } + /* TODO!!! assert that len < page size */ fespi_tx(bank, SPIFLASH_WRITE_ENABLE); @@ -769,6 +775,12 @@ static void as_add_set_dir(struct algorithm_steps *as, bool dir) static int steps_add_buffer_write(struct algorithm_steps *as, const uint8_t *buffer, uint32_t chip_offset, uint32_t len) { + if (chip_offset & 0xFF000000) { + LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x", + chip_offset); + return ERROR_FAIL; + } + as_add_tx1(as, SPIFLASH_WRITE_ENABLE); as_add_txwm_wait(as); as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD); -- cgit v1.1 From cb282e81bc1aabe2147c1f4c199c66fece49681e Mon Sep 17 00:00:00 2001 From: Darius Rad Date: Mon, 16 Apr 2018 21:09:13 -0400 Subject: Fix polling for system bus busy. --- src/target/riscv/riscv-013.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index cec01f3..3b43ebf 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1784,8 +1784,8 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs) LOG_ERROR("Timed out after %ds waiting for sbbusy to go low (sbcs=0x%x). " "Increase the timeout with riscv set_command_timeout_sec.", riscv_command_timeout_sec, *sbcs); + return ERROR_FAIL; } - return ERROR_FAIL; } } -- cgit v1.1 From 31494f68a45953b81483c8064ff82e5330dd1a10 Mon Sep 17 00:00:00 2001 From: Darius Rad Date: Tue, 1 May 2018 11:44:39 -0400 Subject: Properly retry system bus access if busy error was detected. --- src/target/riscv/riscv-013.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 3b43ebf..4bf5d50 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1913,6 +1913,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR); next_address = sb_read_address(target); info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1; + continue; } unsigned error = get_field(sbcs, DMI_SBCS_SBERROR); @@ -2351,6 +2352,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR); next_address = sb_read_address(target); info->bus_master_write_delay += info->bus_master_write_delay / 10 + 1; + continue; } unsigned error = get_field(sbcs, DMI_SBCS_SBERROR); -- cgit v1.1 From 67b4e2c5223e79c934a2522b811a4708c9294d7a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 2 May 2018 15:14:16 -0700 Subject: counter*h registers only exist on RV32 Fixes #245. Change-Id: If05ec9773dc9975931434f09c431eba122a6e8d0 --- src/target/riscv/riscv.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index bdae76a..bd09ef7 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2381,6 +2381,72 @@ int riscv_init_registers(struct target *target) r->exist = riscv_supports_extension(target, riscv_current_hartid(target), 'S') || riscv_supports_extension(target, riscv_current_hartid(target), 'N'); break; + + case CSR_CYCLEH: + case CSR_TIMEH: + case CSR_INSTRETH: + case CSR_HPMCOUNTER3H: + case CSR_HPMCOUNTER4H: + case CSR_HPMCOUNTER5H: + case CSR_HPMCOUNTER6H: + case CSR_HPMCOUNTER7H: + case CSR_HPMCOUNTER8H: + case CSR_HPMCOUNTER9H: + case CSR_HPMCOUNTER10H: + case CSR_HPMCOUNTER11H: + case CSR_HPMCOUNTER12H: + case CSR_HPMCOUNTER13H: + case CSR_HPMCOUNTER14H: + case CSR_HPMCOUNTER15H: + case CSR_HPMCOUNTER16H: + case CSR_HPMCOUNTER17H: + case CSR_HPMCOUNTER18H: + case CSR_HPMCOUNTER19H: + case CSR_HPMCOUNTER20H: + case CSR_HPMCOUNTER21H: + case CSR_HPMCOUNTER22H: + case CSR_HPMCOUNTER23H: + case CSR_HPMCOUNTER24H: + case CSR_HPMCOUNTER25H: + case CSR_HPMCOUNTER26H: + case CSR_HPMCOUNTER27H: + case CSR_HPMCOUNTER28H: + case CSR_HPMCOUNTER29H: + case CSR_HPMCOUNTER30H: + case CSR_HPMCOUNTER31H: + case CSR_MCYCLEH: + case CSR_MINSTRETH: + case CSR_MHPMCOUNTER3H: + case CSR_MHPMCOUNTER4H: + case CSR_MHPMCOUNTER5H: + case CSR_MHPMCOUNTER6H: + case CSR_MHPMCOUNTER7H: + case CSR_MHPMCOUNTER8H: + case CSR_MHPMCOUNTER9H: + case CSR_MHPMCOUNTER10H: + case CSR_MHPMCOUNTER11H: + case CSR_MHPMCOUNTER12H: + case CSR_MHPMCOUNTER13H: + case CSR_MHPMCOUNTER14H: + case CSR_MHPMCOUNTER15H: + case CSR_MHPMCOUNTER16H: + case CSR_MHPMCOUNTER17H: + case CSR_MHPMCOUNTER18H: + case CSR_MHPMCOUNTER19H: + case CSR_MHPMCOUNTER20H: + case CSR_MHPMCOUNTER21H: + case CSR_MHPMCOUNTER22H: + case CSR_MHPMCOUNTER23H: + case CSR_MHPMCOUNTER24H: + case CSR_MHPMCOUNTER25H: + case CSR_MHPMCOUNTER26H: + case CSR_MHPMCOUNTER27H: + case CSR_MHPMCOUNTER28H: + case CSR_MHPMCOUNTER29H: + case CSR_MHPMCOUNTER30H: + case CSR_MHPMCOUNTER31H: + r->exist = riscv_xlen(target) == 32; + break; } if (!r->exist && expose_csr) { -- cgit v1.1 From 909c9d4ab2e5ee5180ef81248608fa2109c3dba7 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 3 May 2018 17:58:44 -0700 Subject: Conform to OpenOCD style Change-Id: I3954a8ac254b460560fa1414c5921777e4005645 --- src/target/riscv/riscv-013.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 1869038..f3fe76b 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2722,9 +2722,8 @@ static int riscv013_select_current_hart(struct target *target) RISCV_INFO(r); dm013_info_t *dm = get_dm(target); - if (r->current_hartid == dm->current_hartid) { + if (r->current_hartid == dm->current_hartid) return ERROR_OK; - } uint32_t dmcontrol; if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK) -- cgit v1.1 From 2a103bae443b94b41a1071f9f9c62a80a45bcad0 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 7 May 2018 15:15:40 -0700 Subject: Don't error if hart select isn't implemented. It's not implemented for 0.11 because we don't need it. Returning error caused 0.11 targets to not be debuggable since change 848062d0d11679de25be573981df45e2c4880db8. Change-Id: I8b04a1fcf3c3e8bf8340cbf39aaf475d2a213519 --- src/target/riscv/riscv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index bd09ef7..6281fad 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1706,7 +1706,7 @@ int riscv_set_current_hartid(struct target *target, int hartid) { RISCV_INFO(r); if (!r->select_current_hart) - return ERROR_FAIL; + return ERROR_OK; int previous_hartid = riscv_current_hartid(target); r->current_hartid = hartid; -- cgit v1.1