CsrPlugin now catch illegal CSR access (wrong address + to low privilege level)

This commit is contained in:
Charles Papon 2017-05-09 00:40:44 +02:00
parent fe184636dd
commit 736478ff1d
4 changed files with 119 additions and 82 deletions

View File

@ -12,16 +12,27 @@ import scala.collection.mutable
* Created by spinalvm on 21.03.17. * Created by spinalvm on 21.03.17.
*/ */
trait CsrAccess trait CsrAccess{
def canWrite : Boolean = false
def canRead : Boolean = false
}
object CsrAccess { object CsrAccess {
object WRITE_ONLY extends CsrAccess object WRITE_ONLY extends CsrAccess{
object READ_ONLY extends CsrAccess override def canWrite : Boolean = true
object READ_WRITE extends CsrAccess }
object READ_ONLY extends CsrAccess{
override def canRead : Boolean = true
}
object READ_WRITE extends CsrAccess{
override def canWrite : Boolean = true
override def canRead : Boolean = true
}
object NONE extends CsrAccess object NONE extends CsrAccess
} }
case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int) case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int)
case class MachineCsrConfig( case class MachineCsrConfig(
catchIllegalAccess : Boolean,
mvendorid : BigInt, mvendorid : BigInt,
marchid : BigInt, marchid : BigInt,
mimpid : BigInt, mimpid : BigInt,
@ -36,9 +47,12 @@ case class MachineCsrConfig(
mbadaddrAccess : CsrAccess, mbadaddrAccess : CsrAccess,
mcycleAccess : CsrAccess, mcycleAccess : CsrAccess,
minstretAccess : CsrAccess, minstretAccess : CsrAccess,
ucycleAccess : CsrAccess,
wfiGen : Boolean, wfiGen : Boolean,
ecallGen : Boolean ecallGen : Boolean
) ){
assert(!ucycleAccess.canWrite)
}
case class CsrWrite(that : Data, bitOffset : Int) case class CsrWrite(that : Data, bitOffset : Int)
@ -82,6 +96,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
var timerInterrupt : Bool = null var timerInterrupt : Bool = null
var externalInterrupt : Bool = null var externalInterrupt : Bool = null
var privilege : Bits = null var privilege : Bits = null
var selfException : Flow[ExceptionCause] = null
object EnvCtrlEnum extends SpinalEnum(binarySequential){ object EnvCtrlEnum extends SpinalEnum(binarySequential){
val NONE, EBREAK, MRET= newElement() val NONE, EBREAK, MRET= newElement()
@ -144,6 +159,9 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
externalInterrupt = in Bool() setName("externalInterrupt") externalInterrupt = in Bool() setName("externalInterrupt")
privilege = RegInit(B"11") privilege = RegInit(B"11")
if(catchIllegalAccess)
selfException = newExceptionPort(pipeline.execute)
} }
@ -205,6 +223,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid )) if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid )) if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
//Machine CSR
misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions) misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP) READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
READ_WRITE(CSR.MIP, 3 -> mip.MSIP) READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
@ -221,6 +240,9 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
minstretAccess(CSR.MINSTRET, minstret(31 downto 0)) minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32)) minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
//User CSR
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
//Manage counters //Manage counters
@ -350,30 +372,46 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
execute plug new Area { execute plug new Area {
import execute._ import execute._
val illegalAccess = True
if(catchIllegalAccess) {
selfException.valid := arbitration.isValid && input(IS_CSR) && illegalAccess
selfException.code := 2
selfException.badAddr.assignDontCare()
}
val imm = IMM(input(INSTRUCTION)) val imm = IMM(input(INSTRUCTION))
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1) val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
val readData = B(0, 32 bits) val readData = B(0, 32 bits)
val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid) clearWhen(!arbitration.isStuck) val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid && !memory.arbitration.isStuck) clearWhen(!arbitration.isStuck)
val writeData = input(INSTRUCTION)(13).mux( val writeData = input(INSTRUCTION)(13).mux(
False -> writeSrc, False -> writeSrc,
True -> Mux(input(INSTRUCTION)(12), memory.input(REGFILE_WRITE_DATA) & ~writeSrc, memory.input(REGFILE_WRITE_DATA) | writeSrc) True -> Mux(input(INSTRUCTION)(12), memory.input(REGFILE_WRITE_DATA) & ~writeSrc, memory.input(REGFILE_WRITE_DATA) | writeSrc)
) )
val writeInstruction = arbitration.isValid && input(IS_CSR) val writeOpcode = (!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0))) || (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)))
val writeInstruction = arbitration.isValid && input(IS_CSR) && writeOpcode
arbitration.haltIt setWhen(writeInstruction && (!readDataRegValid || memory.arbitration.isValid)) arbitration.haltIt setWhen(writeInstruction && !readDataRegValid)
val writeEnable = writeInstruction && !memory.arbitration.isValid && readDataRegValid val writeEnable = writeInstruction && !arbitration.isStuckByOthers && !arbitration.removeIt && readDataRegValid
assert(!(arbitration.removeIt && writeEnable),"Can't remove CSR instruction when write occure")
when(arbitration.isValid && input(IS_CSR)) { when(arbitration.isValid && input(IS_CSR)) {
output(REGFILE_WRITE_DATA) := readData output(REGFILE_WRITE_DATA) := readData
} }
//Translation of the csrMapping into real logic //Translation of the csrMapping into real logic
switch(input(INSTRUCTION)(csrRange)) { val csrAddress = input(INSTRUCTION)(csrRange)
switch(csrAddress) {
for ((address, jobs) <- csrMapping.mapping) { for ((address, jobs) <- csrMapping.mapping) {
is(address) { is(address) {
val withWrite = jobs.exists(_.isInstanceOf[CsrWrite])
val withRead = jobs.exists(_.isInstanceOf[CsrRead])
if(withRead && withWrite) {
illegalAccess := False
} else {
if (withWrite) illegalAccess.clearWhen(writeOpcode)
if (withRead) illegalAccess.clearWhen(!writeOpcode)
}
when(writeEnable) { when(writeEnable) {
for (element <- jobs) element match { for (element <- jobs) element match {
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits)) case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
@ -388,6 +426,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
} }
} }
} }
illegalAccess setWhen(privilege.asUInt < csrAddress(9 downto 8).asUInt)
} }
} }
} }

View File

@ -111,5 +111,8 @@ object Riscv{
def MINSTRET = 0xB02 // MRW Machine instructions-retired counter. def MINSTRET = 0xB02 // MRW Machine instructions-retired counter.
def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only. def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only. def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
def UCYCLE = 0xC00 // UR Machine ucycle counter.
} }
} }

View File

@ -40,6 +40,7 @@ object TopLevel {
val csrConfigAll = MachineCsrConfig( val csrConfigAll = MachineCsrConfig(
catchIllegalAccess = true,
mvendorid = 11, mvendorid = 11,
marchid = 22, marchid = 22,
mimpid = 33, mimpid = 33,
@ -55,10 +56,12 @@ object TopLevel {
mcycleAccess = CsrAccess.READ_WRITE, mcycleAccess = CsrAccess.READ_WRITE,
minstretAccess = CsrAccess.READ_WRITE, minstretAccess = CsrAccess.READ_WRITE,
ecallGen = true, ecallGen = true,
wfiGen = true wfiGen = true,
ucycleAccess = CsrAccess.READ_ONLY
) )
val csrConfigSmall = MachineCsrConfig( val csrConfigSmall = MachineCsrConfig(
catchIllegalAccess = false,
mvendorid = null, mvendorid = null,
marchid = null, marchid = null,
mimpid = null, mimpid = null,
@ -74,10 +77,12 @@ object TopLevel {
mcycleAccess = CsrAccess.NONE, mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE, minstretAccess = CsrAccess.NONE,
ecallGen = false, ecallGen = false,
wfiGen = false wfiGen = false,
ucycleAccess = CsrAccess.NONE
) )
val csrConfigSmallest = MachineCsrConfig( val csrConfigSmallest = MachineCsrConfig(
catchIllegalAccess = false,
mvendorid = null, mvendorid = null,
marchid = null, marchid = null,
mimpid = null, mimpid = null,
@ -93,7 +98,8 @@ object TopLevel {
mcycleAccess = CsrAccess.NONE, mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE, minstretAccess = CsrAccess.NONE,
ecallGen = false, ecallGen = false,
wfiGen = false wfiGen = false,
ucycleAccess = CsrAccess.NONE
) )
val configFull = VexRiscvConfig( val configFull = VexRiscvConfig(
@ -239,74 +245,63 @@ object TopLevel {
val configTest = VexRiscvConfig( val configTest = VexRiscvConfig(
plugins = List( plugins = List(
new PcManagerSimplePlugin(0x00000000l, true), new PcManagerSimplePlugin(0x00000000l, true),
// new IBusSimplePlugin( new IBusSimplePlugin(
// interfaceKeepData = true, interfaceKeepData = true,
// catchAccessFault = false catchAccessFault = true
),
// new IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine =32,
// wayCount = 1,
// wrappedMemAccess = true,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = true,
// catchAccessFault = true,
// catchMemoryTranslationMiss = true,
// asyncTagMemory = false,
// twoStageLogic = true
// ),
// askMemoryTranslation = true,
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 4
// )
// ), // ),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 4096,
bytePerLine =32,
wayCount = 1,
wrappedMemAccess = true,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = true,
catchAccessFault = true,
catchMemoryTranslationMiss = true,
asyncTagMemory = false,
twoStageLogic = true
),
askMemoryTranslation = true,
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 4
)
),
// new DBusSimplePlugin( new DBusSimplePlugin(
// catchAddressMisaligned = false, catchAddressMisaligned = true,
// catchAccessFault = false catchAccessFault = true
// ), ),
// new DBusCachedPlugin( // new DBusCachedPlugin(
// config = new DataCacheConfig( // config = new DataCacheConfig(
// cacheSize = 2048, // cacheSize = 4096,
// bytePerLine = 32, // bytePerLine = 32,
// wayCount = 1, // wayCount = 1,
// addressWidth = 32, // addressWidth = 32,
// cpuDataWidth = 32, // cpuDataWidth = 32,
// memDataWidth = 32, // memDataWidth = 32,
// catchAccessFault = false // catchAccessError = true,
// catchIllegal = true,
// catchUnaligned = true,
// catchMemoryTranslationMiss = true,
// tagSizeShift = 2
// ),
// askMemoryTranslation = true,
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 6
// ) // )
// ), // ),
new DBusCachedPlugin(
config = new DataCacheConfig(
cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true,
tagSizeShift = 2
),
askMemoryTranslation = true,
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 6
)
),
new MemoryTranslatorPlugin( // new MemoryTranslatorPlugin(
tlbSize = 32, // tlbSize = 32,
virtualRange = _(31 downto 28) === 0xC, // virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF // ioRange = _(31 downto 28) === 0xF
), // ),
new CsrPlugin(csrConfigSmall), new CsrPlugin(csrConfigSmall),
new DecoderSimplePlugin( new DecoderSimplePlugin(
catchIllegalInstruction = false catchIllegalInstruction = true
), ),
new RegFilePlugin( new RegFilePlugin(
regFileReadyKind = Plugin.SYNC, regFileReadyKind = Plugin.SYNC,
@ -334,7 +329,7 @@ object TopLevel {
// new MachineCsr(csrConfig), // new MachineCsr(csrConfig),
new BranchPlugin( new BranchPlugin(
earlyBranch = false, earlyBranch = false,
catchAddressMisaligned = false, catchAddressMisaligned = true,
prediction = NONE prediction = NONE
) )
) )

View File

@ -5,7 +5,7 @@ TRACE_START=0
CSR=yes CSR=yes
MMU=yes MMU=yes
DHRYSTONE=yes DHRYSTONE=yes
FREE_RTOS=yes FREE_RTOS=no
REDO=10 REDO=10
REF=no REF=no
TRACE_WITH_TIME=no TRACE_WITH_TIME=no