New supervisor mode
authorAndrew Waterman <waterman@cs.berkeley.edu>
Sat, 27 Jul 2013 03:25:18 +0000 (20:25 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Sat, 27 Jul 2013 03:25:18 +0000 (20:25 -0700)
riscv/insns/eret.h
riscv/mmu.cc
riscv/mmu.h
riscv/opcodes.h
riscv/pcr.h
riscv/processor.cc

index cd968bdeb41c4b60d947880d8aedbb7066d5e2e0..96d951c4e7cc7cc804a8a6aa138f0d5c58a03e9d 100644 (file)
@@ -1,5 +1,5 @@
 require_supervisor;
-if(sr & SR_ET)
-  throw trap_illegal_instruction;
-set_pcr(PCR_SR, ((sr & SR_PS) ? sr : (sr & ~SR_S)) | SR_ET);
+set_pcr(PCR_SR, ((sr & ~(SR_PS | SR_EI)) |
+                ((sr & SR_PS) ? 0 : SR_S)) |
+                ((sr & SR_PEI) ? SR_EI : 0));
 set_pc(epc);
index 8b63a43180621e45693c7fc06e7e25b6fa53ef4a..01cbb97e9a63ecdb0677fa5cb4f1577c1a6013ee 100644 (file)
@@ -40,9 +40,9 @@ reg_t mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch)
   reg_t pte_perm = pte & PTE_PERM;
   if (proc == NULL || (proc->sr & SR_S))
     pte_perm = (pte_perm/(PTE_SX/PTE_UX)) & PTE_PERM;
-  pte_perm |= pte & PTE_E;
+  pte_perm |= pte & PTE_V;
 
-  reg_t perm = (fetch ? PTE_UX : store ? PTE_UW : PTE_UR) | PTE_E;
+  reg_t perm = (fetch ? PTE_UX : store ? PTE_UW : PTE_UR) | PTE_V;
   if(unlikely((pte_perm & perm) != perm))
   {
     if (fetch)
@@ -53,7 +53,7 @@ reg_t mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch)
   }
 
   reg_t pgoff = addr & (PGSIZE-1);
-  reg_t pgbase = pte >> PTE_PPN_SHIFT << PGSHIFT;
+  reg_t pgbase = pte >> PGSHIFT << PGSHIFT;
   reg_t paddr = pgbase + pgoff;
 
   if (unlikely(tracer.interested_in_range(pgbase, pgbase + PGSIZE, store, fetch)))
@@ -80,7 +80,7 @@ pte_t mmu_t::walk(reg_t addr)
   else if (proc == NULL || !(proc->sr & SR_VM))
   {
     if(addr < memsz)
-      pte = PTE_E | PTE_PERM | ((addr >> PGSHIFT) << PTE_PPN_SHIFT);
+      pte = PTE_V | PTE_PERM | ((addr >> PGSHIFT) << PGSHIFT);
   }
   else
   {
@@ -97,23 +97,23 @@ pte_t mmu_t::walk(reg_t addr)
         break;
 
       ptd = *(pte_t*)(mem+pte_addr);
-      if(ptd & PTE_E)
+
+      if (!(ptd & PTE_V)) // invalid mapping
+        break;
+      else if (ptd & PTE_T) // next level of page table
+        base = (ptd >> PGSHIFT) << PGSHIFT;
+      else // the actual PTE
       {
         // if this PTE is from a larger PT, fake a leaf
         // PTE so the TLB will work right
         reg_t vpn = addr >> PGSHIFT;
-        ptd |= (vpn & ((1<<(ptshift))-1)) << PTE_PPN_SHIFT;
+        ptd |= (vpn & ((1<<(ptshift))-1)) << PGSHIFT;
 
-        // fault if physical addr is invalid
-        reg_t ppn = ptd >> PTE_PPN_SHIFT;
-        if((ppn << PGSHIFT) + (addr & (PGSIZE-1)) < memsz)
+        // fault if physical addr is out of range
+        if (((ptd >> PGSHIFT) << PGSHIFT) < memsz)
           pte = ptd;
         break;
       }
-      else if(!(ptd & PTE_T))
-        break;
-
-      base = (ptd >> PTE_PPN_SHIFT) << PGSHIFT;
     }
   }
 
