From 95487c248a6eb660b9bd1aa49e28da5a1ab21059 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 10 Jul 2018 09:56:32 -0700 Subject: [PATCH] Refactor and fix LR/SC implementation (#217) - Use physical addresses to avoid homonym ambiguity (closes #215) - Yield reservation on store-conditional (https://github.com/riscv/riscv-isa-manual/commit/03a5e722fc0fe7b94dd0a49f550ff7b41a63f612) - Don't yield reservation on exceptions (it's no longer required). --- riscv/insns/lr_d.h | 2 +- riscv/insns/lr_w.h | 2 +- riscv/insns/sc_d.h | 4 +++- riscv/insns/sc_w.h | 4 +++- riscv/mmu.cc | 1 + riscv/mmu.h | 24 ++++++++++++++++++++++++ riscv/processor.cc | 3 --- riscv/processor.h | 3 --- riscv/sim.cc | 2 +- 9 files changed, 34 insertions(+), 11 deletions(-) diff --git a/riscv/insns/lr_d.h b/riscv/insns/lr_d.h index 077590f..52090c3 100644 --- a/riscv/insns/lr_d.h +++ b/riscv/insns/lr_d.h @@ -1,4 +1,4 @@ require_extension('A'); require_rv64; -p->get_state()->load_reservation = RS1; +MMU.acquire_load_reservation(RS1); WRITE_RD(MMU.load_int64(RS1)); diff --git a/riscv/insns/lr_w.h b/riscv/insns/lr_w.h index 767251f..c5845a6 100644 --- a/riscv/insns/lr_w.h +++ b/riscv/insns/lr_w.h @@ -1,3 +1,3 @@ require_extension('A'); -p->get_state()->load_reservation = RS1; +MMU.acquire_load_reservation(RS1); WRITE_RD(MMU.load_int32(RS1)); diff --git a/riscv/insns/sc_d.h b/riscv/insns/sc_d.h index 01a45ce..aeeabd3 100644 --- a/riscv/insns/sc_d.h +++ b/riscv/insns/sc_d.h @@ -1,9 +1,11 @@ require_extension('A'); require_rv64; -if (RS1 == p->get_state()->load_reservation) +if (MMU.check_load_reservation(RS1)) { MMU.store_uint64(RS1, RS2); WRITE_RD(0); } else WRITE_RD(1); + +MMU.yield_load_reservation(); diff --git a/riscv/insns/sc_w.h b/riscv/insns/sc_w.h index 68ec577..4b4be50 100644 --- a/riscv/insns/sc_w.h +++ b/riscv/insns/sc_w.h @@ -1,8 +1,10 @@ require_extension('A'); -if (RS1 == p->get_state()->load_reservation) +if (MMU.check_load_reservation(RS1)) { MMU.store_uint32(RS1, RS2); WRITE_RD(0); } else WRITE_RD(1); + +MMU.yield_load_reservation(); diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 3a0bd39..021f587 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -12,6 +12,7 @@ mmu_t::mmu_t(simif_t* sim, processor_t* proc) matched_trigger(NULL) { flush_tlb(); + yield_load_reservation(); } mmu_t::~mmu_t() diff --git a/riscv/mmu.h b/riscv/mmu.h index 4380448..715d839 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -180,6 +180,29 @@ public: amo_func(uint32) amo_func(uint64) + inline void yield_load_reservation() + { + load_reservation_address = (reg_t)-1; + } + + inline void acquire_load_reservation(reg_t vaddr) + { + reg_t paddr = translate(vaddr, LOAD); + if (auto host_addr = sim->addr_to_mem(paddr)) + load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr; + else + throw trap_load_access_fault(vaddr); // disallow LR to I/O space + } + + inline bool check_load_reservation(reg_t vaddr) + { + reg_t paddr = translate(vaddr, STORE); + if (auto host_addr = sim->addr_to_mem(paddr)) + return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr; + else + throw trap_store_access_fault(vaddr); // disallow SC to I/O space + } + static const reg_t ICACHE_ENTRIES = 1024; inline size_t icache_index(reg_t addr) @@ -261,6 +284,7 @@ private: simif_t* sim; processor_t* proc; memtracer_list_t tracer; + reg_t load_reservation_address; uint16_t fetch_temp; // implement an instruction cache for simulator performance diff --git a/riscv/processor.cc b/riscv/processor.cc index 90266b9..9fc5d5f 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -121,7 +121,6 @@ void state_t::reset(reg_t max_isa) misa = max_isa; prv = PRV_M; pc = DEFAULT_RSTVEC; - load_reservation = -1; tselect = 0; for (unsigned int i = 0; i < num_triggers; i++) mcontrol[i].type = 2; @@ -298,8 +297,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc) set_csr(CSR_MSTATUS, s); set_privilege(PRV_M); } - - yield_load_reservation(); } void processor_t::disasm(insn_t insn) diff --git a/riscv/processor.h b/riscv/processor.h index 3e67215..fd90ce3 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -135,8 +135,6 @@ struct state_t STEP_STEPPED } single_step; - reg_t load_reservation; - #ifdef RISCV_ENABLE_COMMITLOG commit_log_reg_t log_reg_write; reg_t last_inst_priv; @@ -197,7 +195,6 @@ public: } reg_t legalize_privilege(reg_t); void set_privilege(reg_t); - void yield_load_reservation() { state.load_reservation = (reg_t)-1; } void update_histogram(reg_t pc); const disassembler_t* get_disassembler() { return disassembler; } diff --git a/riscv/sim.cc b/riscv/sim.cc index c9bbac0..b7080f0 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -109,7 +109,7 @@ void sim_t::step(size_t n) if (current_step == INTERLEAVE) { current_step = 0; - procs[current_proc]->yield_load_reservation(); + procs[current_proc]->get_mmu()->yield_load_reservation(); if (++current_proc == procs.size()) { current_proc = 0; clint->increment(INTERLEAVE / INSNS_PER_RTC_TICK); -- 2.30.2