diff --git a/src/dev/arm/smmu_v3_transl.cc b/src/dev/arm/smmu_v3_transl.cc index c453dd9a93..ba0757f3d9 100644 --- a/src/dev/arm/smmu_v3_transl.cc +++ b/src/dev/arm/smmu_v3_transl.cc @@ -243,7 +243,7 @@ SMMUTranslationProcess::TranslResult SMMUTranslationProcess::bypass(Addr addr) const { TranslResult tr; - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = addr; tr.addrMask = 0; tr.writable = 1; @@ -336,8 +336,8 @@ SMMUTranslationProcess::microTLBLookup(Yield &yield, TranslResult &tr) "micro TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x paddr=%#x\n", request.addr, e->vaMask, request.sid, request.ssid, e->pa); - tr.fault = FAULT_NONE; - tr.addr = e->pa + (request.addr & ~e->vaMask);; + tr.fault = Fault(FAULT_NONE); + tr.addr = e->pa + (request.addr & ~e->vaMask);; tr.addrMask = e->vaMask; tr.writable = e->permissions; @@ -370,7 +370,7 @@ SMMUTranslationProcess::ifcTLBLookup(Yield &yield, TranslResult &tr, "paddr=%#x\n", request.addr, e->vaMask, request.sid, request.ssid, e->pa); - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = e->pa + (request.addr & ~e->vaMask);; tr.addrMask = e->vaMask; tr.writable = e->permissions; @@ -402,7 +402,7 @@ SMMUTranslationProcess::smmuTLBLookup(Yield &yield, TranslResult &tr) "SMMU TLB hit vaddr=%#x amask=%#x asid=%#x vmid=%#x paddr=%#x\n", request.addr, e->vaMask, context.asid, context.vmid, e->pa); - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = e->pa + (request.addr & ~e->vaMask);; tr.addrMask = e->vaMask; tr.writable = e->permissions; @@ -767,7 +767,7 @@ SMMUTranslationProcess::walkStage1And2(Yield &yield, Addr addr, DPRINTF(SMMUv3, "S1 PTE not valid - fault\n"); TranslResult tr; - tr.fault = FAULT_TRANSLATION; + tr.fault = Fault(FAULT_TRANSLATION, FaultClass::IN, false); return tr; } @@ -777,7 +777,7 @@ SMMUTranslationProcess::walkStage1And2(Yield &yield, Addr addr, DPRINTF(SMMUv3, "S1 page not writable - fault\n"); TranslResult tr; - tr.fault = FAULT_PERMISSION; + tr.fault = Fault(FAULT_PERMISSION, FaultClass::IN, false); return tr; } @@ -799,15 +799,17 @@ SMMUTranslationProcess::walkStage1And2(Yield &yield, Addr addr, } TranslResult tr; - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addrMask = pt_ops->pageMask(pte, level); tr.addr = walkPtr + (addr & ~tr.addrMask); tr.writable = pt_ops->isWritable(pte, level, false); if (context.stage2Enable) { TranslResult s2tr = translateStage2(yield, tr.addr, true); - if (s2tr.isFaulting()) + if (s2tr.isFaulting()) { + s2tr.fault.clss = FaultClass::IN; return s2tr; + } tr = combineTranslations(tr, s2tr); } @@ -852,7 +854,7 @@ SMMUTranslationProcess::walkStage2(Yield &yield, Addr addr, bool final_tr, DPRINTF(SMMUv3, " S2 PTE not valid - fault\n"); TranslResult tr; - tr.fault = FAULT_TRANSLATION; + tr.fault = Fault(FAULT_TRANSLATION, FaultClass::TT, true, addr); return tr; } @@ -862,7 +864,7 @@ SMMUTranslationProcess::walkStage2(Yield &yield, Addr addr, bool final_tr, DPRINTF(SMMUv3, " S2 PTE not writable = fault\n"); TranslResult tr; - tr.fault = FAULT_PERMISSION; + tr.fault = Fault(FAULT_PERMISSION, FaultClass::TT, true, addr); return tr; } @@ -877,7 +879,7 @@ SMMUTranslationProcess::walkStage2(Yield &yield, Addr addr, bool final_tr, } TranslResult tr; - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addrMask = pt_ops->pageMask(pte, level); tr.addr = walkPtr + (addr & ~tr.addrMask); tr.writable = pt_ops->isWritable(pte, level, true); @@ -913,7 +915,7 @@ SMMUTranslationProcess::translateStage1And2(Yield &yield, Addr addr) TranslResult tr; if (walk_ep) { if (walk_ep->leaf) { - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = walk_ep->pa + (addr & ~walk_ep->vaMask); tr.addrMask = walk_ep->vaMask; tr.writable = walk_ep->permissions; @@ -924,8 +926,9 @@ SMMUTranslationProcess::translateStage1And2(Yield &yield, Addr addr) Addr table_addr = context.ttb0; if (context.stage2Enable) { TranslResult s2tr = translateStage2(yield, table_addr, false); - if (s2tr.isFaulting()) + if (s2tr.isFaulting()) { return s2tr; + } table_addr = s2tr.addr; } @@ -957,7 +960,7 @@ SMMUTranslationProcess::translateStage2(Yield &yield, Addr addr, bool final_tr) if (ipa_ep) { TranslResult tr; - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = ipa_ep->pa + (addr & ~ipa_ep->ipaMask); tr.addrMask = ipa_ep->ipaMask; tr.writable = ipa_ep->permissions; @@ -995,7 +998,7 @@ SMMUTranslationProcess::translateStage2(Yield &yield, Addr addr, bool final_tr) TranslResult tr; if (walk_ep) { if (walk_ep->leaf) { - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = walk_ep->pa + (addr & ~walk_ep->vaMask); tr.addrMask = walk_ep->vaMask; tr.writable = walk_ep->permissions; @@ -1040,7 +1043,7 @@ SMMUTranslationProcess::combineTranslations(const TranslResult &s1tr, assert(!s1tr.isFaulting()); TranslResult tr; - tr.fault = FAULT_NONE; + tr.fault = Fault(FAULT_NONE); tr.addr = s2tr.addr; tr.addrMask = s1tr.addrMask | s2tr.addrMask; tr.writable = s1tr.writable & s2tr.writable; @@ -1429,8 +1432,10 @@ SMMUTranslationProcess::doReadCD(Yield &yield, if (context.stage2Enable) { tr = translateStage2(yield, l2_addr, false); - if (tr.isFaulting()) + if (tr.isFaulting()) { + tr.fault.clss = FaultClass::CD; return tr; + } l2_addr = tr.addr; } @@ -1451,8 +1456,10 @@ SMMUTranslationProcess::doReadCD(Yield &yield, if (context.stage2Enable) { tr = translateStage2(yield, cd_addr, false); - if (tr.isFaulting()) + if (tr.isFaulting()) { + tr.fault.clss = FaultClass::CD; return tr; + } cd_addr = tr.addr; } diff --git a/src/dev/arm/smmu_v3_transl.hh b/src/dev/arm/smmu_v3_transl.hh index bb98b1a832..33a4fab2c0 100644 --- a/src/dev/arm/smmu_v3_transl.hh +++ b/src/dev/arm/smmu_v3_transl.hh @@ -83,21 +83,73 @@ class SMMUTranslationProcess : public SMMUProcess uint8_t s2t0sz; }; - enum FaultType + enum FaultType : uint8_t { FAULT_NONE, - FAULT_TRANSLATION, // F_TRANSLATION - FAULT_PERMISSION, // F_PERMISSION + FAULT_UUT = 0x1, // F_UUT = Unsupported Upstream Transaction + FAULT_BAD_STREAMID = 0x2, // C_BAD_STREAMID = Transaction streamID out of range + FAULT_STE_FETCH = 0x3, // F_STE_FETCH = Fetch of STE caused external abort + FAULT_BAD_STE = 0x4, // C_BAD_STE = Invalid STE + FAULT_BAD_ATS_TREQ = 0x5, // F_BAD_ATS_TREQ + FAULT_STREAM_DISABLED = 0x6, // F_STREAM_DISABLED = Non-substream trans disabled + FAULT_TRANSL_FORBIDDEN = 0x7, // F_TRANSL_FORBIDDEN = SMMU bypass not allowed + FAULT_BAD_SUBSTREAMID = 0x8, // F_BAD_SUBSTREAMID = Bad substreamID + FAULT_CD_FETCH = 0x9, // F_CD_FETCH = Fetch of CD caused external abort + FAULT_BAD_CD = 0xa, // C_BAD_CD = Invalid CD + FAULT_WALK_EABT = 0xb, // F_WALK_EABT = Table walk/update caused external abort + FAULT_TRANSLATION = 0x10, // F_TRANSLATION = Translation Fault + FAULT_ADDR_SIZE = 0x11, // F_ADDR_SIZE = Address Size fault + FAULT_ACCESS = 0x12, // F_ACCESS = Access flag fault + FAULT_PERMISSION = 0x13, // F_PERMISSION = Permission fault + FAULT_TLB_CONFLICT = 0x20, // F_TLB_CONFLICT = TLB conflict + FAULT_CFG_CONFLICT = 0x21, // F_CFG_CONFLICT = Config cache conflict + FAULT_PAGE_REQUEST = 0x24, // E_PAGE_REQUEST + FAULT_VMS_FETCH = 0x25, // F_VMS_FETCH + }; + + /* The class of the operation that caused the fault */ + enum FaultClass + { + CD = 0x0, // CD fetch + TT = 0x1, // Stage1 translation table fetch + IN = 0x2, // Input address caused fault + RESERVED = 0x3 + }; + + struct Fault + { + explicit Fault(FaultType _type, + FaultClass _clss=FaultClass::RESERVED, + bool _stage2=false, Addr _ipa=0) + : type(_type), clss(_clss), stage2(_stage2), ipa(_ipa) + {} + + Fault(const Fault &rhs) = default; + Fault& operator=(const Fault &rhs) = default; + + bool isFaulting() const { return type != FAULT_NONE; } + + FaultType type; + FaultClass clss; + bool stage2; + Addr ipa; }; struct TranslResult { - FaultType fault; - Addr addr; - Addr addrMask; - bool writable; + TranslResult() + : fault(FaultType::FAULT_NONE), + addr(0), addrMask(0), writable(false) + {} - bool isFaulting() const { return fault != FAULT_NONE; } + TranslResult& operator=(const TranslResult &rhs) = default; + + bool isFaulting() const { return fault.isFaulting(); } + + Fault fault; + Addr addr; + Addr addrMask; + bool writable; }; SMMUv3DeviceInterface &ifc;