You copied the Doc URL to your clipboard.
AArch32 Translation.Translation Pseudocode
Library pseudocode for aarch32/translation/translation/AArch32.FirstStageTranslate
// AArch32.FirstStageTranslate() // ============================= // Perform a stage 1 translation walk. The function used by Address Translation operations is // similar except it uses the translation regime specified for the instruction. AddressDescriptor AArch32.FirstStageTranslate(bits(32) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, integer size) if PSTATE.EL == EL2 then s1_enabled = HSCTLR.M == '1'; elsif EL2Enabled() then tge = (if ELUsingAArch32(EL2) then HCR.TGE else HCR_EL2.TGE); dc = (if ELUsingAArch32(EL2) then HCR.DC else HCR_EL2.DC); s1_enabled = tge == '0' && dc == '0' && SCTLR.M == '1'; else s1_enabled = SCTLR.M == '1'; TLBRecord S1; S1.addrdesc.fault = AArch32.NoFault(); ipaddress = bits(40) UNKNOWN; secondstage = FALSE; s2fs1walk = FALSE; if s1_enabled then // First stage enabled use_long_descriptor_format = PSTATE.EL == EL2 || TTBCR.EAE == '1'; if use_long_descriptor_format then S1 = AArch32.TranslationTableWalkLD(ipaddress, vaddress, acctype, iswrite, secondstage, s2fs1walk, size); permissioncheck = TRUE; domaincheck = FALSE; else S1 = AArch32.TranslationTableWalkSD(vaddress, acctype, iswrite, size); permissioncheck = TRUE; domaincheck = TRUE; else S1 = AArch32.TranslateAddressS1Off(vaddress, acctype, iswrite); permissioncheck = FALSE; domaincheck = FALSE; InGuardedPage = FALSE; // No memory is guarded when stage 1 address translation is disabled if !IsFault(S1.addrdesc) && UsingAArch32() && HaveTrapLoadStoreMultipleDeviceExt() && AArch32.ExecutingLSMInstr() then if S1.addrdesc.memattrs.memtype == MemType_Device && S1.addrdesc.memattrs.device != DeviceType_GRE then nTLSMD = if S1TranslationRegime() == EL2 then HSCTLR.nTLSMD else SCTLR.nTLSMD; if nTLSMD == '0' then S1.addrdesc.fault = AArch32.AlignmentFault(acctype, iswrite, secondstage); // Check for unaligned data accesses to Device memory if (((!wasaligned && acctype != AccType_IFETCH) || acctype == AccType_DCZVA) && !IsFault(S1.addrdesc) && S1.addrdesc.memattrs.memtype == MemType_Device) then S1.addrdesc.fault = AArch32.AlignmentFault(acctype, iswrite, secondstage); if !IsFault(S1.addrdesc) && domaincheck && !(acctype IN {AccType_DC, AccType_DC_UNPRIV, AccType_IC}) then (permissioncheck, abort) = AArch32.CheckDomain(S1.domain, vaddress, S1.level, acctype, iswrite); S1.addrdesc.fault = abort; if !IsFault(S1.addrdesc) && permissioncheck then S1.addrdesc.fault = AArch32.CheckPermission(S1.perms, vaddress, S1.level, S1.domain, S1.addrdesc.paddress.NS, acctype, iswrite); // Check for instruction fetches from Device memory not marked as execute-never. If there has // not been a Permission Fault then the memory is not marked execute-never. if (!IsFault(S1.addrdesc) && S1.addrdesc.memattrs.memtype == MemType_Device && acctype == AccType_IFETCH) then S1.addrdesc = AArch32.InstructionDevice(S1.addrdesc, vaddress, ipaddress, S1.level, S1.domain, acctype, iswrite, secondstage, s2fs1walk); return S1.addrdesc;
Library pseudocode for aarch32/translation/translation/AArch32.FullTranslate
// AArch32.FullTranslate() // ======================= // Perform both stage 1 and stage 2 translation walks for the current translation regime. The // function used by Address Translation operations is similar except it uses the translation // regime specified for the instruction. AddressDescriptor AArch32.FullTranslate(bits(32) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, integer size) // First Stage Translation S1 = AArch32.FirstStageTranslate(vaddress, acctype, iswrite, wasaligned, size); if !IsFault(S1) && HasS2Translation() then s2fs1walk = FALSE; result = AArch32.SecondStageTranslate(S1, vaddress, acctype, iswrite, wasaligned, s2fs1walk, size); else result = S1; return result;
Library pseudocode for aarch32/translation/translation/AArch32.SecondStageTranslate
// AArch32.SecondStageTranslate() // ============================== // Perform a stage 2 translation walk. The function used by Address Translation operations is // similar except it uses the translation regime specified for the instruction. AddressDescriptor AArch32.SecondStageTranslate(AddressDescriptor S1, bits(32) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, boolean s2fs1walk, integer size) assert HasS2Translation(); assert IsZero(S1.paddress.address<47:40>); hwupdatewalk = FALSE; if !ELUsingAArch32(EL2) then return AArch64.SecondStageTranslate(S1, ZeroExtend(vaddress, 64), acctype, iswrite, wasaligned, s2fs1walk, size, hwupdatewalk); s2_enabled = HCR.VM == '1' || HCR.DC == '1'; secondstage = TRUE; if s2_enabled then // Second stage enabled ipaddress = S1.paddress.address<39:0>; S2 = AArch32.TranslationTableWalkLD(ipaddress, vaddress, acctype, iswrite, secondstage, s2fs1walk, size); // Check for unaligned data accesses to Device memory if (((!wasaligned && acctype != AccType_IFETCH) || (acctype == AccType_DCZVA && !s2fs1walk)) && S2.addrdesc.memattrs.memtype == MemType_Device && !IsFault(S2.addrdesc)) then S2.addrdesc.fault = AArch32.AlignmentFault(acctype, iswrite, secondstage); // Check for permissions on Stage2 translations if !IsFault(S2.addrdesc) then S2.addrdesc.fault = AArch32.CheckS2Permission(S2.perms, vaddress, ipaddress, S2.level, acctype, iswrite, s2fs1walk); // Check for instruction fetches from Device memory not marked as execute-never. As there // has not been a Permission Fault then the memory is not marked execute-never. if (!s2fs1walk && !IsFault(S2.addrdesc) && S2.addrdesc.memattrs.memtype == MemType_Device && acctype == AccType_IFETCH) then domain = bits(4) UNKNOWN; S2.addrdesc = AArch32.InstructionDevice(S2.addrdesc, vaddress, ipaddress, S2.level, domain, acctype, iswrite, secondstage, s2fs1walk); if (s2fs1walk && !IsFault(S2.addrdesc) && S2.addrdesc.memattrs.memtype == MemType_Device) then // Check for protected table walk. if HCR.PTW == '1' then domain = bits(4) UNKNOWN; S2.addrdesc.fault = AArch32.PermissionFault(ipaddress, domain, S2.level, acctype, iswrite, secondstage, s2fs1walk); else // Translation table walk occurs as Normal Non-cacheable memory. S2.addrdesc.memattrs.memtype = MemType_Normal; S2.addrdesc.memattrs.inner.attrs = MemAttr_NC; S2.addrdesc.memattrs.outer.attrs = MemAttr_NC; S2.addrdesc.memattrs.shareable = TRUE; S2.addrdesc.memattrs.outershareable = TRUE; if s2fs1walk then result = AArch32.CombineS1S2Desc(S1, S2.addrdesc, AccType_TTW); else result = AArch32.CombineS1S2Desc(S1, S2.addrdesc, acctype); else result = S1; return result;
Library pseudocode for aarch32/translation/translation/AArch32.SecondStageWalk
// AArch32.SecondStageWalk() // ========================= // Perform a stage 2 translation on a stage 1 translation table walk access. AddressDescriptor AArch32.SecondStageWalk(AddressDescriptor S1, bits(32) vaddress, AccType acctype, boolean iswrite, integer size) assert HasS2Translation(); s2fs1walk = TRUE; wasaligned = TRUE; return AArch32.SecondStageTranslate(S1, vaddress, acctype, iswrite, wasaligned, s2fs1walk, size);
Library pseudocode for aarch32/translation/translation/AArch32.TranslateAddress
// AArch32.TranslateAddress() // ========================== // Main entry point for translating an address AddressDescriptor AArch32.TranslateAddress(bits(32) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, integer size) if !ELUsingAArch32(S1TranslationRegime()) then return AArch64.TranslateAddress(ZeroExtend(vaddress, 64), acctype, iswrite, wasaligned, size); result = AArch32.FullTranslate(vaddress, acctype, iswrite, wasaligned, size); if !IsFault(result) then result.fault = AArch32.CheckDebug(vaddress, acctype, iswrite, size); // Update virtual address for abort functions result.vaddress = ZeroExtend(vaddress); return result;