aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Buchner <ryan.buchner@arilinc.com>2023-04-11 10:42:58 -0700
committerrbuchner <ryan.buchner@arilinc.com>2023-05-11 23:00:58 -0700
commit8a34e1a5b3bc68b915127af15ea9254f7d812727 (patch)
treead52d74291e6b2affe232c82204a5f5d2735131b
parenta0c5bf31ba22119bf365c5fcff262736d1b4ac49 (diff)
downloadriscv-isa-sim-8a34e1a5b3bc68b915127af15ea9254f7d812727.zip
riscv-isa-sim-8a34e1a5b3bc68b915127af15ea9254f7d812727.tar.gz
riscv-isa-sim-8a34e1a5b3bc68b915127af15ea9254f7d812727.tar.bz2
Add structure (mem_access_info_t) for holding memory access information
Add complementary function for generating access information. Update mmu_t::translate() to accept a mem_access_info_t.
-rw-r--r--riscv/mmu.cc28
-rw-r--r--riscv/mmu.h34
2 files changed, 41 insertions, 21 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 6a5fdee..e2341fb 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -52,25 +52,16 @@ void throw_access_exception(bool virt, reg_t addr, access_type type)
}
}
-reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, xlate_flags_t xlate_flags)
+reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len)
{
+ reg_t addr = access_info.vaddr;
+ access_type type = access_info.type;
if (!proc)
return addr;
- bool virt = proc->state.v;
- bool hlvx = xlate_flags.hlvx;
- reg_t mode = proc->state.prv;
- if (type != FETCH) {
- if (in_mprv()) {
- mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP);
- if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M)
- virt = true;
- }
- if (xlate_flags.forced_virt) {
- virt = true;
- mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP);
- }
- }
+ bool virt = access_info.effective_virt;
+ bool hlvx = access_info.flags.hlvx;
+ reg_t mode = (reg_t) access_info.effective_priv;
reg_t paddr = walk(addr, type, mode, virt, hlvx) | (addr & (PGSIZE-1));
if (!pmp_ok(paddr, len, type, mode))
@@ -80,12 +71,13 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, xlate_flags_t xl
tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
{
+ auto access_info = generate_access_info(vaddr, FETCH, {false, false, false});
check_triggers(triggers::OPERATION_EXECUTE, vaddr);
tlb_entry_t result;
reg_t vpn = vaddr >> PGSHIFT;
if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) {
- reg_t paddr = translate(vaddr, sizeof(fetch_temp), FETCH, {false, false, false});
+ reg_t paddr = translate(access_info, sizeof(fetch_temp));
if (auto host_addr = sim->addr_to_mem(paddr)) {
result = refill_tlb(vaddr, paddr, host_addr, FETCH);
} else {
@@ -207,7 +199,7 @@ void mmu_t::load_slow_path_intrapage(reg_t addr, reg_t len, uint8_t* bytes, xlat
return;
}
- reg_t paddr = translate(addr, len, LOAD, xlate_flags);
+ reg_t paddr = translate(generate_access_info(addr, LOAD, xlate_flags), len);
if (xlate_flags.lr && !sim->reservable(paddr)) {
throw trap_load_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
@@ -263,7 +255,7 @@ void mmu_t::store_slow_path_intrapage(reg_t addr, reg_t len, const uint8_t* byte
return;
}
- reg_t paddr = translate(addr, len, STORE, xlate_flags);
+ reg_t paddr = translate(generate_access_info(addr, STORE, xlate_flags), len);
if (actually_store) {
if (auto host_addr = sim->addr_to_mem(paddr)) {
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 6e79539..1039de1 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -48,6 +48,14 @@ struct xlate_flags_t {
}
};
+struct mem_access_info_t {
+ const reg_t vaddr;
+ const reg_t effective_priv;
+ const bool effective_virt;
+ const xlate_flags_t flags;
+ const access_type type;
+};
+
void throw_access_exception(bool virt, reg_t addr, access_type type);
// this class implements a processor's port into the virtual memory system.
@@ -57,6 +65,26 @@ class mmu_t
private:
std::map<reg_t, reg_t> alloc_cache;
std::vector<std::pair<reg_t, reg_t >> addr_tbl;
+
+ mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) {
+ if (!proc)
+ return {addr, 0, false, {false, false, false}, type};
+ bool virt = proc->state.v;
+ reg_t mode = proc->state.prv;
+ if (type != FETCH) {
+ if (in_mprv()) {
+ mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP);
+ if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M)
+ virt = true;
+ }
+ if (xlate_flags.forced_virt) {
+ virt = true;
+ mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP);
+ }
+ }
+ return {addr, mode, virt, xlate_flags, type};
+ }
+
public:
mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc);
~mmu_t();
@@ -182,7 +210,7 @@ public:
void clean_inval(reg_t addr, bool clean, bool inval) {
convert_load_traps_to_store_traps({
- const reg_t paddr = translate(addr, blocksz, LOAD, {false, false, false}) & ~(blocksz - 1);
+ const reg_t paddr = translate(generate_access_info(addr, LOAD, {false, false, false}), blocksz) & ~(blocksz - 1);
if (sim->reservable(paddr)) {
if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
tracer.clean_invalidate(paddr, blocksz, clean, inval);
@@ -204,7 +232,7 @@ public:
store_slow_path(vaddr, size, nullptr, {false, false, false}, false, true);
}
- reg_t paddr = translate(vaddr, 1, STORE, {false, false, false});
+ reg_t paddr = translate(generate_access_info(vaddr, STORE, {false, false, false}), 1);
if (sim->reservable(paddr))
return load_reservation_address == paddr;
else
@@ -360,7 +388,7 @@ private:
bool mmio(reg_t paddr, size_t len, uint8_t* bytes, access_type type);
bool mmio_ok(reg_t paddr, access_type type);
void check_triggers(triggers::operation_t operation, reg_t address, std::optional<reg_t> data = std::nullopt);
- reg_t translate(reg_t addr, reg_t len, access_type type, xlate_flags_t xlate_flags);
+ reg_t translate(mem_access_info_t access_info, reg_t len);
reg_t pte_load(reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type, size_t ptesize) {
if (ptesize == 4)