Skip to content

Commit

Permalink
riscv: fix read/write virtual memory across page boundaries
Browse files Browse the repository at this point in the history
When read/write virtual addresses cross page boundaries,
the physical addresses are not necessarily contiguous and
need to call virt2phys again.
  • Loading branch information
zqb-all committed Oct 12, 2024
1 parent a4020f1 commit 179aab2
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 15 deletions.
67 changes: 52 additions & 15 deletions src/target/riscv/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -3071,20 +3071,38 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr
static int riscv_read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
uint32_t current_count = 0;

if (count == 0) {
LOG_TARGET_WARNING(target, "0-length read from 0x%" TARGET_PRIxADDR, address);
return ERROR_OK;
}

target_addr_t physical_addr;
int result = target->type->virt2phys(target, address, &physical_addr);
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Address translation failed.");
return result;
if (address % size) {
LOG_TARGET_ERROR(target, "Address 0x%" TARGET_PRIxADDR " not align to size %d", address, size);
return ERROR_FAIL;
}

RISCV_INFO(r);
return r->read_memory(target, physical_addr, size, count, buffer, size);
while (current_count < count) {
uint32_t offset = address & (RISCV_PGSIZE - 1);
uint32_t chunk_count = MIN(count - current_count, (RISCV_PGSIZE - offset) / size);

target_addr_t physical_addr;
int result = target->type->virt2phys(target, address, &physical_addr);
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Address translation failed.");
return result;
}

RISCV_INFO(r);
result = r->read_memory(target, physical_addr, size, chunk_count, buffer + current_count * size, size);
if (result != ERROR_OK)
return result;

current_count += chunk_count;
address += chunk_count * size;
}
return ERROR_OK;
}

static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address,
Expand All @@ -3099,22 +3117,41 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
static int riscv_write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
uint32_t current_count = 0;

if (count == 0) {
LOG_TARGET_WARNING(target, "0-length write to 0x%" TARGET_PRIxADDR, address);
return ERROR_OK;
}

target_addr_t physical_addr;
int result = target->type->virt2phys(target, address, &physical_addr);
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Address translation failed.");
return result;
}

struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->write_memory(target, physical_addr, size, count, buffer);

if (address % size) {
LOG_TARGET_ERROR(target, "Address 0x%" TARGET_PRIxADDR " not align to size %d", address, size);
return ERROR_FAIL;
}

while (current_count < count) {
uint32_t offset = address & (RISCV_PGSIZE - 1);
uint32_t chunk_count = MIN(count - current_count, (RISCV_PGSIZE - offset) / size);

target_addr_t physical_addr;
int result = target->type->virt2phys(target, address, &physical_addr);
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Address translation failed.");
return result;
}

result = tt->write_memory(target, physical_addr, size, chunk_count, buffer + current_count * size);
if (result != ERROR_OK)
return result;

current_count += chunk_count;
address += chunk_count * size;
}
return ERROR_OK;
}

static const char *riscv_get_gdb_arch(const struct target *target)
Expand Down
1 change: 1 addition & 0 deletions src/target/riscv/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct riscv_program;
#define RISCV_HGATP_MODE(xlen) ((xlen) == 32 ? HGATP32_MODE : HGATP64_MODE)
#define RISCV_HGATP_PPN(xlen) ((xlen) == 32 ? HGATP32_PPN : HGATP64_PPN)
#define RISCV_PGSHIFT 12
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)

#define PG_MAX_LEVEL 5

Expand Down

0 comments on commit 179aab2

Please sign in to comment.