implement PUM functionality
authorAndrew Waterman <waterman@cs.berkeley.edu>
Fri, 19 Feb 2016 21:06:57 +0000 (13:06 -0800)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 2 Mar 2016 20:15:25 +0000 (12:15 -0800)
riscv/encoding.h
riscv/mmu.cc
riscv/mmu.h
riscv/processor.cc

index a88205f7ef0d59b8748f0f2a15e8d071c6f16145..b2ef0bfdb2aa7bf6f39296f4e0a7b8d6cc3bb00e 100644 (file)
@@ -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
 
 #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
 #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
index b8fb02891fb82b2f30a159ca8412376c630999cc..45457d9833296794611ad1b61a092b15735e9863 100644 (file)
@@ -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 {
index b6697cd3056deb2036019d5de599df2a41f11c69..b9948c53e05e52e8b6d317febdb2cd7aa3a66b3a 100644 (file)
@@ -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);
index e948a47a9e28651090c9600df05ebec052214120..067378700982f44f12d2ddd662be5baabfa8af55 100644 (file)
@@ -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);