target/riscv: merged read/write functions to one access function
Commit merges read/write functions to access function. It allows to decrease amount of code duplication. Signed-off-by: Farid Khaydari <f.khaydari@syntacore.com>
This commit is contained in:
parent
5de7310881
commit
c65ef19e04
|
@ -2325,6 +2325,15 @@ error:
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int access_memory(struct target *target, const riscv_mem_access_args_t args)
|
||||||
|
{
|
||||||
|
assert(riscv_mem_access_is_valid(args));
|
||||||
|
const bool is_write = riscv_mem_access_is_write(args);
|
||||||
|
if (is_write)
|
||||||
|
return write_memory(target, args);
|
||||||
|
return read_memory(target, args);
|
||||||
|
}
|
||||||
|
|
||||||
static int arch_state(struct target *target)
|
static int arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -2417,8 +2426,7 @@ static int init_target(struct command_context *cmd_ctx,
|
||||||
LOG_DEBUG("init");
|
LOG_DEBUG("init");
|
||||||
RISCV_INFO(generic_info);
|
RISCV_INFO(generic_info);
|
||||||
/* TODO: replace read and write with single access function*/
|
/* TODO: replace read and write with single access function*/
|
||||||
generic_info->read_memory = read_memory;
|
generic_info->access_memory = access_memory;
|
||||||
generic_info->write_memory = write_memory;
|
|
||||||
generic_info->authdata_read = &riscv011_authdata_read;
|
generic_info->authdata_read = &riscv011_authdata_read;
|
||||||
generic_info->authdata_write = &riscv011_authdata_write;
|
generic_info->authdata_write = &riscv011_authdata_write;
|
||||||
generic_info->print_info = &riscv011_print_info;
|
generic_info->print_info = &riscv011_print_info;
|
||||||
|
|
|
@ -64,8 +64,7 @@ static int register_read_direct(struct target *target, riscv_reg_t *value,
|
||||||
enum gdb_regno number);
|
enum gdb_regno number);
|
||||||
static int register_write_direct(struct target *target, enum gdb_regno number,
|
static int register_write_direct(struct target *target, enum gdb_regno number,
|
||||||
riscv_reg_t value);
|
riscv_reg_t value);
|
||||||
static int read_memory(struct target *target, const riscv_mem_access_args_t args);
|
static int riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args);
|
||||||
static int write_memory(struct target *target, const riscv_mem_access_args_t args);
|
|
||||||
static bool riscv013_get_impebreak(const struct target *target);
|
static bool riscv013_get_impebreak(const struct target *target);
|
||||||
static unsigned int riscv013_get_progbufsize(const struct target *target);
|
static unsigned int riscv013_get_progbufsize(const struct target *target);
|
||||||
|
|
||||||
|
@ -1215,7 +1214,7 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch,
|
||||||
.count = 2,
|
.count = 2,
|
||||||
.increment = 4,
|
.increment = 4,
|
||||||
};
|
};
|
||||||
if (read_memory(target, args) != ERROR_OK)
|
if (riscv013_access_memory(target, args) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
*value = buf_get_u64(buffer,
|
*value = buf_get_u64(buffer,
|
||||||
/* first = */ 0, /* bit_num = */ 64);
|
/* first = */ 0, /* bit_num = */ 64);
|
||||||
|
@ -1257,7 +1256,7 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch,
|
||||||
.count = 2,
|
.count = 2,
|
||||||
.increment = 4,
|
.increment = 4,
|
||||||
};
|
};
|
||||||
if (write_memory(target, args) != ERROR_OK)
|
if (riscv013_access_memory(target, args) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2802,8 +2801,7 @@ static int init_target(struct command_context *cmd_ctx,
|
||||||
generic_info->dmi_write = &dmi_write;
|
generic_info->dmi_write = &dmi_write;
|
||||||
generic_info->get_dmi_address = &riscv013_get_dmi_address;
|
generic_info->get_dmi_address = &riscv013_get_dmi_address;
|
||||||
/* TODO: replace read and write with single access function*/
|
/* TODO: replace read and write with single access function*/
|
||||||
generic_info->read_memory = read_memory;
|
generic_info->access_memory = &riscv013_access_memory;
|
||||||
generic_info->write_memory = write_memory;
|
|
||||||
generic_info->data_bits = &riscv013_data_bits;
|
generic_info->data_bits = &riscv013_data_bits;
|
||||||
generic_info->print_info = &riscv013_print_info;
|
generic_info->print_info = &riscv013_print_info;
|
||||||
generic_info->get_impebreak = &riscv013_get_impebreak;
|
generic_info->get_impebreak = &riscv013_get_impebreak;
|
||||||
|
@ -3500,7 +3498,8 @@ typedef enum {
|
||||||
MEM_ACCESS_RESULT_TYPE_FAILED, "failed (DM register access failed)") \
|
MEM_ACCESS_RESULT_TYPE_FAILED, "failed (DM register access failed)") \
|
||||||
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PRIV_MOD_FAILED, \
|
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PRIV_MOD_FAILED, \
|
||||||
MEM_ACCESS_RESULT_TYPE_FAILED, "failed (privilege modification failed)") \
|
MEM_ACCESS_RESULT_TYPE_FAILED, "failed (privilege modification failed)") \
|
||||||
|
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_REG_WRITE_FAILED, \
|
||||||
|
MEM_ACCESS_RESULT_TYPE_FAILED, "failed (register write failed)") \
|
||||||
|
|
||||||
#define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) name,
|
#define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) name,
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -3669,16 +3668,9 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
|
||||||
{
|
{
|
||||||
assert(riscv_mem_access_is_read(args));
|
assert(riscv_mem_access_is_read(args));
|
||||||
|
|
||||||
mem_access_result_t skip_reason = mem_should_skip_abstract(target, args);
|
|
||||||
if (skip_reason != MEM_ACCESS_OK)
|
|
||||||
return skip_reason;
|
|
||||||
|
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
|
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
|
||||||
|
|
||||||
LOG_TARGET_DEBUG(target, "Reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, args.count,
|
|
||||||
args.size, args.address);
|
|
||||||
|
|
||||||
memset(args.read_buffer, 0, args.count * args.size);
|
memset(args.read_buffer, 0, args.count * args.size);
|
||||||
|
|
||||||
/* Convert the size (bytes) to width (bits) */
|
/* Convert the size (bytes) to width (bits) */
|
||||||
|
@ -3766,17 +3758,10 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
|
||||||
{
|
{
|
||||||
assert(riscv_mem_access_is_write(args));
|
assert(riscv_mem_access_is_write(args));
|
||||||
|
|
||||||
mem_access_result_t skip_reason = mem_should_skip_abstract(target, args);
|
|
||||||
if (skip_reason != MEM_ACCESS_OK)
|
|
||||||
return skip_reason;
|
|
||||||
|
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
int result = ERROR_OK;
|
int result = ERROR_OK;
|
||||||
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
|
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
|
||||||
|
|
||||||
LOG_TARGET_DEBUG(target, "writing %d words of %d bytes from 0x%" TARGET_PRIxADDR, args.count,
|
|
||||||
args.size, args.address);
|
|
||||||
|
|
||||||
/* Convert the size (bytes) to width (bits) */
|
/* Convert the size (bytes) to width (bits) */
|
||||||
unsigned int width = args.size << 3;
|
unsigned int width = args.size << 3;
|
||||||
|
|
||||||
|
@ -4373,55 +4358,81 @@ read_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
|
||||||
{
|
{
|
||||||
assert(riscv_mem_access_is_read(args));
|
assert(riscv_mem_access_is_read(args));
|
||||||
|
|
||||||
mem_access_result_t skip_reason = mem_should_skip_progbuf(target, args);
|
|
||||||
if (skip_reason != MEM_ACCESS_OK)
|
|
||||||
return skip_reason;
|
|
||||||
|
|
||||||
LOG_TARGET_DEBUG(target, "reading %" PRIu32 " elements of %" PRIu32
|
|
||||||
" bytes from 0x%" TARGET_PRIxADDR, args.count, args.size, args.address);
|
|
||||||
|
|
||||||
if (dm013_select_target(target) != ERROR_OK)
|
|
||||||
return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED;
|
|
||||||
|
|
||||||
select_dmi(target);
|
select_dmi(target);
|
||||||
|
|
||||||
memset(args.read_buffer, 0, args.count * args.size);
|
memset(args.read_buffer, 0, args.count * args.size);
|
||||||
|
|
||||||
if (execute_autofence(target) != ERROR_OK)
|
if (execute_autofence(target) != ERROR_OK)
|
||||||
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
|
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
|
||||||
|
|
||||||
|
int res = (args.count == 1) ?
|
||||||
|
read_memory_progbuf_inner_one(target, args) :
|
||||||
|
read_memory_progbuf_inner(target, args);
|
||||||
|
|
||||||
|
return res == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mem_access_result_t
|
||||||
|
write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args);
|
||||||
|
|
||||||
|
static mem_access_result_t
|
||||||
|
access_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
|
||||||
|
{
|
||||||
|
mem_access_result_t skip_reason = mem_should_skip_progbuf(target, args);
|
||||||
|
if (skip_reason != MEM_ACCESS_OK)
|
||||||
|
return skip_reason;
|
||||||
|
|
||||||
|
const bool is_read = riscv_mem_access_is_read(args);
|
||||||
|
const char *const access_type = is_read ? "reading" : "writing";
|
||||||
|
LOG_TARGET_DEBUG(target, "%s %" PRIu32 " words of %" PRIu32
|
||||||
|
" bytes at 0x%" TARGET_PRIxADDR, access_type, args.count,
|
||||||
|
args.size, args.address);
|
||||||
|
|
||||||
|
if (dm013_select_target(target) != ERROR_OK)
|
||||||
|
return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED;
|
||||||
|
|
||||||
riscv_reg_t mstatus = 0;
|
riscv_reg_t mstatus = 0;
|
||||||
riscv_reg_t mstatus_old = 0;
|
riscv_reg_t mstatus_old = 0;
|
||||||
riscv_reg_t dcsr = 0;
|
riscv_reg_t dcsr = 0;
|
||||||
riscv_reg_t dcsr_old = 0;
|
riscv_reg_t dcsr_old = 0;
|
||||||
if (modify_privilege_for_virt2phys_mode(target, &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
|
if (modify_privilege_for_virt2phys_mode(target,
|
||||||
|
&mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
|
||||||
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
|
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
|
||||||
|
|
||||||
int result = (args.count == 1) ?
|
mem_access_result_t result = is_read ?
|
||||||
read_memory_progbuf_inner_one(target, args) :
|
read_memory_progbuf(target, args) :
|
||||||
read_memory_progbuf_inner(target, args);
|
write_memory_progbuf(target, args);
|
||||||
|
|
||||||
if (restore_privilege_from_virt2phys_mode(target, mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
|
if (restore_privilege_from_virt2phys_mode(target,
|
||||||
|
mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
|
||||||
return MEM_ACCESS_FAILED;
|
return MEM_ACCESS_FAILED;
|
||||||
|
|
||||||
return (result == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args);
|
||||||
|
static int
|
||||||
|
write_memory_bus_v1(struct target *target, const riscv_mem_access_args_t args);
|
||||||
|
|
||||||
static mem_access_result_t
|
static mem_access_result_t
|
||||||
read_memory_sysbus(struct target *target, const riscv_mem_access_args_t args)
|
access_memory_sysbus(struct target *target, const riscv_mem_access_args_t args)
|
||||||
{
|
{
|
||||||
assert(riscv_mem_access_is_read(args));
|
assert(riscv_mem_access_is_valid(args));
|
||||||
|
|
||||||
mem_access_result_t skip_reason = mem_should_skip_sysbus(target, args);
|
mem_access_result_t skip_reason = mem_should_skip_sysbus(target, args);
|
||||||
if (skip_reason != MEM_ACCESS_OK)
|
if (skip_reason != MEM_ACCESS_OK)
|
||||||
return skip_reason;
|
return skip_reason;
|
||||||
|
|
||||||
|
RISCV013_INFO(info);
|
||||||
int ret = ERROR_FAIL;
|
int ret = ERROR_FAIL;
|
||||||
uint64_t sbver = get_field(get_info(target)->sbcs, DM_SBCS_SBVERSION);
|
const bool is_read = riscv_mem_access_is_read(args);
|
||||||
|
const uint64_t sbver = get_field(info->sbcs, DM_SBCS_SBVERSION);
|
||||||
if (sbver == 0)
|
if (sbver == 0)
|
||||||
ret = read_memory_bus_v0(target, args);
|
ret = is_read ? read_memory_bus_v0(target, args) :
|
||||||
|
write_memory_bus_v0(target, args);
|
||||||
else if (sbver == 1)
|
else if (sbver == 1)
|
||||||
ret = read_memory_bus_v1(target, args);
|
ret = is_read ? read_memory_bus_v1(target, args) :
|
||||||
|
write_memory_bus_v1(target, args);
|
||||||
else
|
else
|
||||||
LOG_TARGET_ERROR(target,
|
LOG_TARGET_ERROR(target,
|
||||||
"Unknown system bus version: %" PRIu64, sbver);
|
"Unknown system bus version: %" PRIu64, sbver);
|
||||||
|
@ -4429,15 +4440,42 @@ read_memory_sysbus(struct target *target, const riscv_mem_access_args_t args)
|
||||||
return (ret == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
return (ret == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_memory(struct target *target, const riscv_mem_access_args_t args)
|
static mem_access_result_t
|
||||||
|
access_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
|
||||||
{
|
{
|
||||||
assert(riscv_mem_access_is_read(args));
|
assert(riscv_mem_access_is_valid(args));
|
||||||
|
|
||||||
if (args.count == 0)
|
mem_access_result_t skip_reason = mem_should_skip_abstract(target, args);
|
||||||
return ERROR_OK;
|
if (skip_reason != MEM_ACCESS_OK)
|
||||||
|
return skip_reason;
|
||||||
|
|
||||||
|
const bool is_read = riscv_mem_access_is_read(args);
|
||||||
|
const char *const access_type = is_read ? "reading" : "writing";
|
||||||
|
LOG_TARGET_DEBUG(target, "%s %d words of %d bytes at 0x%"
|
||||||
|
TARGET_PRIxADDR, access_type, args.count,
|
||||||
|
args.size, args.address);
|
||||||
|
|
||||||
|
int result = is_read ? read_memory_abstract(target, args) :
|
||||||
|
write_memory_abstract(target, args);
|
||||||
|
|
||||||
|
return result == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args)
|
||||||
|
{
|
||||||
|
assert(riscv_mem_access_is_valid(args));
|
||||||
|
|
||||||
|
const bool is_read = riscv_mem_access_is_read(args);
|
||||||
|
const char *const access_type = is_read ? "read" : "write";
|
||||||
|
if (!is_read && args.increment != args.size) {
|
||||||
|
LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size");
|
||||||
|
return ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (!IS_PWR_OF_2(args.size) || args.size < 1 || args.size > 16) {
|
if (!IS_PWR_OF_2(args.size) || args.size < 1 || args.size > 16) {
|
||||||
LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory read: %d", args.size);
|
LOG_TARGET_ERROR(target, "BUG: Unsupported size for "
|
||||||
|
"memory %s: %d", access_type, args.size);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4452,32 +4490,32 @@ static int read_memory(struct target *target, const riscv_mem_access_args_t args
|
||||||
riscv_mem_access_method_t method = r->mem_access_methods[i];
|
riscv_mem_access_method_t method = r->mem_access_methods[i];
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case RISCV_MEM_ACCESS_PROGBUF:
|
case RISCV_MEM_ACCESS_PROGBUF:
|
||||||
skip_reason[method] = read_memory_progbuf(target, args);
|
skip_reason[method] = access_memory_progbuf(target, args);
|
||||||
break;
|
break;
|
||||||
case RISCV_MEM_ACCESS_SYSBUS:
|
case RISCV_MEM_ACCESS_SYSBUS:
|
||||||
skip_reason[method] = read_memory_sysbus(target, args);
|
skip_reason[method] = access_memory_sysbus(target, args);
|
||||||
break;
|
break;
|
||||||
case RISCV_MEM_ACCESS_ABSTRACT:
|
case RISCV_MEM_ACCESS_ABSTRACT:
|
||||||
skip_reason[method] = read_memory_abstract(target, args);
|
skip_reason[method] = access_memory_abstract(target, args);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method);
|
LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method);
|
||||||
assert(false);
|
assert(false && "Unknown memory access method");
|
||||||
return ERROR_FAIL;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_mem_access_failed(skip_reason[method]))
|
if (is_mem_access_failed(skip_reason[method]))
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
const bool success = (skip_reason[method] == MEM_ACCESS_OK);
|
const bool success = (skip_reason[method] == MEM_ACCESS_OK);
|
||||||
log_mem_access_result(target, success, method, /* is_read = */ true);
|
log_mem_access_result(target, success, method, is_read);
|
||||||
if (success)
|
if (success)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
LOG_TARGET_ERROR(target, "Failed to read memory (addr=0x%" PRIx64 ")\n"
|
LOG_TARGET_ERROR(target, "Failed to %s memory (addr=0x%" PRIx64 ")\n"
|
||||||
" progbuf=%s, sysbus=%s, abstract=%s", args.address,
|
" progbuf=%s, sysbus=%s, abstract=%s", access_type, args.address,
|
||||||
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]),
|
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]),
|
||||||
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]),
|
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]),
|
||||||
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT]));
|
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT]));
|
||||||
|
@ -4917,118 +4955,14 @@ write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
|
||||||
{
|
{
|
||||||
assert(riscv_mem_access_is_write(args));
|
assert(riscv_mem_access_is_write(args));
|
||||||
|
|
||||||
mem_access_result_t skip_reason = mem_should_skip_progbuf(target, args);
|
|
||||||
if (skip_reason != MEM_ACCESS_OK)
|
|
||||||
return skip_reason;
|
|
||||||
|
|
||||||
LOG_TARGET_DEBUG(target, "writing %" PRIu32 " words of %" PRIu32
|
|
||||||
" bytes to 0x%" TARGET_PRIxADDR, args.count, args.size, args.address);
|
|
||||||
|
|
||||||
if (dm013_select_target(target) != ERROR_OK)
|
|
||||||
return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED;
|
|
||||||
|
|
||||||
uint64_t mstatus = 0;
|
|
||||||
uint64_t mstatus_old = 0;
|
|
||||||
uint64_t dcsr = 0;
|
|
||||||
uint64_t dcsr_old = 0;
|
|
||||||
if (modify_privilege_for_virt2phys_mode(target, &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
|
|
||||||
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
|
|
||||||
|
|
||||||
int result = write_memory_progbuf_inner(target, args);
|
int result = write_memory_progbuf_inner(target, args);
|
||||||
|
|
||||||
if (restore_privilege_from_virt2phys_mode(target, mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
|
|
||||||
return MEM_ACCESS_FAILED;
|
|
||||||
|
|
||||||
if (execute_autofence(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mem_access_result_t
|
|
||||||
write_memory_sysbus(struct target *target, const riscv_mem_access_args_t args)
|
|
||||||
{
|
|
||||||
assert(riscv_mem_access_is_write(args));
|
|
||||||
|
|
||||||
riscv013_info_t *info = get_info(target);
|
|
||||||
mem_access_result_t skip_reason = mem_should_skip_sysbus(target, args);
|
|
||||||
if (skip_reason != MEM_ACCESS_OK)
|
|
||||||
return skip_reason;
|
|
||||||
|
|
||||||
/* TODO: write_memory_bus_* should return mem_access_result_t too*/
|
|
||||||
int ret = ERROR_FAIL;
|
|
||||||
uint64_t sbver = get_field(info->sbcs, DM_SBCS_SBVERSION);
|
|
||||||
if (sbver == 0)
|
|
||||||
ret = write_memory_bus_v0(target, args);
|
|
||||||
else if (sbver == 1)
|
|
||||||
ret = write_memory_bus_v1(target, args);
|
|
||||||
else
|
|
||||||
LOG_TARGET_ERROR(target,
|
|
||||||
"Unknown system bus version: %" PRIu64, sbver);
|
|
||||||
|
|
||||||
if (ret != ERROR_OK)
|
|
||||||
skip_reason = MEM_ACCESS_FAILED;
|
|
||||||
|
|
||||||
return skip_reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int write_memory(struct target *target, const riscv_mem_access_args_t args)
|
|
||||||
{
|
|
||||||
assert(riscv_mem_access_is_write(args));
|
|
||||||
|
|
||||||
if (args.increment != args.size) {
|
|
||||||
LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size");
|
|
||||||
return ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_PWR_OF_2(args.size) || args.size < 1 || args.size > 16) {
|
|
||||||
LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory write: %d", args.size);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem_access_result_t skip_reason[] = {
|
|
||||||
[RISCV_MEM_ACCESS_PROGBUF] = MEM_ACCESS_DISABLED,
|
|
||||||
[RISCV_MEM_ACCESS_SYSBUS] = MEM_ACCESS_DISABLED,
|
|
||||||
[RISCV_MEM_ACCESS_ABSTRACT] = MEM_ACCESS_DISABLED
|
|
||||||
};
|
|
||||||
|
|
||||||
RISCV_INFO(r);
|
|
||||||
for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; ++i) {
|
|
||||||
riscv_mem_access_method_t method = r->mem_access_methods[i];
|
|
||||||
switch (method) {
|
|
||||||
case RISCV_MEM_ACCESS_PROGBUF:
|
|
||||||
skip_reason[method] = write_memory_progbuf(target, args);
|
|
||||||
break;
|
|
||||||
case RISCV_MEM_ACCESS_SYSBUS:
|
|
||||||
skip_reason[method] = write_memory_sysbus(target, args);
|
|
||||||
break;
|
|
||||||
case RISCV_MEM_ACCESS_ABSTRACT:
|
|
||||||
skip_reason[method] = write_memory_abstract(target, args);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method);
|
|
||||||
assert(false);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_mem_access_failed(skip_reason[method]))
|
|
||||||
goto failure;
|
|
||||||
|
|
||||||
const bool success = (skip_reason[method] == MEM_ACCESS_OK);
|
|
||||||
log_mem_access_result(target, success, method, /* is_read = */ false);
|
|
||||||
if (success)
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
failure:
|
|
||||||
LOG_TARGET_ERROR(target, "Failed to write memory (addr=0x%" PRIx64 ")\n"
|
|
||||||
"progbuf=%s, sysbus=%s, abstract=%s", args.address,
|
|
||||||
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]),
|
|
||||||
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]),
|
|
||||||
mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT]));
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool riscv013_get_impebreak(const struct target *target)
|
static bool riscv013_get_impebreak(const struct target *target)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(r);
|
RISCV013_INFO(r);
|
||||||
|
|
|
@ -3140,7 +3140,7 @@ static int riscv_address_translate(struct target *target,
|
||||||
.increment = 4,
|
.increment = 4,
|
||||||
.count = (1 << info->pte_shift) / 4,
|
.count = (1 << info->pte_shift) / 4,
|
||||||
};
|
};
|
||||||
int retval = r->read_memory(target, args);
|
int retval = r->access_memory(target, args);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
@ -3384,7 +3384,7 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr
|
||||||
.increment = size,
|
.increment = size,
|
||||||
};
|
};
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
return r->read_memory(target, args);
|
return r->access_memory(target, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address,
|
static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address,
|
||||||
|
@ -3399,7 +3399,7 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
|
||||||
};
|
};
|
||||||
|
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
return r->write_memory(target, args);
|
return r->access_memory(target, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t args)
|
static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t args)
|
||||||
|
@ -3419,12 +3419,8 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
if (!mmu_enabled) {
|
if (!mmu_enabled)
|
||||||
if (is_write)
|
return r->access_memory(target, args);
|
||||||
return r->write_memory(target, args);
|
|
||||||
else
|
|
||||||
return r->read_memory(target, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = check_virt_memory_access(target, args.address,
|
result = check_virt_memory_access(target, args.address,
|
||||||
args.size, args.count, is_write);
|
args.size, args.count, is_write);
|
||||||
|
@ -3451,13 +3447,12 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t
|
||||||
riscv_mem_access_args_t current_access = args;
|
riscv_mem_access_args_t current_access = args;
|
||||||
current_access.address = physical_addr;
|
current_access.address = physical_addr;
|
||||||
current_access.count = chunk_count;
|
current_access.count = chunk_count;
|
||||||
if (is_write) {
|
if (is_write)
|
||||||
current_access.write_buffer += current_count * args.size;
|
current_access.write_buffer += current_count * args.size;
|
||||||
result = r->write_memory(target, current_access);
|
else
|
||||||
} else {
|
|
||||||
current_access.read_buffer += current_count * args.size;
|
current_access.read_buffer += current_count * args.size;
|
||||||
result = r->read_memory(target, current_access);
|
|
||||||
}
|
result = r->access_memory(target, current_access);
|
||||||
if (result != ERROR_OK)
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -5170,7 +5165,7 @@ COMMAND_HANDLER(handle_repeat_read)
|
||||||
.count = count,
|
.count = count,
|
||||||
.increment = 0,
|
.increment = 0,
|
||||||
};
|
};
|
||||||
int result = r->read_memory(target, args);
|
int result = r->access_memory(target, args);
|
||||||
if (result == ERROR_OK) {
|
if (result == ERROR_OK) {
|
||||||
target_handle_md_output(cmd, target, address, size, count, buffer,
|
target_handle_md_output(cmd, target, address, size, count, buffer,
|
||||||
false);
|
false);
|
||||||
|
|
|
@ -303,8 +303,7 @@ struct riscv_info {
|
||||||
riscv_sample_config_t *config,
|
riscv_sample_config_t *config,
|
||||||
int64_t until_ms);
|
int64_t until_ms);
|
||||||
|
|
||||||
int (*read_memory)(struct target *target, const riscv_mem_access_args_t args);
|
int (*access_memory)(struct target *target, const riscv_mem_access_args_t args);
|
||||||
int (*write_memory)(struct target *target, const riscv_mem_access_args_t args);
|
|
||||||
|
|
||||||
unsigned int (*data_bits)(struct target *target);
|
unsigned int (*data_bits)(struct target *target);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue