Closed xvuko closed 1 year ago
Interesting. Have you verified this with other RAM offsets?
Interesting. Have you verified this with other RAM offsets?
Yes. This is minimal example:
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#define MINIRV32_DECORATE
#define MINIRV32_IMPLEMENTATION
static uint32_t ram_offset = 0x10000000;
#define MINIRV32_RAM_IMAGE_OFFSET (ram_offset)
#define MINI_RV32_RAM_SIZE (16u)
#include <mini-rv32ima.h>
#define R_A0 10
#define R_A1 11
void do_write(uint32_t addr, uint32_t value) {
uint32_t image[MINI_RV32_RAM_SIZE / 4] = {
// sw a1, 0(a0)
0x00b52023,
};
struct MiniRV32IMAState state = {
.pc = MINIRV32_RAM_IMAGE_OFFSET,
.regs = {
[R_A0] = addr,
[R_A1] = value,
}
};
printf("pc: 0x%08x wr_value: 0x%08x wr_addr: 0x%08x\n", state.pc, value, addr);
int ret = MiniRV32IMAStep(&state, (uint8_t *)image, 0, 0, 1);
printf("mcause: 0x%08x mval: 0x%08x ret: 0x%08x\n", state.mcause, state.mtval, ret);
}
void check_offset(uint32_t ram_off) {
ram_offset = ram_off;
printf("write to valid address 0x11100000 (SYSCON)\n");
do_write(0x11100000, 0xdeadbeef);
printf("\n");
printf("write to invalid address: 0x13000000\n");
do_write(0x13000000, 0xdeadbeef);
}
int main(int argc, char **argv) {
check_offset(0x80000000);
printf("\n");
check_offset(0x40000000);
}
Without my changes this returns:
write to valid address 0x11100000 (SYSCON)
pc: 0x80000000 wr_value: 0xdeadbeef wr_addr: 0x11100000
mcause: 0x00000000 mval: 0x00000000 ret: 0xdeadbeef
write to invalid address: 0x13000000
pc: 0x80000000 wr_value: 0xdeadbeef wr_addr: 0x13000000
mcause: 0x00000007 mval: 0x93000000 ret: 0x00000000
write to valid address 0x11100000 (SYSCON)
pc: 0x40000000 wr_value: 0xdeadbeef wr_addr: 0x11100000
mcause: 0x00000007 mval: 0xd1100000 ret: 0x00000000
write to invalid address: 0x13000000
pc: 0x40000000 wr_value: 0xdeadbeef wr_addr: 0x13000000
mcause: 0x00000007 mval: 0xd3000000 ret: 0x00000000
With ram offset changed to 0x40000000
SYSCON write fails;
In both ram offsets mtval is not set to address that caused access fault: 0x13000000
After applying changes:
write to valid address 0x11100000 (SYSCON)
pc: 0x80000000 wr_value: 0xdeadbeef wr_addr: 0x11100000
mcause: 0x00000000 mval: 0x00000000 ret: 0xdeadbeef
write to invalid address: 0x13000000
pc: 0x80000000 wr_value: 0xdeadbeef wr_addr: 0x13000000
mcause: 0x00000007 mval: 0x13000000 ret: 0x00000000
write to valid address 0x11100000 (SYSCON)
pc: 0x40000000 wr_value: 0xdeadbeef wr_addr: 0x11100000
mcause: 0x00000000 mval: 0x00000000 ret: 0xdeadbeef
write to invalid address: 0x13000000
pc: 0x40000000 wr_value: 0xdeadbeef wr_addr: 0x13000000
mcause: 0x00000007 mval: 0x13000000 ret: 0x00000000
SYSCON write succeds in both ram offsets
mtval is set to 0x13000000
Excellent.
Note that this was working correctly only with default RAM offset. In uint32 field (x - 2^31 - 2^31) is equal x.