Skip to content

Commit 92d7a57

Browse files
committed
[NFC] target/riscv: refactor riscv_read_memory,riscv_write_memory
Reduce duplicate code
1 parent 4a1bd80 commit 92d7a57

File tree

1 file changed

+35
-52
lines changed

1 file changed

+35
-52
lines changed

src/target/riscv/riscv.c

Lines changed: 35 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,51 +3083,6 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr
30833083
return r->read_memory(target, phys_address, size, count, buffer, size);
30843084
}
30853085

3086-
static int riscv_read_memory(struct target *target, target_addr_t address,
3087-
uint32_t size, uint32_t count, uint8_t *buffer)
3088-
{
3089-
if (count == 0) {
3090-
LOG_TARGET_WARNING(target, "0-length read from 0x%" TARGET_PRIxADDR, address);
3091-
return ERROR_OK;
3092-
}
3093-
3094-
int mmu_enabled;
3095-
int result = riscv_mmu(target, &mmu_enabled);
3096-
if (result != ERROR_OK)
3097-
return result;
3098-
3099-
RISCV_INFO(r);
3100-
3101-
if (!mmu_enabled)
3102-
return r->read_memory(target, address, size, count, buffer, size);
3103-
3104-
result = check_virt_memory_access(target, address, size, count, false);
3105-
if (result != ERROR_OK)
3106-
return result;
3107-
3108-
uint32_t current_count = 0;
3109-
while (current_count < count) {
3110-
target_addr_t physical_addr;
3111-
result = target->type->virt2phys(target, address, &physical_addr);
3112-
if (result != ERROR_OK) {
3113-
LOG_TARGET_ERROR(target, "Address translation failed.");
3114-
return result;
3115-
}
3116-
3117-
/* TODO: For simplicity, this algorithm assumes the worst case - the smallest possible page size,
3118-
* which is 4 KiB. The algorithm can be improved to detect the real page size, and allow to use larger
3119-
* memory transfers and avoid extra unnecessary virt2phys address translations. */
3120-
uint32_t chunk_count = MIN(count - current_count, (RISCV_PGSIZE - RISCV_PGOFFSET(address)) / size);
3121-
result = r->read_memory(target, physical_addr, size, chunk_count, buffer + current_count * size, size);
3122-
if (result != ERROR_OK)
3123-
return result;
3124-
3125-
current_count += chunk_count;
3126-
address += chunk_count * size;
3127-
}
3128-
return ERROR_OK;
3129-
}
3130-
31313086
static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address,
31323087
uint32_t size, uint32_t count, const uint8_t *buffer)
31333088
{
@@ -3137,11 +3092,16 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
31373092
return tt->write_memory(target, phys_address, size, count, buffer);
31383093
}
31393094

3140-
static int riscv_write_memory(struct target *target, target_addr_t address,
3141-
uint32_t size, uint32_t count, const uint8_t *buffer)
3095+
static int riscv_rw_memory(struct target *target, target_addr_t address, uint32_t size,
3096+
uint32_t count, uint8_t *read_buffer, const uint8_t *write_buffer)
31423097
{
3098+
/* Exactly one of the buffers must be set, the other must be NULL */
3099+
assert(!!read_buffer != !!write_buffer);
3100+
3101+
const bool is_write = write_buffer ? true : false;
31433102
if (count == 0) {
3144-
LOG_TARGET_WARNING(target, "0-length write to 0x%" TARGET_PRIxADDR, address);
3103+
LOG_TARGET_WARNING(target, "0-length %s 0x%" TARGET_PRIxADDR,
3104+
is_write ? "write to" : "read from", address);
31453105
return ERROR_OK;
31463106
}
31473107

@@ -3150,14 +3110,19 @@ static int riscv_write_memory(struct target *target, target_addr_t address,
31503110
if (result != ERROR_OK)
31513111
return result;
31523112

3113+
RISCV_INFO(r);
31533114
struct target_type *tt = get_target_type(target);
31543115
if (!tt)
31553116
return ERROR_FAIL;
31563117

3157-
if (!mmu_enabled)
3158-
return tt->write_memory(target, address, size, count, buffer);
3118+
if (!mmu_enabled) {
3119+
if (is_write)
3120+
return tt->write_memory(target, address, size, count, write_buffer);
3121+
else
3122+
return r->read_memory(target, address, size, count, read_buffer, size);
3123+
}
31593124

3160-
result = check_virt_memory_access(target, address, size, count, true);
3125+
result = check_virt_memory_access(target, address, size, count, is_write);
31613126
if (result != ERROR_OK)
31623127
return result;
31633128

@@ -3170,8 +3135,14 @@ static int riscv_write_memory(struct target *target, target_addr_t address,
31703135
return result;
31713136
}
31723137

3138+
/* TODO: For simplicity, this algorithm assumes the worst case - the smallest possible page size,
3139+
* which is 4 KiB. The algorithm can be improved to detect the real page size, and allow to use larger
3140+
* memory transfers and avoid extra unnecessary virt2phys address translations. */
31733141
uint32_t chunk_count = MIN(count - current_count, (RISCV_PGSIZE - RISCV_PGOFFSET(address)) / size);
3174-
result = tt->write_memory(target, physical_addr, size, chunk_count, buffer + current_count * size);
3142+
if (is_write)
3143+
result = tt->write_memory(target, physical_addr, size, chunk_count, write_buffer + current_count * size);
3144+
else
3145+
result = r->read_memory(target, physical_addr, size, chunk_count, read_buffer + current_count * size, size);
31753146
if (result != ERROR_OK)
31763147
return result;
31773148

@@ -3181,6 +3152,18 @@ static int riscv_write_memory(struct target *target, target_addr_t address,
31813152
return ERROR_OK;
31823153
}
31833154

3155+
static int riscv_read_memory(struct target *target, target_addr_t address,
3156+
uint32_t size, uint32_t count, uint8_t *buffer)
3157+
{
3158+
return riscv_rw_memory(target, address, size, count, buffer, NULL);
3159+
}
3160+
3161+
static int riscv_write_memory(struct target *target, target_addr_t address,
3162+
uint32_t size, uint32_t count, const uint8_t *buffer)
3163+
{
3164+
return riscv_rw_memory(target, address, size, count, NULL, buffer);
3165+
}
3166+
31843167
static const char *riscv_get_gdb_arch(const struct target *target)
31853168
{
31863169
switch (riscv_xlen(target)) {

0 commit comments

Comments
 (0)