From c370e33d2f4b43f0668af92c9a2e92d8d446969d Mon Sep 17 00:00:00 2001 From: ranvd Date: Tue, 25 Jun 2024 01:24:57 +0800 Subject: [PATCH] Correct LR/SC implementation LR/SC needs to ensure the address is valid and the value does not change. In the original implementation, it only checks if the address is valid. --- riscv.c | 9 +++++++-- riscv.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/riscv.c b/riscv.c index 699846f..b7cdd65 100644 --- a/riscv.c +++ b/riscv.c @@ -311,8 +311,10 @@ static void mmu_load(vm_t *vm, if (vm->error) return; - if (unlikely(reserved)) + if (unlikely(reserved)) { vm->lr_reservation = addr | 1; + vm->lr_val = *value; + } } static bool mmu_store(vm_t *vm, @@ -328,8 +330,11 @@ static bool mmu_store(vm_t *vm, return false; if (unlikely(cond)) { - if (vm->lr_reservation != (addr | 1)) + uint32_t cas_value; + vm->mem_load(vm, addr, width, &cas_value); + if ((vm->lr_reservation != (addr | 1)) || vm->lr_val != cas_value) return false; + vm->lr_reservation = 0; } else { if (unlikely(vm->lr_reservation & 1) && diff --git a/riscv.h b/riscv.h index fda402e..44b0c31 100644 --- a/riscv.h +++ b/riscv.h @@ -56,6 +56,7 @@ struct __vm_internal { /* LR reservation virtual address. last bit is 1 if valid */ uint32_t lr_reservation; + uint32_t lr_val; /* Assumed to contain an aligned address at all times */ uint32_t pc;