Initial commit of optimized PMP plugin

This commit is contained in:
Samuel Lindemer 2021-03-26 10:12:03 +01:00
parent 98eaeaabc8
commit bf399cc927
7 changed files with 521 additions and 320 deletions

View File

@ -32,6 +32,14 @@ object CsrAccess {
object NONE extends CsrAccess
}
object CsrPlugin {
object IS_CSR extends Stageable(Bool)
object CSR_WRITE_OPCODE extends Stageable(Bool)
object CSR_READ_OPCODE extends Stageable(Bool)
object IS_PMP_CFG extends Stageable(Bool)
object IS_PMP_ADDR extends Stageable(Bool)
}
case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int)
case class CsrPluginConfig(
catchIllegalAccess : Boolean,
@ -399,6 +407,7 @@ trait IWake{
class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake{
import config._
import CsrAccess._
import CsrPlugin._
assert(!(wfiGenAsNop && wfiGenAsWait))
@ -440,9 +449,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
}
object ENV_CTRL extends Stageable(EnvCtrlEnum())
object IS_CSR extends Stageable(Bool)
object CSR_WRITE_OPCODE extends Stageable(Bool)
object CSR_READ_OPCODE extends Stageable(Bool)
object PIPELINED_CSR_READ extends Stageable(Bits(32 bits))
var allowInterrupts : Bool = null
@ -1029,9 +1035,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|| (input(INSTRUCTION)(14 downto 13) === B"11" && imm.z === 0)
)
insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000"
if (pipeline.serviceExist(classOf[PmpPlugin])) {
insert(IS_PMP_CFG) := input(INSTRUCTION)(31 downto 24) === 0x3a
insert(IS_PMP_ADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b
}
}
execute plug new Area{
import execute._
//Manage WFI instructions
@ -1103,25 +1113,27 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc)
)
when(arbitration.isValid && input(IS_CSR)) {
if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData
arbitration.haltItself setWhen(blockedBySideEffects)
}
if(pipelineCsrRead){
insert(PIPELINED_CSR_READ) := readData
when(memory.arbitration.isValid && memory.input(IS_CSR)) {
memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ)
val csrAddress = input(INSTRUCTION)(csrRange)
val pmpAccess = if (pipeline.serviceExist(classOf[PmpPlugin])) {
input(IS_PMP_CFG) | input(IS_PMP_ADDR)
} else False
when (~pmpAccess) {
when(arbitration.isValid && input(IS_CSR)) {
if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData
arbitration.haltItself setWhen(blockedBySideEffects)
}
if(pipelineCsrRead){
insert(PIPELINED_CSR_READ) := readData
when(memory.arbitration.isValid && memory.input(IS_CSR)) {
memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ)
}
}
}.elsewhen(arbitration.isValid && input(IS_CSR)) {
illegalAccess := False
}
//
// Component.current.rework{
// when(arbitration.isFiring && input(IS_CSR)) {
// memory.input(REGFILE_WRITE_DATA).getDrivingReg := readData
// }
// }
//Translation of the csrMapping into real logic
val csrAddress = input(INSTRUCTION)(csrRange)
Component.current.afterElaboration{
def doJobs(jobs : ArrayBuffer[Any]): Unit ={
val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite] || j.isInstanceOf[CsrDuringWrite])

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Samuel Lindemer <samuel.lindemer@ri.se>
* Copyright (c) 2021 Samuel Lindemer <samuel.lindemer@ri.se>
*
* SPDX-License-Identifier: MIT
*/
@ -7,9 +7,11 @@
package vexriscv.plugin
import vexriscv.{VexRiscv, _}
import vexriscv.plugin.CsrPlugin.{_}
import vexriscv.plugin.MemoryTranslatorPort.{_}
import spinal.core._
import spinal.lib._
import scala.collection.mutable.ArrayBuffer
import spinal.lib.fsm._
/* Each 32-bit pmpcfg# register contains four 8-bit configuration sections.
* These section numbers contain flags which apply to regions defined by the
@ -63,104 +65,70 @@ import scala.collection.mutable.ArrayBuffer
* register defines a 4-byte wide region.
*/
case class PmpRegister(previous : PmpRegister) extends Area {
trait Pmp {
def OFF = 0
def TOR = 1
def NA4 = 2
def NAPOT = 3
val state = new Area {
val r, w, x = Reg(Bool)
val l = RegInit(False)
val a = Reg(UInt(2 bits)) init(0)
val addr = Reg(UInt(32 bits))
def xlen = 32
def rBit = 0
def wBit = 1
def xBit = 2
def aBits = 4 downto 3
def lBit = 7
}
class PmpSetter() extends Component with Pmp {
val io = new Bundle {
val a = in Bits(2 bits)
val addr = in UInt(xlen bits)
val prevHi = in UInt(30 bits)
val boundLo, boundHi = out UInt(30 bits)
}
// CSR writes connect to these signals rather than the internal state
// registers. This makes locking and WARL possible.
val csr = new Area {
val r, w, x = Bool
val l = Bool
val a = UInt(2 bits)
val addr = UInt(32 bits)
}
val shifted = io.addr(29 downto 0)
io.boundLo := shifted
io.boundHi := shifted
// Last valid assignment wins; nothing happens if a user-initiated write did
// not occur on this clock cycle.
csr.r := state.r
csr.w := state.w
csr.x := state.x
csr.l := state.l
csr.a := state.a
csr.addr := state.addr
// Computed PMP region bounds
val region = new Area {
val valid, locked = Bool
val start, end = UInt(32 bits)
}
when(~state.l) {
state.r := csr.r
state.w := csr.w
state.x := csr.x
state.l := csr.l
state.a := csr.a
state.addr := csr.addr
if (csr.l == True & csr.a == TOR) {
previous.state.l := True
switch (io.a) {
is (TOR) {
io.boundLo := io.prevHi
}
}
val shifted = state.addr |<< 2
val mask = state.addr & ~(state.addr + 1)
val masked = (state.addr & ~mask) |<< 2
// PMP changes take effect two clock cycles after the initial CSR write (i.e.,
// settings propagate from csr -> state -> region).
region.locked := state.l
region.valid := True
switch(csr.a) {
is(TOR) {
if (previous == null) region.start := 0
else region.start := previous.region.end
region.end := shifted
is (NA4) {
io.boundHi := shifted + 1
}
is(NA4) {
region.start := shifted
region.end := shifted + 4
}
is(NAPOT) {
region.start := masked
region.end := masked + ((mask + 1) |<< 3)
}
default {
region.start := 0
region.end := shifted
region.valid := False
is (NAPOT) {
val mask = io.addr & ~(io.addr + 1)
val boundLo = (io.addr ^ mask)(29 downto 0)
io.boundLo := boundLo
io.boundHi := boundLo + ((mask + 1) |<< 3)(29 downto 0)
}
}
}
case class ProtectedMemoryTranslatorPort(bus : MemoryTranslatorBus)
class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
// Each pmpcfg# CSR configures four regions.
assert((regions % 4) == 0)
val pmps = ArrayBuffer[PmpRegister]()
val portsInfo = ArrayBuffer[ProtectedMemoryTranslatorPort]()
class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator with Pmp {
assert(regions % 4 == 0)
assert(regions <= 16)
var setter : PmpSetter = null
var dPort, iPort : ProtectedMemoryTranslatorPort = null
override def newTranslationPort(priority : Int, args : Any): MemoryTranslatorBus = {
val port = ProtectedMemoryTranslatorPort(MemoryTranslatorBus(new MemoryTranslatorBusParameter(0, 0)))
portsInfo += port
priority match {
case PRIORITY_INSTRUCTION => iPort = port
case PRIORITY_DATA => dPort = port
}
port.bus
}
override def setup(pipeline: VexRiscv): Unit = {
setter = new PmpSetter()
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline.config._
import pipeline._
@ -169,78 +137,201 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv]
val csrService = pipeline.service(classOf[CsrInterface])
val privilegeService = pipeline.service(classOf[PrivilegeService])
val core = pipeline plug new Area {
val pmpaddr = Mem(UInt(xlen bits), regions)
val pmpcfg = Reg(Bits(8 * regions bits)) init(0)
val boundLo, boundHi = Mem(UInt(30 bits), regions)
val cfgRegion = pmpcfg.subdivideIn(8 bits)
val cfgRegister = pmpcfg.subdivideIn(xlen bits)
val lockMask = Reg(Bits(4 bits)) init(B"4'0")
// Instantiate pmpaddr0 ... pmpaddr# CSRs.
for (i <- 0 until regions) {
if (i == 0) {
pmps += PmpRegister(null)
} else {
pmps += PmpRegister(pmps.last)
execute plug new Area {
import execute._
val csrAddress = input(INSTRUCTION)(csrRange)
val accessAddr = input(IS_PMP_ADDR)
val accessCfg = input(IS_PMP_CFG)
val pmpWrite = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) & (accessAddr | accessCfg)
val pmpRead = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) & (accessAddr | accessCfg)
val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt
val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0)
val readAddr = pmpaddr.readAsync(pmpIndex).asBits
val readCfg = cfgRegister(pmpSelect)
val readToWrite = Mux(accessCfg, readCfg, readAddr)
val writeSrc = input(SRC1)
val writeData = input(INSTRUCTION)(13).mux(
False -> writeSrc,
True -> Mux(
input(INSTRUCTION)(12),
readToWrite & ~writeSrc,
readToWrite | writeSrc
)
)
val writer = new Area {
when (accessCfg) {
when (pmpRead) {
output(REGFILE_WRITE_DATA).assignFromBits(readCfg)
}
when (pmpWrite) {
switch(pmpSelect) {
for (i <- 0 until (regions / 4)) {
is(i) {
for (j <- Range(0, xlen, 8)) {
val bitRange = j + xlen * i + lBit downto j + xlen * i
val overwrite = writeData.subdivideIn(8 bits)(j / 8)
val locked = cfgRegister(i).subdivideIn(8 bits)(j / 8)(lBit)
lockMask(j / 8) := locked
when (~locked) {
pmpcfg(bitRange).assignFromBits(overwrite)
if (j != 0 || i != 0) {
when (overwrite(lBit) & overwrite(aBits) === TOR) {
pmpcfg(j + xlen * i - 1) := True
}
}
}
}
}
}
}
}
}.elsewhen (accessAddr) {
when (pmpRead) {
output(REGFILE_WRITE_DATA) := readAddr
}
}
csrService.r(0x3b0 + i, pmps(i).state.addr)
csrService.w(0x3b0 + i, pmps(i).csr.addr)
val locked = cfgRegion(pmpIndex)(lBit)
pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & pmpWrite & accessAddr)
}
// Instantiate pmpcfg0 ... pmpcfg# CSRs.
for (i <- 0 until (regions / 4)) {
csrService.r(0x3a0 + i,
31 -> pmps((i * 4) + 3).state.l, 23 -> pmps((i * 4) + 2).state.l,
15 -> pmps((i * 4) + 1).state.l, 7 -> pmps((i * 4) ).state.l,
27 -> pmps((i * 4) + 3).state.a, 26 -> pmps((i * 4) + 3).state.x,
25 -> pmps((i * 4) + 3).state.w, 24 -> pmps((i * 4) + 3).state.r,
19 -> pmps((i * 4) + 2).state.a, 18 -> pmps((i * 4) + 2).state.x,
17 -> pmps((i * 4) + 2).state.w, 16 -> pmps((i * 4) + 2).state.r,
11 -> pmps((i * 4) + 1).state.a, 10 -> pmps((i * 4) + 1).state.x,
9 -> pmps((i * 4) + 1).state.w, 8 -> pmps((i * 4) + 1).state.r,
3 -> pmps((i * 4) ).state.a, 2 -> pmps((i * 4) ).state.x,
1 -> pmps((i * 4) ).state.w, 0 -> pmps((i * 4) ).state.r
)
csrService.w(0x3a0 + i,
31 -> pmps((i * 4) + 3).csr.l, 23 -> pmps((i * 4) + 2).csr.l,
15 -> pmps((i * 4) + 1).csr.l, 7 -> pmps((i * 4) ).csr.l,
27 -> pmps((i * 4) + 3).csr.a, 26 -> pmps((i * 4) + 3).csr.x,
25 -> pmps((i * 4) + 3).csr.w, 24 -> pmps((i * 4) + 3).csr.r,
19 -> pmps((i * 4) + 2).csr.a, 18 -> pmps((i * 4) + 2).csr.x,
17 -> pmps((i * 4) + 2).csr.w, 16 -> pmps((i * 4) + 2).csr.r,
11 -> pmps((i * 4) + 1).csr.a, 10 -> pmps((i * 4) + 1).csr.x,
9 -> pmps((i * 4) + 1).csr.w, 8 -> pmps((i * 4) + 1).csr.r,
3 -> pmps((i * 4) ).csr.a, 2 -> pmps((i * 4) ).csr.x,
1 -> pmps((i * 4) ).csr.w, 0 -> pmps((i * 4) ).csr.r
)
}
val controller = new StateMachine {
val counter = Reg(UInt(log2Up(regions) bits)) init(0)
val enable = RegInit(False)
// Connect memory ports to PMP logic.
val ports = for ((port, portId) <- portsInfo.zipWithIndex) yield new Area {
val stateIdle : State = new State with EntryPoint {
onEntry {
lockMask := B"4'x0"
enable := False
counter := 0
}
onExit {
enable := True
arbitration.haltItself := True
}
whenIsActive {
when (pmpWrite) {
when (accessCfg) {
goto(stateCfg)
}.elsewhen (accessAddr) {
goto(stateAddr)
}
}
}
}
val address = port.bus.cmd(0).virtualAddress
port.bus.rsp.physicalAddress := address
val stateCfg : State = new State {
onEntry (counter := pmpIndex(log2Up(regions) - 3 downto 0) @@ U"2'00")
whenIsActive {
counter := counter + 1
when (counter(1 downto 0) === 3) {
goto(stateIdle)
} otherwise {
arbitration.haltItself := True
}
}
}
// Only the first matching PMP region applies.
val hits = pmps.map(pmp => pmp.region.valid &
pmp.region.start <= address &
pmp.region.end > address &
(pmp.region.locked | ~privilegeService.isMachine()))
val stateAddr : State = new State {
onEntry (counter := pmpIndex)
whenIsActive {
counter := counter + 1
when (counter === (pmpIndex + 1) | counter === 0) {
goto(stateIdle)
} otherwise {
arbitration.haltItself := True
}
}
}
// M-mode has full access by default, others have none.
when(CountOne(hits) === 0) {
port.bus.rsp.allowRead := privilegeService.isMachine()
port.bus.rsp.allowWrite := privilegeService.isMachine()
port.bus.rsp.allowExecute := privilegeService.isMachine()
when (accessCfg) {
setter.io.a := writeData.subdivideIn(8 bits)(counter(1 downto 0))(aBits)
setter.io.addr := pmpaddr(counter)
} otherwise {
port.bus.rsp.allowRead := MuxOH(OHMasking.first(hits), pmps.map(_.state.r))
port.bus.rsp.allowWrite := MuxOH(OHMasking.first(hits), pmps.map(_.state.w))
port.bus.rsp.allowExecute := MuxOH(OHMasking.first(hits), pmps.map(_.state.x))
setter.io.a := cfgRegion(counter)(aBits)
when (counter === pmpIndex) {
setter.io.addr := writeData.asUInt
} otherwise {
setter.io.addr := pmpaddr(counter)
}
}
when (counter === 0) {
setter.io.prevHi := 0
} otherwise {
setter.io.prevHi := boundHi(counter - 1)
}
when (enable &
((accessCfg & ~lockMask(counter(1 downto 0))) |
(accessAddr & ~cfgRegion(counter)(lBit)))) {
boundLo(counter) := setter.io.boundLo
boundHi(counter) := setter.io.boundHi
}
}
}
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
port.bus.rsp.isPaging := False
port.bus.rsp.exception := False
port.bus.rsp.refilling := False
port.bus.busy := False
pipeline plug new Area {
def getHits(address : UInt) = {
(0 until regions).map(i =>
address >= boundLo(U(i, log2Up(regions) bits)) &
address < boundHi(U(i, log2Up(regions) bits)) &
(cfgRegion(i)(lBit) | ~privilegeService.isMachine()) &
cfgRegion(i)(aBits) =/= 0
)
}
val dGuard = new Area {
val address = dPort.bus.cmd(0).virtualAddress
dPort.bus.rsp.physicalAddress := address
dPort.bus.rsp.isIoAccess := ioRange(address)
dPort.bus.rsp.isPaging := False
dPort.bus.rsp.exception := False
dPort.bus.rsp.refilling := False
dPort.bus.rsp.allowExecute := False
dPort.bus.busy := False
val hits = getHits(address(31 downto 2))
when(~hits.orR) {
dPort.bus.rsp.allowRead := privilegeService.isMachine()
dPort.bus.rsp.allowWrite := privilegeService.isMachine()
} otherwise {
val oneHot = OHMasking.first(hits)
dPort.bus.rsp.allowRead := MuxOH(oneHot, cfgRegion.map(cfg => cfg(rBit)))
dPort.bus.rsp.allowWrite := MuxOH(oneHot, cfgRegion.map(cfg => cfg(wBit)))
}
}
val iGuard = new Area {
val address = iPort.bus.cmd(0).virtualAddress
iPort.bus.rsp.physicalAddress := address
iPort.bus.rsp.isIoAccess := ioRange(address)
iPort.bus.rsp.isPaging := False
iPort.bus.rsp.exception := False
iPort.bus.rsp.refilling := False
iPort.bus.rsp.allowRead := False
iPort.bus.rsp.allowWrite := False
iPort.bus.busy := False
val hits = getHits(address(31 downto 2))
when(~hits.orR) {
iPort.bus.rsp.allowExecute := privilegeService.isMachine()
} otherwise {
val oneHot = OHMasking.first(hits)
iPort.bus.rsp.allowExecute := MuxOH(oneHot, cfgRegion.map(cfg => cfg(xBit)))
}
}
}
}
}
}

View File

@ -17,26 +17,26 @@ Disassembly of section .crt_section:
80000018 <test0>:
80000018: 00000e13 li t3,0
8000001c: 00000f17 auipc t5,0x0
80000020: 27cf0f13 addi t5,t5,636 # 80000298 <fail>
80000020: 330f0f13 addi t5,t5,816 # 8000034c <fail>
80000024: 800000b7 lui ra,0x80000
80000028: 80008237 lui tp,0x80008
8000002c: deadc137 lui sp,0xdeadc
80000030: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbc4b>
80000034: 0020a023 sw sp,0(ra) # 80000000 <pass+0xfffffd5c>
80000038: 00222023 sw sp,0(tp) # 80008000 <pass+0x7d5c>
80000030: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbb97>
80000034: 0020a023 sw sp,0(ra) # 80000000 <pass+0xfffffca8>
80000038: 00222023 sw sp,0(tp) # 80008000 <pass+0x7ca8>
8000003c: 0000a183 lw gp,0(ra)
80000040: 24311c63 bne sp,gp,80000298 <fail>
80000040: 30311663 bne sp,gp,8000034c <fail>
80000044: 00022183 lw gp,0(tp) # 0 <_start-0x80000000>
80000048: 24311863 bne sp,gp,80000298 <fail>
80000048: 30311263 bne sp,gp,8000034c <fail>
8000004c: 071202b7 lui t0,0x7120
80000050: 3a029073 csrw pmpcfg0,t0
80000054: 3a002373 csrr t1,pmpcfg0
80000058: 24629063 bne t0,t1,80000298 <fail>
80000058: 2e629a63 bne t0,t1,8000034c <fail>
8000005c: 191f02b7 lui t0,0x191f0
80000060: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc>
80000064: 3a129073 csrw pmpcfg1,t0
80000068: 000f02b7 lui t0,0xf0
8000006c: 50628293 addi t0,t0,1286 # f0506 <_start-0x7ff0fafa>
80000068: 000f12b7 lui t0,0xf1
8000006c: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6>
80000070: 3a229073 csrw pmpcfg2,t0
80000074: 0f1e22b7 lui t0,0xf1e2
80000078: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700>
@ -44,7 +44,7 @@ Disassembly of section .crt_section:
80000080: 200002b7 lui t0,0x20000
80000084: 3b029073 csrw pmpaddr0,t0
80000088: 3b002373 csrr t1,pmpaddr0
8000008c: 20629663 bne t0,t1,80000298 <fail>
8000008c: 2c629063 bne t0,t1,8000034c <fail>
80000090: fff00293 li t0,-1
80000094: 3b129073 csrw pmpaddr1,t0
80000098: 200022b7 lui t0,0x20002
@ -85,119 +85,166 @@ Disassembly of section .crt_section:
80000124: 0020a023 sw sp,0(ra)
80000128: 00222023 sw sp,0(tp) # 0 <_start-0x80000000>
8000012c: 0000a183 lw gp,0(ra)
80000130: 16311463 bne sp,gp,80000298 <fail>
80000130: 20311e63 bne sp,gp,8000034c <fail>
80000134: 00000193 li gp,0
80000138: 00022183 lw gp,0(tp) # 0 <_start-0x80000000>
8000013c: 14311e63 bne sp,gp,80000298 <fail>
8000013c: 20311863 bne sp,gp,8000034c <fail>
80000140 <test1>:
80000140: 00100e13 li t3,1
80000144: 00000f17 auipc t5,0x0
80000148: 154f0f13 addi t5,t5,340 # 80000298 <fail>
80000148: 208f0f13 addi t5,t5,520 # 8000034c <fail>
8000014c: 079212b7 lui t0,0x7921
80000150: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8>
80000154: 3a029073 csrw pmpcfg0,t0
80000158: 3a002373 csrr t1,pmpcfg0
8000015c: 12629e63 bne t0,t1,80000298 <fail>
8000015c: 1e629863 bne t0,t1,8000034c <fail>
80000160: 800080b7 lui ra,0x80008
80000164: deadc137 lui sp,0xdeadc
80000168: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbc4b>
8000016c: 0020a023 sw sp,0(ra) # 80008000 <pass+0x7d5c>
80000168: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbb97>
8000016c: 0020a023 sw sp,0(ra) # 80008000 <pass+0x7ca8>
80000170: 00000f17 auipc t5,0x0
80000174: 010f0f13 addi t5,t5,16 # 80000180 <test2>
80000178: 0000a183 lw gp,0(ra)
8000017c: 11c0006f j 80000298 <fail>
8000017c: 1d00006f j 8000034c <fail>
80000180 <test2>:
80000180: 00200e13 li t3,2
80000184: 00000f17 auipc t5,0x0
80000188: 114f0f13 addi t5,t5,276 # 80000298 <fail>
80000188: 1c8f0f13 addi t5,t5,456 # 8000034c <fail>
8000018c: 071202b7 lui t0,0x7120
80000190: 3a029073 csrw pmpcfg0,t0
80000194: 3a002373 csrr t1,pmpcfg0
80000198: 3b205073 csrwi pmpaddr2,0
8000019c: 3b202373 csrr t1,pmpaddr2
800001a0: 0e030c63 beqz t1,80000298 <fail>
800001a4: 0e628a63 beq t0,t1,80000298 <fail>
800001a8: 800080b7 lui ra,0x80008
800001ac: deadc137 lui sp,0xdeadc
800001b0: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbc4b>
800001b4: 0020a023 sw sp,0(ra) # 80008000 <pass+0x7d5c>
800001b8: 00000f17 auipc t5,0x0
800001bc: 010f0f13 addi t5,t5,16 # 800001c8 <test3>
800001c0: 0000a183 lw gp,0(ra)
800001c4: 0d40006f j 80000298 <fail>
80000198: 1a628a63 beq t0,t1,8000034c <fail>
8000019c: 200042b7 lui t0,0x20004
800001a0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001>
800001a4: 3b305073 csrwi pmpaddr3,0
800001a8: 3b302373 csrr t1,pmpaddr3
800001ac: 1a031063 bnez t1,8000034c <fail>
800001b0: 18628e63 beq t0,t1,8000034c <fail>
800001b4: 200022b7 lui t0,0x20002
800001b8: 3b205073 csrwi pmpaddr2,0
800001bc: 3b202373 csrr t1,pmpaddr2
800001c0: 18030663 beqz t1,8000034c <fail>
800001c4: 18629463 bne t0,t1,8000034c <fail>
800001c8: 800080b7 lui ra,0x80008
800001cc: deadc137 lui sp,0xdeadc
800001d0: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbb97>
800001d4: 0020a023 sw sp,0(ra) # 80008000 <pass+0x7ca8>
800001d8: 00000f17 auipc t5,0x0
800001dc: 010f0f13 addi t5,t5,16 # 800001e8 <test3>
800001e0: 0000a183 lw gp,0(ra)
800001e4: 1680006f j 8000034c <fail>
800001c8 <test3>:
800001c8: 00300e13 li t3,3
800001cc: 00000f17 auipc t5,0x0
800001d0: 0ccf0f13 addi t5,t5,204 # 80000298 <fail>
800001d4: 00000117 auipc sp,0x0
800001d8: 01010113 addi sp,sp,16 # 800001e4 <test4>
800001dc: 34111073 csrw mepc,sp
800001e0: 30200073 mret
800001e8 <test3>:
800001e8: 00300e13 li t3,3
800001ec: 00000f17 auipc t5,0x0
800001f0: 160f0f13 addi t5,t5,352 # 8000034c <fail>
800001f4: 00ff02b7 lui t0,0xff0
800001f8: 3b32a073 csrs pmpaddr3,t0
800001fc: 3b302373 csrr t1,pmpaddr3
80000200: 14629663 bne t0,t1,8000034c <fail>
80000204: 0ff00293 li t0,255
80000208: 3b32a073 csrs pmpaddr3,t0
8000020c: 3b302373 csrr t1,pmpaddr3
80000210: 00ff02b7 lui t0,0xff0
80000214: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01>
80000218: 12629a63 bne t0,t1,8000034c <fail>
8000021c: 00ff02b7 lui t0,0xff0
80000220: 3b32b073 csrc pmpaddr3,t0
80000224: 3b302373 csrr t1,pmpaddr3
80000228: 0ff00293 li t0,255
8000022c: 12629063 bne t0,t1,8000034c <fail>
80000230: 00ff02b7 lui t0,0xff0
80000234: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01>
80000238: 3a02b073 csrc pmpcfg0,t0
8000023c: 3a002373 csrr t1,pmpcfg0
80000240: 079202b7 lui t0,0x7920
80000244: 10629463 bne t0,t1,8000034c <fail>
80000248: 00ff02b7 lui t0,0xff0
8000024c: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9>
80000250: 3a02a073 csrs pmpcfg0,t0
80000254: 3a002373 csrr t1,pmpcfg0
80000258: 079202b7 lui t0,0x7920
8000025c: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9>
80000260: 0e629663 bne t0,t1,8000034c <fail>
800001e4 <test4>:
800001e4: 00400e13 li t3,4
800001e8: 00000f17 auipc t5,0x0
800001ec: 0b0f0f13 addi t5,t5,176 # 80000298 <fail>
800001f0: deadc137 lui sp,0xdeadc
800001f4: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbc4b>
800001f8: 800080b7 lui ra,0x80008
800001fc: 0020a023 sw sp,0(ra) # 80008000 <pass+0x7d5c>
80000200: 00000f17 auipc t5,0x0
80000204: 010f0f13 addi t5,t5,16 # 80000210 <test5>
80000208: 0000a183 lw gp,0(ra)
8000020c: 08c0006f j 80000298 <fail>
80000210 <test5>:
80000210: 00500e13 li t3,5
80000214: deadc137 lui sp,0xdeadc
80000218: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbc4b>
8000021c: 800000b7 lui ra,0x80000
80000220: 0020a023 sw sp,0(ra) # 80000000 <pass+0xfffffd5c>
80000224: 0000a183 lw gp,0(ra)
80000228: 06311863 bne sp,gp,80000298 <fail>
8000022c <test6>:
8000022c: 00600e13 li t3,6
80000230: 800100b7 lui ra,0x80010
80000234: 0000a183 lw gp,0(ra) # 80010000 <pass+0xfd5c>
80000238: 00000f17 auipc t5,0x0
8000023c: 06cf0f13 addi t5,t5,108 # 800002a4 <pass>
80000240: 0030a023 sw gp,0(ra)
80000244: 0540006f j 80000298 <fail>
80000248 <test7>:
80000248: 00700e13 li t3,7
8000024c: 00000f17 auipc t5,0x0
80000250: 04cf0f13 addi t5,t5,76 # 80000298 <fail>
80000254: deadc137 lui sp,0xdeadc
80000258: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbc4b>
8000025c: 800300b7 lui ra,0x80030
80000260: ff808093 addi ra,ra,-8 # 8002fff8 <pass+0x2fd54>
80000264: 00222023 sw sp,0(tp) # 0 <_start-0x80000000>
80000264 <test4>:
80000264: 00400e13 li t3,4
80000268: 00000f17 auipc t5,0x0
8000026c: fa8f0f13 addi t5,t5,-88 # 80000210 <test5>
80000270: 00022183 lw gp,0(tp) # 0 <_start-0x80000000>
80000274: 0240006f j 80000298 <fail>
8000026c: 0e4f0f13 addi t5,t5,228 # 8000034c <fail>
80000270: 00000117 auipc sp,0x0
80000274: 01010113 addi sp,sp,16 # 80000280 <test5>
80000278: 34111073 csrw mepc,sp
8000027c: 30200073 mret
80000278 <test8>:
80000278: 00800e13 li t3,8
8000027c: 800400b7 lui ra,0x80040
80000280: ff808093 addi ra,ra,-8 # 8003fff8 <pass+0x3fd54>
80000284: 0000a183 lw gp,0(ra)
80000288: 00000f17 auipc t5,0x0
8000028c: 01cf0f13 addi t5,t5,28 # 800002a4 <pass>
80000290: 0030a023 sw gp,0(ra)
80000294: 0040006f j 80000298 <fail>
80000280 <test5>:
80000280: 00500e13 li t3,5
80000284: 00000f17 auipc t5,0x0
80000288: 0c8f0f13 addi t5,t5,200 # 8000034c <fail>
8000028c: deadc137 lui sp,0xdeadc
80000290: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbb97>
80000294: 800080b7 lui ra,0x80008
80000298: 0020a023 sw sp,0(ra) # 80008000 <pass+0x7ca8>
8000029c: 00000f17 auipc t5,0x0
800002a0: 010f0f13 addi t5,t5,16 # 800002ac <test6>
800002a4: 0000a183 lw gp,0(ra)
800002a8: 0a40006f j 8000034c <fail>
80000298 <fail>:
80000298: f0100137 lui sp,0xf0100
8000029c: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffc80>
800002a0: 01c12023 sw t3,0(sp)
800002ac <test6>:
800002ac: 00600e13 li t3,6
800002b0: 00000f17 auipc t5,0x0
800002b4: 09cf0f13 addi t5,t5,156 # 8000034c <fail>
800002b8: deadc137 lui sp,0xdeadc
800002bc: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbb97>
800002c0: 800000b7 lui ra,0x80000
800002c4: 0020a023 sw sp,0(ra) # 80000000 <pass+0xfffffca8>
800002c8: 0000a183 lw gp,0(ra)
800002cc: 08311063 bne sp,gp,8000034c <fail>
800002a4 <pass>:
800002a4: f0100137 lui sp,0xf0100
800002a8: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffc7c>
800002ac: 00012023 sw zero,0(sp)
800002d0 <test7>:
800002d0: 00700e13 li t3,7
800002d4: 00000f17 auipc t5,0x0
800002d8: 078f0f13 addi t5,t5,120 # 8000034c <fail>
800002dc: 800400b7 lui ra,0x80040
800002e0: 0000a183 lw gp,0(ra) # 80040000 <pass+0x3fca8>
800002e4: 00000f17 auipc t5,0x0
800002e8: 074f0f13 addi t5,t5,116 # 80000358 <pass>
800002ec: 0030a023 sw gp,0(ra)
800002f0: 05c0006f j 8000034c <fail>
800002f4 <test8>:
800002f4: 00800e13 li t3,8
800002f8: 00000f17 auipc t5,0x0
800002fc: 054f0f13 addi t5,t5,84 # 8000034c <fail>
80000300: deadc137 lui sp,0xdeadc
80000304: eef10113 addi sp,sp,-273 # deadbeef <pass+0x5eadbb97>
80000308: 800300b7 lui ra,0x80030
8000030c: ff808093 addi ra,ra,-8 # 8002fff8 <pass+0x2fca0>
80000310: 00222023 sw sp,0(tp) # 0 <_start-0x80000000>
80000314: 00000f17 auipc t5,0x0
80000318: 010f0f13 addi t5,t5,16 # 80000324 <test9>
8000031c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000>
80000320: 02c0006f j 8000034c <fail>
80000324 <test9>:
80000324: 00900e13 li t3,9
80000328: 00000f17 auipc t5,0x0
8000032c: 024f0f13 addi t5,t5,36 # 8000034c <fail>
80000330: 800400b7 lui ra,0x80040
80000334: ff808093 addi ra,ra,-8 # 8003fff8 <pass+0x3fca0>
80000338: 0000a183 lw gp,0(ra)
8000033c: 00000f17 auipc t5,0x0
80000340: 01cf0f13 addi t5,t5,28 # 80000358 <pass>
80000344: 0030a023 sw gp,0(ra)
80000348: 0040006f j 8000034c <fail>
8000034c <fail>:
8000034c: f0100137 lui sp,0xf0100
80000350: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffbcc>
80000354: 01c12023 sw t3,0(sp)
80000358 <pass>:
80000358: f0100137 lui sp,0xf0100
8000035c: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffbc8>
80000360: 00012023 sw zero,0(sp)

Binary file not shown.

View File

@ -1,13 +1,13 @@
:0200000480007A
:100000009700000093800001739050306F00C00093
:1000100073101F3473002030130E0000170F000000
:10002000130FCF27B70000803782008037C1ADDEC5
:10002000130F0F33B70000803782008037C1ADDE79
:100030001301F1EE23A020002320220083A1000061
:10004000631C31248321020063183124B702120794
:100050007390023A7323003A63906224B7021F1927
:10006000938242307390123AB7020F00938262502B
:10004000631631308321020063123130B702120788
:100050007390023A7323003A639A622EB7021F1913
:10006000938242307390123AB7120F009382A2909B
:100070007390223AB7221E0F938202907390323A05
:10008000B70200207390023B7323003B639662200B
:10008000B70200207390023B7323003B6390622C05
:100090009302F0FF7390123BB72200207390223B33
:1000A000B74200209382F2FF7390323BB7420020A8
:1000B0009382F2FF7390423BB74200209382F2FF9B
@ -18,29 +18,41 @@
:100100007390C23B930200007390D23B93020000B5
:100110007390E23B930200007390F23B3701C10001
:100120001301E1FE23A020002320220083A1000070
:10013000631431169301000083210200631E311401
:10014000130E1000170F0000130F4F15B712920770
:10015000938282807390023A7323003A639E621204
:10013000631E3120930100008321020063183120E7
:10014000130E1000170F0000130F8F20B712920725
:10015000938282807390023A7323003A6398621EFE
:10016000B780008037C1ADDE1301F1EE23A020007F
:10017000170F0000130F0F0183A100006F00C011C3
:10018000130E2000170F0000130F4F11B7021207B4
:100190007390023A7323003A7350203B7323203B41
:1001A000630C030E638A620EB780008037C1ADDE38
:1001B0001301F1EE23A02000170F0000130F0F0111
:1001C00083A100006F00400D130E3000170F0000D8
:1001D000130FCF0C1701000013010101731011342C
:1001E00073002030130E4000170F0000130F0F0B89
:1001F00037C1ADDE1301F1EEB780008023A02000EF
:10020000170F0000130F0F0183A100006F00C0083B
:10021000130E500037C1ADDE1301F1EEB7000080C0
:1002200023A0200083A1000063183106130E600094
:10023000B700018083A10000170F0000130FCF0645
:1002400023A030006F004005130E7000170F000050
:10025000130FCF0437C1ADDE1301F1EEB7000380F9
:10026000938080FF23202200170F0000130F8FFAC6
:10027000832102006F004002130E8000B70004804B
:10028000938080FF83A10000170F0000130FCF01A0
:1002900023A030006F004000370110F0130141F23D
:1002A0002320C101370110F0130101F223200100C6
:10017000170F0000130F0F0183A100006F00001D77
:10018000130E2000170F0000130F8F1CB702120769
:100190007390023A7323003A638A621AB7420020CE
:1001A0009382F2FF7350303B7323303B6310031A8A
:1001B000638E6218B72200207350203B7323203BCC
:1001C0006306031863946218B780008037C1ADDE00
:1001D0001301F1EE23A02000170F0000130F0F01F1
:1001E00083A100006F008016130E3000170F00006F
:1001F000130F0F16B702FF0073A0323B7323303B7F
:10020000639662149302F00F73A0323B7323303B6A
:10021000B702FF009382F20F639A6212B702FF00E7
:1002200073B0323B7323303B9302F00F6390621242
:10023000B702FF009382F20F73B0023A7323003AC1
:10024000B702920763946210B702FF009382727044
:1002500073A0023A7323003AB70292079382727036
:100260006396620E130E4000170F0000130F4F0E1F
:1002700017010000130101017310113473002030C5
:10028000130E5000170F0000130F8F0C37C1ADDE97
:100290001301F1EEB780008023A02000170F0000AB
:1002A000130F0F0183A100006F00400A130E6000BE
:1002B000170F0000130FCF0937C1ADDE1301F1EEA8
:1002C000B700008023A0200083A100006310310844
:1002D000130E7000170F0000130F8F07B700048074
:1002E00083A10000170F0000130F4F0723A0300059
:1002F0006F00C005130E8000170F0000130F4F058D
:1003000037C1ADDE1301F1EEB7000380938080FFAB
:1003100023202200170F0000130F0F01832102007A
:100320006F00C002130E9000170F0000130F4F0252
:10033000B7000480938080FF83A10000170F0000A6
:10034000130FCF0123A030006F004000370110F0E1
:10035000130141F22320C101370110F0130101F212
:040360002320010055
:040000058000000077
:00000001FF

View File

@ -8,28 +8,28 @@ onChipRam 0x0000000080000000 0x0000000000020000 w !xr
Linker script and memory map
LOAD build/src/crt.o
LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a
START GROUP
LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/libc.a
LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/libgloss.a
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libgloss.a
END GROUP
LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a
.crt_section 0x0000000080000000 0x2b0
.crt_section 0x0000000080000000 0x364
0x0000000080000000 . = ALIGN (0x4)
*crt.o(.text)
.text 0x0000000080000000 0x2b0 build/src/crt.o
.text 0x0000000080000000 0x364 build/src/crt.o
0x0000000080000000 _start
0x0000000080000010 trap
OUTPUT(build/pmp.elf elf32-littleriscv)
.data 0x00000000800002b0 0x0
.data 0x00000000800002b0 0x0 build/src/crt.o
.data 0x0000000080000364 0x0
.data 0x0000000080000364 0x0 build/src/crt.o
.bss 0x00000000800002b0 0x0
.bss 0x00000000800002b0 0x0 build/src/crt.o
.bss 0x0000000080000364 0x0
.bss 0x0000000080000364 0x0 build/src/crt.o
.riscv.attributes
0x0000000000000000 0x1e
0x0000000000000000 0x1a
.riscv.attributes
0x0000000000000000 0x1e build/src/crt.o
0x0000000000000000 0x1a build/src/crt.o

View File

@ -8,15 +8,15 @@
#define TRAP_RA x30
#define PMPCFG0 0x07120000
#define PMPCFG0_ 0x07920808 // locked
#define PMPCFG0_ 0x07920808
#define PMPCFG1 0x191f0304
#define PMPCFG2 0x000f0506
#define PMPCFG2 0x000f090a
#define PMPCFG3 0x0f1e1900
#define PMPADDR0 0x20000000 // OFF
#define PMPADDR1 0xffffffff // OFF
#define PMPADDR0 0x20000000 // OFF (test0) -> TOR (test1) -> OFF (test2)
#define PMPADDR1 0xffffffff // OFF (test0) -> TOR (test1) -> OFF (test2)
#define PMPADDR2 0x20002000 // NA4 W
#define PMPADDR3 0x20003fff // OFF RWX
#define PMPADDR3 0x20003fff // OFF RWX -> 0x00000000 OFF RWX (test2)
#define PMPADDR4 0x20003fff // OFF X
#define PMPADDR5 0x20003fff // OFF RW
#define PMPADDR6 0x20001fff // NAPOT RWX
@ -132,10 +132,17 @@ test2:
li x5, PMPCFG0
csrw pmpcfg0, x5 // "unlock" region 2
csrr x6, pmpcfg0
beq x5, x6, fail
li x5, PMPADDR3
csrwi pmpaddr3, 0x0
csrr x6, pmpaddr3
bnez x6, fail
beq x5, x6, fail
li x5, PMPADDR2
csrwi pmpaddr2, 0x0
csrr x6, pmpaddr2
beqz x6, fail
beq x5, x6, fail
beqz x6, fail
bne x5, x6, fail
li x1, 0x80008000
li x2, 0xdeadbeef
sw x2, 0x0(x1) // should still be OK (write 0x80008000)
@ -143,54 +150,86 @@ test2:
lw x3, 0x0(x1) // should still fault (read 0x80008000)
j fail
// jump into user mode
// verify masked CSR read/write operations
test3:
li TEST_ID, 3
la TRAP_RA, fail
la x2, test4
li x5, 0x00ff0000
csrs pmpaddr3, x5
csrr x6, pmpaddr3
bne x5, x6, fail
li x5, 0x000000ff
csrs pmpaddr3, x5
csrr x6, pmpaddr3
li x5, 0x00ff00ff
bne x5, x6, fail
li x5, 0x00ff0000
csrc pmpaddr3, x5
csrr x6, pmpaddr3
li x5, 0x000000ff
bne x5, x6, fail
li x5, 0x00ff00ff
csrc pmpcfg0, x5
csrr x6, pmpcfg0
li x5, 0x07920000
bne x5, x6, fail
li x5, 0x00ff0707
csrs pmpcfg0, x5
csrr x6, pmpcfg0
li x5, 0x07920707
bne x5, x6, fail
// jump into user mode
test4:
li TEST_ID, 4
la TRAP_RA, fail
la x2, test5
csrw mepc, x2
mret
// attempt to read/write region 2 from user mode
test4:
li TEST_ID, 4
test5:
li TEST_ID, 5
la TRAP_RA, fail
li x2, 0xdeadbeef
li x1, 0x80008000
sw x2, 0x0(x1) // should be OK (write 0x80008000)
la TRAP_RA, test5
la TRAP_RA, test6
lw x3, 0x0(x1) // should fault (read 0x80008000)
j fail
// attempt to read/write other regions from user mode
test5:
li TEST_ID, 5
test6:
li TEST_ID, 6
la TRAP_RA, fail
li x2, 0xdeadbeef
li x1, 0x80000000
sw x2, 0x0(x1)
lw x3, 0x0(x1)
bne x2, x3, fail // should be OK (read/write 0x80000000)
test6:
li TEST_ID, 6
li x1, 0x80010000
lw x3, 0x0(x1) // should be OK (read 0x80010000)
la TRAP_RA, pass
sw x3, 0x0(x1) // should fault (write 0x80010000)
j fail
test7:
li TEST_ID, 7
la TRAP_RA, fail
li x1, 0x80040000
lw x3, 0x0(x1) // should be OK (read 0x80040000)
la TRAP_RA, pass
sw x3, 0x0(x1) // should fault (write 0x80040000)
j fail
test8:
li TEST_ID, 8
la TRAP_RA, fail
li x2, 0xdeadbeef
li x1, 0x8002fff8
sw x2, 0x0(x4) // should be OK (write 0x8002fff8)
la TRAP_RA, test5
la TRAP_RA, test9
lw x3, 0x0(x4) // should fault (read 0x8002fff8)
j fail
test8:
li TEST_ID, 8
test9:
li TEST_ID, 9
la TRAP_RA, fail
li x1, 0x8003fff8
lw x3, 0x0(x1) // should be OK (read 0x8003fff8)
la TRAP_RA, pass