diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-02-19 13:06:57 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-02 12:15:25 -0800 |
commit | c0c61f09d8eb21a41b5472a85abdcac62ad665d6 (patch) | |
tree | 2744a382679bb9d43db46efb2fcb8efaee901dd5 /riscv/mmu.cc | |
parent | 48e4425644c9984ea73df6633f13c8ff60d44d4d (diff) | |
download | spike-c0c61f09d8eb21a41b5472a85abdcac62ad665d6.zip spike-c0c61f09d8eb21a41b5472a85abdcac62ad665d6.tar.gz spike-c0c61f09d8eb21a41b5472a85abdcac62ad665d6.tar.bz2 |
implement PUM functionality
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r-- | riscv/mmu.cc | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc index b8fb028..45457d9 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -35,9 +35,12 @@ reg_t mmu_t::translate(reg_t addr, access_type type) return addr; reg_t mode = proc->state.prv; - if (type != FETCH && proc->state.prv == PRV_M && - get_field(proc->state.mstatus, MSTATUS_MPRV)) - mode = get_field(proc->state.mstatus, MSTATUS_MPP); + bool pum = false; + if (type != FETCH) { + if (get_field(proc->state.mstatus, MSTATUS_MPRV)) + mode = get_field(proc->state.mstatus, MSTATUS_MPP); + pum = (mode == PRV_S && get_field(proc->state.mstatus, MSTATUS_PUM)); + } if (get_field(proc->state.mstatus, MSTATUS_VM) == VM_MBARE) mode = PRV_M; @@ -45,7 +48,7 @@ reg_t mmu_t::translate(reg_t addr, access_type type) reg_t msb_mask = (reg_t(2) << (proc->xlen-1))-1; // zero-extend from xlen return addr & msb_mask; } - return walk(addr, mode > PRV_U, type) | (addr & (PGSIZE-1)); + return walk(addr, type, mode > PRV_U, pum) | (addr & (PGSIZE-1)); } const uint16_t* mmu_t::fetch_slow_path(reg_t addr) @@ -102,7 +105,7 @@ void mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, access_type type) tlb_data[idx] = mem + paddr - vaddr; } -reg_t mmu_t::walk(reg_t addr, bool supervisor, access_type type) +reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum) { int levels, ptidxbits, ptesize; switch (get_field(proc->get_state()->mstatus, MSTATUS_VM)) @@ -136,6 +139,8 @@ reg_t mmu_t::walk(reg_t addr, bool supervisor, access_type type) if (PTE_TABLE(pte)) { // next level of page table base = ppn << PGSHIFT; + } else if (pum && PTE_CHECK_PERM(pte, 0, type == STORE, type == FETCH)) { + break; } else if (!PTE_CHECK_PERM(pte, supervisor, type == STORE, type == FETCH)) { break; } else { |