From 8bd7e3932b9df9aa32a53f53c072319bb9252c30 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 5 Jul 2016 19:19:49 -0700 Subject: [PATCH] Implement priv-1.9 PTE scheme --- rocket/src/main/scala/csr.scala | 4 ++- rocket/src/main/scala/ptw.scala | 46 ++++++++++++++++++++------------- rocket/src/main/scala/tlb.scala | 25 ++++++++---------- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/rocket/src/main/scala/csr.scala b/rocket/src/main/scala/csr.scala index 017a115e..039a07f2 100644 --- a/rocket/src/main/scala/csr.scala +++ b/rocket/src/main/scala/csr.scala @@ -17,7 +17,8 @@ class MStatus extends Bundle { val sd_rv32 = Bool() val zero2 = UInt(width = 2) val vm = UInt(width = 5) - val zero1 = UInt(width = 5) + val zero1 = UInt(width = 4) + val mxr = Bool() val pum = Bool() val mprv = Bool() val xs = UInt(width = 2) @@ -463,6 +464,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) reg_mstatus.mprv := new_mstatus.mprv when (supportedModes contains new_mstatus.mpp) { reg_mstatus.mpp := new_mstatus.mpp } if (supportedModes.size > 2) { + reg_mstatus.mxr := new_mstatus.mxr reg_mstatus.pum := new_mstatus.pum reg_mstatus.spp := new_mstatus.spp reg_mstatus.spie := new_mstatus.spie diff --git a/rocket/src/main/scala/ptw.scala b/rocket/src/main/scala/ptw.scala index 34f4820c..ac91083f 100644 --- a/rocket/src/main/scala/ptw.scala +++ b/rocket/src/main/scala/ptw.scala @@ -9,8 +9,10 @@ import Util._ import cde.{Parameters, Field} class PTWReq(implicit p: Parameters) extends CoreBundle()(p) { - val addr = UInt(width = vpnBits) val prv = Bits(width = 2) + val pum = Bool() + val mxr = Bool() + val addr = UInt(width = vpnBits) val store = Bool() val fetch = Bool() } @@ -34,23 +36,32 @@ class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p) { } class PTE(implicit p: Parameters) extends CoreBundle()(p) { - val ppn = Bits(width = ppnBits) - val reserved_for_software = Bits(width = 3) + val reserved_for_hardware = Bits(width = 16) + val ppn = UInt(width = 38) + val reserved_for_software = Bits(width = 2) val d = Bool() + val a = Bool() + val g = Bool() + val u = Bool() + val x = Bool() + val w = Bool() val r = Bool() - val typ = Bits(width = 4) val v = Bool() - def table(dummy: Int = 0) = v && typ < 2 - def leaf(dummy: Int = 0) = v && typ >= 2 - def ur(dummy: Int = 0) = leaf() && typ < 8 - def uw(dummy: Int = 0) = ur() && typ(0) - def ux(dummy: Int = 0) = ur() && typ(1) - def sr(dummy: Int = 0) = leaf() - def sw(dummy: Int = 0) = leaf() && typ(0) - def sx(dummy: Int = 0) = v && typ >= 4 && typ(1) - def access_ok(prv: Bits, store: Bool, fetch: Bool) = - Mux(prv(0), Mux(fetch, sx(), Mux(store, sw(), sr())), Mux(fetch, ux(), Mux(store, uw(), ur()))) + def table(dummy: Int = 0) = v && !r && !w && !x + def leaf(dummy: Int = 0) = v && (r || (x && !w)) + def ur(dummy: Int = 0) = sr() && u + def uw(dummy: Int = 0) = sw() && u + def ux(dummy: Int = 0) = sx() && u + def sr(dummy: Int = 0) = leaf() && r + def sw(dummy: Int = 0) = leaf() && w + def sx(dummy: Int = 0) = leaf() && x + + def access_ok(req: PTWReq) = { + val perm_ok = Mux(req.fetch, x, Mux(req.store, w, r || (x && req.mxr))) + val priv_ok = Mux(u, !req.pum, req.prv(0)) + leaf() && priv_ok && perm_ok + } } class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { @@ -106,14 +117,13 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { (hit, Mux1H(hits, data)) } - val perm_ok = pte.access_ok(r_req.prv, r_req.store, r_req.fetch) - val set_dirty_bit = perm_ok && (!pte.r || (r_req.store && !pte.d)) + val set_dirty_bit = pte.access_ok(r_req) && (!pte.a || (r_req.store && !pte.d)) when (io.mem.resp.valid && state === s_wait && !set_dirty_bit) { r_pte := pte } val pte_wdata = Wire(init=new PTE().fromBits(0)) - pte_wdata.r := true + pte_wdata.a := true pte_wdata.d := r_req.store io.mem.req.valid := state === s_req || state === s_set_dirty @@ -162,7 +172,7 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { } when (io.mem.resp.valid) { state := s_done - when (pte.leaf() && set_dirty_bit) { + when (set_dirty_bit) { state := s_set_dirty } when (pte.table() && count < pgLevels-1) { diff --git a/rocket/src/main/scala/tlb.scala b/rocket/src/main/scala/tlb.scala index a6d5565b..e99873b1 100644 --- a/rocket/src/main/scala/tlb.scala +++ b/rocket/src/main/scala/tlb.scala @@ -56,12 +56,11 @@ class TLB(implicit val p: Parameters) extends Module with HasTLBParameters { val hits = hitsVec.toBits // permission bit arrays - val ur_array = Reg(UInt(width = entries)) // user read permission - val uw_array = Reg(UInt(width = entries)) // user write permission - val ux_array = Reg(UInt(width = entries)) // user execute permission - val sr_array = Reg(UInt(width = entries)) // supervisor read permission - val sw_array = Reg(UInt(width = entries)) // supervisor write permission - val sx_array = Reg(UInt(width = entries)) // supervisor execute permission + val pte_array = Reg(new PTE) + val u_array = Reg(UInt(width = entries)) // user permission + val sw_array = Reg(UInt(width = entries)) // write permission + val sx_array = Reg(UInt(width = entries)) // execute permission + val sr_array = Reg(UInt(width = entries)) // read permission val dirty_array = Reg(UInt(width = entries)) // PTE dirty bit when (io.ptw.resp.valid) { val pte = io.ptw.resp.bits.pte @@ -70,9 +69,7 @@ class TLB(implicit val p: Parameters) extends Module with HasTLBParameters { val mask = UIntToOH(r_refill_waddr) valid := valid | mask - ur_array := Mux(pte.ur(), ur_array | mask, ur_array & ~mask) - uw_array := Mux(pte.uw(), uw_array | mask, uw_array & ~mask) - ux_array := Mux(pte.ux(), ux_array | mask, ux_array & ~mask) + u_array := Mux(pte.u, u_array | mask, u_array & ~mask) sr_array := Mux(pte.sr(), sr_array | mask, sr_array & ~mask) sw_array := Mux(pte.sw(), sw_array | mask, sw_array & ~mask) sx_array := Mux(pte.sx(), sx_array | mask, sx_array & ~mask) @@ -88,10 +85,10 @@ class TLB(implicit val p: Parameters) extends Module with HasTLBParameters { val priv_s = priv === PRV.S val priv_uses_vm = priv <= PRV.S && !io.ptw.status.debug - val pum_ok = ~Mux(io.ptw.status.pum, ur_array, UInt(0)) - val r_array = Mux(priv_s, sr_array & pum_ok, ur_array) - val w_array = Mux(priv_s, sw_array & pum_ok, uw_array) - val x_array = Mux(priv_s, sx_array, ux_array) + val priv_ok = Mux(priv_s, ~Mux(io.ptw.status.pum, u_array, UInt(0)), u_array) + val w_array = priv_ok & sw_array + val x_array = priv_ok & sx_array + val r_array = priv_ok & (sr_array | Mux(io.ptw.status.mxr, x_array, UInt(0))) val vm_enabled = Bool(usingVM) && io.ptw.status.vm(3) && priv_uses_vm && !io.req.bits.passthrough val bad_va = @@ -118,8 +115,8 @@ class TLB(implicit val p: Parameters) extends Module with HasTLBParameters { io.resp.ppn := Mux(vm_enabled, Mux1H(hitsVec, ppns), io.req.bits.vpn(ppnBits-1,0)) io.ptw.req.valid := state === s_request + io.ptw.req.bits := io.ptw.status io.ptw.req.bits.addr := r_refill_tag - io.ptw.req.bits.prv := io.ptw.status.prv io.ptw.req.bits.store := r_req.store io.ptw.req.bits.fetch := r_req.instruction