From: Andrew Waterman Date: Sat, 27 Jul 2013 03:25:18 +0000 (-0700) Subject: New supervisor mode X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7a16302b4d8049d80bb56a0cd00cc226170c1ca7;p=riscv-isa-sim.git New supervisor mode --- diff --git a/riscv/insns/eret.h b/riscv/insns/eret.h index cd968bd..96d951c 100644 --- a/riscv/insns/eret.h +++ b/riscv/insns/eret.h @@ -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); diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 8b63a43..01cbb97 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -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; } } diff --git a/riscv/mmu.h b/riscv/mmu.h index 64b11d3..a754b60 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -13,28 +13,14 @@ // 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 diff --git a/riscv/opcodes.h b/riscv/opcodes.h index e3fcf16..fd86d9d 100644 --- a/riscv/opcodes.h +++ b/riscv/opcodes.h @@ -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) diff --git a/riscv/pcr.h b/riscv/pcr.h index 11bfc65..77cee01 100644 --- a/riscv/pcr.h +++ b/riscv/pcr.h @@ -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_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 @@ -22,16 +22,18 @@ #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 @@ -65,8 +67,30 @@ #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 @@ -88,6 +112,10 @@ 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 diff --git a/riscv/processor.cc b/riscv/processor.cc index e7c0872..4dff486 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -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;