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:
Farid Khaydari 2024-10-05 14:19:15 +03:00
parent f51900b4a2
commit bcf9bab90c
4 changed files with 378 additions and 308 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);