aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUdit Khanna <udit.khanna@sifive.com>2020-07-31 17:10:08 -0700
committerUdit Khanna <udit.khanna@sifive.com>2020-07-31 17:10:08 -0700
commitd123f1e09b73b2721ee5f491b71ce89e5a99ddef (patch)
tree5e5e651a7805ed2b7c01266f63c368d8eff4a7a9
parent6859ccfa4a20295810dfe9d92582504b8ce23643 (diff)
downloadspike-load_reservation_set_size.zip
spike-load_reservation_set_size.tar.gz
spike-load_reservation_set_size.tar.bz2
add configurable LR/SC reservation setload_reservation_set_size
-rw-r--r--riscv/dts.cc19
-rw-r--r--riscv/dts.h2
-rw-r--r--riscv/mmu.h54
-rw-r--r--riscv/processor.h2
-rw-r--r--riscv/sim.cc5
-rw-r--r--riscv/sim.h13
-rw-r--r--riscv/simif.h11
7 files changed, 95 insertions, 11 deletions
diff --git a/riscv/dts.cc b/riscv/dts.cc
index 56b76e6..3f22046 100644
--- a/riscv/dts.cc
+++ b/riscv/dts.cc
@@ -51,6 +51,7 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
s << " CPU" << i << ": cpu@" << i << " {\n"
" device_type = \"cpu\";\n"
" reg = <" << i << ">;\n"
+ " reservation-set-size = <64>;\n"
" status = \"okay\";\n"
" compatible = \"riscv\";\n"
" riscv,isa = \"" << procs[i]->get_isa_string() << "\";\n"
@@ -180,7 +181,6 @@ std::string dts_compile(const std::string& dts)
return dtb.str();
}
-
static int fdt_get_node_addr_size(void *fdt, int node, reg_t *addr,
unsigned long *size, const char *field)
{
@@ -257,6 +257,23 @@ int fdt_parse_pmp_num(void *fdt, reg_t *pmp_num, const char *compatible)
return 0;
}
+int fdt_parse_reservation_set_size(void *fdt, reg_t *reservation_set_size,
+ const char *compatible)
+{
+ int nodeoffset, rc;
+
+ nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ if (nodeoffset < 0)
+ return nodeoffset;
+
+ rc = fdt_get_node_addr_size(fdt, nodeoffset, reservation_set_size, NULL,
+ "reservation-set-size");
+ if (rc < 0 || !reservation_set_size)
+ return -ENODEV;
+
+ return 0;
+}
+
int fdt_parse_pmp_alignment(void *fdt, reg_t *pmp_align,
const char *compatible)
{
diff --git a/riscv/dts.h b/riscv/dts.h
index 1f01e0f..a1adfe4 100644
--- a/riscv/dts.h
+++ b/riscv/dts.h
@@ -20,4 +20,6 @@ int fdt_parse_pmp_num(void *fdt, reg_t *pmp_num,
const char *compatible);
int fdt_parse_pmp_alignment(void *fdt, reg_t *pmp_align,
const char *compatible);
+int fdt_parse_reservation_set_size(void *fdt, reg_t *reservation_set_size,
+ const char *compatible);
#endif
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 990f137..d8157d1 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -241,28 +241,64 @@ public:
inline void yield_load_reservation()
{
- load_reservation_address = (reg_t)-1;
+ auto reserv_set = sim->get_reservation_set();
+ for (auto& entry: reserv_set) {
+ if (entry.second.id == proc->id) {
+ entry.second.valid = false;
+ }
+ }
+ }
+
+ inline void check_reservation_set()
+ {
+ if (sim->get_reservation_set().size() > sim->get_reservation_set_size())
+ throw trap_load_access_fault(0, 0 , 0);
}
inline void acquire_load_reservation(reg_t vaddr)
{
reg_t paddr = translate(vaddr, 1, LOAD, 0);
- if (auto host_addr = sim->addr_to_mem(paddr))
- load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr;
- else
+ if (auto host_addr = sim->addr_to_mem(paddr)) {
+ reg_t load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr;
+ auto& reserv_set = sim->get_reservation_set();
+ auto exist = reserv_set.count(load_reservation_address);
+ if (exist > 1) {
+ auto& entry = reserv_set[load_reservation_address];
+ if (entry.id == proc->id && entry.valid) {
+ throw trap_load_access_fault(vaddr,0, 0); // disallow nested LR
+ }
+ }
+ reserv_set[load_reservation_address] = {proc->id, true};
+ check_reservation_set();
+ } else {
throw trap_load_access_fault(vaddr, 0, 0); // disallow LR to I/O space
+ }
}
inline bool check_load_reservation(reg_t vaddr, size_t size)
{
if (vaddr & (size-1))
throw trap_store_address_misaligned(vaddr, 0, 0);
-
+
reg_t paddr = translate(vaddr, 1, STORE, 0);
- if (auto host_addr = sim->addr_to_mem(paddr))
- return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr;
- else
+ if (auto host_addr = sim->addr_to_mem(paddr)) {
+ reg_t reserved_addr = refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr;
+ auto reserv_set = sim->get_reservation_set();
+ auto exist = reserv_set.count(reserved_addr);
+ if (exist > 0) {
+ auto entry = reserv_set[reserved_addr];
+ if (entry.id == proc->id && entry.valid) {
+ sim->get_reservation_set().erase(reserved_addr);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else {
throw trap_store_access_fault(vaddr, 0, 0); // disallow SC to I/O space
+ }
}
static const reg_t ICACHE_ENTRIES = 1024;
@@ -346,7 +382,6 @@ 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
@@ -431,6 +466,7 @@ private:
trigger_matched_t *matched_trigger;
friend class processor_t;
+
};
struct vm_info {
diff --git a/riscv/processor.h b/riscv/processor.h
index 6c16eb9..447d5a5 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -47,6 +47,7 @@ typedef struct
uint8_t cause;
} dcsr_t;
+
typedef enum
{
ACTION_DEBUG_EXCEPTION = MCONTROL_ACTION_DEBUG_EXCEPTION,
@@ -429,7 +430,6 @@ private:
FILE *log_file;
bool halt_on_reset;
std::vector<bool> extension_table;
-
std::vector<insn_desc_t> instructions;
std::map<reg_t,uint64_t> pc_histogram;
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 2aced1b..f68e5c3 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -99,6 +99,11 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch,
procs[i]->set_pmp_num(pmp_num);
procs[i]->set_pmp_granularity(pmp_granularity);
}
+
+ reg_t reservation_set_size = 0;
+ fdt_parse_reservation_set_size((void *)dtb.c_str(), &reservation_set_size, "riscv");
+ set_reservation_set_size(reservation_set_size);
+
}
sim_t::~sim_t()
diff --git a/riscv/sim.h b/riscv/sim.h
index c6e5582..1424b24 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -57,6 +57,17 @@ public:
// Callback for processors to let the simulation know they were reset.
void proc_reset(unsigned id);
+ std::map<reg_t, reservation> reservation_set;
+ reg_t reservation_set_size;
+
+ void set_reservation_set_size(reg_t set_size) {
+ if(set_size == 0) {
+ reservation_set_size = 1;
+ } else {
+ reservation_set_size = set_size;
+ }
+ }
+
private:
std::vector<std::pair<reg_t, mem_t*>> mems;
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices;
@@ -137,6 +148,8 @@ private:
size_t chunk_align() { return 8; }
size_t chunk_max_size() { return 8; }
+ std::map<reg_t, reservation>& get_reservation_set() { return reservation_set; }
+ reg_t get_reservation_set_size() { return reservation_set_size; }
public:
// Initialize this after procs, because in debug_module_t::reset() we
// enumerate processors, which segfaults if procs hasn't been initialized
diff --git a/riscv/simif.h b/riscv/simif.h
index 1d982b3..5834a87 100644
--- a/riscv/simif.h
+++ b/riscv/simif.h
@@ -4,6 +4,13 @@
#define _RISCV_SIMIF_H
#include "decode.h"
+#include <map>
+
+// LR/SC
+struct reservation {
+ uint32_t id;
+ bool valid;
+};
// this is the interface to the simulator used by the processors and memory
class simif_t
@@ -16,6 +23,10 @@ public:
virtual bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
// Callback for processors to let the simulation know they were reset.
virtual void proc_reset(unsigned id) = 0;
+
+ // get the LR/SC's reservation set
+ virtual std::map<reg_t, reservation>& get_reservation_set() = 0;
+ virtual reg_t get_reservation_set_size() = 0;
};
#endif