target/riscv: support disable auto fence
Support disable automatic fence, it's useful for debug some cache related issue.
This commit is contained in:
parent
9ff272e34b
commit
340e38a9ed
|
@ -11631,6 +11631,19 @@ riscv exec_progbuf 0x0330000f 0x0000100f
|
||||||
riscv exec_progbuf 0x94a20405
|
riscv exec_progbuf 0x94a20405
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@deffn {Command} {riscv autofence} [on|off]
|
||||||
|
When on (default), OpenOCD will automatically execute RISC-V fence instructions
|
||||||
|
(@var{fence.i} and @var{fence rw, rw}) in these cases:
|
||||||
|
@itemize @bullet
|
||||||
|
@item before step or resume,
|
||||||
|
@item before memory read via the Program Buffer,
|
||||||
|
@item after memory write via the Program Buffer.
|
||||||
|
@end itemize
|
||||||
|
When off, users need to take care of memory coherency themselves, for example
|
||||||
|
using the @var{riscv exec_progbuf} command to execute fences or CMO instructions
|
||||||
|
(RISC-V Cache Management Operations).
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@section ARC Architecture
|
@section ARC Architecture
|
||||||
@cindex ARC
|
@cindex ARC
|
||||||
|
|
||||||
|
|
|
@ -2913,11 +2913,15 @@ static int deassert_reset(struct target *target)
|
||||||
return dm_write(target, DM_DMCONTROL, control);
|
return dm_write(target, DM_DMCONTROL, control);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int execute_fence(struct target *target)
|
static int execute_autofence(struct target *target)
|
||||||
{
|
{
|
||||||
if (dm013_select_target(target) != ERROR_OK)
|
if (dm013_select_target(target) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
RISCV_INFO(r);
|
||||||
|
if (!r->autofence)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
/* FIXME: For non-coherent systems we need to flush the caches right
|
/* FIXME: For non-coherent systems we need to flush the caches right
|
||||||
* here, but there's no ISA-defined way of doing that. */
|
* here, but there's no ISA-defined way of doing that. */
|
||||||
struct riscv_program program;
|
struct riscv_program program;
|
||||||
|
@ -2939,8 +2943,9 @@ static int execute_fence(struct target *target)
|
||||||
LOG_TARGET_ERROR(target, "Unexpected error during fence execution");
|
LOG_TARGET_ERROR(target, "Unexpected error during fence execution");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
LOG_TARGET_DEBUG(target, "Unable to execute fence");
|
LOG_TARGET_DEBUG(target, "Unable to execute fence.i and fence rw, rw");
|
||||||
}
|
}
|
||||||
|
LOG_TARGET_DEBUG(target, "Successfully executed fence.i and fence rw, rw");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2954,6 +2959,7 @@ static int execute_fence(struct target *target)
|
||||||
}
|
}
|
||||||
LOG_TARGET_DEBUG(target, "Unable to execute fence.i");
|
LOG_TARGET_DEBUG(target, "Unable to execute fence.i");
|
||||||
}
|
}
|
||||||
|
LOG_TARGET_DEBUG(target, "Successfully executed fence.i");
|
||||||
|
|
||||||
riscv_program_init(&program, target);
|
riscv_program_init(&program, target);
|
||||||
riscv_program_fence_rw_rw(&program);
|
riscv_program_fence_rw_rw(&program);
|
||||||
|
@ -2964,6 +2970,7 @@ static int execute_fence(struct target *target)
|
||||||
}
|
}
|
||||||
LOG_TARGET_DEBUG(target, "Unable to execute fence rw, rw");
|
LOG_TARGET_DEBUG(target, "Unable to execute fence rw, rw");
|
||||||
}
|
}
|
||||||
|
LOG_TARGET_DEBUG(target, "Successfully executed fence rw, rw");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4273,7 +4280,7 @@ read_memory_progbuf(struct target *target, target_addr_t address,
|
||||||
|
|
||||||
memset(buffer, 0, count*size);
|
memset(buffer, 0, count*size);
|
||||||
|
|
||||||
if (execute_fence(target) != ERROR_OK)
|
if (execute_autofence(target) != ERROR_OK)
|
||||||
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
|
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
|
||||||
|
|
||||||
uint64_t mstatus = 0;
|
uint64_t mstatus = 0;
|
||||||
|
@ -4864,7 +4871,7 @@ write_memory_progbuf(struct target *target, target_addr_t address,
|
||||||
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old))
|
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old))
|
||||||
return MEM_ACCESS_FAILED;
|
return MEM_ACCESS_FAILED;
|
||||||
|
|
||||||
if (execute_fence(target) != ERROR_OK)
|
if (execute_autofence(target) != ERROR_OK)
|
||||||
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
|
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
|
||||||
|
|
||||||
return result == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
return result == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
||||||
|
@ -5351,18 +5358,12 @@ static int riscv013_get_dmi_scan_length(struct target *target)
|
||||||
return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH;
|
return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int maybe_execute_fence_i(struct target *target)
|
|
||||||
{
|
|
||||||
if (has_sufficient_progbuf(target, 2))
|
|
||||||
return execute_fence(target);
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper Functions. */
|
/* 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 step)
|
||||||
{
|
{
|
||||||
if (maybe_execute_fence_i(target) != ERROR_OK)
|
if (has_sufficient_progbuf(target, 2))
|
||||||
return ERROR_FAIL;
|
if (execute_autofence(target) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (set_dcsr_ebreak(target, step) != ERROR_OK)
|
if (set_dcsr_ebreak(target, step) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
|
@ -4521,6 +4521,22 @@ COMMAND_HANDLER(riscv_set_maskisr)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(riscv_set_autofence)
|
||||||
|
{
|
||||||
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
|
RISCV_INFO(r);
|
||||||
|
|
||||||
|
if (CMD_ARGC == 0) {
|
||||||
|
command_print(CMD, "autofence: %s", r->autofence ? "on" : "off");
|
||||||
|
return ERROR_OK;
|
||||||
|
} else if (CMD_ARGC == 1) {
|
||||||
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->autofence);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(riscv_set_ebreakm)
|
COMMAND_HANDLER(riscv_set_ebreakm)
|
||||||
{
|
{
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
|
@ -5428,6 +5444,15 @@ static const struct command_registration riscv_exec_command_handlers[] = {
|
||||||
"hw - translate vaddr to paddr by hardware, "
|
"hw - translate vaddr to paddr by hardware, "
|
||||||
"off - no address translation."
|
"off - no address translation."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "autofence",
|
||||||
|
.handler = riscv_set_autofence,
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.usage = "[on|off]",
|
||||||
|
.help = "When on (default), OpenOCD will automatically execute fence instructions in some situations. "
|
||||||
|
"When off, users need to take care of memory coherency themselves, for example by using "
|
||||||
|
"`riscv exec_progbuf` to execute fence or CMO instructions."
|
||||||
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5569,6 +5594,8 @@ static void riscv_info_init(struct target *target, struct riscv_info *r)
|
||||||
r->wp_allow_equality_match_trigger = true;
|
r->wp_allow_equality_match_trigger = true;
|
||||||
r->wp_allow_ge_lt_trigger = true;
|
r->wp_allow_ge_lt_trigger = true;
|
||||||
r->wp_allow_napot_trigger = true;
|
r->wp_allow_napot_trigger = true;
|
||||||
|
|
||||||
|
r->autofence = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int riscv_resume_go_all_harts(struct target *target)
|
static int riscv_resume_go_all_harts(struct target *target)
|
||||||
|
|
|
@ -321,6 +321,8 @@ struct riscv_info {
|
||||||
bool wp_allow_equality_match_trigger;
|
bool wp_allow_equality_match_trigger;
|
||||||
bool wp_allow_napot_trigger;
|
bool wp_allow_napot_trigger;
|
||||||
bool wp_allow_ge_lt_trigger;
|
bool wp_allow_ge_lt_trigger;
|
||||||
|
|
||||||
|
bool autofence;
|
||||||
};
|
};
|
||||||
|
|
||||||
COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key,
|
COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key,
|
||||||
|
|
Loading…
Reference in New Issue