Centralised all todo in linux.scala

Sorted out fence fence.i instruction in iBus/dBus plugins.
Fixed MMU permitions while in used mode and bypassing the MMU
This commit is contained in:
Charles Papon 2019-04-05 12:17:29 +02:00
parent 888e1c0b8a
commit 446e9625af
10 changed files with 23 additions and 25 deletions

View File

@ -49,8 +49,7 @@ object GenFull extends App{
), ),
new MmuPlugin( new MmuPlugin(
virtualRange = _(31 downto 28) === 0xC, virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF, ioRange = _(31 downto 28) === 0xF
allowUserIo = false
), ),
new DecoderSimplePlugin( new DecoderSimplePlugin(
catchIllegalInstruction = true catchIllegalInstruction = true

View File

@ -90,12 +90,11 @@ https://github.com/riscv/riscv-qemu/wiki#build-and-install
//TODO test dcache flush //TODO test dcache flush
//TODO have to check, look like supervisor can't get interrupt if the machine mod didn't delegated it, have to check exactly //TODO have to check, look like supervisor can't get interrupt if the machine mod didn't delegated it, have to check exactly
//TODO IBus cached and uncached, do not allow supervisor if it's a user page ? io.cpu.fetch.mmuException
object LinuxGen { object LinuxGen {
def configFull(litex : Boolean, withMmu : Boolean) = { def configFull(litex : Boolean, withMmu : Boolean) = {
val config = VexRiscvConfig( val config = VexRiscvConfig(
plugins = List( plugins = List(
new DummyFencePlugin(), //TODO should be removed for design with caches
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config //Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
// new IBusSimplePlugin( // new IBusSimplePlugin(
// resetVector = 0x80000000l, // resetVector = 0x80000000l,
@ -179,7 +178,7 @@ object LinuxGen {
), ),
new RegFilePlugin( new RegFilePlugin(
regFileReadyKind = plugin.SYNC, regFileReadyKind = plugin.SYNC,
zeroBoot = true //TODO zeroBoot = true
), ),
new IntAluPlugin, new IntAluPlugin,
new SrcPlugin( new SrcPlugin(
@ -240,10 +239,7 @@ object LinuxGen {
) )
) )
if(withMmu) config.plugins += new MmuPlugin( if(withMmu) config.plugins += new MmuPlugin(
virtualRange = a => True, ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF)
// virtualRange = x => x(31 downto 24) =/= 0x81,
ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF),
allowUserIo = true //TODO ??
) else { ) else {
config.plugins += new StaticMemoryTranslatorPlugin( config.plugins += new StaticMemoryTranslatorPlugin(
ioRange = _(31 downto 28) === 0xF ioRange = _(31 downto 28) === 0xF

View File

@ -8,7 +8,6 @@ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import spinal.lib.bus.simple._ import spinal.lib.bus.simple._
//TODO flush
case class DataCacheConfig(cacheSize : Int, case class DataCacheConfig(cacheSize : Int,
bytePerLine : Int, bytePerLine : Int,

View File

@ -411,7 +411,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.fetch.cacheMiss := !hit.valid io.cpu.fetch.cacheMiss := !hit.valid
io.cpu.fetch.error := hit.error io.cpu.fetch.error := hit.error
io.cpu.fetch.mmuRefilling := mmuRsp.refilling io.cpu.fetch.mmuRefilling := mmuRsp.refilling
io.cpu.fetch.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.fetch.isUser)) //TODO Do not allow supervisor if it's a user page ? io.cpu.fetch.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.fetch.isUser))
}) })
} }
@ -441,7 +441,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.decode.cacheMiss := !hit.valid io.cpu.decode.cacheMiss := !hit.valid
io.cpu.decode.error := hit.error io.cpu.decode.error := hit.error
io.cpu.decode.mmuRefilling := mmuRsp.refilling io.cpu.decode.mmuRefilling := mmuRsp.refilling
io.cpu.decode.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.decode.isUser)) //TODO Do not allow supervisor if it's a user page ? io.cpu.decode.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.decode.isUser))
io.cpu.decode.physicalAddress := mmuRsp.physicalAddress io.cpu.decode.physicalAddress := mmuRsp.physicalAddress
}) })
} }

View File

@ -813,7 +813,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
import lastStage._ import lastStage._
//Manage MRET / SRET instructions //Manage MRET / SRET instructions
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { //TODO do not allow user mode already implemented somewhere else ? when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
fetcher.haltIt() fetcher.haltIt()
jumpInterface.valid := True jumpInterface.valid := True
beforeLastStage.arbitration.flushAll := True beforeLastStage.arbitration.flushAll := True
@ -885,7 +885,6 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
//Manage MRET / SRET instructions //Manage MRET / SRET instructions
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
//TODO check MPP value too
when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) { when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) {
illegalInstruction := True illegalInstruction := True
} }

View File

@ -113,6 +113,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
MEMORY_MANAGMENT -> True MEMORY_MANAGMENT -> True
)) ))
decoderService.add(FENCE, Nil)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig) mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack) redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack)
@ -284,6 +286,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING)) mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.memory.isValid setWhen(memory.input(IS_DBUS_SHARING)) cache.io.cpu.memory.isValid setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.memory.mmuBus.rsp.allowUser setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.writeBack.isValid setWhen(writeBack.input(IS_DBUS_SHARING)) cache.io.cpu.writeBack.isValid setWhen(writeBack.input(IS_DBUS_SHARING))
dBusAccess.rsp.valid := writeBack.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) dBusAccess.rsp.valid := writeBack.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt)
dBusAccess.rsp.data := cache.io.cpu.writeBack.data dBusAccess.rsp.data := cache.io.cpu.writeBack.data

View File

@ -292,6 +292,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
) )
} }
decoderService.add(FENCE, Nil)
rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory) rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
if(catchSomething) { if(catchSomething) {

View File

@ -78,8 +78,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
super.setup(pipeline) super.setup(pipeline)
//def MANAGEMENT = M"-----------------100-----0001111"
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(FLUSH_ALL, False) decoderService.addDefault(FLUSH_ALL, False)
decoderService.add(FENCE_I, List( decoderService.add(FENCE_I, List(

View File

@ -7,6 +7,7 @@ import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import spinal.lib.bus.simple._ import spinal.lib.bus.simple._
import vexriscv.Riscv.{FENCE, FENCE_I}
case class IBusSimpleCmd() extends Bundle{ case class IBusSimpleCmd() extends Bundle{
@ -192,6 +193,9 @@ class IBusSimplePlugin(resetVector : BigInt,
super.setup(pipeline) super.setup(pipeline)
iBus = master(IBusSimpleBus(false)).setName("iBus") iBus = master(IBusSimpleBus(false)).setName("iBus")
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.add(FENCE_I, Nil)
if(catchSomething) { if(catchSomething) {
decodeExceptionPort = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.decode,1) decodeExceptionPort = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.decode,1)
} }

View File

@ -38,17 +38,16 @@ case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConf
case class MmuPortConfig(portTlbSize : Int) case class MmuPortConfig(portTlbSize : Int)
class MmuPlugin(virtualRange : UInt => Bool, class MmuPlugin(ioRange : UInt => Bool,
ioRange : UInt => Bool, virtualRange : UInt => Bool = address => True,
allowUserIo : Boolean, // allowUserIo : Boolean = false,
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator { enableMmuInMachineMode : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
var dBusAccess : DBusAccess = null var dBusAccess : DBusAccess = null
val portsInfo = ArrayBuffer[MmuPort]() val portsInfo = ArrayBuffer[MmuPort]()
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = { override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
// val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage) val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length)
val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length /*,exceptionBus*/)
portsInfo += port portsInfo += port
port.bus port.bus
} }
@ -96,7 +95,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
} }
for(offset <- List(CSR.MSTATUS, CSR.SSTATUS)) csrService.rw(offset, 19 -> status.mxr, 18 -> status.sum, 17 -> status.mprv) for(offset <- List(CSR.MSTATUS, CSR.SSTATUS)) csrService.rw(offset, 19 -> status.mxr, 18 -> status.sum, 17 -> status.mprv)
csrService.rw(CSR.SATP, 31 -> satp.mode, 0 -> satp.ppn) //TODO write only ? csrService.rw(CSR.SATP, 31 -> satp.mode, 0 -> satp.ppn)
} }
val core = pipeline plug new Area { val core = pipeline plug new Area {
@ -109,7 +108,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault()) val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
val entryToReplace = Counter(port.args.portTlbSize) val entryToReplace = Counter(port.args.portTlbSize)
val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode
if(!allowMachineModeMmu) { if(!enableMmuInMachineMode) {
requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine()) requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine())
when(privilegeService.isMachine()) { when(privilegeService.isMachine()) {
if (port.priority == MmuPort.PRIORITY_DATA) { if (port.priority == MmuPort.PRIORITY_DATA) {
@ -133,7 +132,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
port.bus.rsp.allowRead := True port.bus.rsp.allowRead := True
port.bus.rsp.allowWrite := True port.bus.rsp.allowWrite := True
port.bus.rsp.allowExecute := True port.bus.rsp.allowExecute := True
port.bus.rsp.allowUser := Bool(allowUserIo) port.bus.rsp.allowUser := True
port.bus.rsp.exception := False port.bus.rsp.exception := False
port.bus.rsp.refilling := False port.bus.rsp.refilling := False
} }