diff options
-rw-r--r-- | riscv/encoding.h | 15 | ||||
-rw-r--r-- | riscv/mmu.cc | 15 | ||||
-rw-r--r-- | riscv/mmu.h | 2 | ||||
-rw-r--r-- | riscv/processor.cc | 12 |
4 files changed, 26 insertions, 18 deletions
diff --git a/riscv/encoding.h b/riscv/encoding.h index a88205f..b2ef0bf 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -17,7 +17,8 @@ #define MSTATUS_FS 0x00006000 #define MSTATUS_XS 0x00018000 #define MSTATUS_MPRV 0x00020000 -#define MSTATUS_VM 0x007C0000 +#define MSTATUS_PUM 0x00040000 +#define MSTATUS_VM 0x1F000000 #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000 @@ -28,7 +29,7 @@ #define SSTATUS_SPP 0x00000100 #define SSTATUS_FS 0x00006000 #define SSTATUS_XS 0x00018000 -#define SSTATUS_VM 0x007C0000 +#define SSTATUS_PUM 0x00040000 #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 @@ -669,10 +670,10 @@ #define CSR_MCPUID 0xf00 #define CSR_MIMPID 0xf01 #define CSR_MHARTID 0xf10 -#define CSR_MTOHOST 0x780 -#define CSR_MFROMHOST 0x781 -#define CSR_MRESET 0x782 -#define CSR_MIOBASE 0x784 +#define CSR_MTOHOST 0x7c0 +#define CSR_MFROMHOST 0x7c1 +#define CSR_MRESET 0x7c2 +#define CSR_MIOBASE 0x7c4 #define CSR_CYCLEH 0xc80 #define CSR_TIMEH 0xc81 #define CSR_INSTRETH 0xc82 @@ -682,7 +683,7 @@ #define CSR_STIMEH 0xd81 #define CSR_STIMEHW 0xa81 #define CSR_MTIMECMPH 0x361 -#define CSR_MTIMEH 0x741 +#define CSR_MTIMEH 0x781 #define CAUSE_MISALIGNED_FETCH 0x0 #define CAUSE_FAULT_FETCH 0x1 #define CAUSE_ILLEGAL_INSTRUCTION 0x2 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 { diff --git a/riscv/mmu.h b/riscv/mmu.h index b6697cd..b9948c5 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -161,7 +161,7 @@ private: void refill_tlb(reg_t vaddr, reg_t paddr, access_type type); // perform a page table walk for a given VA; set referenced/dirty bits - reg_t walk(reg_t addr, bool supervisor, access_type type); + reg_t walk(reg_t addr, access_type type, bool supervisor, bool pum); // handle uncommon cases: TLB misses, page faults, MMIO const uint16_t* fetch_slow_path(reg_t addr); diff --git a/riscv/processor.cc b/riscv/processor.cc index e948a47..0673787 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -306,11 +306,12 @@ void processor_t::set_csr(int which, reg_t val) state.suinstret_delta = (val << 32) | (uint32_t)state.suinstret_delta; break; case CSR_MSTATUS: { - if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV)) + if ((val ^ state.mstatus) & + (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_PUM)) mmu->flush_tlb(); reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE - | MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_FS + | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_PUM | (ext ? MSTATUS_XS : 0); if (validate_vm(max_xlen, get_field(val, MSTATUS_VM))) @@ -356,7 +357,7 @@ void processor_t::set_csr(int which, reg_t val) } case CSR_SSTATUS: { reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS - | SSTATUS_XS; + | SSTATUS_XS | SSTATUS_PUM; set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask)); break; } @@ -443,8 +444,9 @@ reg_t processor_t::get_csr(int which) break; return (state.minstret + state.suinstret_delta) >> 32; case CSR_SSTATUS: { - reg_t sstatus = state.mstatus & - (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS); + reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS + | SSTATUS_XS | SSTATUS_PUM; + reg_t sstatus = state.mstatus & mask; if ((sstatus & SSTATUS_FS) == SSTATUS_FS || (sstatus & SSTATUS_XS) == SSTATUS_XS) sstatus |= (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD); |