You copied the Doc URL to your clipboard.
AArch64 Translation.Translation Pseudocode
Library pseudocode for aarch64/translation/translation/AArch64.CheckAndUpdateDescriptor
// AArch64.CheckAndUpdateDescriptor() // ================================== // Check and update translation table descriptor if hardware update is configured FaultRecord AArch64.CheckAndUpdateDescriptor(DescriptorUpdate result, FaultRecord fault, boolean secondstage, bits(64) vaddress, AccType acctype, boolean iswrite, boolean s2fs1walk, boolean hwupdatewalk) boolean hw_update_AF = FALSE; boolean hw_update_AP = FALSE; // Check if access flag can be updated // Address translation instructions are permitted to update AF but not required if result.AF then if fault.statuscode == Fault_None || ConstrainUnpredictable(Unpredictable_AFUPDATE) == Constraint_TRUE then hw_update_AF = TRUE; if result.AP && fault.statuscode == Fault_None then write_perm_req = (iswrite || acctype IN {AccType_ATOMICRW,AccType_ORDEREDRW, AccType_ORDEREDATOMICRW }) && !s2fs1walk; hw_update_AP = (write_perm_req && !(acctype IN {AccType_AT, AccType_DC, AccType_DC_UNPRIV})) || hwupdatewalk; if hw_update_AF || hw_update_AP then if secondstage || !HasS2Translation() then descaddr2 = result.descaddr; else hwupdatewalk = TRUE; descaddr2 = AArch64.SecondStageWalk(result.descaddr, vaddress, acctype, iswrite, 8, hwupdatewalk); if IsFault(descaddr2) then return descaddr2.fault; accdesc = CreateAccessDescriptor(AccType_ATOMICRW, FALSE); desc = _Mem[descaddr2, 8, accdesc]; el = AArch64.AccessUsesEL(acctype); case el of when EL3 reversedescriptors = SCTLR_EL3.EE == '1'; when EL2 reversedescriptors = SCTLR_EL2.EE == '1'; otherwise reversedescriptors = SCTLR_EL1.EE == '1'; if reversedescriptors then desc = BigEndianReverse(desc); if hw_update_AF then desc<10> = '1'; if hw_update_AP then desc<7> = (if secondstage then '1' else '0'); _Mem[descaddr2,8,accdesc] = if reversedescriptors then BigEndianReverse(desc) else desc; return fault;
Library pseudocode for aarch64/translation/translation/AArch64.FirstStageTranslate
// AArch64.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 AArch64.FirstStageTranslate(bits(64) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, integer size) if HaveNV2Ext() && acctype == AccType_NV2REGISTER then s1_enabled = SCTLR_EL2.M == '1'; elsif HasS2Translation() then s1_enabled = HCR_EL2.TGE == '0' && HCR_EL2.DC == '0' && SCTLR_EL1.M == '1'; else s1_enabled = SCTLR[].M == '1'; TLBRecord S1; S1.addrdesc.fault = AArch64.NoFault(); ipaddress = bits(52) UNKNOWN; secondstage = FALSE; s2fs1walk = FALSE; if s1_enabled then // First stage enabled S1 = AArch64.TranslationTableWalk(ipaddress, TRUE, vaddress, acctype, iswrite, secondstage, s2fs1walk, size); permissioncheck = TRUE; if acctype == AccType_IFETCH then InGuardedPage = S1.GP == '1'; // Global state updated on instruction fetch that denotes // if the fetched instruction is from a guarded page. else S1 = AArch64.TranslateAddressS1Off(vaddress, acctype, iswrite); permissioncheck = 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 SCTLR_EL2.nTLSMD else SCTLR_EL1.nTLSMD; if nTLSMD == '0' then S1.addrdesc.fault = AArch64.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 = AArch64.AlignmentFault(acctype, iswrite, secondstage); if !IsFault(S1.addrdesc) && permissioncheck then S1.addrdesc.fault = AArch64.CheckPermission(S1.perms, vaddress, S1.level, 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 = AArch64.InstructionDevice(S1.addrdesc, vaddress, ipaddress, S1.level, acctype, iswrite, secondstage, s2fs1walk); // Check and update translation table descriptor if required hwupdatewalk = FALSE; s2fs1walk = FALSE; S1.addrdesc.fault = AArch64.CheckAndUpdateDescriptor(S1.descupdate, S1.addrdesc.fault, secondstage, vaddress, acctype, iswrite, s2fs1walk, hwupdatewalk); return S1.addrdesc;
Library pseudocode for aarch64/translation/translation/AArch64.FullTranslate
// AArch64.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 AArch64.FullTranslate(bits(64) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, integer size) // First Stage Translation S1 = AArch64.FirstStageTranslate(vaddress, acctype, iswrite, wasaligned, size); if !IsFault(S1) && !(HaveNV2Ext() && acctype == AccType_NV2REGISTER) && HasS2Translation() then s2fs1walk = FALSE; hwupdatewalk = FALSE; result = AArch64.SecondStageTranslate(S1, vaddress, acctype, iswrite, wasaligned, s2fs1walk, size, hwupdatewalk); else result = S1; return result;
Library pseudocode for aarch64/translation/translation/AArch64.SecondStageTranslate
// AArch64.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 AArch64.SecondStageTranslate(AddressDescriptor S1, bits(64) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, boolean s2fs1walk, integer size, boolean hwupdatewalk) assert HasS2Translation(); s2_enabled = HCR_EL2.VM == '1' || HCR_EL2.DC == '1'; secondstage = TRUE; if s2_enabled then // Second stage enabled ipaddress = S1.paddress.address<51:0>; NS = S1.paddress.NS == '1'; S2 = AArch64.TranslationTableWalk(ipaddress, NS, vaddress, acctype, iswrite, secondstage, s2fs1walk, size); // Check for unaligned data accesses to Device memory if ((!wasaligned && acctype != AccType_IFETCH) || (acctype == AccType_DCZVA)) && S2.addrdesc.memattrs.memtype == MemType_Device && !IsFault(S2.addrdesc) then S2.addrdesc.fault = AArch64.AlignmentFault(acctype, iswrite, secondstage); // Check for permissions on Stage2 translations if !IsFault(S2.addrdesc) then S2.addrdesc.fault = AArch64.CheckS2Permission(S2.perms, vaddress, ipaddress, S2.level, acctype, iswrite, NS,s2fs1walk, hwupdatewalk); // 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 S2.addrdesc = AArch64.InstructionDevice(S2.addrdesc, vaddress, ipaddress, S2.level, acctype, iswrite, secondstage, s2fs1walk); if (s2fs1walk && !IsFault(S2.addrdesc) && S2.addrdesc.memattrs.memtype == MemType_Device) then // Check for protected table walk. if HCR_EL2.PTW == '1' then S2.addrdesc.fault = AArch64.PermissionFault(ipaddress, NS, 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; // Check and update translation table descriptor if required S2.addrdesc.fault = AArch64.CheckAndUpdateDescriptor(S2.descupdate, S2.addrdesc.fault, secondstage, vaddress, acctype, iswrite, s2fs1walk, hwupdatewalk); result = AArch64.CombineS1S2Desc(S1, S2.addrdesc); else result = S1; return result;
Library pseudocode for aarch64/translation/translation/AArch64.SecondStageWalk
// AArch64.SecondStageWalk() // ========================= // Perform a stage 2 translation on a stage 1 translation page table walk access. AddressDescriptor AArch64.SecondStageWalk(AddressDescriptor S1, bits(64) vaddress, AccType acctype, boolean iswrite, integer size, boolean hwupdatewalk) assert HasS2Translation(); s2fs1walk = TRUE; wasaligned = TRUE; return AArch64.SecondStageTranslate(S1, vaddress, acctype, iswrite, wasaligned, s2fs1walk, size, hwupdatewalk);
Library pseudocode for aarch64/translation/translation/AArch64.TranslateAddress
// AArch64.TranslateAddress() // ========================== // Main entry point for translating an address AddressDescriptor AArch64.TranslateAddress(bits(64) vaddress, AccType acctype, boolean iswrite, boolean wasaligned, integer size) result = AArch64.FullTranslate(vaddress, acctype, iswrite, wasaligned, size); if !(acctype IN {AccType_PTW, AccType_IC, AccType_AT}) && !IsFault(result) then result.fault = AArch64.CheckDebug(vaddress, acctype, iswrite, size); // Update virtual address for abort functions result.vaddress = ZeroExtend(vaddress); return result;