Skip to content

Commit

Permalink
Using progbuf for set_dcsr_break now works
Browse files Browse the repository at this point in the history
  • Loading branch information
cgsfv committed Apr 25, 2024
1 parent b6da5a0 commit 84ed43e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 32 deletions.
12 changes: 12 additions & 0 deletions src/target/riscv/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ static uint32_t jal(unsigned int rd, uint32_t imm)
return imm_j(imm) | inst_rd(rd) | MATCH_JAL;
}

static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrci(unsigned int csr, uint16_t imm)
{
return imm_i(csr) | inst_rs1(imm) | MATCH_CSRRCI;
}

static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrsi(unsigned int csr, uint16_t imm)
{
Expand Down Expand Up @@ -143,6 +149,12 @@ static uint32_t csrr(unsigned int rd, unsigned int csr)
return imm_i(csr) | inst_rd(rd) | MATCH_CSRRS;
}

static uint32_t csrrc(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrc(unsigned int rd, unsigned int rs, unsigned int csr)
{
return imm_i(csr) | inst_rs1(rs) | inst_rd(rd) | MATCH_CSRRC;
}

static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr)
{
Expand Down
73 changes: 43 additions & 30 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include "debug_reg_printer.h"
#include "field_helpers.h"

static int riscv013_on_step_or_resume(struct target *target, bool step);
static int riscv013_on_step_or_resume(struct target *target, bool skip, bool step);
static int riscv013_step_or_resume_current_hart(struct target *target,
bool step);
static int riscv013_clear_abstract_error(struct target *target);
Expand Down Expand Up @@ -1778,25 +1778,40 @@ static int set_dcsr_ebreak(struct target *target, bool step)
RISCV_INFO(r);
RISCV013_INFO(info);

if ((info->nscratch >= 1) && has_sufficient_progbuf(target, 6)) {
uint64_t ebreak_bits = 0;
if ((info->nscratch >= 1) && has_sufficient_progbuf(target, 8)) {
uint64_t set_ebreak_bits = 0;
uint64_t clr_ebreak_bits = 0;
if (r->riscv_ebreakm)
ebreak_bits |= CSR_DCSR_EBREAKM;
set_ebreak_bits |= CSR_DCSR_EBREAKM;
else
clr_ebreak_bits |= CSR_DCSR_EBREAKM;
if (r->riscv_ebreaks && riscv_supports_extension(target, 'S'))
ebreak_bits |= CSR_DCSR_EBREAKS;
set_ebreak_bits |= CSR_DCSR_EBREAKS;
else
clr_ebreak_bits |= CSR_DCSR_EBREAKS;
if (r->riscv_ebreaku && riscv_supports_extension(target, 'U'))
ebreak_bits |= CSR_DCSR_EBREAKU;
set_ebreak_bits |= CSR_DCSR_EBREAKU;
else
clr_ebreak_bits |= CSR_DCSR_EBREAKU;
if (r->riscv_ebreaku && riscv_supports_extension(target, 'H'))
ebreak_bits |= CSR_DCSR_EBREAKVS;
set_ebreak_bits |= CSR_DCSR_EBREAKVS;
else
clr_ebreak_bits |= CSR_DCSR_EBREAKVS;
if (r->riscv_ebreaku && riscv_supports_extension(target, 'H'))
ebreak_bits |= CSR_DCSR_EBREAKVU;
set_ebreak_bits |= CSR_DCSR_EBREAKVU;
else
clr_ebreak_bits |= CSR_DCSR_EBREAKVU;
struct riscv_program program;
riscv_program_init(&program, target);
riscv_program_insert(&program, csrw(S0, CSR_DSCRATCH0));
riscv_program_insert(&program, lui(S0, ebreak_bits));
riscv_program_insert(&program, lui(S0, set_ebreak_bits));
riscv_program_insert(&program, csrrs(ZERO, S0, CSR_DCSR));
riscv_program_insert(&program, lui(S0, clr_ebreak_bits));
riscv_program_insert(&program, csrrc(ZERO, S0, CSR_DCSR));
if (step)
riscv_program_insert(&program, csrsi(CSR_DCSR, 0x4));
else
riscv_program_insert(&program, csrci(CSR_DCSR, 0x4));
riscv_program_insert(&program, csrr(S0, CSR_DSCRATCH0));
if (riscv_program_exec(&program, target) != ERROR_OK)
return ERROR_FAIL;
Expand All @@ -1822,8 +1837,7 @@ static int set_dcsr_ebreak(struct target *target, bool step)

static int halt_set_dcsr_ebreak(struct target *target)
{
RISCV013_INFO(info);
LOG_TARGET_INFO(target, "Halt to set DCSR.ebreak*");
LOG_TARGET_DEBUG(target, "Halt to set DCSR.ebreak*");

/* Remove this hart from the halt group. This won't work on all targets
* because the debug spec allows halt groups to be hard-coded, but I
Expand Down Expand Up @@ -1868,12 +1882,11 @@ static int halt_set_dcsr_ebreak(struct target *target)

halt_result = riscv013_halt_go(target);
if (halt_result == ERROR_OK) {
if (riscv013_resume_prep(target) == ERROR_OK) {
resume_result = riscv013_resume_go(target);
if (riscv013_on_step_or_resume(target, true, false) == ERROR_OK) {
resume_result = riscv013_step_or_resume_current_hart(target, false);
if (resume_result == ERROR_OK) {
target->state = TARGET_RUNNING;
target->debug_reason = DBG_REASON_NOTHALTED;
info->dcsr_ebreak_is_set = true;
} else if (resume_result == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
LOG_TARGET_INFO(target, "riscv013_resume_go aborted");
target->state = TARGET_UNAVAILABLE;
Expand Down Expand Up @@ -2061,9 +2074,6 @@ static int examine(struct target *target)
if (get_field(s, DM_DMSTATUS_ANYHAVERESET))
dm_write(target, DM_DMCONTROL,
set_dmcontrol_hartsel(DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_ACKHAVERESET, i));
if (get_field(s, DM_DMSTATUS_HASRESETHALTREQ))
dm_write(target, DM_DMCONTROL,
set_dmcontrol_hartsel(DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_CLRRESETHALTREQ, i));
}

LOG_TARGET_DEBUG(target, "Detected %d harts.", dm->hart_count);
Expand All @@ -2084,10 +2094,10 @@ static int examine(struct target *target)
if (riscv_get_hart_state(target, &state_at_examine_start) != ERROR_OK)
return ERROR_FAIL;

/* Skip full examination of hart if it is unavailable */
/* Skip full examination and reporting of hart if it is currently unavailable */
const bool hart_unavailable_at_examine_start = state_at_examine_start == RISCV_STATE_UNAVAILABLE;
if (hart_unavailable_at_examine_start) {
LOG_TARGET_DEBUG(target, "Did not fully examine hart %d as it was unavailable, deferring examine.", info->index);
LOG_TARGET_DEBUG(target, "Did not fully examine hart %d as it was currently unavailable, deferring examine.", info->index);
target->state = TARGET_UNAVAILABLE;
target->defer_examine = true;
return ERROR_OK;
Expand Down Expand Up @@ -2743,8 +2753,8 @@ static int riscv013_get_hart_state(struct target *target, enum riscv_hart_state
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
return ERROR_FAIL;
if (get_field(dmstatus, DM_DMSTATUS_ANYHAVERESET)) {
// LOG_TARGET_INFO(target, "Hart unexpectedly reset!");
// info->dcsr_ebreak_is_set = false;
LOG_TARGET_DEBUG(target, "Hart unexpectedly reset!");
info->dcsr_ebreak_is_set = false;
/* TODO: Can we make this more obvious to eg. a gdb user? */
uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE |
DM_DMCONTROL_ACKHAVERESET;
Expand Down Expand Up @@ -2781,7 +2791,6 @@ static int riscv013_get_hart_state(struct target *target, enum riscv_hart_state
static int handle_became_available(struct target *target,
enum riscv_hart_state previous_riscv_state)
{
RISCV013_INFO(info);
if (dm013_select_target(target) != ERROR_OK) {
LOG_TARGET_INFO(target, "dm013_select_target failed");
return ERROR_FAIL;
Expand All @@ -2791,7 +2800,6 @@ static int handle_became_available(struct target *target,
if (result == ERROR_OK) {
target->state = TARGET_RUNNING;
target->debug_reason = DBG_REASON_NOTHALTED;
info->dcsr_ebreak_is_set = true;
} else if (result == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
LOG_TARGET_INFO(target, "riscv013_step_or_resume_current_hart aborted");
target->state = TARGET_UNAVAILABLE;
Expand Down Expand Up @@ -5025,7 +5033,12 @@ static int riscv013_halt_go(struct target *target)
"Some harts may be unexpectedly halted.");
}
}
if (riscv013_halt_target(target) != ERROR_OK) {

int result = riscv013_halt_target(target);
if (result == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
else if (result != ERROR_OK) {
return ERROR_FAIL;
}

Expand Down Expand Up @@ -5090,12 +5103,12 @@ static int riscv013_step_current_hart(struct target *target)
static int riscv013_resume_prep(struct target *target)
{
assert(target->state == TARGET_HALTED);
return riscv013_on_step_or_resume(target, false);
return riscv013_on_step_or_resume(target, false, false);
}

static int riscv013_on_step(struct target *target)
{
return riscv013_on_step_or_resume(target, true);
return riscv013_on_step_or_resume(target, false, true);
}

static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
Expand Down Expand Up @@ -5231,17 +5244,17 @@ void riscv013_fill_dm_nop_u64(struct target *target, char *buf)
riscv013_fill_dmi_nop_u64(target, buf);
}

static int maybe_execute_fence_i(struct target *target)
static int maybe_execute_fence_i(struct target *target, bool skip)
{
if (has_sufficient_progbuf(target, 2))
if (!skip && has_sufficient_progbuf(target, 2))
return execute_fence(target);
return ERROR_OK;
}

/* Helper Functions. */
static int riscv013_on_step_or_resume(struct target *target, bool step)
static int riscv013_on_step_or_resume(struct target *target, bool skip, bool step)
{
if (maybe_execute_fence_i(target) != ERROR_OK)
if (maybe_execute_fence_i(target, skip) != ERROR_OK)
return ERROR_FAIL;

if (set_dcsr_ebreak(target, step) != ERROR_OK)
Expand Down
4 changes: 2 additions & 2 deletions src/target/target.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ int target_examine_one(struct target *target)
}

if (target->defer_examine) {
LOG_USER("[%s] Target unavailable for full examination.", target_name(target));
LOG_USER("[%s] Target currently unavailable for full examination.", target_name(target));
target->defer_examine = defer_state;
target_reset_examined(target);
} else {
Expand All @@ -698,7 +698,7 @@ int target_examine_one(struct target *target)
}
target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);

LOG_TARGET_INFO(target, "Examination succeed");
LOG_TARGET_DEBUG(target, "Examination succeed");
return ERROR_OK;
}

Expand Down

0 comments on commit 84ed43e

Please sign in to comment.