Refactor and fix LR/SC implementation (#217)
authorAndrew Waterman <aswaterman@gmail.com>
Tue, 10 Jul 2018 16:56:32 +0000 (09:56 -0700)
committerGitHub <noreply@github.com>
Tue, 10 Jul 2018 16:56:32 +0000 (09:56 -0700)
- 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
riscv/insns/lr_w.h
riscv/insns/sc_d.h
riscv/insns/sc_w.h
riscv/mmu.cc
riscv/mmu.h
riscv/processor.cc
riscv/processor.h
riscv/sim.cc

index 077590f65950bc886b4af3150ba09b9f9a620658..52090c31b87ccfbf1ef216e461a17d421059ee24 100644 (file)
@@ -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));
index 767251f9e07775dfe2edc01b726f1f661e43feb5..c5845a68e1b42dc5f642118a67df4c0ff1e3a756 100644 (file)
@@ -1,3 +1,3 @@
 require_extension('A');
-p->get_state()->load_reservation = RS1;
+MMU.acquire_load_reservation(RS1);
 WRITE_RD(MMU.load_int32(RS1));
index 01a45ce9094af383e151d039863e8de6df42d9e3..aeeabd350d36e0c98e2c76bf02dc8adc1f87905b 100644 (file)
@@ -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();
index 68ec57717aa190ca52e170b4047df859ce69e20d..4b4be505840b0102fe1ffa9c8e9712b9b0658f1d 100644 (file)
@@ -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();
index 3a0bd39b89471470cef1155f201a646b673cbfab..021f587eaac5ac23c42ae0fa8b88c93c4ca27ec5 100644 (file)
@@ -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()
index 4380448f955f73ff4e51f956ad43164076153bec..715d8397338a10174878df55aff05531e623155b 100644 (file)
@@ -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
index 90266b99aef5ba60fbe36de1dfaa89693afc4b11..9fc5d5f63a6558c1e8258a7f705fa638d7be9d0c 100644 (file)
@@ -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)
index 3e67215b46df9e29493b050c2d59e5cd586507cf..fd90ce3da8943861569a4f35508f8dd4f07e0a27 100644 (file)
@@ -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; }
 
index c9bbac0e028da5a2965e0e7bf8243771b750a96c..b7080f0f0e4b464fa1d5825e91a3a3dd99919308 100644 (file)
@@ -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);