dev-arm: Record additional information in the TranslResult

A faulting translation should return additional information
(other than the fault type). This will be used by future
patches to properly populate the SMMU event record of the
event queue

As we currenlty support two faults only:

1) F_TRANSLATION
2) F_PERMISSION

We add to TranslResult the relevant fault information only:
type, class, stage and ipa

Change-Id: I0a81d5fc202e1b6135cecdcd6dfd2239c2f1ba7e
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Giacomo Travaglini
2024-03-05 18:19:56 +00:00
parent 3d1f68f205
commit ef10db5a3e
2 changed files with 86 additions and 27 deletions

View File

@@ -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;
}

View File

@@ -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;