Browse Source

add configurable LR/SC reservation set

load_reservation_set_size
Udit Khanna 6 years ago
parent
commit
d123f1e09b
  1. 19
      riscv/dts.cc
  2. 2
      riscv/dts.h
  3. 52
      riscv/mmu.h
  4. 2
      riscv/processor.h
  5. 5
      riscv/sim.cc
  6. 13
      riscv/sim.h
  7. 11
      riscv/simif.h

19
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)
{

2
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

52
riscv/mmu.h

@ -241,16 +241,38 @@ 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)
@ -259,10 +281,24 @@ public:
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 {

2
riscv/processor.h

@ -47,6 +47,7 @@ typedef struct
uint8_t cause;
} dcsr_t;
typedef enum
{
ACTION_DEBUG_EXCEPTION = MCONTROL_ACTION_DEBUG_EXCEPTION,
@ -430,7 +431,6 @@ private:
bool halt_on_reset;
std::vector<bool> extension_table;
std::vector<insn_desc_t> instructions;
std::map<reg_t,uint64_t> pc_histogram;

5
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()

13
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

11
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

Loading…
Cancel
Save