index 64b11d3b31ff440d588ea84ccc7937160777de02..a754b607c9a49890b189fb3b55ed93868aabf6fe 100644 (file)
 
 // virtual memory configuration
 typedef reg_t pte_t;
-const reg_t LEVELS = sizeof(pte_t) == sizeof(uint64_t) ? 3 : 2;
-const reg_t PGSHIFT = 13;
+const reg_t LEVELS = sizeof(pte_t) == 8 ? 3 : 2;
+const reg_t PTIDXBITS = 10;
+const reg_t PGSHIFT = PTIDXBITS + (sizeof(pte_t) == 8 ? 3 : 2);
 const reg_t PGSIZE = 1 << PGSHIFT;
-const reg_t PTIDXBITS = PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2);
 const reg_t VPN_BITS = PTIDXBITS * LEVELS;
 const reg_t PPN_BITS = 8*sizeof(reg_t) - PGSHIFT;
 const reg_t VA_BITS = VPN_BITS + PGSHIFT;
 
-// page table entry (PTE) fields
-#define PTE_T    0x001 // Entry is a page Table descriptor
-#define PTE_E    0x002 // Entry is a page table Entry
-#define PTE_R    0x004 // Referenced
-#define PTE_D    0x008 // Dirty
-#define PTE_UX   0x010 // User eXecute permission
-#define PTE_UW   0x020 // User Read permission
-#define PTE_UR   0x040 // User Write permission
-#define PTE_SX   0x080 // Supervisor eXecute permission
-#define PTE_SW   0x100 // Supervisor Read permission
-#define PTE_SR   0x200 // Supervisor Write permission
-#define PTE_PERM (PTE_SR | PTE_SW | PTE_SX | PTE_UR | PTE_UW | PTE_UX)
-#define PTE_PPN_SHIFT  13 // LSB of physical page number in the PTE
-
 // this class implements a processor's port into the virtual memory system.
 // an MMU and instruction cache are maintained for simulator performance.
 class mmu_t
index e3fcf160a2e38817638ab90180573cb2e6b352ab..fd86d9d29a394ce873e49db0db08c7c2011d1553 100644 (file)
@@ -13,7 +13,7 @@ DECLARE_INSN(fcvt_d_w, 0xe0d3, 0x3ff1ff)
 DECLARE_INSN(lw, 0x103, 0x3ff)
 DECLARE_INSN(add, 0x33, 0x1ffff)
 DECLARE_INSN(fcvt_d_s, 0x100d3, 0x3ff1ff)
-DECLARE_INSN(mfpcr, 0x17b, 0x3fffff)
+DECLARE_INSN(mfpcr, 0xf3, 0x3fffff)
 DECLARE_INSN(fmax_d, 0x190d3, 0x1ffff)
 DECLARE_INSN(bne, 0xe3, 0x3ff)
 DECLARE_INSN(rdcycle, 0x277, 0x7ffffff)
@@ -21,7 +21,7 @@ DECLARE_INSN(fcvt_s_d, 0x11053, 0x3ff1ff)
 DECLARE_INSN(bgeu, 0x3e3, 0x3ff)
 DECLARE_INSN(fadd_d, 0xd3, 0x1f1ff)
 DECLARE_INSN(sltiu, 0x193, 0x3ff)
-DECLARE_INSN(mtpcr, 0x1fb, 0x1ffff)
+DECLARE_INSN(mtpcr, 0x73, 0x1ffff)
 DECLARE_INSN(break, 0xf7, 0xffffffff)
 DECLARE_INSN(fcvt_s_w, 0xe053, 0x3ff1ff)
 DECLARE_INSN(mul, 0x433, 0x1ffff)
