Update to new PTE format
authorAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 6 Jul 2016 10:22:18 +0000 (03:22 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 6 Jul 2016 10:22:18 +0000 (03:22 -0700)
riscv/encoding.h
riscv/mmu.cc
riscv/mmu.h
riscv/processor.cc
tests/mprv.S

index fa2d2dc1c35726f111a65de3da99e3ef27e37f13..641954a8716971d6fd0075a75a200bbb9437b0ba 100644 (file)
@@ -18,6 +18,7 @@
 #define MSTATUS_XS          0x00018000
 #define MSTATUS_MPRV        0x00020000
 #define MSTATUS_PUM         0x00040000
+#define MSTATUS_MXR         0x00080000
 #define MSTATUS_VM          0x1F000000
 #define MSTATUS32_SD        0x80000000
 #define MSTATUS64_SD        0x8000000000000000
 
 // page table entry (PTE) fields
 #define PTE_V     0x001 // Valid
-#define PTE_TYPE  0x01E // Type
-#define PTE_R     0x020 // Referenced
-#define PTE_D     0x040 // Dirty
-#define PTE_SOFT  0x380 // Reserved for Software
-
-#define PTE_TYPE_TABLE        0x00
-#define PTE_TYPE_TABLE_GLOBAL 0x02
-#define PTE_TYPE_URX_SR       0x04
-#define PTE_TYPE_URWX_SRW     0x06
-#define PTE_TYPE_UR_SR        0x08
-#define PTE_TYPE_URW_SRW      0x0A
-#define PTE_TYPE_URX_SRX      0x0C
-#define PTE_TYPE_URWX_SRWX    0x0E
-#define PTE_TYPE_SR           0x10
-#define PTE_TYPE_SRW          0x12
-#define PTE_TYPE_SRX          0x14
-#define PTE_TYPE_SRWX         0x16
-#define PTE_TYPE_SR_GLOBAL    0x18
-#define PTE_TYPE_SRW_GLOBAL   0x1A
-#define PTE_TYPE_SRX_GLOBAL   0x1C
-#define PTE_TYPE_SRWX_GLOBAL  0x1E
+#define PTE_R     0x002 // Read
+#define PTE_W     0x004 // Write
+#define PTE_X     0x008 // Execute
+#define PTE_U     0x010 // User
+#define PTE_G     0x020 // Global
+#define PTE_A     0x040 // Accessed
+#define PTE_D     0x080 // Dirty
+#define PTE_SOFT  0x300 // Reserved for Software
 
 #define PTE_PPN_SHIFT 10
 
-#define PTE_TABLE(PTE) ((0x0000000AU >> ((PTE) & 0x1F)) & 1)
-#define PTE_UR(PTE)    ((0x0000AAA0U >> ((PTE) & 0x1F)) & 1)
-#define PTE_UW(PTE)    ((0x00008880U >> ((PTE) & 0x1F)) & 1)
-#define PTE_UX(PTE)    ((0x0000A0A0U >> ((PTE) & 0x1F)) & 1)
-#define PTE_SR(PTE)    ((0xAAAAAAA0U >> ((PTE) & 0x1F)) & 1)
-#define PTE_SW(PTE)    ((0x88888880U >> ((PTE) & 0x1F)) & 1)
-#define PTE_SX(PTE)    ((0xA0A0A000U >> ((PTE) & 0x1F)) & 1)
-
-#define PTE_CHECK_PERM(PTE, SUPERVISOR, STORE, FETCH) \
-  ((STORE) ? ((SUPERVISOR) ? PTE_SW(PTE) : PTE_UW(PTE)) : \
-   (FETCH) ? ((SUPERVISOR) ? PTE_SX(PTE) : PTE_UX(PTE)) : \
-             ((SUPERVISOR) ? PTE_SR(PTE) : PTE_UR(PTE)))
+#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
 
 #ifdef __riscv
 
index eb8fed5d42f4e87670ab3c74b335d242329c6b0c..602b09010399899a79c2db74248d310a5fe51e8b 100644 (file)
@@ -35,11 +35,9 @@ reg_t mmu_t::translate(reg_t addr, access_type type)
     return addr;
 
   reg_t mode = proc->state.prv;
-  bool pum = false;
   if (type != FETCH) {
     if (!proc->state.dcsr.cause && 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;
@@ -48,7 +46,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, type, mode > PRV_U, pum) | (addr & (PGSIZE-1));
+  return walk(addr, type, mode) | (addr & (PGSIZE-1));
 }
 
 const uint16_t* mmu_t::fetch_slow_path(reg_t vaddr)
@@ -115,7 +113,7 @@ void mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, access_type type)
   tlb_data[idx] = sim->addr_to_mem(paddr) - vaddr;
 }
 
-reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum)
+reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode)
 {
   int levels, ptidxbits, ptesize;
   switch (get_field(proc->get_state()->mstatus, MSTATUS_VM))
@@ -126,6 +124,10 @@ reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum)
     default: abort();
   }
 
+  bool supervisor = mode == PRV_S;
+  bool pum = get_field(proc->state.mstatus, MSTATUS_PUM);
+  bool mxr = get_field(proc->state.mstatus, MSTATUS_MXR);
+
   // verify bits xlen-1:va_bits-1 are all equal
   int va_bits = PGSHIFT + levels * ptidxbits;
   reg_t mask = (reg_t(1) << (proc->xlen - (va_bits-1))) - 1;
@@ -149,13 +151,17 @@ reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum)
 
     if (PTE_TABLE(pte)) { // next level of page table
       base = ppn << PGSHIFT;
-    } else if (pum && PTE_CHECK_PERM(pte, 0, type == STORE, type == FETCH)) {
+    } else if ((pte & PTE_U) ? supervisor && pum : !supervisor) {
+      break;
+    } else if (!(pte & PTE_R) && (pte & PTE_W)) { // reserved
       break;
-    } else if (!PTE_CHECK_PERM(pte, supervisor, type == STORE, type == FETCH)) {
+    } else if (type == FETCH ? !(pte & PTE_X) :
+               type == LOAD ?  !(pte & PTE_R) && !(mxr && (pte & PTE_X)) :
+                               !((pte & PTE_R) && (pte & PTE_W))) {
       break;
     } else {
-      // set referenced and possibly dirty bits.
-      *(uint32_t*)ppte |= PTE_R | ((type == STORE) * PTE_D);
+      // set accessed and possibly dirty bits.
+      *(uint32_t*)ppte |= PTE_A | ((type == STORE) * PTE_D);
       // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
       reg_t vpn = addr >> PGSHIFT;
       reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
index 03be15d9e86cde8dfdebd244802128b80c0529af..0652d47ee2e66f066f794892bd3c958600a64373 100644 (file)
@@ -160,7 +160,7 @@ private:
   const char* fill_from_mmio(reg_t vaddr, reg_t paddr);
 
   // perform a page table walk for a given VA; set referenced/dirty bits
-  reg_t walk(reg_t addr, access_type type, bool supervisor, bool pum);
+  reg_t walk(reg_t addr, access_type type, reg_t prv);
 
   // handle uncommon cases: TLB misses, page faults, MMIO
   const uint16_t* fetch_slow_path(reg_t addr);
index b7500c46bbcf4153977d1e7daf7a72bcaf9bded7..50906f64c6e54ae0f8d4f7a063aee55b841fb263 100644 (file)
@@ -305,12 +305,12 @@ void processor_t::set_csr(int which, reg_t val)
       break;
     case CSR_MSTATUS: {
       if ((val ^ state.mstatus) &
-          (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_PUM))
+          (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_PUM | MSTATUS_MXR))
         mmu->flush_tlb();
 
       reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
                  | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_PUM
-                 | (ext ? MSTATUS_XS : 0);
+                 | MSTATUS_MXR | (ext ? MSTATUS_XS : 0);
 
       if (validate_vm(max_xlen, get_field(val, MSTATUS_VM)))
         mask |= MSTATUS_VM;
index df346b3504ddc291ed3282424b2a0278c9a64f5f..58eba0b787ff94a5dd38cc5bb766434cb97eced2 100644 (file)
@@ -34,5 +34,5 @@ data:
 
         .balign 0x1000
 page_table:
-        .word   ((0x80000000 >> 2) | PTE_V | PTE_TYPE_URWX_SRWX)
+        .word   ((0x80000000 >> 2) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X)
         .word   0