From deadf03299345875bd6f85ca09ac948e28df0f9b Mon Sep 17 00:00:00 2001 From: Shengwen Cheng Date: Tue, 23 Jun 2026 20:11:17 +0800 Subject: [PATCH] Delay AMO rd write until store succeeds Do not commit the AMO destination register before the store succeeds. `AMO_OP` wrote `rd` before confirming that `mmu_store()` succeeded. If the store raised a fault, such as a COW/page fault, the destination register could be committed even though the guest kernel would handle the fault and retry the same instruction. This patch delays the `rd` write until after `mmu_store()` returns and `vm->error` is known to be clear. --- riscv.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/riscv.c b/riscv.c index 48f855f6..a6be612e 100644 --- a/riscv.c +++ b/riscv.c @@ -1399,16 +1399,17 @@ static void op_jump_link(hart_t *vm, uint8_t rd, uint32_t addr) } } -#define AMO_OP(STORED_EXPR) \ - do { \ - value2 = vm->x_regs[decoded_rs2(decoded)]; \ - mmu_load(vm, addr, RV_MEM_LW, &value, false); \ - if (vm->error) \ - return; \ - set_dest_idx(vm, decoded_rd(decoded), value); \ - mmu_store(vm, addr, RV_MEM_SW, (STORED_EXPR), false); \ - if (vm->error) \ - return; \ +#define AMO_OP(STORED_EXPR) \ + do { \ + value2 = vm->x_regs[decoded_rs2(decoded)]; \ + mmu_load(vm, addr, RV_MEM_LW, &value, false); \ + if (vm->error) \ + return; \ + uint32_t stored = (STORED_EXPR); \ + mmu_store(vm, addr, RV_MEM_SW, stored, false); \ + if (vm->error) \ + return; \ + set_dest_idx(vm, decoded_rd(decoded), value); \ } while (0) static void op_amo(hart_t *vm, const decoded_insn_t *decoded)