@@ -47,7 +47,7 @@ DECLARE_INSN(addw, 0x3b, 0x1ffff)
 DECLARE_INSN(sll, 0xb3, 0x1ffff)
 DECLARE_INSN(xor, 0x233, 0x1ffff)
 DECLARE_INSN(sub, 0x10033, 0x1ffff)
-DECLARE_INSN(eret, 0x27b, 0xffffffff)
+DECLARE_INSN(eret, 0x273, 0xffffffff)
 DECLARE_INSN(blt, 0x263, 0x3ff)
 DECLARE_INSN(mtfsr, 0x1f053, 0x3fffff)
 DECLARE_INSN(sc_w, 0x1052b, 0x1ffff)
@@ -90,7 +90,7 @@ DECLARE_INSN(amomaxu_w, 0x1d2b, 0x1ffff)
 DECLARE_INSN(fcvt_wu_s, 0xb053, 0x3ff1ff)
 DECLARE_INSN(rdtime, 0x677, 0x7ffffff)
 DECLARE_INSN(andi, 0x393, 0x3ff)
-DECLARE_INSN(clearpcr, 0x7b, 0x3ff)
+DECLARE_INSN(clearpcr, 0x1f3, 0x3ff)
 DECLARE_INSN(fmv_x_s, 0x1c053, 0x3fffff)
 DECLARE_INSN(fsgnjn_d, 0x60d3, 0x1ffff)
 DECLARE_INSN(fnmadd_s, 0x4f, 0x1ff)
@@ -129,7 +129,7 @@ DECLARE_INSN(amomax_w, 0x152b, 0x1ffff)
 DECLARE_INSN(fsgnj_d, 0x50d3, 0x1ffff)
 DECLARE_INSN(mulhu, 0x5b3, 0x1ffff)
 DECLARE_INSN(fence_v_g, 0x2af, 0x3ff)
-DECLARE_INSN(setpcr, 0xfb, 0x3ff)
+DECLARE_INSN(setpcr, 0x173, 0x3ff)
 DECLARE_INSN(fcvt_lu_s, 0x9053, 0x3ff1ff)
 DECLARE_INSN(fcvt_s_l, 0xc053, 0x3ff1ff)
 DECLARE_INSN(auipc, 0x17, 0x7f)
index 11bfc6556809a847732ad2dee895a448c27ee29b..77cee01d83f17932ca070409ef1f4fae1d89197f 100644 (file)
@@ -3,18 +3,18 @@
 #ifndef _RISCV_PCR_H
 #define _RISCV_PCR_H
 
-#define SR_ET    0x00000001
-#define SR_EF    0x00000002
-#define SR_EV    0x00000004
-#define SR_EC    0x00000008
-#define SR_PS    0x00000010
-#define SR_S     0x00000020
-#define SR_U64   0x00000040
-#define SR_S64   0x00000080
-#define SR_VM    0x00000100
+#define SR_    0x00000001
+#define SR_PS    0x00000002
+#define SR_EI    0x00000004
+#define SR_PEI   0x00000008
+#define SR_EF    0x00000010
+#define SR_U64   0x00000020
+#define SR_S64   0x00000040
+#define SR_VM    0x00000080
+#define SR_EV    0x00000100
 #define SR_IM    0x00FF0000
 #define SR_IP    0xFF000000
-#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM|SR_IP)
+#define SR_ZERO  ~(SR_S|SR_PS|SR_EI|SR_PEI|SR_EF|SR_U64|SR_S64|SR_VM|SR_EV|SR_IM|SR_IP)
 #define SR_IM_SHIFT 16
 #define SR_IP_SHIFT 24
 
 #define PCR_EPC      1
 #define PCR_BADVADDR 2
 #define PCR_EVEC     3
-#define PCR_COUNT    4
-#define PCR_COMPARE  5
-#define PCR_CAUSE    6
-#define PCR_PTBR     7
-#define PCR_SEND_IPI 8
-#define PCR_CLR_IPI  9
-#define PCR_COREID   10
-#define PCR_IMPL     11
-#define PCR_K0       12
-#define PCR_K1       13
+#define PCR_CAUSE    4
+#define PCR_PTBR     5
+#define PCR_ASID     6
+#define PCR_FATC     7
+#define PCR_COUNT    8
+#define PCR_COMPARE  9
+#define PCR_SEND_IPI 10
+#define PCR_CLR_IPI  11
+#define PCR_HARTID   12
+#define PCR_IMPL     13
+#define PCR_K0       14
+#define PCR_K1       15
 #define PCR_VECBANK  18
 #define PCR_VECCFG   19
 #define PCR_RESET    29
 #define CAUSE_VECTOR_FAULT_LOAD 30
 #define CAUSE_VECTOR_FAULT_STORE 31
 
+// page table entry (PTE) fields
+#define PTE_V    0x001 // Entry is a page Table descriptor
+#define PTE_T    0x002 // Entry is a page Table, not a terminal node
+#define PTE_G    0x004 // Global
+#define PTE_UR   0x008 // User Write permission
+#define PTE_UW   0x010 // User Read permission
+#define PTE_UX   0x020 // User eXecute permission
+#define PTE_SR   0x040 // Supervisor Read permission
+#define PTE_SW   0x080 // Supervisor Write permission
+#define PTE_SX   0x100 // Supervisor eXecute permission
+#define PTE_PERM (PTE_SR | PTE_SW | PTE_SX | PTE_UR | PTE_UW | PTE_UX)
+
 #ifdef __riscv
 
+#ifdef __riscv64
+# define RISCV_PGLEVELS 3
+# define RISCV_PGSHIFT 13
+#else
+# define RISCV_PGLEVELS 2
+# define RISCV_PGSHIFT 12
+#endif
+#define RISCV_PGLEVEL_BITS 10
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
+
 #define ASM_CR(r)   _ASM_CR(r)
 #define _ASM_CR(r)  cr##r
 
           asm volatile ("clearpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
           __tmp; })
 
+#define rdcycle() ({ unsigned long __tmp; \
+          asm volatile ("rdcycle %0" : "=r"(__tmp)); \
+          __tmp; })
+
 #endif
 
 #endif
index e7c0872c6f494ae622558f367d8c5972aabb9f9f..4dff4861e7625300da6b33a17e460743c20bcb84 100644 (file)
@@ -68,7 +68,7 @@ void processor_t::take_interrupt()
   uint32_t interrupts = (sr & SR_IP) >> SR_IP_SHIFT;
   interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
 
-  if(interrupts && (sr & SR_ET))
+  if(interrupts && (sr & SR_EI))
     for(int i = 0; ; i++, interrupts >>= 1)
       if(interrupts & 1)
         throw interrupt_t(i);
@@ -144,7 +144,9 @@ void processor_t::take_trap(reg_t t, bool noisy)
   }
 
   // switch to supervisor, set previous supervisor bit, disable traps
-  set_pcr(PCR_SR, (((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
+  set_pcr(PCR_SR, (((sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
+                  ((sr & SR_S) ? SR_PS : 0) |
+                  ((sr & SR_EI) ? SR_PEI : 0));
   cause = t;
   epc = pc;
   pc = evec;
@@ -177,9 +179,6 @@ void processor_t::set_pcr(int which, reg_t val)
 #ifndef RISCV_ENABLE_FPU
       sr &= ~SR_EF;
 #endif
-#ifndef RISCV_ENABLE_RVC
-      sr &= ~SR_EC;
-#endif
 #ifndef RISCV_ENABLE_VEC
       sr &= ~SR_EV;
 #endif
@@ -245,7 +244,11 @@ reg_t processor_t::get_pcr(int which)
       return cause;
     case PCR_PTBR:
       return mmu.get_ptbr();
-    case PCR_COREID:
+    case PCR_ASID:
+      return 0;
+    case PCR_FATC:
+      mmu.flush_tlb();
+    case PCR_HARTID:
       return id;
     case PCR_IMPL:
       return 1;