From 8c11b456707e67b07de5e836469dbce1427cb917 Mon Sep 17 00:00:00 2001 From: Toby Jaffey Date: Tue, 9 Dec 2025 10:46:29 +0000 Subject: [PATCH] Move CPU core out of RAM. This limits possibilities for self-modifying code hacks, but is cleaner/safer. --- precompiled/self.bin | Bin 4980 -> 4964 bytes uvm32/uvm32.c | 25 +++++++++++-------------- uvm32/uvm32.h | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/precompiled/self.bin b/precompiled/self.bin index 57c733e3bc1a59ee10c8607b81147d95d63ec59c..5d6602d9e070fb02d47d709b9fd02bcf2d61b9c0 100755 GIT binary patch literal 4964 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 au>8+T>X!dYZ1~!a9Xp!_cYbTfll1>kwvjUc literal 4980 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 = UVM32_STATUS_PAUSED; UVM32_MEMSET(vmst->memory, 0x00, UVM32_MEMORY_SIZE); - // The core lives at the end of RAM. - vmst->core = (struct MiniRV32IMAState*)(vmst->memory + UVM32_MEMORY_SIZE - sizeof(struct MiniRV32IMAState)); - vmst->core->pc = MINIRV32_RAM_IMAGE_OFFSET; + vmst->core.pc = MINIRV32_RAM_IMAGE_OFFSET; // https://projectf.io/posts/riscv-cheat-sheet/ // setup stack pointer // la sp, _sstack // addi sp,sp,-16 - vmst->core->regs[2] = (MINIRV32_RAM_IMAGE_OFFSET + UVM32_MEMORY_SIZE - sizeof(struct MiniRV32IMAState)) - 16; - vmst->core->regs[10] = 0x00; //hart ID - vmst->core->regs[11] = 0; - vmst->core->extraflags |= 3; // Machine-mode. + vmst->core.regs[2] = (MINIRV32_RAM_IMAGE_OFFSET + UVM32_MEMORY_SIZE - sizeof(struct MiniRV32IMAState)) - 16; + vmst->core.regs[10] = 0x00; //hart ID + vmst->core.regs[11] = 0; + vmst->core.extraflags |= 3; // Machine-mode. vmst->mappings = mappings; vmst->numMappings = numMappings; } bool uvm32_load(uvm32_state_t *vmst, uint8_t *rom, int len) { - // RAM needs at least image then MiniRV32IMAState (core) - if (len > UVM32_MEMORY_SIZE - sizeof(struct MiniRV32IMAState)) { + if (len > UVM32_MEMORY_SIZE) { // too big return false; } @@ -143,14 +140,14 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter) while(vmst->status == UVM32_STATUS_RUNNING) { uint64_t elapsedUs = 1; uint32_t ret; - ret = MiniRV32IMAStep(vmst, vmst->core, vmst->memory, 0, elapsedUs, 1); + ret = MiniRV32IMAStep(vmst, &vmst->core, vmst->memory, 0, elapsedUs, 1); if (3 == ret) { - const uint32_t syscall = vmst->core->regs[17]; // a7 - uint32_t value = vmst->core->regs[10]; // a0 + const uint32_t syscall = vmst->core.regs[17]; // a7 + uint32_t value = vmst->core.regs[10]; // a0 bool syscall_valid = false; // on exception we should jump to mtvec, but we handle directly // and skip over the ecall instruction - vmst->core->pc += 4; + vmst->core.pc += 4; switch(syscall) { // inbuilt syscalls case UVM32_SYSCALL_HALT: @@ -180,7 +177,7 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter) break; case UVM32_SYSCALL_TYP_U32_RD: // pass link to r1 for user function to update - vmst->ioevt.data.syscall.val.u32p = &vmst->core->regs[11]; + vmst->ioevt.data.syscall.val.u32p = &vmst->core.regs[11]; break; } vmst->ioevt.typ = UVM32_EVT_SYSCALL; diff --git a/uvm32/uvm32.h b/uvm32/uvm32.h index 876d5c4..e6747fb 100644 --- a/uvm32/uvm32.h +++ b/uvm32/uvm32.h @@ -90,7 +90,7 @@ typedef enum { typedef struct { uvm32_status_t status; uvm32_err_t err; - struct MiniRV32IMAState* core; // points at end of memory + struct MiniRV32IMAState core; uint8_t memory[UVM32_MEMORY_SIZE]; uvm32_evt_t ioevt; // for building up in callbacks const uvm32_mapping_t *mappings;