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);
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)
}
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)))
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
{
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;
}
}
// 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
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)
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)
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)
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)
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)
#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_S 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
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);
}
// 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;
#ifndef RISCV_ENABLE_FPU
sr &= ~SR_EF;
#endif
-#ifndef RISCV_ENABLE_RVC
- sr &= ~SR_EC;
-#endif
#ifndef RISCV_ENABLE_VEC
sr &= ~SR_EV;
#endif
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;