target/riscv: pass memory access info in struct, move write_memory pointer
This changes will allow to unite read_memory/write_memory fucntions to one access function (1) Replaced read/write functions arguments with one structure (2) Unified read_memory/write_memory function pointers to be stored in same structure Signed-off-by: Farid Khaydari <f.khaydari@syntacore.com>
This commit is contained in:
parent
f51900b4a2
commit
bcf9bab90c
|
@ -1972,9 +1972,14 @@ static int deassert_reset(struct target *target)
|
|||
return wait_for_state(target, TARGET_RUNNING);
|
||||
}
|
||||
|
||||
static int read_memory(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment)
|
||||
static int read_memory(struct target *target, const riscv_mem_access_args_t args)
|
||||
{
|
||||
target_addr_t address = args.address;
|
||||
uint32_t size = args.size;
|
||||
uint32_t count = args.count;
|
||||
uint8_t *buffer = args.buffer.read;
|
||||
uint32_t increment = args.increment;
|
||||
|
||||
if (increment != size) {
|
||||
LOG_ERROR("read_memory with custom increment not implemented");
|
||||
return ERROR_NOT_IMPLEMENTED;
|
||||
|
@ -2142,9 +2147,18 @@ static int setup_write_memory(struct target *target, uint32_t size)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int write_memory(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||
static int write_memory(struct target *target, const riscv_mem_access_args_t args)
|
||||
{
|
||||
if (args.increment != args.size) {
|
||||
LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size");
|
||||
return ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
target_addr_t address = args.address;
|
||||
uint32_t size = args.size;
|
||||
uint32_t count = args.count;
|
||||
const uint8_t *buffer = args.buffer.write;
|
||||
|
||||
riscv011_info_t *info = get_info(target);
|
||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||
|
||||
|
@ -2371,7 +2385,9 @@ static int init_target(struct command_context *cmd_ctx,
|
|||
{
|
||||
LOG_DEBUG("init");
|
||||
RISCV_INFO(generic_info);
|
||||
/* TODO: replace read and write with single access function*/
|
||||
generic_info->read_memory = read_memory;
|
||||
generic_info->write_memory = write_memory;
|
||||
generic_info->authdata_read = &riscv011_authdata_read;
|
||||
generic_info->authdata_write = &riscv011_authdata_write;
|
||||
generic_info->print_info = &riscv011_print_info;
|
||||
|
@ -2406,7 +2422,5 @@ struct target_type riscv011_target = {
|
|||
.assert_reset = assert_reset,
|
||||
.deassert_reset = deassert_reset,
|
||||
|
||||
.write_memory = write_memory,
|
||||
|
||||
.arch_state = arch_state,
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2867,8 +2867,16 @@ static int riscv_address_translate(struct target *target,
|
|||
|
||||
uint8_t buffer[8];
|
||||
assert(info->pte_shift <= 3);
|
||||
int retval = r->read_memory(target, pte_address,
|
||||
4, (1 << info->pte_shift) / 4, buffer, 4);
|
||||
const riscv_mem_access_args_t args = {
|
||||
.address = pte_address,
|
||||
.buffer.read = buffer,
|
||||
.size = 4,
|
||||
.increment = 4,
|
||||
.count = (1 << info->pte_shift) / 4,
|
||||
.is_virtual = false,
|
||||
.is_read = true,
|
||||
};
|
||||
int retval = r->read_memory(target, args);
|
||||
if (retval != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
|
@ -3104,29 +3112,42 @@ static int check_virt_memory_access(struct target *target, target_addr_t address
|
|||
static int riscv_read_phys_memory(struct target *target, target_addr_t phys_address,
|
||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
const riscv_mem_access_args_t args = {
|
||||
.address = phys_address,
|
||||
.buffer.read = buffer,
|
||||
.size = size,
|
||||
.increment = size,
|
||||
.count = count,
|
||||
.is_read = true,
|
||||
.is_virtual = false,
|
||||
};
|
||||
RISCV_INFO(r);
|
||||
return r->read_memory(target, phys_address, size, count, buffer, size);
|
||||
return r->read_memory(target, args);
|
||||
}
|
||||
|
||||
static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address,
|
||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||
{
|
||||
struct target_type *tt = get_target_type(target);
|
||||
if (!tt)
|
||||
return ERROR_FAIL;
|
||||
return tt->write_memory(target, phys_address, size, count, buffer);
|
||||
const riscv_mem_access_args_t args = {
|
||||
.address = phys_address,
|
||||
.buffer.write = buffer,
|
||||
.size = size,
|
||||
.increment = size,
|
||||
.count = count,
|
||||
.is_read = false,
|
||||
.is_virtual = false,
|
||||
};
|
||||
|
||||
RISCV_INFO(r);
|
||||
return r->write_memory(target, args);
|
||||
}
|
||||
|
||||
static int riscv_rw_memory(struct target *target, target_addr_t address, uint32_t size,
|
||||
uint32_t count, uint8_t *read_buffer, const uint8_t *write_buffer)
|
||||
static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t args)
|
||||
{
|
||||
/* Exactly one of the buffers must be set, the other must be NULL */
|
||||
assert(!!read_buffer != !!write_buffer);
|
||||
|
||||
const bool is_write = write_buffer ? true : false;
|
||||
if (count == 0) {
|
||||
const bool is_write = !args.is_read;
|
||||
if (args.count == 0) {
|
||||
LOG_TARGET_WARNING(target, "0-length %s 0x%" TARGET_PRIxADDR,
|
||||
is_write ? "write to" : "read from", address);
|
||||
is_write ? "write to" : "read from", args.address);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -3136,25 +3157,23 @@ static int riscv_rw_memory(struct target *target, target_addr_t address, uint32_
|
|||
return result;
|
||||
|
||||
RISCV_INFO(r);
|
||||
struct target_type *tt = get_target_type(target);
|
||||
if (!tt)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (!mmu_enabled) {
|
||||
if (is_write)
|
||||
return tt->write_memory(target, address, size, count, write_buffer);
|
||||
return r->write_memory(target, args);
|
||||
else
|
||||
return r->read_memory(target, address, size, count, read_buffer, size);
|
||||
return r->read_memory(target, args);
|
||||
}
|
||||
|
||||
result = check_virt_memory_access(target, address, size, count, is_write);
|
||||
result = check_virt_memory_access(target, args.address,
|
||||
args.size, args.count, is_write);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
uint32_t current_count = 0;
|
||||
while (current_count < count) {
|
||||
target_addr_t current_address = args.address;
|
||||
while (current_count < args.count) {
|
||||
target_addr_t physical_addr;
|
||||
result = target->type->virt2phys(target, address, &physical_addr);
|
||||
result = target->type->virt2phys(target, current_address, &physical_addr);
|
||||
if (result != ERROR_OK) {
|
||||
LOG_TARGET_ERROR(target, "Address translation failed.");
|
||||
return result;
|
||||
|
@ -3163,16 +3182,24 @@ static int riscv_rw_memory(struct target *target, target_addr_t address, uint32_
|
|||
/* TODO: For simplicity, this algorithm assumes the worst case - the smallest possible page size,
|
||||
* which is 4 KiB. The algorithm can be improved to detect the real page size, and allow to use larger
|
||||
* memory transfers and avoid extra unnecessary virt2phys address translations. */
|
||||
uint32_t chunk_count = MIN(count - current_count, (RISCV_PGSIZE - RISCV_PGOFFSET(address)) / size);
|
||||
uint32_t chunk_count = MIN(args.count - current_count,
|
||||
(RISCV_PGSIZE - RISCV_PGOFFSET(current_address))
|
||||
/ args.size);
|
||||
|
||||
riscv_mem_access_args_t current_access = args;
|
||||
current_access.address = physical_addr;
|
||||
current_access.buffer.write += current_count * args.size;
|
||||
current_access.count = chunk_count;
|
||||
current_access.is_virtual = false;
|
||||
if (is_write)
|
||||
result = tt->write_memory(target, physical_addr, size, chunk_count, write_buffer + current_count * size);
|
||||
result = r->write_memory(target, current_access);
|
||||
else
|
||||
result = r->read_memory(target, physical_addr, size, chunk_count, read_buffer + current_count * size, size);
|
||||
result = r->read_memory(target, current_access);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
current_count += chunk_count;
|
||||
address += chunk_count * size;
|
||||
current_address += chunk_count * args.size;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -3180,13 +3207,33 @@ static int riscv_rw_memory(struct target *target, target_addr_t address, uint32_
|
|||
static int riscv_read_memory(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
return riscv_rw_memory(target, address, size, count, buffer, NULL);
|
||||
const riscv_mem_access_args_t args = {
|
||||
.address = address,
|
||||
.buffer.write = buffer,
|
||||
.size = size,
|
||||
.increment = size,
|
||||
.count = count,
|
||||
.is_read = true,
|
||||
.is_virtual = riscv_virt2phys_mode_is_hw(target),
|
||||
};
|
||||
|
||||
return riscv_rw_memory(target, args);
|
||||
}
|
||||
|
||||
static int riscv_write_memory(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||
{
|
||||
return riscv_rw_memory(target, address, size, count, NULL, buffer);
|
||||
const riscv_mem_access_args_t args = {
|
||||
.address = address,
|
||||
.buffer.write = buffer,
|
||||
.size = size,
|
||||
.increment = size,
|
||||
.count = count,
|
||||
.is_read = false,
|
||||
.is_virtual = riscv_virt2phys_mode_is_hw(target),
|
||||
};
|
||||
|
||||
return riscv_rw_memory(target, args);
|
||||
}
|
||||
|
||||
static const char *riscv_get_gdb_arch(const struct target *target)
|
||||
|
@ -4797,7 +4844,16 @@ COMMAND_HANDLER(handle_repeat_read)
|
|||
LOG_ERROR("malloc failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
int result = r->read_memory(target, address, size, count, buffer, 0);
|
||||
const riscv_mem_access_args_t args = {
|
||||
.address = address,
|
||||
.buffer.read = buffer,
|
||||
.size = size,
|
||||
.count = count,
|
||||
.increment = 0,
|
||||
.is_read = true,
|
||||
.is_virtual = false,
|
||||
};
|
||||
int result = r->read_memory(target, args);
|
||||
if (result == ERROR_OK) {
|
||||
target_handle_md_output(cmd, target, address, size, count, buffer,
|
||||
false);
|
||||
|
|
|
@ -129,6 +129,22 @@ struct reg_name_table {
|
|||
char **reg_names;
|
||||
};
|
||||
|
||||
typedef struct riscv_mem_access_info {
|
||||
target_addr_t address;
|
||||
|
||||
union {
|
||||
uint8_t *read;
|
||||
const uint8_t *write;
|
||||
} buffer;
|
||||
|
||||
uint32_t size;
|
||||
uint32_t increment;
|
||||
uint32_t count;
|
||||
|
||||
bool is_virtual;
|
||||
bool is_read;
|
||||
} riscv_mem_access_args_t;
|
||||
|
||||
struct riscv_info {
|
||||
unsigned int common_magic;
|
||||
|
||||
|
@ -256,8 +272,8 @@ struct riscv_info {
|
|||
riscv_sample_config_t *config,
|
||||
int64_t until_ms);
|
||||
|
||||
int (*read_memory)(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
|
||||
int (*read_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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue