Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(exception): check high address bits of jump target #3003

Merged
merged 27 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b7bf1cc
exception: check high bits of target in brh and jmp
Tang-Haojin May 23, 2024
a86ad4b
Frontend: Receive backend PF and AF signals and invoke corresponding …
Yan-Muzi May 24, 2024
8dd803a
fix: backend ipf and iaf are not guaranteed to be correct when redire…
Yan-Muzi May 27, 2024
04ecede
fix: new redirect request should overwrite previous redirect request
Yan-Muzi May 27, 2024
bea09e1
FTQ: add some comments for backend IPF and IAF
Yan-Muzi Jun 2, 2024
96329f5
fix: more accurately control ipf and iaf signals sent to ICache
Yan-Muzi Jun 24, 2024
b5a9fef
feat: notify backend if ipf and iaf are sent from backend
Yan-Muzi Jun 24, 2024
3f873c8
Merge branch 'master' into high-address-check
Yan-Muzi Jul 9, 2024
7a8c464
IFU: add some comments
Yan-Muzi Jul 10, 2024
93d433e
HighAddress: check igpf
Tang-Haojin Aug 8, 2024
b1ecea5
Merge remote-tracking branch 'origin/master' into high-address-check
Tang-Haojin Aug 8, 2024
ebb0eac
Merge branch 'master' into high-address-check
ngc7331 Aug 12, 2024
21a0ca2
Merge commit '8b9535b8ff104373776344175e045080e7f3ddb2' into high-add…
Tang-Haojin Aug 30, 2024
7473c9f
feat(CSR): implement high addr check for trap and mret for ifetch
Tang-Haojin Aug 30, 2024
d060f69
Merge remote-tracking branch 'origin/master' into high-address-check
Tang-Haojin Aug 30, 2024
09eed61
feat(CSR): add Sv48 and Sv48x4 support for AddrTransType
Tang-Haojin Aug 30, 2024
52e4ca1
fix(ICacheMainPipe): use s0_itlb_exception
Tang-Haojin Aug 30, 2024
3f2d348
Merge remote-tracking branch 'origin/master' into high-address-check
Tang-Haojin Sep 3, 2024
7fd3957
Merge remote-tracking branch 'origin/master' into high-address-check
Tang-Haojin Sep 4, 2024
384accc
save complete tval
Tang-Haojin Sep 6, 2024
5b51017
Merge remote-tracking branch 'origin/master' into high-address-check
Tang-Haojin Sep 6, 2024
bf95695
adapt nmi
Tang-Haojin Sep 6, 2024
1e7f88e
fix TrapEntryMNEvent
Tang-Haojin Sep 6, 2024
9bc7d32
bump ready-to-run
Tang-Haojin Sep 6, 2024
943552c
Merge remote-tracking branch 'origin/master' into high-address-check
Tang-Haojin Sep 8, 2024
76eef45
code refactor
Tang-Haojin Sep 9, 2024
0b37b5a
Merge branch 'master' into high-address-check
Tang-Haojin Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/main/scala/xiangshan/Bundle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ class CfiUpdateInfo(implicit p: Parameters) extends XSBundle with HasBPUParamete
val isMisPred = Bool()
val shift = UInt((log2Ceil(numBr)+1).W)
val addIntoHist = Bool()
// raise exceptions from backend
val backendIPF = Bool() // instruction page fault
val backendIAF = Bool() // instruction access fault

def fromFtqRedirectSram(entry: Ftq_Redirect_SRAMEntry) = {
// this.hist := entry.ghist
Expand Down Expand Up @@ -585,6 +588,14 @@ class DistributedCSRUpdateReq(implicit p: Parameters) extends XSBundle {
}
}

class AddrTransType(implicit p: Parameters) extends XSBundle {
val bare, sv39, sv39x4 = Bool()

def checkAccessFault(target: UInt): Bool = bare && target(XLEN - 1, PAddrBits).orR
def checkPageFault(target: UInt): Bool = sv39 && target(XLEN - 1, 39) =/= VecInit.fill(XLEN - 39)(target(38)).asUInt ||
sv39x4 && target(XLEN - 1, 41) =/= VecInit.fill(XLEN - 41)(target(40)).asUInt
}

class L1CacheErrorInfo(implicit p: Parameters) extends XSBundle {
// L1CacheErrorInfo is also used to encode customized CACHE_ERROR CSR
val source = Output(new Bundle() {
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/xiangshan/backend/CtrlBlock.scala
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ class CtrlBlockImp(
when (s6_flushFromRobValid) {
io.frontend.toFtq.redirect.bits.level := RedirectLevel.flush
io.frontend.toFtq.redirect.bits.cfiUpdate.target := RegEnable(flushTarget, s5_flushFromRobValidAhead)
// TODO: trap/xtvec may cause IAF/IPF
io.frontend.toFtq.redirect.bits.cfiUpdate.backendIAF := false.B
io.frontend.toFtq.redirect.bits.cfiUpdate.backendIPF := false.B
}

for (i <- 0 until DecodeWidth) {
Expand Down
5 changes: 4 additions & 1 deletion src/main/scala/xiangshan/backend/MemBlock.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,10 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
}
val allRedirect = Seq(lsq.io.nuke_rollback, lsq.io.nack_rollback) ++ loadUnits.map(_.io.rollback) ++ hybridUnits.map(_.io.ldu_io.rollback)
val oldestOneHot = selectOldestRedirect(allRedirect)
val oldestRedirect = Mux1H(oldestOneHot, allRedirect)
val oldestRedirect = WireDefault(Mux1H(oldestOneHot, allRedirect))
// memory replay would not cause IAF/IPF
oldestRedirect.bits.cfiUpdate.backendIAF := false.B
oldestRedirect.bits.cfiUpdate.backendIPF := false.B
io.mem_to_ooo.memoryViolation := oldestRedirect
io.mem_to_ooo.lsqio.lqCanAccept := lsq.io.lqCanAccept
io.mem_to_ooo.lsqio.sqCanAccept := lsq.io.sqCanAccept
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/xiangshan/backend/datapath/DataConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object DataConfig {
case class FpData() extends DataConfig("fp", 64)
case class VecData() extends DataConfig("vec", 128)
case class ImmData(len: Int) extends DataConfig("int", len)
case class VAddrData() extends DataConfig("vaddr", 39) // Todo: associate it with the width of vaddr
case class VAddrData() extends DataConfig("vaddr", 41) // Todo: associate it with the width of vaddr
case class V0Data() extends DataConfig("v0", 128)
case class VlData() extends DataConfig("vl", log2Up(VecData().dataWidth) + 1 ) // 8
case class FakeIntData() extends DataConfig("fakeint", 64)
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/xiangshan/backend/exu/ExeUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import xiangshan.backend.datapath.WbConfig.{PregWB, _}
import xiangshan.backend.fu.FuType
import xiangshan.backend.fu.vector.Bundles.{VType, Vxrm}
import xiangshan.backend.fu.fpu.Bundles.Frm
import xiangshan.AddrTransType

class ExeUnitIO(params: ExeUnitParams)(implicit p: Parameters) extends XSBundle {
val flush = Flipped(ValidIO(new Redirect()))
Expand All @@ -42,6 +43,7 @@ class ExeUnitIO(params: ExeUnitParams)(implicit p: Parameters) extends XSBundle
val vtype = OptionWrapper(params.writeVConfig, (Valid(new VType)))
val vlIsZero = OptionWrapper(params.writeVConfig, Output(Bool()))
val vlIsVlmax = OptionWrapper(params.writeVConfig, Output(Bool()))
val instrAddrTransType = Option.when(params.hasJmpFu || params.hasBrhFu)(Input(new AddrTransType))
}

class ExeUnit(val exuParams: ExeUnitParams)(implicit p: Parameters) extends LazyModule {
Expand Down Expand Up @@ -335,6 +337,7 @@ class ExeUnitImp(
io.vxrm.foreach(exuio => funcUnits.foreach(fu => fu.io.vxrm.foreach(fuio => fuio <> exuio)))
io.vlIsZero.foreach(exuio => funcUnits.foreach(fu => fu.io.vlIsZero.foreach(fuio => exuio := fuio)))
io.vlIsVlmax.foreach(exuio => funcUnits.foreach(fu => fu.io.vlIsVlmax.foreach(fuio => exuio := fuio)))
io.instrAddrTransType.foreach(exuio => funcUnits.foreach(fu => fu.io.instrAddrTransType.foreach(fuio => fuio := exuio)))

// debug info
io.out.bits.debug := 0.U.asTypeOf(io.out.bits.debug)
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/xiangshan/backend/exu/ExuBlock.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class ExuBlockImp(
// }
XSPerfAccumulate(s"${(exu.wrapper.exuParams.name)}_fire_cnt", PopCount(exu.io.in.fire))
}
exus.find(_.io.csrio.nonEmpty).map(_.io.csrio.get).foreach { csrio =>
exus.map(_.io.instrAddrTransType.foreach(_ := csrio.instrAddrTransType))
}
val aluFireSeq = exus.filter(_.wrapper.exuParams.fuConfigs.contains(AluCfg)).map(_.io.in.fire)
for (i <- 0 until (aluFireSeq.size + 1)){
XSPerfAccumulate(s"alu_fire_${i}_cnt", PopCount(aluFireSeq) === i.U)
Expand Down
11 changes: 11 additions & 0 deletions src/main/scala/xiangshan/backend/fu/CSR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class CSRFileIO(implicit p: Parameters) extends XSBundle {
val customCtrl = Output(new CustomCSRCtrlIO)
// distributed csr write
val distributedUpdate = Vec(2, Flipped(new DistributedCSRUpdateReq))
// instruction fetch address translation type
val instrAddrTransType = Output(new AddrTransType)
}

class VtypeStruct(implicit p: Parameters) extends XSBundle {
Expand Down Expand Up @@ -1533,6 +1535,15 @@ class CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
debugMode := debugModeNew
}

// instruction fetch address translation type
csrio.instrAddrTransType.bare := privilegeMode === ModeM ||
(!virtMode && tlbBundle.satp.mode === 0.U) ||
(virtMode && tlbBundle.vsatp.mode === 0.U && tlbBundle.hgatp.mode === 0.U)
csrio.instrAddrTransType.sv39 := privilegeMode =/= ModeM && !virtMode && tlbBundle.satp.mode === 8.U ||
virtMode && tlbBundle.vsatp.mode === 8.U
csrio.instrAddrTransType.sv39x4 := virtMode && tlbBundle.vsatp.mode === 0.U && tlbBundle.hgatp.mode === 8.U
assert(PopCount(csrio.instrAddrTransType.asUInt) === 1.U, "Exactly one instr fetch addr trans type can be asserted.")

// Distributed CSR update req
//
// For now we use it to implement customized cache op
Expand Down
4 changes: 4 additions & 0 deletions src/main/scala/xiangshan/backend/fu/FuConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ case class FuConfig (

def isCsr: Boolean = fuType == FuType.csr

def isBrh: Boolean = fuType == FuType.brh

def isJmp: Boolean = fuType == FuType.jmp

def isFence: Boolean = fuType == FuType.fence

def isVecArith: Boolean = fuType == FuType.vialuF || fuType == FuType.vimac ||
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/xiangshan/backend/fu/FuncUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
val vtype = OptionWrapper(cfg.writeVlRf, (Valid(new VType)))
val vlIsZero = OptionWrapper(cfg.writeVlRf, Output(Bool()))
val vlIsVlmax = OptionWrapper(cfg.writeVlRf, Output(Bool()))
val instrAddrTransType = Option.when(cfg.isJmp || cfg.isBrh)(Input(new AddrTransType))
}

abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule {
Expand Down
12 changes: 7 additions & 5 deletions src/main/scala/xiangshan/backend/fu/wrapper/BranchUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import xiangshan.backend.fu.{BranchModule, FuConfig, FuncUnit}
import xiangshan.backend.datapath.DataConfig.VAddrData
import xiangshan.{RedirectLevel, XSModule}

class AddrAddModule(len: Int)(implicit p: Parameters) extends XSModule {
class AddrAddModule(implicit p: Parameters) extends XSModule {
val io = IO(new Bundle {
val pc = Input(UInt(len.W))
val pc = Input(UInt(VAddrBits.W))
val offset = Input(UInt(12.W)) // branch inst only support 12 bits immediate num
val target = Output(UInt(len.W))
val target = Output(UInt(XLEN.W))
})
io.target := io.pc + SignExt(ImmUnion.B.toImm32(io.offset), len)
io.target := SignExt(SignExt(io.pc, VAddrBits + 1) + SignExt(ImmUnion.B.toImm32(io.offset), VAddrBits + 1), XLEN)
}

class BranchUnit(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
val dataModule = Module(new BranchModule)
val addModule = Module(new AddrAddModule(VAddrData().dataWidth))
val addModule = Module(new AddrAddModule)
dataModule.io.src(0) := io.in.bits.data.src(0) // rs1
dataModule.io.src(1) := io.in.bits.data.src(1) // rs2
dataModule.io.func := io.in.bits.ctrl.fuOpType
Expand All @@ -44,6 +44,8 @@ class BranchUnit(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
redirect.bits.cfiUpdate.taken := dataModule.io.taken
redirect.bits.cfiUpdate.predTaken := dataModule.io.pred_taken
redirect.bits.cfiUpdate.target := addModule.io.target
redirect.bits.cfiUpdate.backendIAF := io.instrAddrTransType.get.checkAccessFault(addModule.io.target)
redirect.bits.cfiUpdate.backendIPF := io.instrAddrTransType.get.checkPageFault(addModule.io.target)
}
connect0LatencyCtrlSingal
}
2 changes: 2 additions & 0 deletions src/main/scala/xiangshan/backend/fu/wrapper/JumpUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class JumpUnit(cfg: FuConfig)(implicit p: Parameters) extends PipedFuncUnit(cfg)
redirect.cfiUpdate.taken := true.B
redirect.cfiUpdate.target := jumpDataModule.io.target
redirect.cfiUpdate.isMisPred := jumpDataModule.io.target(VAddrData().dataWidth - 1, 0) =/= jmpTarget || !predTaken
redirect.cfiUpdate.backendIAF := io.instrAddrTransType.get.checkAccessFault(jumpDataModule.io.target)
redirect.cfiUpdate.backendIPF := io.instrAddrTransType.get.checkPageFault(jumpDataModule.io.target)
// redirect.debug_runahead_checkpoint_id := uop.debugInfo.runahead_checkpoint_id // Todo: assign it

io.in.ready := io.out.ready
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/xiangshan/frontend/FrontendBundle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class IFUICacheIO(implicit p: Parameters)extends XSBundle with HasICacheParamete
class FtqToICacheRequestBundle(implicit p: Parameters)extends XSBundle with HasICacheParameters{
val pcMemRead = Vec(5, new FtqICacheInfo)
val readValid = Vec(5, Bool())
val backendIpf = Bool()
val backendIaf = Bool()
}


Expand Down
21 changes: 21 additions & 0 deletions src/main/scala/xiangshan/frontend/NewFtq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,25 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
val validEntries = distanceBetween(bpuPtr, commPtr)
val canCommit = Wire(Bool())

// Instruction page fault and instruction access fault are sent from backend with redirect requests.
// When IPF and IAF are sent, backendPcFaultIfuPtr points to the FTQ entry whose first instruction
// raises IPF or IAF, which is ifuWbPtr_write or IfuPtr_write.
// Only when IFU has written back that FTQ entry can backendIpf and backendIaf be false because this
// makes sure that IAF and IPF are correctly raised instead of being flushed by redirect requests.
val backendIpf = RegInit(false.B)
val backendIaf = RegInit(false.B)
val backendPcFaultIfuPtr = RegInit(FtqPtr(false.B, 0.U))
when (fromBackendRedirect.valid) {
backendIpf := fromBackendRedirect.bits.cfiUpdate.backendIPF
backendIaf := fromBackendRedirect.bits.cfiUpdate.backendIAF
when (fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIAF) {
backendPcFaultIfuPtr := ifuWbPtr_write
Yan-Muzi marked this conversation as resolved.
Show resolved Hide resolved
}
} .elsewhen (ifuWbPtr =/= backendPcFaultIfuPtr) {
backendIpf := false.B
backendIaf := false.B
}

// **********************************************************************
// **************************** enq from bpu ****************************
// **********************************************************************
Expand Down Expand Up @@ -810,6 +829,8 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
io.toICache.req.valid := entry_is_to_send && ifuPtr =/= bpuPtr
io.toICache.req.bits.readValid.zipWithIndex.map{case(copy, i) => copy := toICacheEntryToSend(i) && copied_ifu_ptr(i) =/= copied_bpu_ptr(i)}
io.toICache.req.bits.pcMemRead.zipWithIndex.map{case(copy,i) => copy.fromFtqPcBundle(toICachePcBundle(i))}
io.toICache.req.bits.backendIpf := backendIpf
io.toICache.req.bits.backendIaf := backendIaf
ngc7331 marked this conversation as resolved.
Show resolved Hide resolved
// io.toICache.req.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr
// io.toICache.req.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) =>
// bypassWrtie.startAddr := bpu_in_bypass_buf.tail(i).startAddr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
val s0_req_vsetIdx = (0 until partWayNum + 1).map(i => VecInit(s0_req_vaddr(i).map(get_idx(_))))
val s0_only_first = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && !fromFtqReq(i).crossCacheline)
val s0_double_line = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && fromFtqReq(i).crossCacheline)
val s0_backendIpf = fromFtq.bits.backendIpf
val s0_backendIaf = fromFtq.bits.backendIaf

val s0_final_valid = s0_valid
val s0_final_vaddr = s0_req_vaddr.head
Expand Down Expand Up @@ -237,6 +239,8 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
val s1_req_vaddr = RegEnable(s0_final_vaddr, s0_fire)
val s1_req_vsetIdx = RegEnable(s0_final_vsetIdx, s0_fire)
val s1_double_line = RegEnable(s0_final_double_line, s0_fire)
val s1_backendIpf = RegEnable(s0_backendIpf, s0_fire)
val s1_backendIaf = RegEnable(s0_backendIaf, s0_fire)

/** tlb request and response */
fromITLB.foreach(_.ready := true.B)
Expand Down Expand Up @@ -288,9 +292,9 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
val tlbExcpGPF = VecInit((0 until PortNumber).map(i =>
ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).gpf.instr)))
val tlbExcpPF = VecInit((0 until PortNumber).map(i =>
ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).pf.instr)))
ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).pf.instr || s1_backendIpf)))
val tlbExcpAF = VecInit((0 until PortNumber).map(i =>
ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).af.instr)))
ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).af.instr || s1_backendIaf)))
val tlbExcp = VecInit((0 until PortNumber).map(i => tlbExcpAF(i) || tlbExcpPF(i) || tlbExcpGPF(i)))

val s1_tlb_valid = VecInit((0 until PortNumber).map(i => ValidHoldBypass(tlb_valid_tmp(i), s1_fire)))
Expand Down
Loading