(old) htmldiff from-(new)

Shared Pseudocode Functions

This page displays common pseudocode functions shared by many pages

PseudocodePseudocodes

Library pseudocode for aarch32/at/AArch32_EncodePARLD

// AArch32_EncodePARLD() // ===================== // Returns 64-bit format PAR on address translation instruction. func AArch32_EncodePARLD(addrdesc : AddressDescriptor, ss : SecurityState) begin PAR()[63:0] = Zeros{64}; if !IsFault(addrdesc) then var ns : bit; if ss == SS_NonSecure then ns = ARBITRARY : bit; elsif addrdesc.paddress.paspace == PAS_Secure then ns = '0'; else ns = '1'; end; PAR().F = '0'; PAR().SH = ReportedPARShareability(PAREncodeShareability(addrdesc.memattrs)); PAR().NS = ns; PAR()[10] = ImpDefBit("Non-Faulting PAR"); // IMPDEF PAR().LPAE = '1'; PAR().PA = addrdesc.paddress.address[39:12]; PAR().ATTR = ReportedPARAttrs(EncodePARAttrs(addrdesc.memattrs)); else PAR().F = '1'; PAR().FST = AArch32_PARFaultStatusLD(addrdesc.fault); PAR().S2WLK = if addrdesc.fault.s2fs1walk then '1' else '0'; PAR().FSTAGE = if addrdesc.fault.secondstage then '1' else '0'; PAR().LPAE = '1'; PAR()[63:48] = ImpDefBits{16}("Faulting PAR"); // IMPDEF end; return; end;

Library pseudocode for aarch32/at/AArch32_EncodePARSD

// AArch32_EncodePARSD() // ===================== // Returns 32-bit format PAR on address translation instruction. func AArch32_EncodePARSD(addrdesc_in : AddressDescriptor, supersection : bit, ss : SecurityState) begin PAR()[31:0] = Zeros{32}; var addrdesc : AddressDescriptor = addrdesc_in; if !IsFault(addrdesc) then if (addrdesc.memattrs.memtype == MemType_Device || (addrdesc.memattrs.inner.attrs == MemAttr_NC && addrdesc.memattrs.outer.attrs == MemAttr_NC)) then addrdesc.memattrs.shareability = Shareability_OSH; end; var ns : bit; if ss == SS_NonSecure then ns = ARBITRARY : bit; elsif addrdesc.paddress.paspace == PAS_Secure then ns = '0'; else ns = '1'; end; let sh : bits(2) = (if addrdesc.memattrs.shareability != Shareability_NSH then '01' else '00'); PAR().F = '0'; PAR().SS = supersection; PAR().Outer = AArch32_ReportedOuterAttrs(AArch32_PAROuterAttrs(addrdesc.memattrs)); PAR().Inner = AArch32_ReportedInnerAttrs(AArch32_PARInnerAttrs(addrdesc.memattrs)); PAR().SH = ReportedPARShareability(sh); PAR()[8] = ImpDefBit("Non-Faulting PAR"); // IMPDEF PAR().NS = ns; PAR().NOS = if addrdesc.memattrs.shareability == Shareability_OSH then '0' else '1'; PAR().LPAE = '0'; PAR().PA = addrdesc.paddress.address[39:12]; else PAR().F = '1'; PAR().FST = AArch32_PARFaultStatusSD(addrdesc.fault); PAR().LPAE = '0'; PAR()[31:16] = ImpDefBits{16}("Faulting PAR"); // IMPDEF end; return; end;

Library pseudocode for aarch32/debug/VCRMatch/AArch32_VCRMatch

// AArch32_VCRMatch() // ================== func AArch32_VCRMatch(vaddress : bits(32)) => boolean begin var match : boolean; if UsingAArch32() && ELUsingAArch32(EL1) && PSTATE.EL != PSTATE.EL != EL2 then // Each bit position in this string corresponds to a bit in DBGVCR and an exception vector. var match_word : bits(32) = Zeros{}; let ss : SecurityState = CurrentSecurityState(); if vaddress[31:5] == ExcVectorBase()[31:5] then if HaveEL(EL3) && ss == SS_NonSecure then match_word[UInt(vaddress[4:2]) + 24] = '1'; // Non-secure vectors else match_word[UInt(vaddress[4:2]) + 0] = '1'; // Secure vectors (or no EL3) end; end; if (HaveEL(EL3) && ELUsingAArch32(EL3) && vaddress[31:5] == MVBAR()[31:5] && ss == SS_Secure) then match_word[UInt(vaddress[4:2]) + 8] = '1'; // Monitor vectors end; // Mask out bits not corresponding to vectors. var mask : bits(32); if !HaveEL(EL3) then mask = '00000000'::'00000000'::'00000000'::'11011110'; // DBGVCR[31:8] are RES0 elsif !ELUsingAArch32(EL3) then mask = '11011110'::'00000000'::'00000000'::'11011110'; // DBGVCR[15:8] are RES0 else mask = '11011110'::'00000000'::'11011100'::'11011110'; end; match_word = match_word AND DBGVCR() AND mask; match = !IsZero(match_word); // Check for UNPREDICTABLE case - match on Prefetch Abort and Data Abort vectors if !IsZero(match_word[28:27,12:11,4:3]) && DebugTarget() == PSTATE.EL() == PSTATE.EL then match = ConstrainUnpredictableBool(Unpredictable_VCMATCHDAPA); end; if !IsZero(vaddress[1:0]) && match then match = ConstrainUnpredictableBool(Unpredictable_VCMATCHHALF); end; else match = FALSE; end; return match; end;

Library pseudocode for aarch32/debug/watchpoint/AArch32_WatchpointByteMatch

// AArch32_WatchpointByteMatch() // ============================= func AArch32_WatchpointByteMatch(n : integer, vaddress : bits(32)) => boolean begin let dbgtop : integer{} = 31; let cmpbottom : integer{} = if DBGWVR(n)[2] == '1' then 2 else 3; // Word or doubleword var bottom = cmpbottom; let select : integer{} = UInt(vaddress[cmpbottom-1:0]); var byte_select_match : boolean = (DBGWCR(n).BAS[select] != '0'); var mask : integer{} = UInt(DBGWCR(n).MASK); // If DBGWCR(n).MASK is a nonzero value and DBGWCR(n).BAS is not set to '11111111', or // DBGWCR(n).BAS specifies a non-contiguous set of bytes behavior is CONSTRAINED // UNPREDICTABLE. if mask > 0 && !IsOnes(DBGWCR(n).BAS) then byte_select_match = ConstrainUnpredictableBool(Unpredictable_WPMASKANDBAS); else let LSB : bits(8) = (DBGWCR(n).BAS AND NOT(DBGWCR(n).BAS - 1)); let MSB : bits(8) = (DBGWCR(n).BAS + LSB); if !IsZero(MSB AND (MSB - 1)) then // Not contiguous byte_select_match = ConstrainUnpredictableBool(Unpredictable_WPBASCONTIGUOUS); bottom = 3; // For the whole doubleword end; end; // If the address mask is set to a reserved value, the behavior is CONSTRAINED UNPREDICTABLE. if mask > 0 && mask <= 2 then var c : Constraint; var unpred_mask : integer; (c, unpred_maskmask) = ( ConstrainUnpredictableInteger(3, 31, Unpredictable_RESWPMASK); assert) as c IN {(Constraint, integer{0..31})); assert c IN {Constraint_DISABLED, Constraint_NONE, Constraint_UNKNOWN}; case c of when Constraint_DISABLED => return FALSE; // Disabled when Constraint_NONE => mask = 0; // No masking // Otherwise the value returned by ConstrainUnpredictableInteger is a not-reserved value otherwise => mask = unpred_mask as integer{3..31}; end; end; let cmpmsb : integer{} = dbgtop; let cmplsb : integer{} = if mask > bottom then mask else bottom; let bottombit : integer{} = bottom; var WVR_match : boolean = (vaddress[cmpmsb:cmplsb] == DBGWVR(n)[cmpmsb:cmplsb]); if mask > bottom then // If masked bits of DBGWVR(n) are not zero, the behavior is CONSTRAINED UNPREDICTABLE. if WVR_match && !IsZero(DBGWVR(n)[cmplsb-1:bottombit]) then WVR_match = ConstrainUnpredictableBool(Unpredictable_WPMASKEDBITS); end; end; return (WVR_match && byte_select_match); end;

Library pseudocode for aarch32/exceptions/aborts/AArch32_ReportDataAbort

// AArch32_ReportDataAbort() // ========================= // Report syndrome information for aborts taken to modes other than Hyp mode. func AArch32_ReportDataAbort(route_to_monitor : boolean, fault : FaultRecord) begin var long_format : boolean; if route_to_monitor && CurrentSecurityState() != SS_Secure then long_format = ((TTBCR_S().EAE == '1') || (IsExternalSyncAbort(fault) && ((PSTATE.EL ==PSTATE.EL == EL2 || TTBCR().EAE == '1') || (fault.secondstage && (ImpDefBool( "Report abort using Long-descriptor format")))));")))))); else long_format = TTBCR().EAE == '1'; end; var syndrome : bits(32) = AArch32_CommonFaultStatus(fault, long_format); // bits of syndrome that are not common to I and D side if fault.accessdesc.acctype IN {AccessType_DC, AccessType_IC, AccessType_AT} then syndrome[13] = '1'; // CM syndrome[11] = '1'; // WnR else syndrome[11] = if fault.write then '1' else '0'; // WnR end; if !long_format then syndrome[7:4] = fault.domain; // Domain end; if fault.accessdesc.acctype == AccessType_IC then var i_syndrome : bits(32); if (!long_format && ImpDefBool("Report I-cache maintenance fault in IFSR")) then i_syndrome = syndrome; syndrome[10,3:0] = EncodeSDFSC(Fault_ICacheMaint, 1); else i_syndrome = ARBITRARY : bits(32); end; if route_to_monitor then IFSR_S() = i_syndrome; else IFSR() = i_syndrome; end; end; if route_to_monitor then DFSR_S() = syndrome; DFAR_S() = fault.vaddress[31:0]; else DFSR() = syndrome; DFAR() = fault.vaddress[31:0]; end; return; end;

Library pseudocode for aarch32/exceptions/aborts/AArch32_ReportPrefetchAbort

// AArch32_ReportPrefetchAbort() // ============================= // Report syndrome information for aborts taken to modes other than Hyp mode. func AArch32_ReportPrefetchAbort(route_to_monitor : boolean, fault : FaultRecord) begin // The encoding used in the IFSR can be Long-descriptor format or Short-descriptor format. // Normally, the current translation table format determines the format. For an abort from // Non-secure state to Monitor mode, the IFSR uses the Long-descriptor format if any of the // following applies: // * The Secure TTBCR.EAE is set to 1. // * It is taken from Hyp mode. // * It is taken from EL1 or EL0, and the Non-secure TTBCR.EAE is set to 1. var long_format : boolean = FALSE; if route_to_monitor && CurrentSecurityState() != SS_Secure then long_format = TTBCR_S().EAE == '1' || PSTATE.EL == PSTATE.EL == EL2 || TTBCR().EAE == '1'; else long_format = TTBCR().EAE == '1'; end; let fsr : bits(32) = AArch32_CommonFaultStatus(fault, long_format); if route_to_monitor then IFSR_S() = fsr; IFAR_S() = fault.vaddress[31:0]; else IFSR() = fsr; IFAR() = fault.vaddress[31:0]; end; return; end;

Library pseudocode for aarch32/exceptions/async/AArch32_TakePhysicalFIQException

// AArch32_TakePhysicalFIQException() // ================================== func AArch32_TakePhysicalFIQException() begin // Check if routed to AArch64 state var route_to_aarch64 : boolean = PSTATE.EL == PSTATE.EL == EL0 && !ELUsingAArch32(EL1); if !route_to_aarch64 && EL2Enabled() && !ELUsingAArch32(EL2) then route_to_aarch64 = HCR_EL2().TGE == '1' || (HCR_EL2().FMO == '1' && !IsInHost()); end; if !route_to_aarch64 then route_to_aarch64 =&& EffectiveSCR_EL3_FIQHaveEL() == '1'; end; if route_to_aarch64 then AArch64_TakePhysicalFIQException(); end; let route_to_monitor : boolean =( EL3) && !ELUsingAArch32(EL3) then route_to_aarch64 = SCR_EL3().FIQ == '1'; end; if route_to_aarch64 then AArch64_TakePhysicalFIQException(); end; let route_to_monitor : boolean = HaveEL(EL3) && SCR().FIQ == '1'; let route_to_hyp : boolean = (PSTATE.EL IN {PSTATE.EL IN {EL0, EL1} && EL2Enabled() && (HCR().TGE == '1' || HCR().FMO == '1')); let preferred_exception_return : bits(32) = ThisInstrAddr{}(); let vect_offset : integer = 0x1C; let lr_offset : integer = 4; if route_to_monitor then AArch32_EnterMonitorMode(preferred_exception_return, lr_offset, vect_offset); elsif PSTATE.EL() && (HCR().TGE == '1' || HCR().FMO == '1')); let preferred_exception_return : bits(32) = ThisInstrAddr{}(); let vect_offset : integer = 0x1C; let lr_offset : integer = 4; if route_to_monitor then AArch32_EnterMonitorMode(preferred_exception_return, lr_offset, vect_offset); elsif PSTATE.EL == EL2 || route_to_hyp then let except : ExceptionRecord = ExceptionSyndrome(Exception_FIQ); AArch32_EnterHypMode(except, preferred_exception_return, vect_offset); else AArch32_EnterMode(M32_FIQ, preferred_exception_return, lr_offset, vect_offset); end; end;

Library pseudocode for aarch32/exceptions/async/AArch32_TakePhysicalIRQException

// AArch32_TakePhysicalIRQException() // ================================== // Take an enabled physical IRQ exception. func AArch32_TakePhysicalIRQException() begin // Check if routed to AArch64 state var route_to_aarch64 : boolean = PSTATE.EL == PSTATE.EL == EL0 && !ELUsingAArch32(EL1); if !route_to_aarch64 && EL2Enabled() && !ELUsingAArch32(EL2) then route_to_aarch64 = HCR_EL2().TGE == '1' || (HCR_EL2().IMO == '1' && !IsInHost()); end; if !route_to_aarch64 then route_to_aarch64 =&& EffectiveSCR_EL3_IRQHaveEL() == '1'; end; if route_to_aarch64 then AArch64_TakePhysicalIRQException(); end; let route_to_monitor : boolean =( EL3) && !ELUsingAArch32(EL3) then route_to_aarch64 = SCR_EL3().IRQ == '1'; end; if route_to_aarch64 then AArch64_TakePhysicalIRQException(); end; let route_to_monitor : boolean = HaveEL(EL3) && SCR().IRQ == '1'; let route_to_hyp : boolean = (PSTATE.EL IN {PSTATE.EL IN {EL0, EL1} && EL2Enabled() && (HCR().TGE == '1' || HCR().IMO == '1')); let preferred_exception_return : bits(32) = ThisInstrAddr{}(); let vect_offset : integer = 0x18; let lr_offset : integer = 4; if route_to_monitor then AArch32_EnterMonitorMode(preferred_exception_return, lr_offset, vect_offset); elsif PSTATE.EL() && (HCR().TGE == '1' || HCR().IMO == '1')); let preferred_exception_return : bits(32) = ThisInstrAddr{}(); let vect_offset : integer = 0x18; let lr_offset : integer = 4; if route_to_monitor then AArch32_EnterMonitorMode(preferred_exception_return, lr_offset, vect_offset); elsif PSTATE.EL == EL2 || route_to_hyp then let except : ExceptionRecord = ExceptionSyndrome(Exception_IRQ); AArch32_EnterHypMode(except, preferred_exception_return, vect_offset); else AArch32_EnterMode(M32_IRQ, preferred_exception_return, lr_offset, vect_offset); end; end;

Library pseudocode for aarch32/exceptions/async/AArch32_TakeVirtualFIQException

// AArch32_TakeVirtualFIQException() // ================================= func AArch32_TakeVirtualFIQException() begin assert PSTATE.EL IN { PSTATE.EL IN {EL0, EL1} && EL2Enabled(); if ELUsingAArch32(EL2) then // Virtual IRQ enabled if TGE==0 and FMO==1 assert HCR().TGE == '0' && HCR().FMO == '1'; else assert HCR_EL2().TGE == '0' && HCR_EL2().FMO == '1'; end; // Check if routed to AArch64 state if PSTATE.EL) then // Virtual IRQ enabled if TGE==0 and FMO==1 assert HCR().TGE == '0' && HCR().FMO == '1'; else assert HCR_EL2().TGE == '0' && HCR_EL2().FMO == '1'; end; // Check if routed to AArch64 state if PSTATE.EL == EL0 && !ELUsingAArch32(EL1) then AArch64_TakeVirtualFIQException(); end; let preferred_exception_return : bits(32)=) = ThisInstrAddr{}(); let vect_offset : integer = 0x1C; let lr_offset : integer = 4; AArch32_EnterMode(M32_FIQ, preferred_exception_return, lr_offset, vect_offset); end;

Library pseudocode for aarch32/exceptions/exceptions/AArch32_ExceptionClass

// AArch32_ExceptionClass() // ======================== // Returns the Exception Class and Instruction Length fields to be reported in HSR func AArch32_ExceptionClass(exceptype : Exception) => (integer,bit) begin var il_is_valid : boolean = TRUE; var ec : integer; case exceptype of when Exception_Uncategorized => ec = 0x00; il_is_valid = FALSE; when Exception_WFxTrap => ec = 0x01; when Exception_CP15RTTrap => ec = 0x03; when Exception_CP15RRTTrap => ec = 0x04; when Exception_CP14RTTrap => ec = 0x05; when Exception_CP14DTTrap => ec = 0x06; when Exception_AdvSIMDFPAccessTrap => ec = 0x07; when Exception_FPIDTrap => ec = 0x08; when Exception_PACTrap => ec = 0x09; when Exception_GPC => ec = 0x1E; when Exception_CP14RRTTrap => ec = 0x0C; when Exception_BranchTarget => ec = 0x0D; when Exception_IllegalState => ec = 0x0E; il_is_valid = FALSE; when Exception_SupervisorCall => ec = 0x11; when Exception_HypervisorCall => ec = 0x12; when Exception_MonitorCall => ec = 0x13; when Exception_InstructionAbort => ec = if PSTATE.EL == PSTATE.EL == EL2 then 0x21 else 0x20; il_is_valid = FALSE; when Exception_PCAlignment => ec = 0x22; il_is_valid = FALSE; when Exception_DataAbort => ec = if PSTATE.EL == PSTATEEL2.ELthen ==0x25 else 0x24; when EL2Exception_NV2DataAbort then=> ec = 0x25 else 0x24; when Exception_FPTrappedException => ec = 0x28; when Exception_Profiling => ec = 0x3D; otherwise => unreachable; end; var il : bit; if il_is_valid then il = if ThisInstrLength() == 32 then '1' else '0'; else il = '1'; end; return (ec,il); end;

Library pseudocode for aarch32/exceptions/exceptions/AArch32_TakeReset

// AArch32_TakeReset() // =================== // Reset into AArch32 state func AArch32_TakeReset(cold_reset : boolean) begin assert !HaveAArch64(); // Enter the highest implemented Exception level in AArch32 state if HaveEL(EL3) then AArch32_WriteMode(M32_Svc); SCR().NS = '0'; // Secure state elsif HaveEL(EL2) then AArch32_WriteMode(M32_Hyp); else AArch32_WriteMode(M32_Svc); end; // Reset System registers in the coproc=0b111x encoding space // and other system components AArch32_ResetControlRegisters(cold_reset); FPEXC().EN = '0'; // Reset all other PSTATE fields, including instruction set and endianness according to the // SCTLR values produced by the above call to ResetControlRegisters() PSTATE.[A,I,F] = '111'; // All asynchronous exceptions masked PSTATE.IT = '00000000'; // IT block state reset if PSTATE.IT = '00000000'; // IT block state reset if HaveEL(EL2) && !HaveEL(EL3) then PSTATE.T = HSCTLR().TE; // Instruction set: TE=0:A32, TE=1:T32. PSTATE.J is RES0. PSTATE.E = HSCTLR().EE; // Endianness: EE=0: little-endian, EE=1: big-endian. else PSTATE.T = SCTLR().TE; // Instruction set: TE=0:A32, TE=1:T32. PSTATE.J is RES0. PSTATE.E = SCTLR().EE; // Endianness: EE=0: little-endian, EE=1: big-endian. end; PSTATE.IL = '0'; // Clear Illegal Execution state bit // All registers, bits and fields not reset by the above pseudocode or by the BranchTo() call // below are UNKNOWN bitstrings after reset. In particular, the return information registers // R14 or ELR_hyp and SPSR have UNKNOWN values, so that it // is impossible to return from a reset in an architecturally defined way. AArch32_ResetGeneralRegisters(); if IsFeatureImplemented(FEAT_SME) || IsFeatureImplemented(FEAT_SVE) then ResetSVERegisters(); else AArch32_ResetSIMDFPRegisters(); end; AArch32_ResetSpecialRegisters(); ResetExternalDebugRegisters(cold_reset); var rv : bits(32); // IMPLEMENTATION DEFINED reset vector if PSTATE.T = HSCTLR().TE; // Instruction set: TE=0:A32, TE=1:T32. PSTATE.J is RES0. PSTATE.E = HSCTLR().EE; // Endianness: EE=0: little-endian, EE=1: big-endian. else PSTATE.T = SCTLR().TE; // Instruction set: TE=0:A32, TE=1:T32. PSTATE.J is RES0. PSTATE.E = SCTLR().EE; // Endianness: EE=0: little-endian, EE=1: big-endian. end; PSTATE.IL = '0'; // Clear Illegal Execution state bit // All registers, bits and fields not reset by the above pseudocode or by the BranchTo() call // below are UNKNOWN bitstrings after reset. In particular, the return information registers // R14 or ELR_hyp and SPSR have UNKNOWN values, so that it // is impossible to return from a reset in an architecturally defined way. AArch32_ResetGeneralRegisters(); if IsFeatureImplemented(FEAT_SME) || IsFeatureImplemented(FEAT_SVE) then ResetSVERegisters(); else AArch32_ResetSIMDFPRegisters(); end; AArch32_ResetSpecialRegisters(); ResetExternalDebugRegisters(cold_reset); var rv : bits(32); // IMPLEMENTATION DEFINED reset vector if HaveEL(EL3) then if MVBAR()[0] == '1' then // Reset vector in MVBAR rv = MVBAR()[31:1]::'0'; else rv = ImpDefBits{32}("reset vector address"); end; else rv = RVBAR()[31:1]::'0'; end; // The reset vector must be correctly aligned assert rv[0] == '0' && (PSTATE.T) then if MVBAR()[0] == '1' then // Reset vector in MVBAR rv = MVBAR()[31:1]::'0'; else rv = ImpDefBits{32}("reset vector address"); end; else rv = RVBAR()[31:1]::'0'; end; // The reset vector must be correctly aligned assert rv[0] == '0' && (PSTATE.T == '1' || rv[1] == '0'); let branch_conditional : boolean = FALSE; EDPRSR().R = '0'; // Leaving Reset State. BranchTo{32}(rv, BranchType_RESET, branch_conditional); end;

Library pseudocode for aarch32/exceptions/syscalls/AArch32_TakeSMCException

// AArch32_TakeSMCException() // ========================== func AArch32_TakeSMCException() begin assert HaveEL(EL3) && ELUsingAArch32(EL3); AArch32_ITAdvance(); HSAdvance(); SSAdvance(); let preferred_exception_return : bits(32) = NextInstrAddr{}(); let vect_offset : integer{} = 0x08; let lr_offset : integer{} = 0; AArch32_EnterMonitorMode(preferred_exception_return, lr_offset, vect_offset); end;

Library pseudocode for aarch32/exceptions/takeexception/AArch32_EnterHypMode

// AArch32_EnterHypMode() // ====================== // Take an exception to Hyp mode. noreturn func AArch32_EnterHypMode(except : ExceptionRecord, preferred_exception_return : bits(32), vect_offset : integer) begin SynchronizeContext(); assert HaveEL(EL2) && CurrentSecurityState() == SS_NonSecure && ELUsingAArch32(EL2); if Halted() then AArch32_EnterHypModeInDebugState(except); end; let spsr : bits(32) = GetPSRFromPSTATE{}(AArch32_NonDebugState); if ! except.exceptype IN {Exception_IRQ, Exception_FIQ} then AArch32_ReportHypEntry(except); end; AArch32_WriteMode(M32_Hyp); SPSR_curr() = spsr; ELR_hyp() = preferred_exception_return; PSTATE.T = HSCTLR().TE; // PSTATE.J is RES0 PSTATE.SS = '0'; if ! PSTATE.T = HSCTLR().TE; // PSTATE.J is RES0 PSTATE.SS = '0'; if !HaveEL(EL3) then PSTATE.A = '1'; PSTATE.I = '1'; PSTATE.F = '1'; else if PSTATE.A = '1'; PSTATE.I = '1'; PSTATE.F = '1'; else if ELUsingAArch32(EL3) then if SCR().EA == '0' then PSTATE.A = '1'; end; if SCR().IRQ == '0' then PSTATE.I = '1'; end; if SCR().FIQ == '0' then PSTATE.F = '1'; end; else if SCR_EL3().EA == '0' then PSTATE.A = '1'; end; if EffectiveSCR_EL3_IRQ() == '0' then PSTATE.I = '1'; end; if EffectiveSCR_EL3_FIQ() == '0' then PSTATE.F = '1'; end; end; end; PSTATE.E = HSCTLR().EE; PSTATE.IL = '0'; PSTATE.IT = '00000000'; if IsFeatureImplemented(FEAT_SSBS) then PSTATE.SSBS) then if SCR().EA == '0' then PSTATE.A = '1'; end; if SCR().IRQ == '0' then PSTATE.I = '1'; end; if SCR().FIQ == '0' then PSTATE.F = '1'; end; else if SCR_EL3().EA == '0' then PSTATE.A = '1'; end; if SCR_EL3().IRQ == '0' then PSTATE.I = '1'; end; if SCR_EL3().FIQ == '0' then PSTATE.F = '1'; end; end; end; PSTATE.E = HSCTLR().EE; PSTATE.IL = '0'; PSTATE.IT = '00000000'; if IsFeatureImplemented(FEAT_SSBS) then PSTATE.SSBS = HSCTLR().DSSBS; end; let branch_conditional : boolean = FALSE; BranchTo{32}(HVBAR()[31:5]::vect_offset[4:0], BranchType_EXCEPTION, branch_conditional); CheckExceptionCatch(TRUE); // Check for debug event on exception entry EndOfInstruction(); end;

Library pseudocode for aarch32/functions/memory/Mem_with_type

// Mem_with_type // ============= accessor Mem_with_type{size : integer{8, 16, 32, 64}}(address : bits(32), accdesc_in : AccessDescriptor ) <=> value_in : bits(size) begin // Perform a read of 'size' bits. The access byte order is reversed for a big-endian access. // Instruction fetches would call AArch32_MemSingle directly. getter let bytes : integer{} = size DIV 8; var accdesc : AccessDescriptor = accdesc_in; var value : bits(size); // Check alignment on size of element accessed, not overall access size var aligned : boolean; if accdesc.ispair then let halfalignment : integer{} = (sizeif DIVaccdesc.ispair 2)then asbytes integer{32}; alignedDIV =2 IsAlignedSize(address,else halfbytes; var DIV 8); else aligned : boolean = IsAlignedSize(address, bytesalignment); end; if !aligned && AArch32_UnalignedAccessFaults(accdesc) then let fault : FaultRecord = AlignmentFault(accdesc, ZeroExtend{64}(address)); AArch32_Abort(fault); end; if aligned then value = AArch32_MemSingle{size}(address, accdesc, aligned); else assert bytes > 1; value[7:0] = AArch32_MemSingle{8}(address, accdesc, aligned); // For subsequent bytes, if they cross to a new translation page which assigns // Device memory type, it is CONSTRAINED UNPREDICTABLE whether an unaligned access // will generate an Alignment Fault. let c : Constraint = ConstrainUnpredictable(Unpredictable_DEVPAGE2); assert c IN {Constraint_FAULT, Constraint_NONE}; if c == Constraint_NONE then aligned = TRUE; end; for i = 1 to bytes-1 do value[i*:8] = AArch32_MemSingle{8}(address+i, accdesc, aligned); end; end; if BigEndian(accdesc.acctype) then value = BigEndianReverse{size}(value); end; return value; end; // Perform a write of 'size' bits. The byte order is reversed for a big-endian access. setter let bytes : integer{} = size DIV 8; var value : bits(size) = value_in; var accdesc : AccessDescriptor = accdesc_in; // Check alignment on size of element accessed, not overall access size var aligned : boolean; if accdesc.ispair then let halfalignment : integer{} = (sizeif DIVaccdesc.ispair 2)then asbytes integer{32}; alignedDIV =2 IsAlignedSize(address,else halfbytes; var DIV 8); else aligned : boolean = IsAlignedSize(address, bytesalignment); end; if !aligned && AArch32_UnalignedAccessFaults(accdesc) then let fault : FaultRecord = AlignmentFault(accdesc, ZeroExtend{64}(address)); AArch32_Abort(fault); end; if BigEndian(accdesc.acctype) then value = BigEndianReverse{size}(value); end; if aligned then AArch32_MemSingle{size}(address, accdesc, aligned) = value; else assert bytes > 1; AArch32_MemSingle{8}(address, accdesc, aligned) = value[7:0]; // For subsequent bytes, if they cross to a new translation page which assigns // Device memory type, it is CONSTRAINED UNPREDICTABLE whether an unaligned access // will generate an Alignment Fault. let c : Constraint = ConstrainUnpredictable(Unpredictable_DEVPAGE2); assert c IN {Constraint_FAULT, Constraint_NONE}; if c == Constraint_NONE then aligned = TRUE; end; for i = 1 to bytes-1 do AArch32_MemSingle{8}(address+i, accdesc, aligned) = value[i*:8]; end; end; return; end; end;

Library pseudocode for aarch32/functions/system/AArch32_WriteModeByInstr

// AArch32_WriteModeByInstr() // ========================== // Function for dealing with writes to PSTATE.M from an AArch32 instruction, and ensuring that // illegal state changes are correctly flagged in PSTATE.IL. func AArch32_WriteModeByInstr(mode : bits(5)) begin var (valid,el) : (boolean, bits(2)) = ELFromM32(mode); // 'valid' is set to FALSE if' mode' is invalid for this implementation or the current value // of SCR.NS/SCR_EL3.NS. Additionally, it is illegal for an instruction to write 'mode' to // PSTATE.EL if it would result in any of: // * A change to a mode that would cause entry to a higher Exception level. if UInt(el) > UInt(PSTATE.EL) then valid = FALSE; end; // * A change to or from Hyp mode. if (PSTATE.M ==PSTATE.EL) then valid = FALSE; end; // * A change to or from Hyp mode. if (PSTATE.M == M32_Hyp || mode == M32_Hyp) && PSTATE.M != mode then valid = FALSE; end; // * When EL2 is implemented, the value of HCR.TGE is '1', a change to a Non-secure EL1 mode. if (PSTATE.M == PSTATE.M != mode then valid = FALSE; end; // * When EL2 is implemented, the value of HCR.TGE is '1', a change to a Non-secure EL1 mode. if (PSTATE.M == M32_Monitor && HaveEL(EL2) && el == EL1 && SCR().NS == '1' && HCR().TGE == '1') then valid = FALSE; end; if !valid then PSTATE.IL&& SCR().NS == '1' && HCR().TGE == '1') then valid = FALSE; end; if !valid then PSTATE.IL = '1'; else AArch32_WriteMode(mode); end; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_DTLBI_ALL

// AArch32_DTLBI_ALL() // =================== // Invalidate all data TLB entries for the indicated translation regime with the // the indicated security state for all TLBs within the indicated broadcast domain. // Invalidation applies to all applicable stage 1 and stage 2 entries. func AArch32_DTLBI_ALL(security : SecurityState, regime : Regime, broadcast_inbroadcast : Broadcast, attr_inattr : TLBIMemAttr) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_DALL; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.level = TLBILevel_Any; r.attr = attr; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_DTLBI_ASID

// AArch32_DTLBI_ASID() // ==================== // Invalidate all data TLB stage 1 entries matching the indicated VMID (where regime supports) // and ASID in the parameter Rt in the indicated translation regime with the // indicated security state for all TLBs within the indicated broadcast domain. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_DTLBI_ASID(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_inbroadcast : Broadcast, attr_inattr : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_DASID; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = TLBILevel_Any; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_DTLBI_VA

// AArch32_DTLBI_VA() // ================== // Invalidate by VA all stage 1 data TLB entries in the indicated broadcast domain // matching the indicated VMID and ASID (where regime supports VMID, ASID) in the indicated regime // with the indicated security state. // ASID, VA and related parameters are derived from Rt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_DTLBI_VA(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_inbroadcast : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_DVA; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; r.address = Zeros{32} :: Rt[31:12] :: Zeros{12}; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_EffectiveBroadcastAArch32_ITLBI_ALL

// AArch32_EffectiveBroadcastAArch32_ITLBI_ALL() // =============================================== // Invalidate all instruction TLB entries for the indicated translation regime with the // the indicated security state for all TLBs within the indicated broadcast domain. // Invalidation applies to all applicable stage 1 and stage 2 entries. func AArch32_ITLBI_ALL(security : AArch32_EffectiveBroadcast(broadcast_in, regime : BroadcastRegime), =>broadcast : Broadcast begin var broadcast, attr : BroadcastTLBIMemAttr =) begin assert broadcast_in; ifPSTATE.EL IN { PSTATEEL3.EL !=, EL2, EL1 then return broadcast; end;}; ifvar (broadcastr ==: Broadcast_NSHTLBIRecord && ((; r.op =ELUsingAArch32TLBIOp_IALL(; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.level =EL2TLBILevel_Any); r.attr = &&attr; TLBI(r); if HCR().FBbroadcast == '1') || (!!=ELUsingAArch32Broadcast_NSH(EL2) && HCR_EL2().FB == '1'))) then broadcast = Broadcast_ForcedISHthen BroadcastTLBI(broadcast, r); end; end; return broadcast; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_ITLBI_ALLAArch32_ITLBI_ASID

// AArch32_ITLBI_ALLAArch32_ITLBI_ASID() // ======================================= // Invalidate all instruction TLB stage 1 entries formatching the indicated translationVMID // (where regime withsupports) and ASID in the parameter Rt in the indicated translation // regime with the indicated security state for all TLBs within the indicated broadcast domain. // InvalidationNote: applies to all applicable stage 1 and stage 2 entries.combined entries are in the scope of this operation. func AArch32_ITLBI_ALLAArch32_ITLBI_ASID(security : SecurityState, regime : Regime, broadcast_invmid : bits(16), broadcast : Broadcast, attr_in attr : TLBIMemAttr), Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attrr : TLBIMemAttrTLBIRecord ; r.op = attr_in; let broadcast : BroadcastTLBIOp_IASID ; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = AArch32_EffectiveBroadcastUseVMID(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end; var r : TLBIRecord; r.op = TLBIOp_IALL; r.from_aarch64 = FALSE; r.security = security; r.regime = (regime;); r.level = TLBILevel_Any; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_ITLBI_ASIDAArch32_ITLBI_VA

// AArch32_ITLBI_ASIDAArch32_ITLBI_VA() // ====================================== // Invalidate allby instructionVA TLBall stage 1 instruction TLB entries matchingin the indicated VMIDbroadcast domain // (wherematching regimethe supports)indicated VMID and ASID in(where theregime parametersupports RtVMID, ASID) in the indicated translationregime // regime with the indicated security statestate. // forASID, allVA TLBsand withinrelated theparameters indicatedare broadcastderived domain.from Rt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_ITLBI_ASIDAArch32_ITLBI_VA(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in broadcast : Broadcast, attr_inlevel : TLBILevel, attr : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attrr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end; var r : TLBIRecord; r.op = TLBIOp_IASIDTLBIOp_IVA; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = TLBILevel_Any(regime); r.level = level; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; r.address = Zeros{32} :: Rt[31:12] :: Zeros{12}; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_ITLBI_VA

// AArch32_ITLBI_VA() // ================== // Invalidate by VA all stage 1 instruction TLB entries in the indicated broadcast domain // matching the indicated VMID and ASID (where regime supports VMID, ASID) in the indicated regime // with the indicated security state. // ASID, VA and related parameters are derived from Rt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_ITLBI_VA(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_in : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end; var r : TLBIRecord; r.op = TLBIOp_IVA; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; r.address = Zeros{32} :: Rt[31:12] :: Zeros{12}; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_TLBI_ASID

// AArch32_TLBI_ASID() // =================== // Invalidate all stage 1 entries matching the indicated VMID (where regime supports) // and ASID in the parameter Rt in the indicated translation regime with the // indicated security state for all TLBs within the indicated broadcast domain. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_TLBI_ASID(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_inbroadcast : Broadcast, attr_inattr : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_ASID; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = TLBILevel_Any; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_TLBI_VA

// AArch32_TLBI_VA() // ================= // Invalidate by VA all stage 1 TLB entries in the indicated broadcast domain // matching the indicated VMID and ASID (where regime supports VMID, ASID) in the indicated regime // with the indicated security state. // ASID, VA and related parameters are derived from Rt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_TLBI_VA(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_inbroadcast : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_VA; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Zeros{8} :: Rt[7:0]; r.address = Zeros{32} :: Rt[31:12] :: Zeros{12}; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_TLBI_VAA

// AArch32_TLBI_VAA() // ================== // Invalidate by VA all stage 1 TLB entries in the indicated broadcast domain // matching the indicated VMID (where regime supports VMID) and all ASID in the indicated regime // with the indicated security state. // VA and related parameters are derived from Rt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch32_TLBI_VAA(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_inbroadcast : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Rt : bits(32)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_VAA; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.address = Zeros{32} :: Rt[31:12] :: Zeros{12}; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/functions/tlbi/AArch32_TLBI_VMALL

// AArch32_TLBI_VMALL() // ==================== // Invalidate all stage 1 entries for the indicated translation regime with the // the indicated security state for all TLBs within the indicated broadcast // domain that match the indicated VMID (where applicable). // Note: stage 1 and stage 2 combined entries are in the scope of this operation. // Note: stage 2 only entries are not in the scope of this operation. func AArch32_TLBI_VMALL(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_inbroadcast : Broadcast, attr_inattr : TLBIMemAttr) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var attr : TLBIMemAttr = attr_in; let broadcast : Broadcast = AArch32_EffectiveBroadcast(broadcast_in); if ExcludeXS() then attr = TLBI_ExcludeXS; end;}; var r : TLBIRecord; r.op = TLBIOp_VMALL; r.from_aarch64 = FALSE; r.security = security; r.regime = regime; r.level = TLBILevel_Any; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.attr = attr; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch32/ic/AArch32_IC

// AArch32_IC() // ============ // Perform Instruction Cache Operation. func AArch32_IC(opscope : CacheOpScope) begin let regval : bits(32) = ARBITRARY : bits(32); AArch32_IC(regval, opscope); end; // AArch32_IC() // ============ // Perform Instruction Cache Operation. func AArch32_IC(regval : bits(32), opscope : CacheOpScope) begin var cache : CacheRecord; cache.acctype = AccessType_IC; cache.cachetype = CacheType_Instruction; cache.cacheop = CacheOp_Invalidate; cache.opscope = opscope; cache.security = SecurityStateAtEL(PSTATE.EL); if opscope IN {PSTATE.EL); if opscope IN {CacheOpScope_ALLU, CacheOpScope_ALLUIS} then if (opscope == CacheOpScope_ALLUIS ||then cache.shareability = AArch32_EffectiveBroadcast(Broadcast_NSH) == Broadcast_ForcedISH) then cache.shareability = Shareability_ISH; else cache.shareability = Shareability_NSH; end; cache.regval = ZeroExtend{64}(regval); CACHE_OP(cache); else assert opscope == CacheOpScope_PoU; if EL2Enabled() then if PSTATE.EL IN { PSTATE.EL IN {EL0, EL1} then cache.is_vmid_valid = TRUE; cache.vmid = VMID(); else cache.is_vmid_valid = FALSE; end; else cache.is_vmid_valid = FALSE; end; if PSTATE.EL(); else cache.is_vmid_valid = FALSE; end; else cache.is_vmid_valid = FALSE; end; if PSTATE.EL == EL0 then cache.is_asid_valid = TRUE; cache.asid = ASID(); else cache.is_asid_valid = FALSE; end; cache.shareability = Shareability_NSH; cache.vaddress = ZeroExtend{64}(regval); let size : integer = 0; let aligned : boolean = TRUE; let accdesc : AccessDescriptor = CreateAccDescIC(cache); let memaddrdesc : AddressDescriptor = AArch32_TranslateAddress(regval, accdesc, aligned, size); if IsFault(memaddrdesc) then AArch32_Abort(memaddrdesc.fault); end; cache.paddress = memaddrdesc.paddress; CACHE_OP(cache); end; return; end;

Library pseudocode for aarch32/translation/attrs/AArch32_MAIRAttr

// AArch32_MAIRAttr() // ================== // Retrieve the memory attribute encoding indexed in the given MAIR func AArch32_MAIRAttr(index : integer, mair : bits(64))MAIRType) => bits(8) begin assert (index < 8); return mair[index*:8]; end;

Library pseudocode for aarch64/debug/brbe/BRBEDebugStateExit

// BRBEDebugStateExit() // ==================== // Called to write Debug state exit branch record when BRBE is active. func BRBEDebugStateExit(target_address : bits(64)) begin if BranchRecordAllowed(PSTATE.EL) then // Debug state is a prohibited region, therefore ccu=1, cc=0, source_address=0 let branch_type : bits(6) = '111001'; let ccu : bit = '1'; let cc : bits(14) = Zeros{}; let el : bits(2) = PSTATE.EL; let mispredict : bit = '0'; UpdateBranchRecordBuffer(ccu, cc, branch_type, el, mispredict, '01', Zeros{64}, target_address); PMUEvent(PMU_EVENT_BRB_FILTRATE); end; return; end;PSTATE.EL) then // Debug state is a prohibited region, therefore ccu=1, cc=0, source_address=0 let branch_type : bits(6) = '111001'; let ccu : bit = '1'; let cc : bits(14) = Zeros{14}; let el : bits(2) = PSTATE.EL; let mispredict : bit = '0'; UpdateBranchRecordBuffer(ccu, cc, branch_type, el, mispredict, '01', Zeros{64}, target_address); PMUEvent(PMU_EVENT_BRB_FILTRATE); end; return; end;

Library pseudocode for aarch64/debug/brbe/BranchEncCycleCount

// BranchEncCycleCount() // ===================== // The first return result is '1' if either of the following is true, and '0' otherwise: // - This is the first Branch record after the PE exited a Prohibited Region. // - This is the first Branch record after cycle counting has been enabled. // If the first return return is '0', the second return result is the encoded cycle count // since the last branch. // The format of this field uses a mantissa and exponent to express the cycle count value. // - bits[7:0] indicate the mantissa M. // - bits[13:8] indicate the exponent E. // The cycle count is expressed using the following function: // cycle_count = (if IsZero(E) then UInt(M) else UInt('1'::M::Zeros{(UInt(E)-1}))))) // A value of all ones in both the mantissa and exponent indicates the cycle count value // exceeded the size of the cycle counter. // If the cycle count is not known, the second return result is zero. func BranchEncCycleCount() => (bit, bits(14)) begin var cc : integer = BranchRawCycleCount(); if !BRBCycleCountingEnabled() || FirstBranchAfterProhibited() then return ('1', Zeros{14}); end; // The format of this field uses a mantissa and exponent to express the cycle count value. // - bits[7:0] indicate the mantissa M. // - bits[13:8] indicate the exponent E. // The cycle count is expressed using the following function: // cycle_count = (if IsZero(E) then UInt(M) else UInt('1'::M::Zeros{(UInt(E)-1})))) // A value of all ones in both the mantissa and exponent indicates the cycle count value // exceeded the size of the cycle counter. var E : bits(6); var M : bits(8); if cc < 2^8 then E = Zeros{6}; M = cc[7:0]; elsif cc >= 2^20 then E = Ones{6}; M = Ones{8}; else E = 1[5:0]; while cc >= 2^9 looplimit 11 do E = E + 1; cc = cc DIVRM 2; end; M = cc[7:0]; end; return ('0', E::M); end;

Library pseudocode for aarch64/debug/breakpoint/AArch64_BreakpointValueMatch

// AArch64_BreakpointValueMatch() // ============================== // Returns breakpoint type to indicate the type of breakpoint and a boolean to indicate // whether the breakpoint matched successfully. For Address Mismatch breakpoints, the // returned boolean is the inverted result. If the breakpoint type return value is Inactive, // then the boolean result is FALSE. func AArch64_BreakpointValueMatch(n_in : integer, vaddress : bits(64), linked_to : boolean, isbreakpnt : boolean, from_linking_enabled : boolean ) => (BreakpointType, boolean) recurselimit 2 begin // "n_in" is the identity of the breakpoint unit to match against. // "vaddress" is the current instruction address, ignored if linked_to is TRUE and for Context // matching breakpoints. // "linked_to" is TRUE if this is a call from StateMatch for linking. // "isbreakpnt" TRUE is this is a call from BreakpointMatch or from StateMatch for a // linked breakpoint or from BreakpointValueMatch for a linked breakpoint with linking enabled. // "from_linking_enabled" is TRUE if this is a call from BreakpointValueMatch for a linked // breakpoint with linking enabled. var n : integer = n_in; var c : Constraint; var dbgtype : bits(5); // If a non-existent breakpoint then it is CONSTRAINED UNPREDICTABLE whether this gives // no match or the breakpoint is mapped to another UNKNOWN implemented breakpoint. if n >= NumBreakpointsImplemented() then (c, n) = ConstrainUnpredictableInteger(0, NumBreakpointsImplemented() - 1, Unpredictable_BPNOTIMPL); assert c IN {Constraint_DISABLED, Constraint_UNKNOWN}; if c == Constraint_DISABLED then return (BreakpointType_Inactive, FALSE); end; end; // If this breakpoint is not enabled, it cannot generate a match. // (This could also happen on a call from StateMatch for linking). if !IsBreakpointEnabled(n) then return (BreakpointType_Inactive, FALSE); end; // If BT is set to a reserved type, behaves either as disabled or as a not-reserved type. if IsFeatureImplemented(FEAT_ABLE) then dbgtype = DBGBCR_EL1(n).[BT2,BT]; else dbgtype = '0' :: DBGBCR_EL1(n).BT; end; (c, dbgtype) = AArch64_ReservedBreakpointType(n, dbgtype); if c == Constraint_DISABLED then return (BreakpointType_Inactive, FALSE); end; // Otherwise the value returned by ConstrainUnpredictableBits must be a not-reserved value // Determine what to compare against. let match_addr : boolean = (dbgtype == 'x0x0x'); let mismatch : boolean = (dbgtype == 'x010x'); let match_vmid : boolean = (dbgtype == 'x10xx'); let match_cid : boolean = (dbgtype == 'x001x'); let match_cid1 : boolean = (dbgtype IN {'x101x', 'xx11x'}); let match_cid2 : boolean = (dbgtype == 'x11xx'); let linking_enabled : boolean = (dbgtype IN {'xxx11', 'x1xx1', '1xxxx'}); // If this is a call from StateMatch, return FALSE if the breakpoint is not // programmed with linking enabled. if linked_to && !linking_enabled then return (BreakpointType_Inactive, FALSE); end; // If called from BreakpointMatch return FALSE for breakpoint with linking enabled. if !linked_to && linking_enabled then return (BreakpointType_Inactive, FALSE); end; let linked : boolean = (dbgtype == 'x0x01'); if from_linking_enabled then // A breakpoint with linking enabled has called this function. assert linked_to && isbreakpnt; if linked then // A breakpoint with linking enabled is linked to a linked breakpoint. This is // architecturally UNPREDICTABLE, but treated as disabled in the pseudo code to // avoid potential recursion in BreakpointValueMatch(). return (BreakpointType_Inactive, FALSE); end; end; // If a linked breakpoint is linked to an address matching breakpoint, // the behavior is CONSTRAINED UNPREDICTABLE. if linked_to && match_addr && isbreakpnt then if !ConstrainUnpredictableBool(Unpredictable_BPLINKEDADDRMATCH) then return (BreakpointType_Inactive, FALSE); end; end; // A breakpoint programmed for address mismatch does not match in AArch32 state. if mismatch && UsingAArch32() then return (BreakpointType_Inactive, FALSE); end; var bvr_match : boolean = FALSE; var bxvr_match : boolean = FALSE; var bp_type : BreakpointType; var mask : integer{0..31}; if IsFeatureImplemented(FEAT_BWE) then mask = UInt(DBGBCR_EL1(n).MASK); // If the mask is set to a reserved value, the behavior is CONSTRAINED UNPREDICTABLE. if mask IN {1, 2} then var unpred_mask : integer; (c, unpred_maskmask) = (ConstrainUnpredictableInteger(3, 31, Unpredictable_RESBPMASK);) as (Constraint, integer{3..31})); assert c IN {Constraint_DISABLED, Constraint_NONE, Constraint_UNKNOWN}; case c of when Constraint_DISABLED => return (BreakpointType_Inactive, FALSE); // Disabled when Constraint_NONE => mask = 0; // No masking // Otherwise the value returned by ConstrainUnpredictableBits must // be a not-reserved value. otherwise => mask = unpred_mask as integer{3..31}; end; end; if mask != 0 then // When DBGBCR_EL1(n).MASK is a valid nonzero value, the behavior is // CONSTRAINED UNPREDICTABLE if any of the following are true: // - DBGBCR_EL1(n).[BT2,BT] is programmed for a Context matching breakpoint. // - DBGBCR_EL1(n).BAS is not '1111' and AArch32 is supported at EL0. if ((match_cid || match_cid1 || match_cid2) || (DBGBCR_EL1(n).BAS != '1111' && HaveAArch32())) then if !ConstrainUnpredictableBool(Unpredictable_BPMASK) then return (BreakpointType_Inactive, FALSE); end; end; else // A stand-alone mismatch of a single address is not supported. if mismatch then return (BreakpointType_Inactive, FALSE); end; end; else mask = 0; end; // Do the comparison. if match_addr then var byte_select_match : boolean; let byte : integer = UInt(vaddress[1:0]); if HaveAArch32() then // T32 instructions can be executed at EL0 in an AArch64 translation regime. assert byte IN {0,2}; // "vaddress" is halfword aligned byte_select_match = (DBGBCR_EL1(n).BAS[byte] == '1'); else assert byte == 0; // "vaddress" is word aligned byte_select_match = TRUE; // DBGBCR_EL1(n).BAS[byte] is RES1 end; // When FEAT_LVA3 is not implemented, if the DBGBVR_EL1(n).RESS field bits are not a // sign extension of the MSB of DBGBVR_EL1(n).VA, it is UNPREDICTABLE whether they // appear to be included in the match. // If 'vaddress' is outside of the current virtual address space, then the access // generates a Translation fault. let dbgtop : AddressSize = DebugAddrTop(); let unpredictable_ress : boolean = (dbgtop < 55 && !IsOnes(DBGBVR_EL1(n)[63:dbgtop]) && !IsZero(DBGBVR_EL1(n)[63:dbgtop]) && ConstrainUnpredictableBool(Unpredictable_DBGxVR_RESS)); let cmpmsb : integer{} = if unpredictable_ress then 63 else dbgtop; let cmplsb : integer{} = if mask > 2 then mask else 2; bvr_match = ((vaddress[cmpmsb:cmplsb] == DBGBVR_EL1(n)[cmpmsb:cmplsb]) && byte_select_match); if mask > 2 then // If masked bits of DBGBVR_EL1(n) are not zero, the behavior // is CONSTRAINED UNPREDICTABLE. let masktop : integer{} = mask - 1; if bvr_match && !IsZero(DBGBVR_EL1(n)[masktop:2]) then bvr_match = ConstrainUnpredictableBool(Unpredictable_BPMASKEDBITS); end; end; elsif match_cid then if IsInHost() then bvr_match = (CONTEXTIDR_EL2()[31:0] == DBGBVR_EL1(n)[31:0]); else bvr_match = (PSTATE.EL IN {EL0, EL1} && CONTEXTIDR_EL1()[31:0] == DBGBVR_EL1(n)[31:0]); end; elsif match_cid1 then bvr_match = (PSTATE.EL IN {EL0, EL1} && !IsInHost() && CONTEXTIDR_EL1()[31:0] == DBGBVR_EL1(n)[31:0]); end; if match_vmid then let vmid : bits(16) = VMID(); var bvr_vmid : bits(16); if !IsFeatureImplemented(FEAT_VMID16) || VTCR_EL2().VS == '0' then bvr_vmid = ZeroExtend{16}(DBGBVR_EL1(n)[39:32]); else bvr_vmid = DBGBVR_EL1(n)[47:32]; end; bxvr_match = (PSTATE.EL IN {EL0, EL1} && EL2Enabled() && !IsInHost() && vmid == bvr_vmid); elsif match_cid2 then bxvr_match = (PSTATE.EL != EL3 && EL2Enabled() && DBGBVR_EL1(n)[63:32] == CONTEXTIDR_EL2()[31:0]); end; let bvr_match_valid : boolean = (match_addr || match_cid || match_cid1); let bxvr_match_valid : boolean = (match_vmid || match_cid2); var value_match : boolean = ((!bxvr_match_valid || bxvr_match) && (!bvr_match_valid || bvr_match)); // A watchpoint might be linked to a linked address matching breakpoint with linking enabled, // which is in turn linked to a context matching breakpoint. if linked_to && linked then // If called from StateMatch and breakpoint is a linked breakpoint then it must be a // watchpoint that is linked to an address matching breakpoint which is linked to a // context matching breakpoint. assert !isbreakpnt && match_addr && IsFeatureImplemented(FEAT_ABLE); let lbnx : bits(2) = (if IsFeatureImplemented(FEAT_Debugv8p9) then DBGBCR_EL1(n).LBNX else '00'); let linked_linked_n : integer{} = UInt(lbnx :: DBGBCR_EL1(n).LBN); var linked_value_match : boolean; let linked_vaddress = ARBITRARY : bits(64); let linked_linked_to = TRUE; let linked_isbreakpnt = TRUE; let linked_from_linking_enabled = TRUE; (bp_type, linked_value_match) = AArch64_BreakpointValueMatch(linked_linked_n, linked_vaddress, linked_linked_to, linked_isbreakpnt, linked_from_linking_enabled); value_match = value_match && linked_value_match; end; if match_addr && !mismatch then bp_type = BreakpointType_AddrMatch; elsif match_addr && mismatch then bp_type = BreakpointType_AddrMismatch; elsif match_vmid || match_cid || match_cid1 || match_cid2 then bp_type = BreakpointType_CtxtMatch; else unreachable; end; return (bp_type, value_match); end;

Library pseudocode for aarch64/debug/ebep

var inst_addr_executedsync_counter_overflowed : bits(64);boolean; varinst_addr_executed : bits(64);

Library pseudocode for aarch64/debug/statisticalprofiling/CheckMDCR_EL3_NSPBTrap

// CheckMDCR_EL3_NSPBTrap() // ======================== // Check if the register access is trappable by MDCR_EL3.[MDCR_EL3().[NSPBE, NSPB] func CheckMDCR_EL3_NSPBTrap() => boolean begin var state_bits : bits(3); var reserved : boolean; (state_bits, reserved) = EffectiveMDCR_EL3_NSPB(); return ((reserved && ConstrainUnpredictableBool(Unpredictable_RESERVEDNSxB_Trap)) || state_bits[0] == '0' || state_bits[1] != SCR_EL3().NS || (IsFeatureImplemented(FEAT_RME) && state_bits[2] != SCR_EL3().NSE)); end; EffectiveSCR_EL3_NS() || (IsFeatureImplemented(FEAT_RME) && state_bits[2] != EffectiveSCR_EL3_NSE())); end;

Library pseudocode for aarch64/debug/statisticalprofiling/EffectiveMDCR_EL3_NSPB

// EffectiveMDCR_EL3_NSPB() // ======================== // Return the Effective value of MDCR_EL3.[MDCR_EL3().[NSPBE, NSPB] field and whether it is a reserved value. readonly func EffectiveMDCR_EL3_NSPB() => (bits(3), boolean) begin var state_bits : bits(3); var reserved : boolean = FALSE; if IsFeatureImplemented(FEAT_RME) then state_bits = MDCR_EL3().[NSPBE, NSPB]; if state_bits == '10x' || (!IsFeatureImplemented(FEAT_Secure) && state_bits == '00x') then // Reserved value reserved = TRUE; (-, state_bits) = ConstrainUnpredictableBits{3}(Unpredictable_RESERVEDNSxB); end; else state_bits = '0' :: MDCR_EL3().NSPB; end; return (state_bits, reserved); end;

Library pseudocode for aarch64/debug/statisticalprofiling/SPEEvent

// SPEEvent() // ========== // Called when a PMU event is generated by the sampled structure. // Sets appropriate bit in SPESampleStorage.events. func SPEEvent(pmuevent : bits(16)) begin if !SPESampleInFlight then return; end; case pmuevent of when PMU_EVENT_DSNP_HIT_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[23] = '1'; // Snoop hit end; when {PMU_EVENT_L1D_LFB_HIT_RD, PMU_EVENT_L2D_LFB_HIT_RD, PMU_EVENT_L3D_LFB_HIT_RD, PMU_EVENT_LL_LFB_HIT_RD} => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[22] = '1'; // Recent fetch end; when {PMU_EVENT_L1D_CACHE_HITM_RD, PMU_EVENT_L2D_CACHE_HITM_RD, PMU_EVENT_L3D_CACHE_HITM_RD, PMU_EVENT_LL_CACHE_HITM_RD}PMU_EVENT_L2D_LFB_HIT_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[2122] = '1'; // ModifiedRecent fetch end; when PMU_EVENT_L2D_CACHE_LMISS_RDPMU_EVENT_L3D_LFB_HIT_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[2022] = '1'; // L2Recent missfetch end; when PMU_EVENT_L2D_CACHE_RDPMU_EVENT_LL_LFB_HIT_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[1922] = '1'; // L2Recent accessfetch end; when PMU_EVENT_SVE_PRED_EMPTY_SPECPMU_EVENT_L1D_CACHE_HITM_RD => if IsFeatureImplemented(FEAT_SPEv1p1FEAT_SPEv1p4) then SPESampleEvents[1821] = '1'; // Empty predicateModified end; when PMU_EVENT_SVE_PRED_NOT_FULL_SPECPMU_EVENT_L2D_CACHE_HITM_RD => if IsFeatureImplemented(FEAT_SPEv1p1FEAT_SPEv1p4) then SPESampleEvents[1721] = '1'; // Partial predicateModified end; when PMU_EVENT_LDST_ALIGN_LATPMU_EVENT_L3D_CACHE_HITM_RD => if IsFeatureImplemented(FEAT_SPEv1p1FEAT_SPEv1p4) then SPESampleEvents[1121] = '1'; // MisalignedModified end; when PMU_EVENT_REMOTE_ACCESSPMU_EVENT_LL_CACHE_HITM_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[1021] = '1'; // Remote accessModified end; when PMU_EVENT_LL_CACHE_MISSPMU_EVENT_L2D_CACHE_LMISS_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[920] = '1'; // LLCL2 miss end; when PMU_EVENT_LL_CACHEPMU_EVENT_L2D_CACHE_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[819] = '1'; // LLCL2 access end; when PMU_EVENT_BR_MIS_PREDPMU_EVENT_SVE_PRED_EMPTY_SPEC => if IsFeatureImplemented(FEAT_SPEv1p1) then SPESampleEvents[718] = '1'; // MispredictedEmpty predicate end; when PMU_EVENT_BR_MIS_PRED_RETIREDPMU_EVENT_SVE_PRED_NOT_FULL_SPEC => if IsFeatureImplemented(FEAT_SPEv1p1) then SPESampleEvents[717] = '1'; // NotPartial takenpredicate end; when PMU_EVENT_DTLB_WALKPMU_EVENT_LDST_ALIGN_LAT => if IsFeatureImplemented(FEAT_SPEv1p1) then SPESampleEvents[511] = '1'; // TLB walkMisaligned end; when PMU_EVENT_L1D_TLBPMU_EVENT_REMOTE_ACCESS => SPESampleEvents[410] = '1'; // TLBRemote access when PMU_EVENT_L1D_CACHE_REFILLPMU_EVENT_LL_CACHE_MISS => if !IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[39] = '1'; // L1LLC refill end;miss when PMU_EVENT_L1D_CACHE_LMISS_RDPMU_EVENT_LL_CACHE => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[38] = '1'; // L1LLC miss end;access when PMU_EVENT_L1D_CACHEPMU_EVENT_BR_MIS_PRED => SPESampleEvents[27] = '1'; // L1 accessMispredicted when PMU_EVENT_INST_RETIREDPMU_EVENT_BR_MIS_PRED_RETIRED => SPESampleEvents[17] = '1'; // RetireNot taken when PMU_EVENT_EXC_TAKENPMU_EVENT_DTLB_WALK => SPESampleEvents[05] = '1'; // ExceptionTLB walk otherwisewhen PMU_EVENT_L1D_TLB => return; end; return; end;SPESampleEvents[4] = '1'; // TLB access when PMU_EVENT_L1D_CACHE_REFILL => if !IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[3] = '1'; // L1 refill end; when PMU_EVENT_L1D_CACHE_LMISS_RD => if IsFeatureImplemented(FEAT_SPEv1p4) then SPESampleEvents[3] = '1'; // L1 miss end; when PMU_EVENT_L1D_CACHE => SPESampleEvents[2] = '1'; // L1 access when PMU_EVENT_INST_RETIRED => SPESampleEvents[1] = '1'; // Retire when PMU_EVENT_EXC_TAKEN => SPESampleEvents[0] = '1'; // Exception otherwise => return; end; return; end;

Library pseudocode for aarch64/debug/takeexceptiondbg/AArch64_TakeExceptionInDebugState

// AArch64_TakeExceptionInDebugState() // =================================== // Take an exception in Debug state to an Exception level using AArch64. noreturn func AArch64_TakeExceptionInDebugState(target_el : bits(2), exception_in : ExceptionRecord) begin assert HaveEL(target_el) && !ELUsingAArch32(target_el) && UInt(target_el) >= UInt(PSTATE.EL); assert target_el !=PSTATE.EL); assert target_el != EL3 || EDSCR().SDD == '0'; var except : ExceptionRecord = exception_in; var sync_errors : boolean; if IsFeatureImplemented(FEAT_IESB) then sync_errors = SCTLR_EL(target_el).IESB == '1'; if IsFeatureImplemented(FEAT_DoubleFault) then sync_errors = sync_errors || (SCR_EL3().[EA,NMEA] == '11' && target_el == EL3); end; // The Effective value of SCTLR[].IESB might be zero in Debug state. if !ConstrainUnpredictableBool(Unpredictable_IESBinDebug) then sync_errors = FALSE; end; else sync_errors = FALSE; end; if !IsFeatureImplemented(FEAT_ExS) || SCTLR_EL(target_el).EIS == '1' then // Synchronize the context, including Instruction Fetch Barrier effect SynchronizeContext(); end; // If coming from AArch32 state, the top parts of the X()[] registers might be set to zero let from_32 : boolean = UsingAArch32(); if from_32 then AArch64_MaybeZeroRegisterUppers(); end; if from_32 && IsFeatureImplemented(FEAT_SME) && PSTATE.SM == '1' then ResetSVEState(); else MaybeZeroSVEUppers(target_el); end; AArch64_ReportException(except, target_el); if IsFeatureImplemented(FEAT_GCS) then PSTATE.EXLOCK = '0'; // Effective value of GCSCR_ELx.EXLOCKEN is 0 in Debug state end; PSTATE.EL = target_el; PSTATE.nRW = '0'; PSTATE.SP = '1'; PSTATE.SM == '1' then ResetSVEState(); else MaybeZeroSVEUppers(target_el); end; AArch64_ReportException(except, target_el); if IsFeatureImplemented(FEAT_GCS) then PSTATE.EXLOCK = '0'; // Effective value of GCSCR_ELx.EXLOCKEN is 0 in Debug state end; PSTATE.EL = target_el; PSTATE.nRW = '0'; PSTATE.SP = '1'; SPSR_ELx() = ARBITRARY : bits(64); ELR_ELx() = ARBITRARY : bits(64); // PSTATE.[SS,D,A,I,F] are not observable and ignored in Debug state, so behave as if UNKNOWN. PSTATE.[SS,D,A,I,F] = ARBITRARY : bits(5); if IsFeatureImplemented(FEAT_SSBS) then PSTATE.SSBS = ARBITRARY : bit; end; if IsFeatureImplemented(FEAT_EBEP) then PSTATE.PM = ARBITRARY : bit; end; if IsFeatureImplemented(FEAT_SEBEP) then PSTATE.PPEND = '0'; end; if IsFeatureImplemented(FEAT_MTE) then PSTATE.TCO = '1'; end; PSTATE.IL = '0'; if IsFeatureImplemented(FEAT_UAO) then PSTATE.UAO = '0'; end; if IsFeatureImplemented(FEAT_UINJ) then PSTATE.UINJ = '0'; end; if IsFeatureImplemented(FEAT_PAuth_LR) then PSTATE.PACM = '0'; end; if (IsFeatureImplemented(FEAT_PAN) && (PSTATE.EL == PSTATE.SSBS = ARBITRARY : bit; end; if IsFeatureImplemented(FEAT_EBEP) then PSTATE.PM = ARBITRARY : bit; end; if IsFeatureImplemented(FEAT_SEBEP) then PSTATE.PPEND = '0'; end; if IsFeatureImplemented(FEAT_MTE) then PSTATE.TCO = '1'; end; PSTATE.IL = '0'; if IsFeatureImplemented(FEAT_UAO) then PSTATE.UAO = '0'; end; if IsFeatureImplemented(FEAT_UINJ) then PSTATE.UINJ = '0'; end; if IsFeatureImplemented(FEAT_PAuth_LR) then PSTATE.PACM = '0'; end; if (IsFeatureImplemented(FEAT_PAN) && (PSTATE.EL == EL1 || (PSTATE.EL ==PSTATE.EL == EL2 && ELIsInHost(EL0))) && SCTLR_ELx().SPAN == '0') then PSTATE.PAN = '1'; end; if from_32 then // Coming from AArch32 PSTATE.IT = '00000000'; PSTATE.T = '0'; // PSTATE.J is RES0 end; if IsFeatureImplemented(FEAT_BTI) then PSTATE.BTYPE().SPAN == '0') then PSTATE.PAN = '1'; end; if from_32 then // Coming from AArch32 PSTATE.IT = '00000000'; PSTATE.T = '0'; // PSTATE.J is RES0 end; if IsFeatureImplemented(FEAT_BTI) then PSTATE.BTYPE = '00'; end; DLR_EL0() = ARBITRARY : bits(64); DSPSR_EL0() = ARBITRARY : bits(64); EDSCR().ERR = '1'; UpdateEDSCRFields(); // Update EDSCR PE state flags. if sync_errors then SynchronizeErrors(); end; EndOfInstruction(); end;

Library pseudocode for aarch64/debug/watchpoint/AArch64_WatchpointByteMatch

// AArch64_WatchpointByteMatch() // ============================= func AArch64_WatchpointByteMatch(n : integer, vaddress : bits(64)) => boolean begin let dbgtop : AddressSize = DebugAddrTop(); let cmpbottom : integer{} = if DBGWVR_EL1(n)[2] == '1' then 2 else 3;// Word or doubleword var bottom : integer{} = cmpbottom; let select : integer{} = UInt(vaddress[cmpbottom-1:0]); var byte_select_match : boolean = (DBGWCR_EL1(n).BAS[select] != '0'); var mask : integer{} = UInt(DBGWCR_EL1(n).MASK); // If DBGWCR_EL1(n).MASK is a nonzero value and DBGWCR_EL1(n).BAS is not set to '11111111', or // DBGWCR_EL1(n).BAS specifies a non-contiguous set of bytes behavior is CONSTRAINED // UNPREDICTABLE. if mask > 0 && !IsOnes(DBGWCR_EL1(n).BAS) then byte_select_match = ConstrainUnpredictableBool(Unpredictable_WPMASKANDBAS); else let LSB : bits(8) = (DBGWCR_EL1(n).BAS AND NOT(DBGWCR_EL1(n).BAS - 1)); let MSB : bits(8) = (DBGWCR_EL1(n).BAS + LSB); if !IsZero(MSB AND (MSB - 1)) then // Not contiguous byte_select_match = ConstrainUnpredictableBool(Unpredictable_WPBASCONTIGUOUS); bottom = 3; // For the whole doubleword end; end; // If the address mask is set to a reserved value, the behavior is CONSTRAINED UNPREDICTABLE. if mask > 0 && mask <= 2 then var c : Constraint; var unpred_mask : integer; (c, unpred_maskmask) = (ConstrainUnpredictableInteger(3, 31, Unpredictable_RESWPMASK);) as (Constraint, integer{0..31})); assert c IN {Constraint_DISABLED, Constraint_NONE, Constraint_UNKNOWN}; case c of when Constraint_DISABLED => return FALSE; // Disabled when Constraint_NONE => mask = 0; // No masking // Otherwise the value returned by ConstrainUnpredictableInteger is a not-reserved value otherwise => mask = unpred_mask as integer{3..31}; end; end; // When FEAT_LVA3 is not implemented, if the DBGWVR_EL1(n).RESS field bits are not a // sign extension of the MSB of DBGWVR_EL1(n).VA, it is UNPREDICTABLE whether they // appear to be included in the match. let unpredictable_ress : boolean = (dbgtop < 55 && !IsOnes(DBGWVR_EL1(n)[63:dbgtop]) && !IsZero(DBGWVR_EL1(n)[63:dbgtop]) && ConstrainUnpredictableBool(Unpredictable_DBGxVR_RESS)); let cmpmsb : integer{} = if unpredictable_ress then 63 else dbgtop; let cmplsb : integer{} = if mask > bottom then mask else bottom; let bottombit : integer{} = bottom; var WVR_match : boolean = (vaddress[cmpmsb:cmplsb] == DBGWVR_EL1(n)[cmpmsb:cmplsb]); if mask > bottom then // If masked bits of DBGWVR_EL1(n) are not zero, the behavior is CONSTRAINED UNPREDICTABLE. if WVR_match && !IsZero(DBGWVR_EL1(n)[cmplsb-1:bottombit]) then WVR_match = ConstrainUnpredictableBool(Unpredictable_WPMASKEDBITS); end; end; return (WVR_match && byte_select_match); end;

Library pseudocode for aarch64/exceptions/async/AArch64_TakePhysicalFIQException

// AArch64_TakePhysicalFIQException() // ================================== func AArch64_TakePhysicalFIQException() begin let route_to_el3 : boolean = EffectiveSCR_EL3_FIQHaveEL() == '1'; let route_to_el2 : boolean = (PSTATEEL3.EL) && SCR_EL3().FIQ == '1'; let route_to_el2 : boolean = (PSTATE.EL IN {EL0, EL1} && EL2Enabled() && (HCR_EL2().TGE == '1' || HCR_EL2().FMO == '1')); let preferred_exception_return : bits(64) = ThisInstrAddr{}(); let vect_offset : integer = 0x100; let except : ExceptionRecord = ExceptionSyndrome(Exception_FIQ); if route_to_el3 then AArch64_TakeException(EL3, except, preferred_exception_return, vect_offset); elsif PSTATE.EL == PSTATE.EL == EL2 || route_to_el2 then assert PSTATE.EL != PSTATE.EL != EL3; AArch64_TakeException(EL2, except, preferred_exception_return, vect_offset); else assert PSTATE.EL, except, preferred_exception_return, vect_offset); else assert PSTATE.EL IN {EL0, EL1}; AArch64_TakeException(EL1, except, preferred_exception_return, vect_offset); end; end;

Library pseudocode for aarch64/exceptions/async/AArch64_TakePhysicalIRQException

// AArch64_TakePhysicalIRQException() // ================================== // Take an enabled physical IRQ exception. func AArch64_TakePhysicalIRQException() begin let route_to_el3 : boolean = EffectiveSCR_EL3_IRQHaveEL() == '1'; let route_to_el2 : boolean = (PSTATEEL3.EL) && SCR_EL3().IRQ == '1'; let route_to_el2 : boolean = (PSTATE.EL IN {EL0, EL1} && EL2Enabled() && (HCR_EL2().TGE == '1' || HCR_EL2().IMO == '1')); let preferred_exception_return : bits(64) = ThisInstrAddr{}(); let vect_offset : integer = 0x80; let except : ExceptionRecord = ExceptionSyndrome(Exception_IRQ); if route_to_el3 then AArch64_TakeException(EL3, except, preferred_exception_return, vect_offset); elsif PSTATE.EL == PSTATE.EL == EL2 || route_to_el2 then assert PSTATE.EL != PSTATE.EL != EL3; AArch64_TakeException(EL2, except, preferred_exception_return, vect_offset); else assert PSTATE.EL, except, preferred_exception_return, vect_offset); else assert PSTATE.EL IN {EL0, EL1}; AArch64_TakeException(EL1, except, preferred_exception_return, vect_offset); end; end;

Library pseudocode for aarch64/exceptions/takeexception/AArch64_TakeException

// AArch64_TakeException() // ======================= // Take an exception to an Exception level using AArch64. noreturn func AArch64_TakeException(target_el : bits(2), exception_in : ExceptionRecord, preferred_exception_return : bits(64), vect_offset_in : integer) begin assert HaveEL(target_el) && !ELUsingAArch32(target_el) && UInt(target_el) >= UInt(PSTATE.EL); ifPSTATE.EL); if Halted() then AArch64_TakeExceptionInDebugState(target_el, exception_in); end; var except : ExceptionRecord = exception_in; var sync_errors : boolean; var iesb_req : boolean; if IsFeatureImplemented(FEAT_IESB) then sync_errors = SCTLR_EL(target_el).IESB == '1'; if IsFeatureImplemented(FEAT_DoubleFault) then sync_errors = sync_errors || (SCR_EL3().[EA,NMEA] == '11' && target_el == EL3); end; if sync_errors && InsertIESBBeforeException(target_el) then SynchronizeErrors(); if except.exceptype != Exception_SError then iesb_req = FALSE; sync_errors = FALSE; TakeUnmaskedPhysicalSErrorInterrupts(iesb_req); end; end; else sync_errors = FALSE; end; var brbe_source_allowed : boolean = FALSE; var brbe_source_address : bits(64) = Zeros{}; if IsFeatureImplemented(FEAT_BRBE) then brbe_source_allowed = BranchRecordAllowed(PSTATE.EL); brbe_source_address = preferred_exception_return; end; if !IsFeatureImplemented(FEAT_ExS) ||PSTATE.EL); brbe_source_address = preferred_exception_return; end; if !IsFeatureImplemented(FEAT_ExS) || SCTLR_EL(target_el).EIS == '1' then // Synchronize the context, including Instruction Fetch Barrier effect SynchronizeContext(); elsif !(except.exceptype == Exception_SoftwareBreakpoint || (except.exceptype IN {Exception_SupervisorCall, Exception_HypervisorCall, Exception_MonitorCall} && !except.trappedsyscallinst)) then InstructionFetchBarrier(); end; // If coming from AArch32 state, the top parts of the X()[] registers might be set to zero let from_32 : boolean = UsingAArch32(); if from_32 then AArch64_MaybeZeroRegisterUppers(); end; if from_32 && IsFeatureImplemented(FEAT_SME) && PSTATE.SM == '1' then ResetSVEState(); else MaybeZeroSVEUppers(target_el); end; var vect_offset : integer = vect_offset_in; if UInt(target_el) > UInt(PSTATE.EL) then var lower_32 : boolean; if target_el == PSTATE.SM == '1' then ResetSVEState(); else MaybeZeroSVEUppers(target_el); end; var vect_offset : integer = vect_offset_in; if UInt(target_el) > UInt(PSTATE.EL) then var lower_32 : boolean; if target_el == EL3 then if EL2Enabled() then lower_32 = ELUsingAArch32(EL2); else lower_32 = ELUsingAArch32(EL1); end; elsif IsInHost() && PSTATE.EL == PSTATE.EL == EL0 && target_el == EL2 then lower_32 = ELUsingAArch32(EL0); else lower_32 = ELUsingAArch32(target_el - 1); end; vect_offset = vect_offset + (if lower_32 then 0x600 else 0x400); elsif PSTATE.SP == '1' then vect_offset = vect_offset + 0x200; end; var spsr : bits(64) = GetPSRFromPSTATE{}( PSTATE.SP == '1' then vect_offset = vect_offset + 0x200; end; assert vect_offset < 2048; let vect_base : bits(64) = VBAR_EL(target_el)[63:11]::Zeros{11}; let target_vector : bits(64) = vect_base + vect_offset; var spsr : bits(64) = GetPSRFromPSTATE{}(AArch64_NonDebugState); if PSTATE.EL == PSTATE.EL == EL1 && target_el == EL1 && EL2Enabled() then if EffectiveHCR_EL2_NVx() IN {'x01', '111'} then spsr[3:2] = '10'; end; end; if IsFeatureImplemented(FEAT_BTI) && !UsingAArch32() then var zero_btype : boolean; // SPSR_ELx[].BTYPE is only guaranteed valid for these exception types if except.exceptype IN {Exception_SError, Exception_IRQ, Exception_FIQ, Exception_SoftwareStep, Exception_PCAlignment, Exception_InstructionAbort, Exception_Breakpoint, Exception_VectorCatch, Exception_SoftwareBreakpoint, Exception_IllegalState, Exception_BranchTarget} then zero_btype = FALSE; else zero_btype = ConstrainUnpredictableBool(Unpredictable_ZEROBTYPE); end; if zero_btype then spsr[11:10] = '00'; end; end; if (IsFeatureImplemented(FEAT_NV2) && except.exceptype == Exception_NV2DataAbort && target_el == EL3) then // External aborts are configured to be taken to EL3 except.exceptype = Exception_DataAbort; end; if ! except.exceptype IN {Exception_IRQ, Exception_FIQ} then AArch64_ReportException(except, target_el); end; if IsFeatureImplemented(FEAT_BRBE) then BRBEException(except,let brbe_source_allowed,brbe_target_address brbe_source_address, target_vector,: target_el, except.trappedsyscallinst); end; if IsFeatureImplementedbits(FEAT_GCS64) then if= PSTATEVBAR_EL.EL(target_el)[63:11]::vect_offset[10:0]; BRBEException(except, brbe_source_allowed, brbe_source_address, brbe_target_address, target_el, except.trappedsyscallinst); end; if IsFeatureImplemented(FEAT_GCS) then if PSTATE.EL == target_el then if GetCurrentEXLOCKEN() then PSTATE.EXLOCK = '1'; else PSTATE.EXLOCK = '0'; end; else PSTATE.EXLOCK = '0'; end; end; PSTATE.EL = target_el; PSTATE.nRW = '0'; PSTATE.SP = '1'; PSTATE.EXLOCK = '1'; else PSTATE.EXLOCK = '0'; end; else PSTATE.EXLOCK = '0'; end; end; PSTATE.EL = target_el; PSTATE.nRW = '0'; PSTATE.SP = '1'; SPSR_ELx() = spsr; ELR_ELx() = preferred_exception_return; PSTATE.SS = '0'; if IsFeatureImplemented(FEAT_SSBS) then PSTATE.SSBS = PSTATE.SS = '0'; if IsFeatureImplemented(FEAT_SSBS) then PSTATE.SSBS = SCTLR_ELx().DSSBS; end; if IsFeatureImplemented(FEAT_EBEP) then PSTATE.PM = '1'; end; if IsFeatureImplemented(FEAT_SEBEP) then PSTATE.PPEND = '0'; PSTATE.PM = '1'; end; if IsFeatureImplemented(FEAT_SEBEP) then PSTATE.PPEND = '0'; ShouldSetPPEND = FALSE; end; if IsFeatureImplemented(FEAT_NMI) then PSTATE.ALLINT = NOT PSTATE.ALLINT = NOT SCTLR_ELx().SPINTMASK; end; PSTATE.[D,A,I,F] = '1111'; if IsFeatureImplemented(FEAT_MTE) then PSTATE.TCO = '1'; end; PSTATE.IL = '0'; if IsFeatureImplemented(FEAT_UAO) then PSTATE.UAO = '0'; end; if IsFeatureImplemented(FEAT_UINJ) then PSTATE.UINJ = '0'; end; if IsFeatureImplemented(FEAT_PAuth_LR) then PSTATE.PACM = '0'; end; if (IsFeatureImplemented(FEAT_PAN) && (PSTATE.EL == PSTATE.TCO = '1'; end; PSTATE.IL = '0'; if IsFeatureImplemented(FEAT_UAO) then PSTATE.UAO = '0'; end; if IsFeatureImplemented(FEAT_UINJ) then PSTATE.UINJ = '0'; end; if IsFeatureImplemented(FEAT_PAuth_LR) then PSTATE.PACM = '0'; end; if (IsFeatureImplemented(FEAT_PAN) && (PSTATE.EL == EL1 || (PSTATE.EL ==PSTATE.EL == EL2 && ELIsInHost(EL0))) && SCTLR_ELx().SPAN == '0') then PSTATE.PAN = '1'; end; if from_32 then // Coming from AArch32 PSTATE.IT = '00000000'; PSTATE.T = '0'; // PSTATE.J is RES0 end; if IsFeatureImplemented(FEAT_BTI) then PSTATE.BTYPE = '00'; end; let branch_conditional : boolean = FALSE; BranchTo{64}( PSTATEVBAR_ELx.PAN = '1'; end; if from_32 then // Coming from AArch32 PSTATE.IT = '00000000'; PSTATE.T = '0'; // PSTATE.J is RES0 end; if IsFeatureImplemented(FEAT_BTI) then PSTATE.BTYPE = '00'; end; let branch_conditional ()[63: boolean = FALSE; BranchTo{64}(target_vector,11]::vect_offset[10:0], BranchType_EXCEPTION, branch_conditional); CheckExceptionCatch(TRUE); // Check for debug event on exception entry if sync_errors then SynchronizeErrors(); iesb_req = TRUE; TakeUnmaskedPhysicalSErrorInterrupts(iesb_req); end; EndOfInstruction(); end;

Library pseudocode for aarch64/exceptions/traps/WaitForEventUntilDelay

// WaitForEventUntilDelay() // ======================== // Returns TRUE if WaitForEvent() returns before WFE trap delay expires, including potentially // some IMPLEMENTATION SPECIFIC additional delay, FALSE otherwise. impdef func WaitForEventUntilDelay(delay_enabled : boolean, delay : integer) => boolean begin return FALSE; end;

Library pseudocode for aarch64/functions/bitmasks/AltDecodeBitMasks

// AltDecodeBitMasks() // =================== // Alternative but logically equivalent implementation of DecodeBitMasks() that // uses simpler primitives to compute tmask and wmask. func AltDecodeBitMasks{M}(immN : bit, imms : bits(6), immr : bits(6), immediate : boolean) => (bits(M), bits(M)) begin var tmask, wmask : bits(64); var tmask_and, wmask_and : bits(6); var tmask_or, wmask_or : bits(6); var levels : bits(6); // Compute log2 of element size // 2^len must be in range [2, M] if immN::NOT(imms) == '000000x' then Undefined(); end; let len : integer{} = HighestSetBitNZ(immN::NOT(imms)); assert 2 <= (2^len) && (2^len) <= M; // Determine s, r and s - r parameters levels = ZeroExtend{6}(Ones{len}); // For logical immediates an all-ones value of s is reserved // since it would generate a useless all-ones result (many times) if immediate && (imms AND levels) == levels then Undefined(); end; let s : integer{} = UInt(imms AND levels); let r : integer{} = UInt(immr AND levels); let diff : integer{} = s - r; // 6-bit subtract with borrow // Compute "top mask" tmask_and = diff[5:0] OR NOT(levels); tmask_or = diff[5:0] AND levels; tmask = Ones{64}; tmask = ((tmask AND Replicate{64, 2}(Replicate{1}(tmask_and[0]) :: Ones{1})) OR Replicate{64, 2}(Zeros{1} :: Replicate{1}(tmask_or[0]))); // optimization of first step: // tmask = Replicate{64}(tmask_and[0] :: '1'); tmask = ((tmask AND Replicate{64, 4}(Replicate{2}(tmask_and[1]) :: Ones{2})) OR Replicate{64, 4}(Zeros{2} :: Replicate{2}(tmask_or[1]))); tmask = ((tmask AND Replicate{64, 8}(Replicate{4}(tmask_and[2]) :: Ones{4})) OR Replicate{64, 8}(Zeros{4} :: Replicate{4}(tmask_or[2]))); tmask = ((tmask AND Replicate{64, 16}(Replicate{8}(tmask_and[3]) :: Ones{8})) OR Replicate{64, 16}(Zeros{8} :: Replicate{8}(tmask_or[3]))); tmask = ((tmask AND Replicate{64, 32}(Replicate{16}(tmask_and[4]) :: Ones{16})) OR Replicate{64, 32}(Zeros{16} :: Replicate{16}(tmask_or[4]))); tmask = ((tmask AND Replicate{64, 64}(Replicate{32}(tmask_and[5]) :: Ones{32})) OR Replicate{64, 64}(Zeros{32} :: Replicate{32}(tmask_or[5]))); // Compute "wraparound mask" wmask_and = immr OR NOT(levels); wmask_or = immr AND levels; wmask = Zeros{64}; wmask = ((wmask AND Replicate{64, 2}(Ones{1} :: Replicate{1}(wmask_and[0]))) OR Replicate{64, 2}(Replicate{1}(wmask_or[0]) :: Zeros{1})); // wmask = Replicate{64}((wmask_or[0] ::: '0');', 32); wmask = ((wmask AND Replicate{64, 4}(Ones{2} :: Replicate{2}(wmask_and[1]))) OR Replicate{64, 4}(Replicate{2}(wmask_or[1]) :: Zeros{2})); wmask = ((wmask AND Replicate{64, 8}(Ones{4} :: Replicate{4}(wmask_and[2]))) OR Replicate{64, 8}(Replicate{4}(wmask_or[2]) :: Zeros{4})); wmask = ((wmask AND Replicate{64, 16}(Ones{8} :: Replicate{8}(wmask_and[3]))) OR Replicate{64, 16}(Replicate{8}(wmask_or[3]) :: Zeros{8})); wmask = ((wmask AND Replicate{64, 32}(Ones{16} :: Replicate{16}(wmask_and[4]))) OR Replicate{64, 32}(Replicate{16}(wmask_or[4]) :: Zeros{16})); wmask = ((wmask AND Replicate{64, 64}(Ones{32} :: Replicate{32}(wmask_and[5]))) OR Replicate{64, 64}(Replicate{32}(wmask_or[5]) :: Zeros{32})); if diff[6] != '0' then // borrow from s - r wmask = wmask AND tmask; else wmask = wmask OR tmask; end; return (wmask[M-1:0], tmask[M-1:0]); end;

Library pseudocode for aarch64/functions/cache/AArch64_WriteTagMem

// AArch64_WriteTagMem() // ===================== // Write to tag memory. func AArch64_WriteTagMem(regval : bits(64), cachetypevaddress : bits(64), accdesc_in : CacheType, accdesc_in : AccessDescriptor, size : integer) begin assert accdesc_in.tagaccess && !accdesc_in.tagchecked; var accdesc : AccessDescriptor = accdesc_in; let vaddress : bits(64) = AlignDownSize{64}(regval, size as integer{16..2048}); let count : integer = size >> LOG2_TAG_GRANULE; var tag : bits(4); if cachetype == CacheType_TagZero then ; let tag =: '0000'; else tag bits(4) = AArch64_AllocationTagFromAddress(vaddress); end; let aligned : boolean = IsAlignedSize{64}(vaddress, TAG_GRANULE); assert aligned; accdesc.tagaccess = IsMTEEnabled(accdesc.el); var (memtagtype, memaddrdesc) = AArch64_TranslateTagAddress(vaddress, accdesc, aligned, size); // Check for aborts or debug exceptions if IsFault(memaddrdesc) then if IsDebugException(memaddrdesc.fault) then AArch64_Abort(memaddrdesc.fault); else memaddrdesc.fault.vaddress = regval; AArch64_Abort(memaddrdesc.fault); end; end; if !accdesc.tagaccess || memtagtype != MemTag_AllocationTagged then return; end; var memstatus : PhysMemRetStatus; for i = 0 to count-1 do memstatus = PhysMemTagWrite(memaddrdesc, accdesc, tag); if IsFault(memstatus) then HandleExternalWriteAbort(memstatus, memaddrdesc, 1, accdesc); end; memaddrdesc.paddress.address = memaddrdesc.paddress.address + TAG_GRANULE; memaddrdesc.vaddress = memaddrdesc.vaddress + TAG_GRANULE; end; return; end;

Library pseudocode for aarch64/functions/dc/AArch64_MemZero

// AArch64_MemZero() // ================= func AArch64_MemZero(regval : bits(64), cachetype : CacheType) begin let size : integer{} = (if cachetype IN {CacheType_TagWrite, CacheType_TagZero} then 4*(2^(UInt(DCZID_EL0().TBS))) else 4*(2^(UInt(DCZID_EL0().BS)))); assert size <= MAX_ZERO_BLOCK_SIZE; if IsFeatureImplemented(FEAT_MTE2) then assert size >= TAG_GRANULE; end; let vaddress : bits(64) = AlignDownSize{}(regval, size); let accdesc : AccessDescriptor = CreateAccDescDCZero(cachetype); if cachetype !=IN { } then AArch64_WriteTagMem(Zeros{64}, vaddress, accdesc, size); end; if cachetype IN {CacheType_Tag, CacheType_TagWrite, CacheType_Data_TagCacheType_DataCacheType_TagZero } then AArch64_WriteTagMem(regval, cachetypevaddress, accdesc, size); end; if cachetype IN {CacheType_Data, CacheType_Data_Tag} then AArch64_DataMemZero(regval, vaddress, accdesc, size); end; return; end;

Library pseudocode for aarch64/functions/ic/AArch64_EffectiveOpScopeAArch64_IC

// AArch64_EffectiveOpScopeAArch64_IC() // ====================================== // Perform Instruction Cache Operation. func AArch64_IC(opscope : AArch64_EffectiveOpScope(opscope_in : CacheOpScope) begin let =>regval : bits(64) = ARBITRARY : bits(64); AArch64_IC(regval, opscope); end; // AArch64_IC() // ============ // Perform Instruction Cache Operation. func AArch64_IC(regval : bits(64), opscope : CacheOpScope ) begin var opscopecache : CacheOpScopeCacheRecord = opscope_in; ifcache.acctype = PSTATEAccessType_IC.EL; cache.cachetype !== EL1CacheType_Instruction then return opscope; end; if IsFeatureImplemented(FEAT_TLBID) then var fnb : bit; if cache.cacheop = IsHCRXEL2EnabledCacheOp_Invalidate(); cache.opscope = &&opscope; if (!opscope IN {HaveEL(EL3) || SCR_EL3().VTLBIDEn == '1') then fnb = HCRX_EL2().FNB; else fnb = '0'; end; case fnb::HCR_EL2().FB of when '00' => pass; when '01' => if opscope == CacheOpScope_ALLU then // The operation is broadcast within the Inner Shareable shareability domain. opscope =, CacheOpScope_ALLUISCacheOpScope_ALLUIS_CnP; end; when '10' => if opscope ==, CacheOpScope_ALLUIS } then // let Thess operation only affects the PE on which the instruction is executed. opscope =: SecurityState = SecurityStateAtEL(PSTATE.EL); cache.cpas = CPASAtSecurityState(ss); case opscope of when CacheOpScope_ALLU; end; when '11' => ifcache.shareability opscope === Shareability_NSH; when CacheOpScope_ALLUIS then // The operation is broadcast to PEs which would share TLB entries with the // current PE if CnP were 1. opscope=> cache.shareability = Shareability_ISH; // When executed at EL1, if the Effective value of HCRX_EL2.VTLBIDEn is '1', // then the operation is broadcast to the set of PEs selected by VTLBID0_EL2.TD0. // Otherwise, the operation is broadcast to all PEs in the Shareability domain. cache.domains = TLBIDomains(Broadcast_ISH, Zeros{16}); when CacheOpScope_ALLUIS_CnP;=> end; end; else ifcache.shareability opscope === CacheOpScope_ALLUShareability_ISH &&; cache.domains = DEFAULT_TLBI_DOMAIN; otherwise => unreachable; end; cache.regval = regval; CACHE_OP(cache); else assert opscope == CacheOpScope_PoU; if EL2Enabled() && HCR_EL2().FB == '1' then opscope =! () then if PSTATE.EL IN {EL0, EL1} then cache.is_vmid_valid = TRUE; cache.vmid = VMID(); else cache.is_vmid_valid = FALSE; end; else cache.is_vmid_valid = FALSE; end; if PSTATE.EL == EL0 then cache.is_asid_valid = TRUE; cache.asid = ASID(); else cache.is_asid_valid = FALSE; end; let vaddress : bits(64) = regval; cache.vaddress = regval; let accdesc : AccessDescriptor = CreateAccDescIC(cache); let aligned : boolean = TRUE; let size : integer = 0; var memaddrdesc : AddressDescriptor = AArch64_TranslateAddress(vaddress, accdesc, aligned, size); if IsFault(memaddrdesc) then memaddrdesc.fault.vaddress = regval; AArch64_Abort(memaddrdesc.fault); end; cache.cpas = CPASAtPAS(memaddrdesc.paddress.paspace); cache.paddress = memaddrdesc.paddress; cache.shareability = memaddrdesc.memattrs.shareability; if memaddrdesc.memattrs.shareability == Shareability_OSH then cache.shareability = Shareability_ISHCacheOpScope_ALLUISIsInHost; end; CACHE_OP(cache); end; return opscope; end;

Library pseudocode for aarch64/functions/ic/AArch64_IC

// AArch64_IC() // ============ // Perform Instruction Cache Operation. func AArch64_IC(opscope : CacheOpScope) begin let regval : bits(64) = ARBITRARY : bits(64); AArch64_IC(regval, opscope); end; // AArch64_IC() // ============ // Perform Instruction Cache Operation. func AArch64_IC(regval : bits(64), opscope_in : CacheOpScope) begin var cache : CacheRecord; var opscope : CacheOpScope = opscope_in; cache.acctype = AccessType_IC; cache.cachetype = CacheType_Instruction; cache.cacheop = CacheOp_Invalidate; cache.opscope = opscope; if opscope IN {CacheOpScope_ALLU, CacheOpScope_ALLUIS_CnP, CacheOpScope_ALLUIS} then let ss : SecurityState = SecurityStateAtEL(PSTATE.EL); cache.cpas = CPASAtSecurityState(ss); opscope = AArch64_EffectiveOpScope(opscope); case opscope of when CacheOpScope_ALLU => cache.shareability = Shareability_NSH; when CacheOpScope_ALLUIS => cache.shareability = Shareability_ISH; // When executed at EL1, if the Effective value of HCRX_EL2.VTLBIDEn is '1', // then the operation is broadcast to the set of PEs selected by VTLBID0_EL2.TD0. // Otherwise, the operation is broadcast to all PEs in the Shareability domain. cache.domains = TLBIDomains(Broadcast_ISH, Zeros{16}); when CacheOpScope_ALLUIS_CnP => cache.shareability = Shareability_ISH; cache.domains = DEFAULT_TLBI_DOMAIN; otherwise => unreachable; end; cache.regval = regval; CACHE_OP(cache); else assert opscope == CacheOpScope_PoU; if EL2Enabled() && !IsInHost() then if PSTATE.EL IN {EL0, EL1} then cache.is_vmid_valid = TRUE; cache.vmid = VMID(); else cache.is_vmid_valid = FALSE; end; else cache.is_vmid_valid = FALSE; end; if PSTATE.EL == EL0 then cache.is_asid_valid = TRUE; cache.asid = ASID(); else cache.is_asid_valid = FALSE; end; let vaddress : bits(64) = regval; cache.vaddress = regval; let accdesc : AccessDescriptor = CreateAccDescIC(cache); let aligned : boolean = TRUE; let size : integer = 0; var memaddrdesc : AddressDescriptor = AArch64_TranslateAddress(vaddress, accdesc, aligned, size); if IsFault(memaddrdesc) then memaddrdesc.fault.vaddress = regval; AArch64_Abort(memaddrdesc.fault); end; cache.cpas = CPASAtPAS(memaddrdesc.paddress.paspace); cache.paddress = memaddrdesc.paddress; cache.shareability = memaddrdesc.memattrs.shareability; if memaddrdesc.memattrs.shareability == Shareability_OSH then cache.shareability = Shareability_ISH; end; if memaddrdesc.memattrs.shareability != Shareability_NSH then // If the Effective value of HCRX_EL2().VTLBIDEn is '1', the invalidation is broadcast // to the set of PEs in the Inner shareable domain selected by VTLBID0_EL2().TD0 when // executed at EL1, or at EL0 when HCR_EL2().TGE is 0. cache.domains = TLBIDomains(Broadcast_ISH, Zeros{16}); end; CACHE_OP(cache); end; return; end;

Library pseudocode for aarch64/functions/memory/AArch64_MemSingleRead

// AArch64_MemSingleRead() // ======================= // Perform an atomic, little-endian read of 'size' bits. func AArch64_MemSingleRead{size : integer{8, 16, 32, 64, 128, 256}}(address : bits(64), accdesc_in : AccessDescriptor, aligned : boolean ) => (bits(size), AddressDescriptor, PhysMemRetStatus) begin var value : bits(size) = ARBITRARY : bits(size); var memstatus : PhysMemRetStatus = ARBITRARY : PhysMemRetStatus; let bytes : integer{} = size DIV 8; memstatus.statuscode = Fault_None; var accdesc : AccessDescriptor = accdesc_in; if IsFeatureImplemented(FEAT_LSE2) then let quantity : integer = MemSingleGranule(); assert ((IsFeatureImplemented(FEAT_LS64WB) && bytes == 32 && accdesc.acctype == AccessType_ASIMD) || AllInAlignedQuantity(address, bytes, quantity)); else assert IsAlignedSize(address, bytes); end; // If the instruction encoding permits tag checking, confer with system register configuration // which may override this. if accdesc.tagchecked then accdesc.tagchecked = AArch64_AccessIsTagChecked(address, accdesc); end; var memaddrdesc : AddressDescriptor; memaddrdesc = AArch64_TranslateAddress(address, accdesc, aligned, bytes); // Check for aborts or debug exceptions if IsFault(memaddrdesc) then return (value, memaddrdesc, memstatus); end; // Memory array access if accdesc.tagchecked then let ltag : bits(4) = AArch64_LogicalAddressTag(address); let fault : FaultRecord = AArch64_CheckTag(memaddrdesc, accdesc, bytes, ltag); if fault.statuscode != Fault_None then memaddrdesc.fault = fault; return (value, memaddrdesc, memstatus); end; end; if accdesc.acctype != AccessType_IFETCH && SPESampleInFlight then let is_load : boolean = TRUE; SPESampleLoadStore(is_load, accdesc, memaddrdesc); end; var atomic : boolean; if IsWBShareable(memaddrdesc.memattrs) then atomic = TRUE; elsif accdesc.exclusive then atomic = TRUE; elsif (accdesc.acctype == AccessType_SVE && accdesc.predicated && bytes == 8 && IsAlignedSize(address, 8)) then // An SVE predicated load of a 128-bit element that is 64-bit aligned // is treated as a pair of 64-bit single-copy atomic accesses. // This is one of the 64-bit single-copy atomic access. atomic = TRUE; elsif aligned then atomic = !accdesc.ispair; else // Misaligned accesses within MemSingleGranule() byte aligned memory but // not Normal Cacheable Writeback are Atomic atomic = ImpDefBool("FEAT_LSE2: access is atomic"); end; if atomic then (memstatus, value) = PhysMemRead{size}(memaddrdesc, accdesc); elsif accdesc.acctype == AccessType_ASIMD && bytes == 32 && accdesc.ispair then // A 32 byte LDP (SIMD&FP) that does not target Normal Inner Write-Back, Outer // Write-Back cacheable, Shareable memory is treated as four 8 byte atomic accesses. // As this access was not split in Mem(), it must be aligned to 32 bytes. assert IsAlignedSize(address, 32); accdesc.ispair = FALSE; for i = 0 to 3 do if !IsFault(memstatus) then // Do not continue past a fault (memstatus, value[i*64+:64]) = PhysMemRead{64}(memaddrdesc, accdesc); end; if !IsFault(memstatus) then memaddrdesc.paddress.address = memaddrdesc.paddress.address + 8; memaddrdesc.vaddress = memaddrdesc.vaddress + 8; end; end; elsif aligned && accdesc.ispair then let half : integer{} = (size DIV 2) as integer{32, 64, 128}; (memstatus, value[0*:half]) = PhysMemRead{half}(memaddrdesc, accdesc); if !IsFault(memstatus) then memaddrdesc.paddress.address = memaddrdesc.paddress.address + (halfbytes DIV 82); memaddrdesc.vaddress = memaddrdesc.vaddress + (halfbytes DIV 82); (memstatus, value[1*:half]) = PhysMemRead{half}(memaddrdesc, accdesc); end; else for i = 0 to bytes-1 do if !IsFault(memstatus) then // Do not continue past a fault (memstatus, value[i*:8]) = PhysMemRead{8}(memaddrdesc, accdesc); end; if !IsFault(memstatus) then memaddrdesc.paddress.address = memaddrdesc.paddress.address + 1; memaddrdesc.vaddress = memaddrdesc.vaddress + 1; end; end; end; if IsFault(memstatus) then return (value, memaddrdesc, memstatus); end; if accdesc.acctype == AccessType_IFETCH then memaddrdesc.fault = AArch64_CheckDebug(address, accdesc, bytes); end; return (value, memaddrdesc, memstatus); end;

Library pseudocode for aarch64/functions/memory/AArch64_MemSingleWrite

// AArch64_MemSingleWrite() // ======================== // Perform an atomic, little-endian write of 'size' bits. func AArch64_MemSingleWrite{size : integer{8, 16, 32, 64, 128, 256}}(address : bits(64), accdesc_in : AccessDescriptor, aligned : boolean, value : bits(size) ) => (AddressDescriptor, PhysMemRetStatus) begin var accdesc : AccessDescriptor = accdesc_in; let bytes : integer{} = size DIV 8; if IsFeatureImplemented(FEAT_LSE2) then let quantity : integer = MemSingleGranule(); assert ((IsFeatureImplemented(FEAT_LS64WB) && bytes == 32 && accdesc.acctype == AccessType_ASIMD) || AllInAlignedQuantity(address, bytes, quantity)); else assert IsAlignedSize(address, bytes); end; // If the instruction encoding permits tag checking, confer with system register configuration // which may override this. if accdesc.tagchecked then accdesc.tagchecked = AArch64_AccessIsTagChecked(address, accdesc); end; var memaddrdesc : AddressDescriptor; var memstatus : PhysMemRetStatus = ARBITRARY : PhysMemRetStatus; memaddrdesc = AArch64_TranslateAddress(address, accdesc, aligned, bytes); // Check for aborts or debug exceptions if IsFault(memaddrdesc) then return (memaddrdesc, memstatus); end; // Effect on exclusives if memaddrdesc.memattrs.shareability != Shareability_NSH then ClearExclusiveByAddress(memaddrdesc.paddress, ProcessorID(), bytes); end; if accdesc.tagchecked then let ltag : bits(4) = AArch64_LogicalAddressTag(address); let fault : FaultRecord = AArch64_CheckTag(memaddrdesc, accdesc, bytes, ltag); if fault.statuscode != Fault_None then memaddrdesc.fault = fault; return (memaddrdesc, memstatus); end; end; if SPESampleInFlight then let is_load : boolean = FALSE; SPESampleLoadStore(is_load, accdesc, memaddrdesc); end; var atomic : boolean; if IsWBShareable(memaddrdesc.memattrs) then atomic = TRUE; elsif accdesc.exclusive then atomic = TRUE; elsif (accdesc.acctype == AccessType_SVE && accdesc.predicated && bytes == 8 && IsAlignedSize(address, 8)) then // An SVE predicated load of a 128-bit element that is 64-bit aligned // is treated as a pair of 64-bit single-copy atomic accesses. // This is one of the 64-bit single-copy atomic access. atomic = TRUE; elsif aligned then atomic = !accdesc.ispair; else // Misaligned accesses within MemSingleGranule() byte aligned memory but // not Normal Cacheable Writeback are Atomic atomic = ImpDefBool("FEAT_LSE2: access is atomic"); end; if atomic then memstatus = PhysMemWrite{size}(memaddrdesc, accdesc, value); if IsFault(memstatus) then return (memaddrdesc, memstatus); end; elsif accdesc.acctype == AccessType_ASIMD && bytes == 32 && accdesc.ispair then // A 32 byte STP (SIMD&FP) that does not target Normal Inner Write-Back, Outer // Write-Back cacheable, Shareable memory is treated as four 8 byte atomic accesses. // As this access was not split in Mem(), it must be aligned to 32 bytes. assert IsAlignedSize(address, 32); accdesc.ispair = FALSE; for i = 0 to 3 do memstatus = PhysMemWrite{64}(memaddrdesc, accdesc, value[64*i+:64]); if IsFault(memstatus) then return (memaddrdesc, memstatus); end; memaddrdesc.paddress.address = memaddrdesc.paddress.address + 8; memaddrdesc.vaddress = memaddrdesc.vaddress + 8; end; elsif aligned && accdesc.ispair then let half : integer{} = (size DIV 2) as integer{32, 64}; memstatus = PhysMemWrite{half}(memaddrdesc, accdesc, value[0*:half]); if IsFault(memstatus) then return (memaddrdesc, memstatus); end; memaddrdesc.paddress.address = memaddrdesc.paddress.address + (halfbytes DIV 82); memaddrdesc.vaddress = memaddrdesc.vaddress + (halfbytes DIV 82); memstatus = PhysMemWrite{half}(memaddrdesc, accdesc, value[1*:half]); if IsFault(memstatus) then return (memaddrdesc, memstatus); end; else for i = 0 to bytes-1 do memstatus = PhysMemWrite{8}(memaddrdesc, accdesc, value[i*:8]); if IsFault(memstatus) then return (memaddrdesc, memstatus); end; memaddrdesc.paddress.address = memaddrdesc.paddress.address + 1; memaddrdesc.vaddress = memaddrdesc.vaddress + 1; end; end; return (memaddrdesc, memstatus); end;

Library pseudocode for aarch64/functions/memory/AArch64_MemTagWrite

// AArch64_MemTagWrite() // ===================== // Store an Allocation Tag to memory. func AArch64_MemTagWrite(address : bits(64), accdesc_in : AccessDescriptor, value : bits(4)) => (AddressDescriptor, PhysMemRetStatus) begin assert accdesc_in.tagaccess && !accdesc_in.tagchecked; var accdesc : AccessDescriptor = accdesc_in; var memaddrdesc : AddressDescriptor = ARBITRARY : AddressDescriptor; var memtagtype : MemTagType = ARBITRARY : MemTagType; var memstatus : PhysMemRetStatus = ARBITRARY : PhysMemRetStatus; let aligned : boolean = IsAlignedSize(address, TAG_GRANULE); // Stores of allocation tags must be aligned if !aligned then memaddrdesc.fault = AlignmentFault(accdesc, address); return (memaddrdesc, memstatus); end; accdesc.tagaccess = IsMTEEnabled(accdesc.el); (memtagtype, memaddrdesc) = AArch64_TranslateTagAddress(address, accdesc, aligned, TAG_GRANULE); // Check for aborts or debug exceptions if IsFault(memaddrdesc) then memaddrdesc.fault.vaddress = memaddrdesc.vaddress; return (memaddrdesc, memstatus); end; if accdesc.tagaccess && memtagtype == MemTag_AllocationTagged then memstatus = PhysMemTagWrite(memaddrdesc, accdesc, value); end; return (memaddrdesc, memstatus); end;

Library pseudocode for aarch64/functions/memory/Mem

// Mem - accessor // ============== accessor Mem{size : integer{8, 16, 32, 64, 128, 256}}(address : bits(64), accdesc_in : AccessDescriptor ) <=> value_in : bits(size) begin // Perform a read of 'size' bits. The access byte order is reversed for a big-endian access. // Instruction fetches would call AArch64_MemSingle directly. getter var accdesc : AccessDescriptor = accdesc_in; let bytes : integer{} = size DIV 8; var value : bits(size); // Check alignment on size of element accessed, not overall access size varlet alignedalignment : boolean; integer{} = (if accdesc.ispair && !accdesc.exclusive then let halfbytes : integer{} = (size DIV 2) else asbytes); var integer{32, 64, 128}; aligned =: IsAlignedSize(address, half DIV 8); else aligned boolean = IsAlignedSize(address, bytesalignment); end; let quantity : integer = MemSingleGranule(); if !aligned && AArch64_UnalignedAccessFaults(accdesc, address, bytes) then let fault : FaultRecord = AlignmentFault(accdesc, address); AArch64_Abort(fault); end; if accdesc.acctype == AccessType_ASIMD && bytes == 16 && IsAlignedSize(address, 8) then // If 128-bit SIMD&FP ordered access are treated as a pair of // 64-bit single-copy atomic accesses, then these single copy atomic // access can be observed in any order. let half : integer{} = (size DIV 2) as integer{64}; let highaddress : bits(64) = AddressIncrement(address, halfbytes DIV 82, accdesc); value[0*:half] = AArch64_MemSingle{half}(address, accdesc, aligned); value[1*:half] = AArch64_MemSingle{half}(highaddress, accdesc, aligned); elsif (accdesc.acctype == AccessType_ASIMD && bytes == 32 && accdesc.ispair && IsAlignedSize(address, 32)) then value = AArch64_MemSingle{size}(address, accdesc, aligned); elsif accdesc.acctype == AccessType_ASIMD && bytes == 32 && IsAlignedSize(address, 8) then // If a 32 byte LDP (SIMD&FP) access is not aligned to 32 bytes but aligned to // 8 bytes, it is treated as four 8 byte single-copy atomic accesses. accdesc.ispair = FALSE; aligned = TRUE; for i = 0 to 3 do let blockaddress : bits(64) = AddressIncrement(address, i*8, accdesc); value[64*i+:64] = AArch64_MemSingle{64}(blockaddress, accdesc, aligned); end; elsif (IsFeatureImplemented(FEAT_LSE2) && AllInAlignedQuantity(address, bytes, quantity)) then value = AArch64_MemSingle{size}(address, accdesc, aligned); elsif ((aligned && accdesc.ispair) || (accdesc.acctype == AccessType_SVE && accdesc.predicated && bytes == 16 && IsAlignedSize(address, 8))) then // Either: an aligned pair access, OR // an SVE predicated load of a 128-bit element that is 64-bit aligned, // which is treated as two 64-bit single-copy atomic accesses. accdesc.ispair = FALSE; let half : integer{} = (size DIV 2) as integer{32, 64, 128}; let highaddress : bits(64) = AddressIncrement(address, halfbytes DIV 82, accdesc); if IsFeatureImplemented(FEAT_LRCPC3) && accdesc.highestaddressfirst then value[1*:half] = AArch64_MemSingle{half}(highaddress, accdesc, aligned); value[0*:half] = AArch64_MemSingle{half}(address, accdesc, aligned); else value[0*:half] = AArch64_MemSingle{half}(address, accdesc, aligned); value[1*:half] = AArch64_MemSingle{half}(highaddress, accdesc, aligned); end; elsif aligned then value = AArch64_MemSingle{size}(address, accdesc, aligned); else assert bytes > 1; if (IsFeatureImplemented(FEAT_LRCPC3) && accdesc.ispair && accdesc.highestaddressfirst) then let half : integer{} = (size DIV 2) as integer{32, 64, 128}; var lowhalf, highhalf : bits(half); for i = 0 to (halfbytes DIV 82)-1 do let byteaddress : bits(64) = AddressIncrement(address, (halfbytes DIV 82) + i, accdesc); // Individual byte access can be observed in any order highhalf[i*:8] = AArch64_MemSingle{8}(byteaddress, accdesc, aligned); end; for i = 0 to (halfbytes DIV 82)-1 do let byteaddress : bits(64) = AddressIncrement(address, i, accdesc); // Individual byte access can be observed in any order lowhalf[i*:8] = AArch64_MemSingle{8}(byteaddress, accdesc, aligned); end; value = highhalf::lowhalf; else value[7:0] = AArch64_MemSingle{8}(address, accdesc, aligned); accdesc.lowestaddress = FALSE; // For subsequent bytes, if they cross to a new translation page which assigns // Device memory type, it is CONSTRAINED UNPREDICTABLE whether an unaligned access // will generate an Alignment Fault. let c : Constraint = ConstrainUnpredictable(Unpredictable_DEVPAGE2); assert c IN {Constraint_FAULT, Constraint_NONE}; if c == Constraint_NONE then aligned = TRUE; end; for i = 1 to bytes-1 do let byteaddress : bits(64) = AddressIncrement(address, i, accdesc); value[i*:8] = AArch64_MemSingle{8}(byteaddress, accdesc, aligned); end; end; end; if BigEndian(accdesc.acctype) then value = BigEndianReverse{size}(value); end; return value; end; // Perform a write of 'size' bits. The byte order is reversed for a big-endian access. setter var value : bits(size) = value_in; let bytes : integer{} = size DIV 8; var accdesc : AccessDescriptor = accdesc_in; // Check alignment on size of element accessed, not overall access size varlet alignedalignment : boolean; integer{} = (if accdesc.ispair && !accdesc.exclusive then let halfbytes : integer{} = (size DIV 2) else asbytes); var integer{32, 64, 128}; aligned =: IsAlignedSize(address, half DIV 8); else aligned boolean = IsAlignedSize(address, bytesalignment); end; let quantity : integer = MemSingleGranule(); if !aligned && AArch64_UnalignedAccessFaults(accdesc, address, bytes) then let fault : FaultRecord = AlignmentFault(accdesc, address); AArch64_Abort(fault); end; if BigEndian(accdesc.acctype) then value = BigEndianReverse{size}(value); end; if accdesc.acctype == AccessType_ASIMD && bytes == 16 && IsAlignedSize(address, 8) then let half : integer{} = (size DIV 2) as integer{64}; // 128-bit SIMD&FP stores are treated as a pair of 64-bit single-copy atomic accesses // 64-bit aligned. let highaddress : bits(64) = AddressIncrement(address, half(bytes DIV 8,2), accdesc); AArch64_MemSingle{half}(address, accdesc, aligned) = value[0+:half]; AArch64_MemSingle{half}(highaddress, accdesc, aligned) = value[half+:half]; elsif (accdesc.acctype == AccessType_ASIMD && bytes == 32 && accdesc.ispair && IsAlignedSize(address, 32)) then AArch64_MemSingle{size}(address, accdesc, aligned) = value; elsif accdesc.acctype == AccessType_ASIMD && bytes == 32 && IsAlignedSize(address, 8) then // If a 32 byte STP (SIMD&FP) access is not aligned to 32 bytes but aligned to // 8 bytes, it is treated as four 8 byte single-copy atomic accesses. accdesc.ispair = FALSE; aligned = TRUE; for i = 0 to 3 do let blockaddress : bits(64) = AddressIncrement(address, i*8, accdesc); AArch64_MemSingle{64}(blockaddress, accdesc, aligned) = value[64*i+:64]; end; elsif (IsFeatureImplemented(FEAT_LSE2) && AllInAlignedQuantity(address, bytes, quantity)) then AArch64_MemSingle{size}(address, accdesc, aligned) = value; elsif ((aligned && accdesc.ispair) || (accdesc.acctype == AccessType_SVE && accdesc.predicated && bytes == 16 && IsAlignedSize(address, 8))) then // Either: an aligned pair access, OR // an SVE predicated load of a 128-bit element that is 64-bit aligned, // which is treated as two 64-bit single-copy atomic accesses. let half : integer{} = (size DIV 2) as integer{32, 64, 128}; accdesc.ispair = FALSE; let highaddress : bits(64) = AddressIncrement(address, half(bytes DIV 8,2), accdesc); if IsFeatureImplemented(FEAT_LRCPC3) && accdesc.highestaddressfirst then AArch64_MemSingle{half}(highaddress, accdesc, aligned) = value[half+:half]; AArch64_MemSingle{half}(address, accdesc, aligned) = value[0+:half]; else AArch64_MemSingle{half}(address, accdesc, aligned) = value[0+:half]; AArch64_MemSingle{half}(highaddress, accdesc, aligned) = value[half+:half]; end; elsif aligned then AArch64_MemSingle{size}(address, accdesc, aligned) = value; else assert bytes > 1; if (IsFeatureImplemented(FEAT_LRCPC3) && accdesc.ispair && accdesc.highestaddressfirst) then let half : integer{} = (size DIV 2) as integer{32, 64}; var lowhalf, highhalf : bits(half); (highhalf, lowhalf) = (value[half+:half], value[0+:half]); for i = 0 to (halfbytes DIV 82)-1 do let byteaddress : bits(64) = AddressIncrement(address, (halfbytes DIV 82) + i, accdesc); // Individual byte access can be observed in any order AArch64_MemSingle{8}(byteaddress, accdesc, aligned) = highhalf[i*:8]; end; for i = 0 to (halfbytes DIV 82)-1 do let byteaddress : bits(64) = AddressIncrement(address, (halfbytes DIV 82) + i, accdesc); // Individual byte access can be observed in any order, // but implies observability of highhalf AArch64_MemSingle{8}(byteaddress, accdesc, aligned) = lowhalf[i*:8]; end; else AArch64_MemSingle{8}(address, accdesc, aligned) = value[7:0]; accdesc.lowestaddress = FALSE; // For subsequent bytes, if they cross to a new translation page which assigns // Device memory type, it is CONSTRAINED UNPREDICTABLE whether an unaligned access // will generate an Alignment Fault. let c : Constraint = ConstrainUnpredictable(Unpredictable_DEVPAGE2); assert c IN {Constraint_FAULT, Constraint_NONE}; if c == Constraint_NONE then aligned = TRUE; end; for i = 1 to bytes-1 do let byteaddress : bits(64) = AddressIncrement(address, i, accdesc); AArch64_MemSingle{8}(byteaddress, accdesc, aligned) = value[i*:8]; end; end; end; end; end;

Library pseudocode for aarch64/functions/memory/NVMem

// NVMem - accessor // ================ accessor NVMem(offset : integer) <=> value : bits(64) begin // This function is the load memory access for the transformed System register read access // when Enhanced Nested Virtualization is enabled with HCR_EL2.NV2 = 1. // The address for the load memory access is calculated using // the formula SignExtend{64}((VNCR_EL2.BADDR ::: Offset[11:0])], 64) where, // * VNCR_EL2.BADDR holds the base address of the memory location, and // * Offset is the unique offset value defined architecturally for each System register that // supports transformation of register access to memory access. getter assert offset > 0 && offset MOD 8 == 0; let directread : boolean = FALSE; let baddr : bits(64) = EffectiveBADDR(VNCR_EL2().BADDR :: Zeros{12}, directread); let address : bits(64) = baddr + offset; let accdesc : AccessDescriptor = CreateAccDescNV2(MemOp_LOAD); return Mem{64}(address, accdesc); end; // This function is the store memory access for the transformed System register write access // when Enhanced Nested Virtualization is enabled with HCR_EL2.NV2 = 1. // The address for the store memory access is calculated using // the formula SignExtend{64}((VNCR_EL2.BADDR ::: Offset[11:0])], 64) where, // * VNCR_EL2.BADDR holds the base address of the memory location, and // * Offset is the unique offset value defined architecturally for each System register that // supports transformation of register access to memory access. setter assert offset > 0 && offset MOD 8 == 0; let directread : boolean = FALSE; let baddr : bits(64) = EffectiveBADDR(VNCR_EL2().BADDR :: Zeros{12}, directread); let address : bits(64) = baddr + offset; let accdesc : AccessDescriptor = CreateAccDescNV2(MemOp_STORE); Mem{64}(address, accdesc) = value; return; end; end; accessor NVMem128(offset : integer) <=> value : bits(128) begin getter assert offset > 0 && offset MOD 16 == 0; let directread : boolean = FALSE; let baddr : bits(64) = EffectiveBADDR(VNCR_EL2().BADDR :: Zeros{12}, directread); let address : bits(64) = baddr + offset; let accdesc : AccessDescriptor = CreateAccDescNV2(MemOp_LOAD); return Mem{128}(address, accdesc); end; setter assert offset > 0 && offset MOD 16 == 0; let directread : boolean = FALSE; let baddr : bits(64) = EffectiveBADDR(VNCR_EL2().BADDR :: Zeros{12}, directread); let address : bits(64) = baddr + offset; let accdesc : AccessDescriptor = CreateAccDescNV2(MemOp_STORE); Mem{128}(address, accdesc) = value; end; end;

Library pseudocode for aarch64/functions/mops/CheckSETConstrainedUnpredictable

// CheckSETConstrainedUnpredictable() // ================================== // Check for CONSTRAINED UNPREDICTABLE behaviour in the SET* and SETG* instructions. func CheckSETConstrainedUnpredictable(memsetn : SETParamsinteger, d : integer, s : integer) begin if (memset.ss == memset.nn || memset.ss == memset.dd || memset.nn == memset.dd) then let c : Constraint = ConstrainUnpredictable(Unpredictable_MOPSOVERLAP); assert c IN {Constraint_UNDEF, Constraint_NOP}; case c of when Constraint_UNDEF => Undefined(); when Constraint_NOP => ExecuteAsNOP(); end; end; if (memset.dd == 31 || memset.nn == 31) then let c : Constraint = ConstrainUnpredictable(Unpredictable_MOPS_R31); assert c IN {Constraint_UNDEF, Constraint_NOP}; case c of when Constraint_UNDEF => Undefined(); when Constraint_NOP => ExecuteAsNOP(); end; end; end;

Library pseudocode for aarch64/functions/pac/addpac/InsertPAC

// InsertPAC() // =========== // Calculates the pointer authentication code for a 64-bit quantity and then // inserts that into pointer authentication code field of that 64-bit quantity. func InsertPAC(ptr : bits(64), modifier : bits(64), modifier2 : bits(64), use_modifier2 : boolean, K : bits(128), data : boolean) => bits(64) begin var PAC : bits(64); var result : bits(64); var ext_ptr : bits(64); var extfield : bits(64); var selbit : bit; var bit55 : bit; let tbi : boolean = EffectiveTBI(ptr, !data, PSTATE.EL) == '1'; let mtx : boolean = (IsFeatureImplemented(FEAT_MTE_NO_ADDRESS_TAGS) && EffectiveMTX(ptr, !data, PSTATE.EL) == '1'); let top_bit : integer{} = if tbi then 55 else 63; let EL3_using_lva3 : boolean = (IsFeatureImplemented(FEAT_LVA3) && TranslationRegime(PSTATE.EL) == Regime_EL3 && AArch64_IASize(TCR_EL3().T0SZ) > 52); let is_VA_56bit : boolean = (TranslationRegime(PSTATE.EL) == Regime_EL3 && AArch64_IASize(TCR_EL3().T0SZ) == 56); // If tagged pointers are in use for a regime with two TTBRs, use bit[55] of // the pointer to select between upper and lower ranges, and preserve this. // This handles the awkward case where there is apparently no correct choice between // the upper and lower address range - ie an addr of 1xxxxxxx0... with TBI0=0 and TBI1=1 // and 0xxxxxxx1 with TBI1=0 and TBI0=1: if PtrHasUpperAndLowerAddRanges() then assert S1TranslationRegime() IN {EL1, EL2}; if S1TranslationRegime() == EL1 then // EL1 translation regime registers if data then if TCR_EL1().TBI1 == '1' || TCR_EL1().TBI0 == '1' then selbit = ptr[55]; else selbit = ptr[63]; end; else if ((TCR_EL1().TBI1 == '1' && TCR_EL1().TBID1 == '0') || (TCR_EL1().TBI0 == '1' && TCR_EL1().TBID0 == '0')) then selbit = ptr[55]; else selbit = ptr[63]; end; end; else // EL2 translation regime registers if data then if TCR_EL2().TBI1 == '1' || TCR_EL2().TBI0 == '1' then selbit = ptr[55]; else selbit = ptr[63]; end; else if ((TCR_EL2().TBI1 == '1' && TCR_EL2().TBID1 == '0') || (TCR_EL2().TBI0 == '1' && TCR_EL2().TBID0 == '0')) then selbit = ptr[55]; else selbit = ptr[63]; end; end; end; else selbit = if tbi then ptr[55] else ptr[63]; end; if IsFeatureImplemented(FEAT_PAuth2) && IsFeatureImplemented(FEAT_CONSTPACFIELD) then selbit = ptr[55]; end; let bottom_PAC_bit : AddressSize = CalculateBottomPACBit(selbit); if EL3_using_lva3 then extfield = Replicate{64}('0'); else extfield = Replicate{64}(selbit); end; // Compute the pointer authentication code for a ptr with good extension bits if tbi then if bottom_PAC_bit <= 55 then ext_ptr = (ptr[63:56] :: extfield[55:bottom_PAC_bit] :: ptr[bottom_PAC_bit-1:0]); else ext_ptr = ptr[63:56] :: ptr[55:0]; end; elsif mtx then if bottom_PAC_bit <= 55 then ext_ptr = (extfield[63:60] :: ptr[59:56] :: extfield[55:bottom_PAC_bit] :: ptr[bottom_PAC_bit-1:0]); else ext_ptr = extfield[63:60] :: ptr[59:56] :: ptr[55:0]; end; else ext_ptr = extfield[63:bottom_PAC_bit] :: ptr[bottom_PAC_bit-1:0]; end; if use_modifier2 then assert IsFeatureImplemented(FEAT_PAuth_LR); PAC = ComputePAC2(ext_ptr, modifier, modifier2, K[127:64], K[63:0]); else PAC = ComputePAC(ext_ptr, modifier, K[127:64], K[63:0]); end; if !IsFeatureImplemented(FEAT_PAuth2) then // If FEAT_PAuth2 is not implemented, the PAC is corrupted if the pointer does not have // a canonical VA. assert bottom_PAC_bit <= 52; if !IsZero(ptr[top_bit:bottom_PAC_bit]) && !IsOnes(ptr[top_bit:bottom_PAC_bit]) then if IsFeatureImplemented(FEAT_EPAC) then PAC = 0x0000000000000000[63:0]; else PAC[top_bit-1] = NOT(PAC[top_bit-1]); end; end; end; // Preserve the determination between upper and lower address at bit[55] and insert PAC into // bits that are not used for the address or the tag(s). if !IsFeatureImplemented(FEAT_PAuth2) then assert (bottom_PAC_bit <= 52); if tbi then result = ptr[63:56]::selbit::PAC[54:bottom_PAC_bit]::ptr[bottom_PAC_bit-1:0]; else result = PAC[63:56]::selbit::PAC[54:bottom_PAC_bit]::ptr[bottom_PAC_bit-1:0]; end; else if EL3_using_lva3 then // Bit 55 is an address bit (when VA size is 56-bits) or // used to store PAC (when VA size is less than 56-bits) if is_VA_56bit then bit55 = ptr[55]; else bit55 = ptr[55] XOR PAC[55]; end; else bit55 = selbit; end; if tbi then if bottom_PAC_bit < 55 then result = (ptr[63:56] :: bit55 :: (ptr[54:bottom_PAC_bit] XOR PAC[54:bottom_PAC_bit]) :: ptr[bottom_PAC_bit-1:0]); else result = (ptr[63:56] :: bit55 :: ptr[54:0]); end; elsif mtx then if bottom_PAC_bit < 55 then result = ((ptr[63:60] XOR PAC[63:60]) :: ptr[59:56] :: bit55 :: (ptr[54:bottom_PAC_bit] XOR PAC[54:bottom_PAC_bit]) :: ptr[bottom_PAC_bit-1:0]); else result = ((ptr[63:60] XOR PAC[63:60]) :: ptr[59:56] :: bit55 :: ptr[54:0]); end; else if bottom_PAC_bit < 55 then result = ((ptr[63:56] XOR PAC[63:56]) :: bit55 :: (ptr[54:bottom_PAC_bit] XOR PAC[54:bottom_PAC_bit]) :: ptr[bottom_PAC_bit-1:0]); else result = ((ptr[63:56] XOR PAC[63:56]) :: bit55 :: ptr[54:0]); end; end; end; return result; end;

Library pseudocode for aarch64/functions/pac/pac/IsAPDAKeyEnabled

// IsAPDAKeyEnabled() // ================== // Returns TRUE if authentication using the APDAKey_EL1 key is enabled. // Otherwise, depending on the state of the PE, generate a trap, or return FALSE. func IsAPDAKeyEnabled() => boolean begin var TrapEL2 : boolean; var TrapEL3 : boolean; var Enable : bits(1); case PSTATE.EL of when PSTATE.EL of when EL0 => let IsEL1Regime : boolean = S1TranslationRegime() == EL1; Enable = if IsEL1Regime then SCTLR_EL1().EnDA else SCTLR_EL2().EnDA; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then var enda2 : bit; if IsEL1Regime then enda2 = if IsSCTLR2EL1Enabled() then SCTLR2_EL1().EnDA2 else '0'; else enda2 = if IsSCTLR2EL2Enabled(); Enable = if IsEL1Regime then SCTLR2_EL2SCTLR_EL1().EnDA2EnDA else '0'; endSCTLR_EL2().EnDA; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then Enable = Enable XOR enda2;(if IsEL1Regime then SCTLR2_EL1().EnDA2 else SCTLR2_EL2().EnDA2); end; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0' && !IsInHost(); TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL1 => Enable = SCTLR_EL1().EnDA; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0'; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL2 => Enable = SCTLR_EL2().EnDA; TrapEL2 = FALSE; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL3 => Enable = SCTLR_EL3().EnDA; TrapEL2 = FALSE; TrapEL3 = FALSE; end; if Enable == '0' then return FALSE; elsif TrapEL3 && EL3SDDUndefPriority() then Undefined(); elsif TrapEL2 then TrapPACUse(EL2); elsif TrapEL3 then if EL3SDDUndef() then Undefined(); else TrapPACUse(EL3); end; else return TRUE; end; end;

Library pseudocode for aarch64/functions/pac/pac/IsAPDBKeyEnabled

// IsAPDBKeyEnabled() // ================== // Returns TRUE if authentication using the APDBKey_EL1 key is enabled. // Otherwise, depending on the state of the PE, generate a trap, or return FALSE. func IsAPDBKeyEnabled() => boolean begin var TrapEL2 : boolean; var TrapEL3 : boolean; var Enable : bits(1); case PSTATE.EL of when PSTATE.EL of when EL0 => let IsEL1Regime : boolean = S1TranslationRegime() == EL1; Enable = if IsEL1Regime then SCTLR_EL1().EnDB else SCTLR_EL2().EnDB; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then var endb2 : bit; if IsEL1Regime then endb2 = if IsSCTLR2EL1Enabled() then SCTLR2_EL1().EnDB2 else '0'; else endb2 = if IsSCTLR2EL2Enabled(); Enable = if IsEL1Regime then SCTLR2_EL2SCTLR_EL1().EnDB2EnDB else '0'; endSCTLR_EL2().EnDB; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then Enable = Enable XOR endb2;(if IsEL1Regime then SCTLR2_EL1().EnDB2 else SCTLR2_EL2().EnDB2); end; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0' && !IsInHost(); TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL1 => Enable = SCTLR_EL1().EnDB; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0'; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL2 => Enable = SCTLR_EL2().EnDB; TrapEL2 = FALSE; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL3 => Enable = SCTLR_EL3().EnDB; TrapEL2 = FALSE; TrapEL3 = FALSE; end; if Enable == '0' then return FALSE; elsif TrapEL3 && EL3SDDUndefPriority() then Undefined(); elsif TrapEL2 then TrapPACUse(EL2); elsif TrapEL3 then if EL3SDDUndef() then Undefined(); else TrapPACUse(EL3); end; else return TRUE; end; end;

Library pseudocode for aarch64/functions/pac/pac/IsAPIAKeyEnabled

// IsAPIAKeyEnabled() // ================== // Returns TRUE if authentication using the APIAKey_EL1 key is enabled. // Otherwise, depending on the state of the PE, generate a trap, or return FALSE. func IsAPIAKeyEnabled() => boolean begin var TrapEL2 : boolean; var TrapEL3 : boolean; var Enable : bits(1); case PSTATE.EL of when PSTATE.EL of when EL0 => let IsEL1Regime : boolean = S1TranslationRegime() == EL1; Enable = if IsEL1Regime then SCTLR_EL1().EnIA else SCTLR_EL2().EnIA; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then var enia2 : bit; if IsEL1Regime then enia2 = if IsSCTLR2EL1Enabled() then SCTLR2_EL1().EnIA2 else '0'; else enia2 = if IsSCTLR2EL2Enabled(); Enable = if IsEL1Regime then SCTLR2_EL2SCTLR_EL1().EnIA2EnIA else '0'; endSCTLR_EL2().EnIA; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then Enable = Enable XOR enia2;(if IsEL1Regime then SCTLR2_EL1().EnIA2 else SCTLR2_EL2().EnIA2); end; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0' && !IsInHost(); TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL1 => Enable = SCTLR_EL1().EnIA; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0'; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL2 => Enable = SCTLR_EL2().EnIA; TrapEL2 = FALSE; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL3 => Enable = SCTLR_EL3().EnIA; TrapEL2 = FALSE; TrapEL3 = FALSE; end; if Enable == '0' then return FALSE; elsif TrapEL3 && EL3SDDUndefPriority() then Undefined(); elsif TrapEL2 then TrapPACUse(EL2); elsif TrapEL3 then if EL3SDDUndef() then Undefined(); else TrapPACUse(EL3); end; else return TRUE; end; end;

Library pseudocode for aarch64/functions/pac/pac/IsAPIBKeyEnabled

// IsAPIBKeyEnabled() // ================== // Returns TRUE if authentication using the APIBKey_EL1 key is enabled. // Otherwise, depending on the state of the PE, generate a trap, or return FALSE. func IsAPIBKeyEnabled() => boolean begin var TrapEL2 : boolean; var TrapEL3 : boolean; var Enable : bits(1); case PSTATE.EL of when PSTATE.EL of when EL0 => let IsEL1Regime : boolean = S1TranslationRegime() == EL1; Enable = if IsEL1Regime then SCTLR_EL1().EnIB else SCTLR_EL2().EnIB; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then var enib2 : bit; if IsEL1Regime then enib2 = if IsSCTLR2EL1Enabled() then SCTLR2_EL1().EnIB2 else '0'; else enib2 = if IsSCTLR2EL2Enabled(); Enable = if IsEL1Regime then SCTLR2_EL2SCTLR_EL1().EnIB2EnIB else '0'; endSCTLR_EL2().EnIB; if IsFeatureImplemented(FEAT_PAuth_EnhCtl) then Enable = Enable XOR enib2;(if IsEL1Regime then SCTLR2_EL1().EnIB2 else SCTLR2_EL2().EnIB2); end; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0' && !IsInHost(); TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL1 => Enable = SCTLR_EL1().EnIB; TrapEL2 = EL2Enabled() && HCR_EL2().API == '0'; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL2 => Enable = SCTLR_EL2().EnIB; TrapEL2 = FALSE; TrapEL3 = HaveEL(EL3) && SCR_EL3().API == '0'; when EL3 => Enable = SCTLR_EL3().EnIB; TrapEL2 = FALSE; TrapEL3 = FALSE; end; if Enable == '0' then return FALSE; elsif TrapEL3 && EL3SDDUndefPriority() then Undefined(); elsif TrapEL2 then TrapPACUse(EL2); elsif TrapEL3 then if EL3SDDUndef() then Undefined(); else TrapPACUse(EL3); end; else return TRUE; end; end;

Library pseudocode for aarch64/functions/ras/AArch64_dESBOperation

// AArch64_dESBOperation() // ======================= // Perform the AArch64 ESB operation for a pending delegated SError exception. func AArch64_dESBOperation() begin assert (IsFeatureImplemented(FEAT_E3DSE) && !ELUsingAArch32(EL3) && PSTATE.EL != PSTATE.EL != EL3); // When FEAT_E3DSE is implemented, SCR_EL3.DSE might inject a delegated SError exception. var dsei_pending, dsei_masked : boolean; dsei_pending = EffectiveSCR_EL3_EnDSE()); // ==When '1'FEAT_E3DSE &&is implemented, SCR_EL3.DSE might inject a delegated SError exception. var dsei_pending, dsei_masked : boolean; dsei_pending = SCR_EL3().().[EnDSE,DSE] == '111'; (dsei_masked, -) = AArch64_DelegatedSErrorTarget(); if dsei_pending && dsei_masked then var target : bits(64) = Zeros{}; target[31] = '1'; // A target[24:0] = VSESR_EL3()[24:0]; VDISR_EL3() = target; ClearPendingDelegatedSError(); end; return; end;

Library pseudocode for aarch64/functions/ras/EffectiveSCR_EL3_EnDSE

// EffectiveSCR_EL3_EnDSE() // ======================== // Return the Effective value of SCR_EL3().EnDSE. func EffectiveSCR_EL3_EnDSE() => bit begin if !IsFeatureImplemented(FEAT_E3DSE) then return '0'; end; if SCR_EL3().EA == '0' && EffectiveSCR_EL3_TMEA() == '0' then return '0'; end; return SCR_EL3().EnDSE; end;

Library pseudocode for aarch64/functions/sysop/SysOp

// SysOp() // ======= func SysOp(op1 : bits(3), CRn : bits(4), CRm : bits(4), op2 : bits(3)) => SystemOp begin case op1::CRn::CRm::op2 of when '000 0111 1000 000' => return Sys_AT; // S1E1R when '000 0111 1000 001' => return Sys_AT; // S1E1W when '000 0111 1000 010' => return Sys_AT; // S1E0R when '000 0111 1000 011' => return Sys_AT; // S1E0W when '000 0111 1001 000' => return Sys_AT; // S1E1RP when '000 0111 1001 001' => return Sys_AT; // S1E1WP when '000 0111 1001 010' => return Sys_AT; // S1E1A when '100 0111 1000 000' => return Sys_AT; // S1E2R when '100 0111 1000 001' => return Sys_AT; // S1E2W when '100 0111 1001 010' => return Sys_AT; // S1E2A when '100 0111 1000 100' => return Sys_AT; // S12E1R when '100 0111 1000 101' => return Sys_AT; // S12E1W when '100 0111 1000 110' => return Sys_AT; // S12E0R when '100 0111 1000 111' => return Sys_AT; // S12E0W when '110 0111 1000 000' => return Sys_AT; // S1E3R when '110 0111 1000 001' => return Sys_AT; // S1E3W when '110 0111 1001 010' => return Sys_AT; // S1E3A when '001 0111 0010 100' => return Sys_BRB; // IALL when '001 0111 0010 101' => return Sys_BRB; // INJ when '000 0111 0110 001' => return Sys_DC; // IVAC when '000 0111 0110 010' => return Sys_DC; // ISW when '000 0111 0110 011' => return Sys_DC; // IGVAC when '000 0111 0110 100' => return Sys_DC; // IGSW when '000 0111 0110 101' => return Sys_DC; // IGDVAC when '000 0111 0110 110' => return Sys_DC; // IGDSW when '000 0111 1010 010' => return Sys_DC; // CSW when '000 0111 1010 100' => return Sys_DC; // CGSW when '000 0111 1010 110' => return Sys_DC; // CGDSW when '000 0111 1110 010' => return Sys_DC; // CISW when '000 0111 1110 100' => return Sys_DC; // CIGSW when '000 0111 1110 110' => return Sys_DC; // CIGDSW when '011 0111 0100 001' => return Sys_DC; // ZVA when '011 0111 0100 011' => return Sys_DC; // GVA when '011 0111 0100 100' => return Sys_DC; // GZVA when '011 0111 1010 001' => return Sys_DC; // CVAC when '011 0111 1010 011' => return Sys_DC; // CGVAC when '011 0111 1010 101' => return Sys_DC; // CGDVAC when '011 0111 1011 001' => return Sys_DC; // CVAU when '011 0111 1100 001' => return Sys_DC; // CVAP when '011 0111 1100 011' => return Sys_DC; // CGVAP when '011 0111 1100 101' => return Sys_DC; // CGDVAP when '011 0111 1101 001' => return Sys_DC; // CVADP when '011 0111 1101 011' => return Sys_DC; // CGVADP when '011 0111 1101 101' => return Sys_DC; // CGDVADP when '011 0111 1110 001' => return Sys_DC; // CIVAC when '011 0111 1110 011' => return Sys_DC; // CIGVAC when '011 0111 1110 101' => return Sys_DC; // CIGDVAC when '100 0111 00001110 100000' => return Sys_MLBI; // ALLE1 when '100 0111 0000 101' => return Sys_MLBI; // VMALLE1 when '100 0111 0000 110' => return Sys_MLBI; // VPIDE1 when '100 0111 0000 111' => return Sys_MLBI; // VPMGE1 when '100 0111 1110 000' => return Sys_DC; // CIPAE when '100 0111 1110 111' => return Sys_DC; // CIGDPAE when '110 0111 1110 001' => return Sys_DC; // CIPAPA when '110 0111 1110 101' => return Sys_DC; // CIGDPAPA when '000 0111 1111 001' => return Sys_DC; // CIVAPS when '000 0111 1111 101' => return Sys_DC; // CIGDVAPS when '000 0111 0001 000' => return Sys_IC; // IALLUIS when '000 0111 0101 000' => return Sys_IC; // IALLU when '011 0111 0101 001' => return Sys_IC; // IVAU when '000 1000 0001 000' => return Sys_TLBI; // VMALLE1OS when '000 1000 0001 001' => return Sys_TLBI; // VAE1OS when '000 1000 0001 010' => return Sys_TLBI; // ASIDE1OS when '000 1000 0001 011' => return Sys_TLBI; // VAAE1OS when '000 1000 0001 101' => return Sys_TLBI; // VALE1OS when '000 1000 0001 111' => return Sys_TLBI; // VAALE1OS when '000 1000 0010 001' => return Sys_TLBI; // RVAE1IS when '000 1000 0010 011' => return Sys_TLBI; // RVAAE1IS when '000 1000 0010 101' => return Sys_TLBI; // RVALE1IS when '000 1000 0010 111' => return Sys_TLBI; // RVAALE1IS when '000 1000 0011 000' => return Sys_TLBI; // VMALLE1IS when '000 1000 0011 001' => return Sys_TLBI; // VAE1IS when '000 1000 0011 010' => return Sys_TLBI; // ASIDE1IS when '000 1000 0011 011' => return Sys_TLBI; // VAAE1IS when '000 1000 0011 101' => return Sys_TLBI; // VALE1IS when '000 1000 0011 111' => return Sys_TLBI; // VAALE1IS when '000 1000 0101 001' => return Sys_TLBI; // RVAE1OS when '000 1000 0101 011' => return Sys_TLBI; // RVAAE1OS when '000 1000 0101 101' => return Sys_TLBI; // RVALE1OS when '000 1000 0101 111' => return Sys_TLBI; // RVAALE1OS when '000 1000 0110 001' => return Sys_TLBI; // RVAE1 when '000 1000 0110 011' => return Sys_TLBI; // RVAAE1 when '000 1000 0110 101' => return Sys_TLBI; // RVALE1 when '000 1000 0110 111' => return Sys_TLBI; // RVAALE1 when '000 1000 0111 000' => return Sys_TLBI; // VMALLE1 when '000 1000 0111 001' => return Sys_TLBI; // VAE1 when '000 1000 0111 010' => return Sys_TLBI; // ASIDE1 when '000 1000 0111 011' => return Sys_TLBI; // VAAE1 when '000 1000 0111 101' => return Sys_TLBI; // VALE1 when '000 1000 0111 111' => return Sys_TLBI; // VAALE1 when '000 1001 0001 000' => return Sys_TLBI; // VMALLE1OSNXS when '000 1001 0001 001' => return Sys_TLBI; // VAE1OSNXS when '000 1001 0001 010' => return Sys_TLBI; // ASIDE1OSNXS when '000 1001 0001 011' => return Sys_TLBI; // VAAE1OSNXS when '000 1001 0001 101' => return Sys_TLBI; // VALE1OSNXS when '000 1001 0001 111' => return Sys_TLBI; // VAALE1OSNXS when '000 1001 0010 001' => return Sys_TLBI; // RVAE1ISNXS when '000 1001 0010 011' => return Sys_TLBI; // RVAAE1ISNXS when '000 1001 0010 101' => return Sys_TLBI; // RVALE1ISNXS when '000 1001 0010 111' => return Sys_TLBI; // RVAALE1ISNXS when '000 1001 0011 000' => return Sys_TLBI; // VMALLE1ISNXS when '000 1001 0011 001' => return Sys_TLBI; // VAE1ISNXS when '000 1001 0011 010' => return Sys_TLBI; // ASIDE1ISNXS when '000 1001 0011 011' => return Sys_TLBI; // VAAE1ISNXS when '000 1001 0011 101' => return Sys_TLBI; // VALE1ISNXS when '000 1001 0011 111' => return Sys_TLBI; // VAALE1ISNXS when '000 1001 0101 001' => return Sys_TLBI; // RVAE1OSNXS when '000 1001 0101 011' => return Sys_TLBI; // RVAAE1OSNXS when '000 1001 0101 101' => return Sys_TLBI; // RVALE1OSNXS when '000 1001 0101 111' => return Sys_TLBI; // RVAALE1OSNXS when '000 1001 0110 001' => return Sys_TLBI; // RVAE1NXS when '000 1001 0110 011' => return Sys_TLBI; // RVAAE1NXS when '000 1001 0110 101' => return Sys_TLBI; // RVALE1NXS when '000 1001 0110 111' => return Sys_TLBI; // RVAALE1NXS when '000 1001 0111 000' => return Sys_TLBI; // VMALLE1NXS when '000 1001 0111 001' => return Sys_TLBI; // VAE1NXS when '000 1001 0111 010' => return Sys_TLBI; // ASIDE1NXS when '000 1001 0111 011' => return Sys_TLBI; // VAAE1NXS when '000 1001 0111 101' => return Sys_TLBI; // VALE1NXS when '000 1001 0111 111' => return Sys_TLBI; // VAALE1NXS when '100 1000 0000 001' => return Sys_TLBI; // IPAS2E1IS when '100 1000 0000 010' => return Sys_TLBI; // RIPAS2E1IS when '100 1000 0000 101' => return Sys_TLBI; // IPAS2LE1IS when '100 1000 0000 110' => return Sys_TLBI; // RIPAS2LE1IS when '100 1000 0001 000' => return Sys_TLBI; // ALLE2OS when '100 1000 0001 001' => return Sys_TLBI; // VAE2OS when '100 1000 0001 100' => return Sys_TLBI; // ALLE1OS when '100 1000 0001 101' => return Sys_TLBI; // VALE2OS when '100 1000 0001 110' => return Sys_TLBI; // VMALLS12E1OS when '100 1000 0010 001' => return Sys_TLBI; // RVAE2IS when '100 1000 0010 101' => return Sys_TLBI; // RVALE2IS when '100 1000 0011 000' => return Sys_TLBI; // ALLE2IS when '100 1000 0011 001' => return Sys_TLBI; // VAE2IS when '100 1000 0011 100' => return Sys_TLBI; // ALLE1IS when '100 1000 0011 101' => return Sys_TLBI; // VALE2IS when '100 1000 0011 110' => return Sys_TLBI; // VMALLS12E1IS when '100 1000 0100 000' => return Sys_TLBI; // IPAS2E1OS when '100 1000 0100 001' => return Sys_TLBI; // IPAS2E1 when '100 1000 0100 010' => return Sys_TLBI; // RIPAS2E1 when '100 1000 0100 011' => return Sys_TLBI; // RIPAS2E1OS when '100 1000 0100 100' => return Sys_TLBI; // IPAS2LE1OS when '100 1000 0100 101' => return Sys_TLBI; // IPAS2LE1 when '100 1000 0100 110' => return Sys_TLBI; // RIPAS2LE1 when '100 1000 0100 111' => return Sys_TLBI; // RIPAS2LE1OS when '100 1000 0101 001' => return Sys_TLBI; // RVAE2OS when '100 1000 0101 101' => return Sys_TLBI; // RVALE2OS when '100 1000 0110 001' => return Sys_TLBI; // RVAE2 when '100 1000 0110 101' => return Sys_TLBI; // RVALE2 when '100 1000 0111 000' => return Sys_TLBI; // ALLE2 when '100 1000 0111 001' => return Sys_TLBI; // VAE2 when '100 1000 0111 100' => return Sys_TLBI; // ALLE1 when '100 1000 0111 101' => return Sys_TLBI; // VALE2 when '100 1000 0111 110' => return Sys_TLBI; // VMALLS12E1 when '100 1001 0000 001' => return Sys_TLBI; // IPAS2E1ISNXS when '100 1001 0000 010' => return Sys_TLBI; // RIPAS2E1ISNXS when '100 1001 0000 101' => return Sys_TLBI; // IPAS2LE1ISNXS when '100 1001 0000 110' => return Sys_TLBI; // RIPAS2LE1ISNXS when '100 1001 0001 000' => return Sys_TLBI; // ALLE2OSNXS when '100 1001 0001 001' => return Sys_TLBI; // VAE2OSNXS when '100 1001 0001 100' => return Sys_TLBI; // ALLE1OSNXS when '100 1001 0001 101' => return Sys_TLBI; // VALE2OSNXS when '100 1001 0001 110' => return Sys_TLBI; // VMALLS12E1OSNXS when '100 1001 0010 001' => return Sys_TLBI; // RVAE2ISNXS when '100 1001 0010 101' => return Sys_TLBI; // RVALE2ISNXS when '100 1001 0011 000' => return Sys_TLBI; // ALLE2ISNXS when '100 1001 0011 001' => return Sys_TLBI; // VAE2ISNXS when '100 1001 0011 100' => return Sys_TLBI; // ALLE1ISNXS when '100 1001 0011 101' => return Sys_TLBI; // VALE2ISNXS when '100 1001 0011 110' => return Sys_TLBI; // VMALLS12E1ISNXS when '100 1001 0100 000' => return Sys_TLBI; // IPAS2E1OSNXS when '100 1001 0100 001' => return Sys_TLBI; // IPAS2E1NXS when '100 1001 0100 010' => return Sys_TLBI; // RIPAS2E1NXS when '100 1001 0100 011' => return Sys_TLBI; // RIPAS2E1OSNXS when '100 1001 0100 100' => return Sys_TLBI; // IPAS2LE1OSNXS when '100 1001 0100 101' => return Sys_TLBI; // IPAS2LE1NXS when '100 1001 0100 110' => return Sys_TLBI; // RIPAS2LE1NXS when '100 1001 0100 111' => return Sys_TLBI; // RIPAS2LE1OSNXS when '100 1001 0101 001' => return Sys_TLBI; // RVAE2OSNXS when '100 1001 0101 101' => return Sys_TLBI; // RVALE2OSNXS when '100 1001 0110 001' => return Sys_TLBI; // RVAE2NXS when '100 1001 0110 101' => return Sys_TLBI; // RVALE2NXS when '100 1001 0111 000' => return Sys_TLBI; // ALLE2NXS when '100 1001 0111 001' => return Sys_TLBI; // VAE2NXS when '100 1001 0111 100' => return Sys_TLBI; // ALLE1NXS when '100 1001 0111 101' => return Sys_TLBI; // VALE2NXS when '100 1001 0111 110' => return Sys_TLBI; // VMALLS12E1NXS when '110 1000 0001 000' => return Sys_TLBI; // ALLE3OS when '110 1000 0001 001' => return Sys_TLBI; // VAE3OS when '110 1000 0001 100' => return Sys_TLBI; // PAALLOS when '110 1000 0001 101' => return Sys_TLBI; // VALE3OS when '110 1000 0010 001' => return Sys_TLBI; // RVAE3IS when '110 1000 0010 101' => return Sys_TLBI; // RVALE3IS when '110 1000 0011 000' => return Sys_TLBI; // ALLE3IS when '110 1000 0011 001' => return Sys_TLBI; // VAE3IS when '110 1000 0011 101' => return Sys_TLBI; // VALE3IS when '110 1000 0100 011' => return Sys_TLBI; // RPAOS when '110 1000 0100 111' => return Sys_TLBI; // RPALOS when '110 1000 0101 001' => return Sys_TLBI; // RVAE3OS when '110 1000 0101 101' => return Sys_TLBI; // RVALE3OS when '110 1000 0110 001' => return Sys_TLBI; // RVAE3 when '110 1000 0110 101' => return Sys_TLBI; // RVALE3 when '110 1000 0111 000' => return Sys_TLBI; // ALLE3 when '110 1000 0111 001' => return Sys_TLBI; // VAE3 when '110 1000 0111 100' => return Sys_TLBI; // PAALL when '110 1000 0111 101' => return Sys_TLBI; // VALE3 when '110 1001 0001 000' => return Sys_TLBI; // ALLE3OSNXS when '110 1001 0001 001' => return Sys_TLBI; // VAE3OSNXS when '110 1001 0001 101' => return Sys_TLBI; // VALE3OSNXS when '110 1001 0010 001' => return Sys_TLBI; // RVAE3ISNXS when '110 1001 0010 101' => return Sys_TLBI; // RVALE3ISNXS when '110 1001 0011 000' => return Sys_TLBI; // ALLE3ISNXS when '110 1001 0011 001' => return Sys_TLBI; // VAE3ISNXS when '110 1001 0011 101' => return Sys_TLBI; // VALE3ISNXS when '110 1001 0101 001' => return Sys_TLBI; // RVAE3OSNXS when '110 1001 0101 101' => return Sys_TLBI; // RVALE3OSNXS when '110 1001 0110 001' => return Sys_TLBI; // RVAE3NXS when '110 1001 0110 101' => return Sys_TLBI; // RVALE3NXS when '110 1001 0111 000' => return Sys_TLBI; // ALLE3NXS when '110 1001 0111 001' => return Sys_TLBI; // VAE3NXS when '110 1001 0111 101' => return Sys_TLBI; // VALE3NXS when '000 1100 0000 000' => return Sys_GSB; // SYS when '000 1100 0000 001' => return Sys_GSB; // ACK when '000 1100 0001 000' => return Sys_GIC; // CDDIS when '000 1100 0001 001' => return Sys_GIC; // CDEN when '000 1100 0001 010' => return Sys_GIC; // CDPRI when '000 1100 0001 011' => return Sys_GIC; // CDAFF when '000 1100 0001 100' => return Sys_GIC; // CDPEND when '000 1100 0001 101' => return Sys_GIC; // CDRCFG when '000 1100 0001 111' => return Sys_GIC; // CDEOI when '000 1100 0010 000' => return Sys_GIC; // CDDI when '000 1100 0010 001' => return Sys_GIC; // CDHM when '100 1100 0001 000' => return Sys_GIC; // VDDIS when '100 1100 0001 001' => return Sys_GIC; // VDEN when '100 1100 0001 010' => return Sys_GIC; // VDPRI when '100 1100 0001 011' => return Sys_GIC; // VDAFF when '100 1100 0001 100' => return Sys_GIC; // VDPEND when '100 1100 0001 101' => return Sys_GIC; // VDRCFG when '100 1100 0010 000' => return Sys_GIC; // VDDI when '100 1100 0010 001' => return Sys_GIC; // VDHM when '110 1100 0001 000' => return Sys_GIC; // LDDIS when '110 1100 0001 001' => return Sys_GIC; // LDEN when '110 1100 0001 010' => return Sys_GIC; // LDPRI when '110 1100 0001 011' => return Sys_GIC; // LDAFF when '110 1100 0001 100' => return Sys_GIC; // LDPEND when '110 1100 0001 101' => return Sys_GIC; // LDRCFG when '110 1100 0010 000' => return Sys_GIC; // LDDI when '110 1100 0010 001' => return Sys_GIC; // LDHM otherwise => return Sys_SYS; end; end;

Library pseudocode for aarch64/functions/sysop/SystemOp

// SystemOp // ======== // System instruction types. type SystemOp of enumeration { Sys_AT, Sys_BRB, Sys_DC, Sys_GIC, Sys_GSB, Sys_IC, Sys_MLBISys_TLBI, Sys_TLBI,Sys_SYS }; Sys_SYS };

Library pseudocode for aarch64/functions/system/AArch64_InterruptPending

// AArch64_InterruptPending() // ========================== // Returns TRUE if there are any pending physical, virtual, or delegated // interrupts, and FALSE otherwise. func AArch64_InterruptPending() => boolean begin let (irq_pending, -) = IRQPending(); let (fiq_pending, -) = FIQPending(); let pending_physical_interrupt : boolean = (irq_pending || fiq_pending || IsPhysicalSErrorPending()); var pending_virtual_interrupt : boolean = FALSE; if EL2Enabled() && PSTATE.EL IN { PSTATE.EL IN {EL0, EL1} && HCR_EL2().TGE == '0' then let virq_pending : boolean = (HCR_EL2().IMO == '1' && (VirtualIRQPending() || HCR_EL2().VI == '1')); let vfiq_pending : boolean = (HCR_EL2().FMO == '1' && (VirtualFIQPending() || HCR_EL2().VF == '1')); let vsei_pending : boolean = ((HCR_EL2().AMO == '1' || (IsFeatureImplemented(FEAT_DoubleFault2) && IsHCRXEL2Enabled() && HCRX_EL2().TMEA == '1')) && (IsVirtualSErrorPending() || HCR_EL2().VSE == '1')); pending_virtual_interrupt = vsei_pending || virq_pending || vfiq_pending; end; let pending_delegated_interrupt : boolean = (IsFeatureImplemented(FEAT_E3DSE) && PSTATE.EL !=PSTATE.EL != EL3 && EffectiveSCR_EL3_EnDSE() == '1' && SCR_EL3().().[EnDSE,DSE] == '111'); return pending_physical_interrupt || pending_virtual_interrupt || pending_delegated_interrupt; end;

Library pseudocode for aarch64/functions/system/BTypeCompatible_PAC

// BTypeCompatible_PAC() // ===================== // Returns TRUE if PACIxSP or PACIxSPPC instructions are implicitly compatible with PSTATE.BTYPE, // FALSE otherwise. func BTypeCompatible_PAC(pacinst : PACInstType) => boolean begin // For only PACIxSP instructions, check if BTI behavior should be disabled if IsFeatureImplemented(FEAT_PAuth_EnhCtl) && pacinst == PACIxSP then var btd : bit; case PSTATE.EL of when PSTATE.EL of when EL0 => btd = if ELIsInHost(EL0) then btd =SCTLR2_EL2().BTD0 ifelse SCTLR2_EL1().BTD0; when IsSCTLR2EL2Enabled() then SCTLR2_EL2().BTD0 else '0'; else btd = if IsSCTLR2EL1Enabled() then SCTLR2_EL1().BTD0 else '0'; end; when EL1 => btd = ifSCTLR2_EL1().BTD; when IsSCTLR2EL1Enabled() then SCTLR2_EL1().BTD else '0'; when EL2 => btd = ifSCTLR2_EL2().BTD; when IsSCTLR2EL2Enabled() then SCTLR2_EL2().BTD else '0'; when EL3 => btd = SCTLR2_EL3().BTD; end; // When BTI compatibility is disabled, // these instructions are not compatible when PSTATE.BTYPE is non-zero if btd == '1' then return IsZero(PSTATE.BTYPE); end; end; if PSTATE.BTYPE != '11' then return TRUE; else let index : integer = if PSTATE.EL=> btd = SCTLR2_EL3().BTD; end; // When BTI compatibility is disabled, // these instructions are not compatible when PSTATE.BTYPE is non-zero if btd == '1' then return IsZero(PSTATE.BTYPE); end; end; if PSTATE.BTYPE != '11' then return TRUE; else let index : integer = if PSTATE.EL == EL0 then 35 else 36; return SCTLR_ELx()[index] == '0'; end; end;

Library pseudocode for aarch64/functions/system/IsHCRXEL2Enabled

// IsHCRXEL2Enabled() // ================== // Returns TRUE if access to HCRX_EL2 register is enabled, and FALSE otherwise. // Indirect read of HCRX_EL2 returns 0 when access is not enabled. readonly func IsHCRXEL2Enabled() => boolean begin if !IsFeatureImplemented(FEAT_HCX) then return FALSE; end; if ELUsingAArch32(EL2) then return FALSE; end; if HaveEL(EL3) && SCR_EL3().HXEn == '0' then return FALSE; end; return EL2Enabled(); end;

Library pseudocode for aarch64/functions/system/IsSystemRegisterMaskingEnabled

// IsSystemRegisterMaskingEnabled() // ================================ // Returns TRUE if access to the MASK registers introduced by FEAT_SRMASK is enabled and the // values in the register are not treated as 0. func IsSystemRegisterMaskingEnabled(el : bits(2)) => boolean begin assert IsFeatureImplemented(FEAT_SRMASK) && el IN {EL1, EL2}; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return FALSE; end; return el == EL2 || !EL2Enabled() || (IsHCRXEL2Enabled() && HCRX_EL2().SRMASKEn == '1'); end;

Library pseudocode for aarch64/functions/tlbi/AArch64_EffectiveBroadcastAArch64_TLBIP_IPAS2

// AArch64_EffectiveBroadcastAArch64_TLBIP_IPAS2() // ================================================= // Invalidate by IPA all stage 2 only TLB entries in the indicated broadcast // domain matching the indicated VMID in the indicated regime with the indicated security state. // Note: stage 1 and stage 2 combined entries are not in the scope of this operation. // IPA and related parameters of the are derived from Xt. func AArch64_TLBIP_IPAS2(security : AArch64_EffectiveBroadcast(broadcast_in, regime : BroadcastRegime), =>vmid : bits(16), broadcast_in : Broadcast begin var, broadcastlevel : TLBILevel, attr : TLBIMemAttr, Xt : bits(128)) begin assert PSTATE.EL IN {EL3, EL2}; var broadcast : Broadcast = broadcast_in; ifvar r : PSTATETLBIRecord.EL !=; r.op = EL1TLBIOp_IPAS2 then; r.from_aarch64 return= broadcastTRUE; r.security = endsecurity; r.regime = regime; r.vmid = vmid; r.use_vmid = TRUE; r.level = level; r.attr = attr; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[107:64] :: Zeros{12}); if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then varr.d64 = fnbTRUE; r.d128 = :r.ttl bit== '00xx'; else r.d64 = r.ttl == '00xx'; r.d128 = TRUE; end; case security of ifwhen IsHCRXEL2EnabledSS_NonSecure()=> r.ipaspace && (!=HaveELPAS_NonSecure(; whenEL3SS_Secure) || SCR_EL3().VTLBIDEn == '1') then=> fnbr.ipaspace = HCRX_EL2().FNB; else fnbif =Xt[63] '0'; end; case== fnb::HCR_EL2().FB of when '001' => pass; when '01' => if broadcast ==then Broadcast_NSHPAS_NonSecure then // The operation is broadcast within the Inner Shareable shareability domain. broadcast =else Broadcast_ForcedISHPAS_Secure; end; when '10' => if broadcast == Broadcast_ISHSS_Realm then // The operation only affects the PE on which the instruction is executed. broadcast=> r.ipaspace = Broadcast_NSHPAS_Realm; otherwise => // Root security state does not have stage 2 translation unreachable; end; when TLBI(r); let '11'domains => if: broadcastbits(16) === Broadcast_ISHTLBIDomains then // The operation is (broadcast, to PEs which would share TLB entries with the // current PE Xt[15:0]); if CnP were 1. (broadcast === Broadcast_ISH_CnPBroadcast_OSH; end; end; else if broadcast ==&& ( Broadcast_NSHIsBroadcast_OSHnISH &&(regime) || EL2EnabledOSHDomainExceedsNIS()(domains))) && HCR_EL2().FB == '1' then broadcast = ; end; if broadcast != Broadcast_NSHBroadcast_ForcedISHBroadcast_OSHnISH; then BroadcastTLBI(broadcast, r, domains); end; end; return broadcast; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBIP_IPAS2AArch64_TLBIP_RIPAS2

// AArch64_TLBIP_IPAS2AArch64_TLBIP_RIPAS2() // =========================================== // InvalidateRange invalidate by IPA all stage 2 only TLB entries in the indicated broadcast // broadcast domain matching the indicated VMID in the indicated regime with the indicated // security state. // Note: stage 1 and stage 2 combined entries are not in the scope of this operation. // The range of IPA and related parameters of the are derived from Xt. func AArch64_TLBIP_IPAS2AArch64_TLBIP_RIPAS2(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr : TLBIMemAttr, Xt : bits(128)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2}; var broadcast :, EL1}; var broadcast : Broadcast = broadcast_in; var r : TLBIRecord; r.op = TLBIOp_IPAS2TLBIOp_RIPAS2; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = TRUE; r.level = level; r.attr = attr; r.ttl = Xt[471:44]; r.address 0] = ZeroExtend{64}(Xt[10738:64] :: Zeros{12});37]; if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then r.d64 = TRUE; r.d128 = r.ttl[1:0] == '00xx00'; else r.d64 = r.ttl[1:0] == '00xx00'; r.d128 = TRUE; end; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIPRange(regime, Xt); if !valid then return; end; case security of when SS_NonSecure => r.ipaspace = PAS_NonSecure; when SS_Secure => r.ipaspace = if Xt[63] == '1' then PAS_NonSecure else PAS_Secure; when SS_Realm => r.ipaspace = PAS_Realm; otherwise => // Root security state does not have stage 2 translation unreachable; end; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBIP_RIPAS2AArch64_TLBIP_RVA

// AArch64_TLBIP_RIPAS2AArch64_TLBIP_RVA() // ========================================= // Range invalidate by IPAVA range all stage 21 only TLB entries in the indicated // broadcast domain matching the indicated VMID and ASID (where regime // supports VMID, ASID) in the indicated regime with the indicated // security state. // ASID, and range related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are not in the scope of this operation. // The range of IPA and related parameters of the are derived from Xt. func AArch64_TLBIP_RIPAS2AArch64_TLBIP_RVA(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr : TLBIMemAttr, Xt : bits(128)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2}; var broadcast :, EL1}; var broadcast : Broadcast = broadcast_in; var r : TLBIRecord; r.op = TLBIOp_RIPAS2TLBIOp_RVA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = TRUE; r.level = level; r.attr = attr; r.ttl[1:0] = Xt[38:37]; if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then r.d64 = TRUE; r.d128 = r.ttl[1:0] == '00'; else r.d64 = r.ttl[1:0] == '00'; r.d128 = TRUE; end; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIPRange(regime, Xt); if !valid then return; end; case security of when SS_NonSecureUseVMID => r.ipaspace = PAS_NonSecure; when SS_Secure => r.ipaspace = if Xt[63] == '1' then PAS_NonSecure else PAS_Secure; when SS_Realm => r.ipaspace = PAS_Realm(regime); r.level = level; r.attr = attr; r.asid = Xt[63:48]; r.ttl[1:0] = Xt[38:37]; if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then otherwiser.d64 = => //TRUE; r.d128 = Rootr.ttl[1:0] security== state'00'; else r.d64 = doesr.ttl[1:0] not== have'00'; r.d128 = stageTRUE; end; var 2valid translation unreachable: boolean; (valid, r.tg, r.address, r.end_address) = TLBIPRange(regime, Xt); if !valid then return; end; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBIP_RVAAArch64_TLBIP_RVAA

// AArch64_TLBIP_RVAAArch64_TLBIP_RVAA() // ======================================= // Range invalidate by VA range all stage 1 TLB entries in the indicated // broadcast domain matching the indicated VMID and ASID (where regimeregimesupports VMID) // supportsand VMID,all ASID) in the indicated regime with the indicated security state. // ASID,VA and range related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBIP_RVAAArch64_TLBIP_RVAA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(128)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = broadcast_in; var r : AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; elsif regime == Regime_EL2 && ELIsInHost(EL2) then regime = Regime_EL20; end; var r : TLBIRecord; r.op = TLBIOp_RVATLBIOp_RVAA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Xt[63:48]; r.ttl[1:0] = Xt[38:37]; if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then r.d64 = TRUE; r.d128 = r.ttl[1:0] == '00'; else r.d64 = r.ttl[1:0] == '00'; r.d128 = TRUE; end; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIPRange(regime, Xt); if !valid then return; end; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBIP_RVAAAArch64_TLBIP_VA

// AArch64_TLBIP_RVAAAArch64_TLBIP_VA() // ====================================== // RangeInvalidate invalidate by VA range all stage 1 TLB entries in the indicated // broadcast domain // matching the indicated VMID and ASID (where regimesupportsregime supports VMID) //, and all ASID) in the indicated regime // with the indicated security state. // ASID, VA rangeand related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBIP_RVAAAArch64_TLBIP_VA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(128)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = broadcast_in; var r : AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; end; var r : TLBIRecord; r.op = TLBIOp_RVAATLBIOp_VA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.ttlr.asid = Xt[163:0] 48]; r.ttl = Xt[3847:3744]; r.address = ZeroExtend{64}(Xt[107:64] :: Zeros{12}); if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then r.d64 = TRUE; r.d128 = r.ttl[1:0] == '0000xx'; else r.d64 = r.ttl[1:0] == '0000xx'; r.d128 = TRUE; end; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIPRange(regime, Xt); if !valid then return; end; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH() || OSHDomainExceedsNIS(domains)))regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBIP_VAAArch64_TLBIP_VAA

// AArch64_TLBIP_VAAArch64_TLBIP_VAA() // ===================================== // Invalidate by VA all stage 1 TLB entries in the indicated broadcast domain // matching the indicated VMID and ASID (where regime supports VMID,) and all ASID) in the indicated regime // with the indicated security state. // ASID, VA and related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBIP_VAAArch64_TLBIP_VAA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(128)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = broadcast_in; var r : AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if regime == Regime_EL10 && ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; elsif regime == Regime_EL2 && ELIsInHost(EL2) then regime = Regime_EL20; end; var r : TLBIRecord; r.op = TLBIOp_VATLBIOp_VAA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Xt[63:48]; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[107:64] :: Zeros{12}); if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then r.d64 = TRUE; r.d128 = r.ttl == '00xx'; else r.d64 = r.ttl == '00xx'; r.d128 = TRUE; end; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH() || OSHDomainExceedsNIS(domains)))regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBIP_VAAAArch64_TLBI_ALL

// AArch64_TLBIP_VAAAArch64_TLBI_ALL() // ===================================== // Invalidate by VA all stage 1 TLB entries infor the indicated broadcasttranslation domainregime with the // matching the indicated VMIDsecurity (wherestate regimefor supports VMID) and all ASIDTLBs inwithin the indicated regime //broadcast with the indicated security state.domain. // VAInvalidation andapplies relatedto parametersall areapplicable derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation.entries. func AArch64_TLBIP_VAAAArch64_TLBI_ALL(security : SecurityState, regime_inregime : Regime, vmid_in : bits(16), broadcast_in : Broadcast, levelattr : TLBILevel, attr_in : TLBIMemAttr, Xt : bits(12864)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2,}; var broadcast : EL1}; var broadcast : Broadcast = broadcast_in; var r : AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; end; var r : TLBIRecord; r.op = TLBIOp_VAATLBIOp_ALL; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid r.level = UseVMIDTLBILevel_Any(regime); r.level = level; r.attr = attr; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[107:64] :: Zeros{12}); if IsFeatureImplemented(FEAT_TLBID) && Xt[32] == '1' then r.d64 = TRUE; r.d128 = r.ttl == '00xx'; else r.d64 = r.ttl == '00xx'; r.d128 = TRUE; end; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_ALLAArch64_TLBI_ASID

// AArch64_TLBI_ALLAArch64_TLBI_ASID() // ===================================== // Invalidate all stage 1 entries formatching the indicated VMID (where regime supports) // and ASID in the parameter Xt in the indicated translation regime with the // the indicated security state for all TLBs within the indicated broadcast domain. // InvalidationNote: applies to all applicable stage 1 and stage 2 entries.combined entries are in the scope of this operation. func AArch64_TLBI_ALLAArch64_TLBI_ASID(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, attr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2}; var broadcast :, EL1}; var broadcast : Broadcast = broadcast_in; var r : TLBIRecord; r.op = ; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMIDTLBIOp_ALLTLBIOp_ASID; r.from_aarch64 = TRUE; r.security = security; r.regime = (regime;); r.level = TLBILevel_Any; r.attr = attr; r.asid = Xt[63:48]; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_ASIDAArch64_TLBI_IPAS2

// AArch64_TLBI_ASIDAArch64_TLBI_IPAS2() // ======================================= // Invalidate by IPA all stage 12 only TLB entries matchingin the indicated VMID (where regime supports)broadcast // anddomain ASIDmatching in the parameterindicated XtVMID in the indicated translation regime with the // indicated security state for all TLBs within the indicated broadcast domain.state. // Note: stage 1 and stage 2 combined entries are not in the scope of this operation. // IPA and related parameters of the are derived from Xt. func AArch64_TLBI_ASIDAArch64_TLBI_IPAS2(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, attr_inlevel : TLBILevel, attr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2,}; var broadcast : EL1}; var broadcast : Broadcast = broadcast_in; var r : AArch64_EffectiveBroadcastTLBIRecord(broadcast_in);; var attr :r.op = TLBIMemAttrTLBIOp_IPAS2 ; r.from_aarch64 = attr_inTRUE; if r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = TRUE; r.level = level; r.attr = attr; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[39:0] :: Zeros{12}); r.d64 = TRUE; r.d128 = r.ttl == '00xx'; case security of when TLBI_AllAttrSS_NonSecure &&=> r.ipaspace = ExcludeXSPAS_NonSecure() then; attr =when TLBI_ExcludeXSSS_Secure; end; var=> r.ipaspace regime= :if Xt[63] == '1' then RegimePAS_NonSecure = regime_in; var vmid : bits(16) = vmid_in; ifelse ELIsInHostPAS_Secure(; whenEL0SS_Realm) then regime=> r.ipaspace = Regime_EL20PAS_Realm; vmid =otherwise => // Root security state does not have stage 2 translation unreachable; end; TLBI(r); if broadcast == VMID_NONE; end; var r : TLBIRecord; r.op = TLBIOp_ASID; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = TLBILevel_Any; r.attr = attr; r.asid = Xt[63:48]; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH() || OSHDomainExceedsNIS(domains)))regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_IPAS2

// AArch64_TLBI_IPAS2() // ==================== // Invalidate by IPA all stage 2 only TLB entries in the indicated broadcast // domain matching the indicated VMID in the indicated regime with the indicated security state. // Note: stage 1 and stage 2 combined entries are not in the scope of this operation. // IPA and related parameters of the are derived from Xt. func AArch64_TLBI_IPAS2(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN {EL3, EL2}; var broadcast : Broadcast = broadcast_in; var r : TLBIRecord; r.op = TLBIOp_IPAS2; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = TRUE; r.level = level; r.attr = attr; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[39:0] :: Zeros{12}); r.d64 = TRUE; r.d128 = r.ttl == '00xx'; case security of when SS_NonSecure => r.ipaspace = PAS_NonSecure; when SS_Secure => r.ipaspace = if Xt[63] == '1' then PAS_NonSecure else PAS_Secure; when SS_Realm => r.ipaspace = PAS_Realm; otherwise => // Root security state does not have stage 2 translation unreachable; end; TLBI(r); if broadcast == Broadcast_OSH && IsBroadcast_OSHnISH() then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_RIPAS2

// AArch64_TLBI_RIPAS2() // ===================== // Range invalidate by IPA all stage 2 only TLB entries in the indicated // broadcast domain matching the indicated VMID in the indicated regime with the indicated // security state. // Note: stage 1 and stage 2 combined entries are not in the scope of this operation. // The range of IPA and related parameters of the are derived from Xt. func AArch64_TLBI_RIPAS2(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = broadcast_in; var r : TLBIRecord; r.op = TLBIOp_RIPAS2; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = TRUE; r.level = level; r.attr = attr; r.ttl[1:0] = Xt[38:37]; r.d64 = TRUE; r.d128 = r.ttl[1:0] == '00'; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIRange(regime, Xt); if !valid then return; end; case security of when SS_NonSecure => r.ipaspace = PAS_NonSecure; when SS_Secure => r.ipaspace = if Xt[63] == '1' then PAS_NonSecure else PAS_Secure; when SS_Realm => r.ipaspace = PAS_Realm; otherwise => // Root security state does not have stage 2 translation unreachable; end; TLBI(r); if broadcast == Broadcast_OSH && IsBroadcast_OSHnISH()(regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_RPA

// AArch64_TLBI_RPA() // ================== // TLB Range Invalidate GPT Information by PA. // Invalidates cached copies of GPT entries from TLBs in the indicated // Shareabilty domain. // The invalidation applies to TLB entries containing GPT information relating // to the indicated physical address range. // When the indicated level is // TLBILevel_Any : this applies to TLB entries containing GPT information // from all levels of the GPT walk // TLBILevel_Last : this applies to TLB entries containing GPT information // from the last level of the GPT walk func AArch64_TLBI_RPA(level : TLBILevel, Xt : bits(64), broadcast : Broadcast) begin assert IsFeatureImplemented(FEAT_RME) && PSTATE.EL == EL3; var r : TLBIRecord; var range_bits : AddressSize; var p : AddressSize; // r.security and r.regime do not apply for TLBI by PA operations r.op = TLBIOp_RPA; r.level = level; r.attr = TLBI_AllAttr; // SIZE field case Xt[47:44] of when '0000' => range_bits = 12; // 4KB when '0001' => range_bits = 14; // 16KB when '0010' => range_bits = 16; // 64KB when '0011' => range_bits = 21; // 2MB when '0100' => range_bits = 25; // 32MB when '0101' => range_bits = 29; // 512MB when '0110' => range_bits = 30; // 1GB when '0111' => range_bits = 34; // 16GB when '1000' => range_bits = 36; // 64GB when '1001' => range_bits = 39; // 512GB otherwise => return; // Reserved encoding, no TLB entries are required to be invalidated end; // If SIZE selects a range smaller than PGS, then PGS is used instead case DecodePGS(GPCCR_EL3().PGS) of when PGS_4KB => p = 12; when PGS_16KB => p = 14; when PGS_64KB => p = 16; otherwise => return; // Reserved encoding, no TLB entries are required to be invalidated end; if range_bits < p then range_bits = p; end; var BaseADDR : bits(5652) = Zeros{}; case GPCCR_EL3().PGS of when '00' => BaseADDR[51:12] = Xt[39:0]; // 4KB when '10' => BaseADDR[51:14] = Xt[39:2]; // 16KB when '01' => BaseADDR[51:16] = Xt[39:4]; // 64KB end; if IsFeatureImplemented(FEAT_D128) && AArch64_PAMax() == 56 then BaseADDR[55:52] = Xt[43:40]; // Extension to Address end; // The calculation here automatically aligns BaseADDR to the size of // the region specififed in SIZE. However, the architecture does not // require this alignment and if BaseADDR is not aligned to the region // specified by SIZE then no entries are required to be invalidated. let range_pbits : integer{} = range_bits; let start_addr : bits(5652) = BaseADDR AND NOT ZeroExtend{5652}(Ones{range_pbits}); let end_addr : bits(5652) = start_addr + ZeroExtend{5652}(Ones{range_pbits}); // PASpace is not considered in TLBI by PA operations r.address = ZeroExtend{64}(start_addr); r.end_address = ZeroExtend{64}(end_addr); TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_RVA

// AArch64_TLBI_RVA() // ================== // Range invalidate by VA range all stage 1 TLB entries in the indicated // broadcast domain matching the indicated VMID and ASID (where regime // supports VMID, ASID) in the indicated regime with the indicated security state. // ASID, and range related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBI_RVA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if regime == Regime_EL10 && ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; elsif regime == Regime_EL2 && ELIsInHost(EL2) then regime = Regime_EL20; end= broadcast_in; var r : TLBIRecord; r.op = TLBIOp_RVA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Xt[63:48]; r.ttl[1:0] = Xt[38:37]; r.d64 = TRUE; r.d128 = r.ttl[1:0] == '00'; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIRange(regime, Xt); if !valid then return; end; TLBI(r); if broadcast == Broadcast_OSH && IsBroadcast_OSHnISH()(regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_RVAA

// AArch64_TLBI_RVAA() // =================== // Range invalidate by VA range all stage 1 TLB entries in the indicated // broadcast domain matching the indicated VMID (where regimesupports VMID) // and all ASID in the indicated regime with the indicated security state. // VA range related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBI_RVAA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_inbroadcast : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcastr : Broadcast = AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; end; var r : TLBIRecord; r.op = TLBIOp_RVAA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.ttl[1:0] = Xt[38:37]; r.d64 = TRUE; r.d128 = r.ttl[1:0] == '00'; var valid : boolean; (valid, r.tg, r.address, r.end_address) = TLBIRange(regime, Xt); if !valid then return; end; TLBI(r); if broadcast == Broadcast_OSH && IsBroadcast_OSHnISH() then broadcast = Broadcast_OSHnISH(regime, Xt); if !valid then return; end; TLBI(r); if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_VA

// AArch64_TLBI_VA() // ================= // Invalidate by VA all stage 1 TLB entries in the indicated broadcast domain // matching the indicated VMID and ASID (where regime supports VMID, ASID) in the indicated regime // with the indicated security state. // ASID, VA and related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBI_VA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if regime == Regime_EL10 && ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; elsif regime == Regime_EL2 && ELIsInHost(EL2) then regime = Regime_EL20; end= broadcast_in; var r : TLBIRecord; r.op = TLBIOp_VA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.asid = Xt[63:48]; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[43:0] :: Zeros{12}); r.d64 = TRUE; r.d128 = r.ttl == '00xx'; TLBI(r); if broadcast == Broadcast_OSH && IsBroadcast_OSHnISH()(regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_VAA

// AArch64_TLBI_VAA() // ================== // Invalidate by VA all stage 1 TLB entries in the indicated broadcast domain // matching the indicated VMID (where regime supports VMID) and all ASID in the indicated regime // with the indicated security state. // VA and related parameters are derived from Xt. // Note: stage 1 and stage 2 combined entries are in the scope of this operation. func AArch64_TLBI_VAA(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, level : TLBILevel, attr_inattr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; end= broadcast_in; var r : TLBIRecord; r.op = TLBIOp_VAA; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.level = level; r.attr = attr; r.ttl = Xt[47:44]; r.address = ZeroExtend{64}(Xt[43:0] :: Zeros{12}); r.d64 = TRUE; r.d128 = r.ttl == '00xx'; TLBI(r); if broadcast == Broadcast_OSH && IsBroadcast_OSHnISH()(regime) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_VMALL

// AArch64_TLBI_VMALL() // ==================== // Invalidate all stage 1 entries for the indicated translation regime with the // the indicated security state for all TLBs within the indicated broadcast // domain that match the indicated VMID (where applicable). // Note: stage 1 and stage 2 combined entries are in the scope of this operation. // Note: stage 2 only entries are not in the scope of this operation. func AArch64_TLBI_VMALL(security : SecurityState, regime_inregime : Regime, vmid_invmid : bits(16), broadcast_in : Broadcast, attr_inattr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2, EL1}; var broadcast : Broadcast = AArch64_EffectiveBroadcast(broadcast_in); var attr : TLBIMemAttr = attr_in; if attr == TLBI_AllAttr && ExcludeXS() then attr = TLBI_ExcludeXS; end; var regime : Regime = regime_in; var vmid : bits(16) = vmid_in; if ELIsInHost(EL0) then regime = Regime_EL20; vmid = VMID_NONE; end= broadcast_in; var r : TLBIRecord; r.op = TLBIOp_VMALL; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.level = TLBILevel_Any; r.vmid = vmid; r.use_vmid = UseVMID(regime); r.attr = attr; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_VMALLS12

// AArch64_TLBI_VMALLS12() // ======================= // Invalidate all stage 1 and stage 2 entries for the indicated translation // regime with the indicated security state for all TLBs within the indicated // broadcast domain that match the indicated VMID. func AArch64_TLBI_VMALLS12(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, attr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2}; var broadcast : Broadcast = AArch64_EffectiveBroadcast(= broadcast_in);; var r : TLBIRecord; r.op = TLBIOp_VMALLS12; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.level = TLBILevel_Any; r.vmid = vmid; r.use_vmid = TRUE; r.attr = attr; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/AArch64_TLBI_VMALLWS2

// AArch64_TLBI_VMALLWS2() // ======================= // Remove stage 2 dirty state from entries for the indicated translation regime // with the indicated security state for all TLBs within the indicated broadcast // domain that match the indicated VMID. func AArch64_TLBI_VMALLWS2(security : SecurityState, regime : Regime, vmid : bits(16), broadcast_in : Broadcast, attr : TLBIMemAttr, Xt : bits(64)) begin assert PSTATE.EL IN { PSTATE.EL IN {EL3, EL2}; assert regime == Regime_EL10; if security == SS_Secure && HaveEL(EL3) && SCR_EL3().EEL2 == '0' then return; end; var broadcast : Broadcast = broadcast_in; var r : TLBIRecord; r.op = TLBIOp_VMALLWS2; r.from_aarch64 = TRUE; r.security = security; r.regime = regime; r.level = TLBILevel_Any; r.vmid = vmid; r.use_vmid = TRUE; r.attr = attr; TLBI(r); let domains : bits(16) = TLBIDomains(broadcast, Xt[15:0]); if (broadcast == Broadcast_OSH && (IsBroadcast_OSHnISH()(regime) || OSHDomainExceedsNIS(domains))) then broadcast = Broadcast_OSHnISH; end; if broadcast != Broadcast_NSH then BroadcastTLBI(broadcast, r, domains); end; return; end;

Library pseudocode for aarch64/functions/tlbi/GPTTLBIMatch

// GPTTLBIMatch() // ============== // Determine whether the GPT TLB entry lies within the scope of invalidation func GPTTLBIMatch(tlbi : TLBIRecord, gpt_entry : GPTEntry) => boolean begin assert tlbi.op IN {TLBIOp_RPA, TLBIOp_PAALL}; var match : boolean; let entry_size_mask : bits(64) = ZeroExtend{}(Ones{gpt_entry.size}); let entry_end_address : bits(64) = (ZeroExtend{64}(gpt_entry.pa[55:0] OR entry_size_mask[55:0])); let entry_start_address : bits(64) = (ZeroExtend{64}(gpt_entry.pa[55:0] AND NOT entry_size_mask[55:0])); case tlbi.op of when TLBIOp_RPA => match = (UInt(tlbi.address[55:0]) <= UInt(entry_end_address[55:0]) && UInt(tlbi.end_address[55:0]) > UInt(entry_start_address[55:0]) && (tlbi.level == TLBILevel_Any || !gpt_entry.istablegpt_entry.level == 1)); when TLBIOp_PAALL => match = TRUE; end; return match; end;

Library pseudocode for aarch64/functions/tlbi/IsBroadcast_OSHnISH

// IsBroadcast_OSHnISH() // ===================== // Returns TRUE if a TLBI *OS* instruction affects TLBs in the Outer shareability domain, // but not in the Inner shareability domain. func IsBroadcast_OSHnISH()(regime => boolean begin case: PSTATERegime.EL) => boolean begin case regime of when EL3Regime_EL3 => return FALSE; when EL2Regime_EL20 => return IsSCTLR2EL2Enabled() && SCTLR2_EL2().TLBOSNIS == '1'; when EL1Regime_EL10 => return IsSCTLR2EL1Enabled() && SCTLR2_EL1().TLBOSNIS == '1'; otherwise => unreachable; end; end;

Library pseudocode for aarch64/functions/tlbi/TLBIDomains

// TLBIDomains() // ============= // Determine the domains the TLBI operation is broadcast to func TLBIDomains(broadcast_in : Broadcast, tlbid_in : bits(16)) => bits(16) begin assert broadcast_in != Broadcast_OSHnISH; var broadcast : Broadcast = broadcast_in; var tlbid : bits(16) = tlbid_in; if !IsFeatureImplemented(FEAT_TLBID) then return DEFAULT_TLBI_DOMAIN; end; if broadcast == Broadcast_NSH then return DEFAULT_TLBI_DOMAIN; end; if broadcast == Broadcast_ISH_CnP then return DEFAULT_TLBI_DOMAIN; end; if PSTATE.EL == PSTATE.EL == EL3 then return DEFAULT_TLBI_DOMAIN; end; let nos : integer{} = UInt(TLBIDIDR_EL1().NOS); assert nos <= 16; if broadcast == PSTATE.EL == EL0 && HCR_EL2().TGE == '1' then return DEFAULT_TLBI_DOMAIN; end; let nos : integer{} = UInt(TLBIDIDR_EL1().NOS); assert nos <= 16; if broadcast == Broadcast_OSH && nos == 0 then return DEFAULT_TLBI_DOMAIN; end; let nis : integer{} = UInt(TLBIDIDR_EL1().NIS); assert nis <= 16; if broadcast == Broadcast_ISH && nis == 0 then return DEFAULT_TLBI_DOMAIN; end; if PSTATE.EL == PSTATE.EL == EL2 then if broadcast == Broadcast_OSH then return ZeroExtend{16}(tlbid[nos-1:0]); else // Broadcast_ISH return ZeroExtend{16}(tlbid[nis-1:0]); end; end; assert PSTATE.EL == PSTATE.EL == EL1 || (PSTATE.EL == EL0 && HCR_EL2().TGE == '0');; if broadcast == Broadcast_ForcedISH then // For a TLBI instruction without an IS or OS qualifier executed at EL1, if HCR_EL2.FB // is 1 then the process for a TLBI IS instruction is followed as though TLBID is zero. broadcast = Broadcast_ISH; tlbid = Zeros{16}; end; assert broadcast IN {Broadcast_ISH, Broadcast_OSH}; // If the Effective value of VTLBID(OS)En is 0 the TLBID field is not transformed. if ((HaveEL(EL3) && SCR_EL3().VTLBIDEn == '0') || !IsHCRXEL2Enabled() || (broadcast == Broadcast_OSH && HCRX_EL2().VTLBIDOSEn == '0') || (broadcast == Broadcast_ISH && HCRX_EL2().VTLBIDEn == '0')) then if broadcast == Broadcast_OSH then return ZeroExtend{16}(tlbid[nos-1:0]); else // Broadcast_ISH return ZeroExtend{16}(tlbid[nis-1:0]); end; end; if broadcast == Broadcast_OSH then let nvos : integer{} = UInt(TLBIDIDR_EL1().NVOS); assert (nos <= 8 && nvos <= 5) || (nos <= 16 && nvos <= 4); // If NVOS is 0, the TLBID field is ignored as only VTLBIDOS[VTLBIDOS_EL2(n]_EL2.TD0).TD0 is implemented. let d : integer{} = if nvos == 0 then 0 else UInt(tlbid[nvos-1:0]); let s : integer{} = if nos <= 8 then 8 else 4; let n : integer = d DIVRM s; let m : integer = d MOD s; var vtlbid : bits(16); if nos <= 8 then vtlbid = ZeroExtend{16}(VTLBIDOS_EL2(n)[8*m+:8]); else vtlbid = VTLBIDOS_EL2(n)[16*m+:16]; end; return ZeroExtend{16}(vtlbid[nos-1:0]); else // Broadcast_ISH let nvis : integer{} = UInt(TLBIDIDR_EL1().NVIS); assert (nis <= 8 && nvis <= 5) || (nis <= 16 && nvis <= 4); // If NVIS is 0, the TLBID field is ignored as only VTLBID[VTLBID_EL2(n]_EL2.TD0).TD0 is implemented. let d : integer{} = if nvis == 0 then 0 else UInt(tlbid[nvis-1:0]); let s : integer{} = if nis <= 8 then 8 else 4; let n : integer = d DIVRM s; let m : integer = d MOD s; var vtlbid : bits(16); if nis <= 8 then vtlbid = ZeroExtend{16}(VTLBID_EL2(n)[8*m+:8]); else vtlbid = VTLBID_EL2(n)[16*m+:16]; end; return ZeroExtend{16}(vtlbid[nis-1:0]); end; end;

Library pseudocode for aarch64/translation/vmsa_faults/AArch64_S1DirectBasePermissions

// AArch64_S1DirectBasePermissions() // ================================= // Computes the stage 1 direct base permissions func AArch64_S1DirectBasePermissions(regime : Regime, walkstate : TTWState, walkparams : S1TTWParams, accdesc : AccessDescriptor) => S1AccessControls begin var r, w, x : bit; var pr, pw, px : bit; var ur, uw, ux : bit; var permissions : Permissions = walkstate.permissions; var s1perms : S1AccessControls; // Descriptors marked with DBM set have the effective value of AP[2] cleared. // This implies no Permission faults caused by lack of write permissions are // reported, and the Dirty bit can be set. if permissions.dbm == '1' && walkparams.hd == '1' then permissions.ap[2] = '0'; end; if HasUnprivileged(regime) then // Apply leaf permissions case permissions.ap[2:1] of when '00' => (pr,pw,ur,uw) = ('1','1','0','0'); // Privileged access when '01' => (pr,pw,ur,uw) = ('1','1','1','1'); // No effect when '10' => (pr,pw,ur,uw) = ('1','0','0','0'); // Read-only, privileged access when '11' => (pr,pw,ur,uw) = ('1','0','1','0'); // Read-only end; // Apply hierarchical permissions case permissions.ap_table of when '00' => (pr,pw,ur,uw) = ( pr, pw, ur, uw); // No effect when '01' => (pr,pw,ur,uw) = ( pr, pw,'0','0'); // Privileged access when '10' => (pr,pw,ur,uw) = ( pr,'0', ur,'0'); // Read-only when '11' => (pr,pw,ur,uw) = ( pr,'0','0','0'); // Read-only, privileged access end; // Locations writable by unprivileged cannot be executed by privileged px = NOT(permissions.pxn OR permissions.pxn_table OR uw); ux = NOT(permissions.uxn OR permissions.uxn_table); if (IsFeatureImplemented(FEAT_PAN) && accdesc.pan && !(regime == Regime_EL10 && walkparams.nv1 == '1')) then var pan : bit; if (ImpDefBool("SCR_EL3.SIF affects EPAN") && accdesc.ss == SS_Secure && walkstate.baseaddress.paspace == PAS_NonSecure && walkparams.sif == '1') then ux = '0'; end; if (ImpDefBool("Realm EL2&0 regime affects EPAN") && accdesc.ss == SS_Realm && regime == Regime_EL20 && walkstate.baseaddress.paspace != PAS_Realm) then ux = '0'; end; letpan = PSTATE.PAN AND (ur OR uw OR (walkparams.epan AND ux)); pr = pr AND NOT(pan); pw := bitpw AND NOT(pan); end; else // Apply leaf permissions case permissions.ap[2] of when '0' => (pr,pw) = ('1','1'); // No effect when '1' => (pr,pw) = ('1','0'); // Read-only end; // Apply hierarchical permissions case permissions.ap_table[1] of when '0' => (pr,pw) = ( pr, pw); // No effect when '1' => (pr,pw) = ( pr,'0'); // Read-only end; px = NOT(permissions.xn OR permissions.xn_table); end; (r,w,x) = if accdesc.el == PSTATE.PAN AND (ur OR uw OR (walkparams.epan AND ux)); pr = pr AND NOT(pan); pw = pw AND NOT(pan); end; else // Apply leaf permissions case permissions.ap[2] of when '0' => (pr,pw) = ('1','1'); // No effect when '1' => (pr,pw) = ('1','0'); // Read-only end; // Apply hierarchical permissions case permissions.ap_table[1] of when '0' => (pr,pw) = ( pr, pw); // No effect when '1' => (pr,pw) = ( pr,'0'); // Read-only end; px = NOT(permissions.xn OR permissions.xn_table); end; (r,w,x) = if accdesc.el == EL0 then (ur,uw,ux) else (pr,pw,px); // Compute WXN value let wxn : bit = walkparams.wxn AND w AND x; // Prevent execution from Non-secure space by PE in secure state if SIF is set if accdesc.ss == SS_Secure && walkstate.baseaddress.paspace == PAS_NonSecure then x = x AND NOT(walkparams.sif); end; // Prevent execution from non-Root space by Root if accdesc.ss == SS_Root && walkstate.baseaddress.paspace != PAS_Root then x = '0'; end; // Prevent execution from non-Realm space by Realm EL2 and Realm EL2&0 if (accdesc.ss == SS_Realm && regime IN {Regime_EL2, Regime_EL20} && walkstate.baseaddress.paspace != PAS_Realm) then x = '0'; end; s1perms.r = r; s1perms.w = w; s1perms.x = x; s1perms.gcs = '0'; s1perms.wxn = wxn; s1perms.overlay = TRUE; return s1perms; end;

Library pseudocode for aarch64/translation/vmsa_faults/AArch64_S1HasAlignmentFaultDueToMemType

// AArch64_S1HasAlignmentFaultDueToMemType() // ========================================= // Returns whether stage 1 output fails alignment requirement on data accesses due to memory type func AArch64_S1HasAlignmentFaultDueToMemType(regime : Regime, accdesc : AccessDescriptor, aligned : boolean, ntlsmd : bit, memattrs : MemoryAttributes) => boolean begin if accdesc.exclusive || accdesc.atomicop || accdesc.acqsc || accdesc.acqpc || accdesc.relsc then if (!aligned && !(IsWBShareable(memattrs) && AArch64_S1DCacheEnabled(regime)) && ConstrainUnpredictableBool(Unpredictable_LSE2_ALIGNMENT_FAULT)) then return TRUE; end; end; iflet memattrs.memtypeisTagWrite !=: MemType_Deviceboolean then return= FALSE; elsifaccdesc.cachetype ((accdesc.acctypeIN =={ AccessType_DCZero && accdesc.cachetype IN {CacheType_Tag, CacheType_TagWrite, CacheType_TagZero }; if memattrs.memtype != MemType_Device then return FALSE; elsif ((accdesc.acctype == AccessType_DCZero})&& isTagWrite) || accdesc.stzgm) then return ConstrainUnpredictable(Unpredictable_DEVICETAGSTORE) == Constraint_FAULT; elsif accdesc.a32lsmd && ntlsmd == '0' then return memattrs.device != DeviceType_GRE; elsif accdesc.acctype == AccessType_DCZero then return TRUE; elsif !aligned then return !(ImpDefBool("Device location supports unaligned access")); else return FALSE; end; end;

Library pseudocode for aarch64/translation/vmsa_faults/AArch64_S1IndirectBasePermissions

// AArch64_S1IndirectBasePermissions() // =================================== // Computes the stage 1 indirect base permissions func AArch64_S1IndirectBasePermissions(regime : Regime, walkstate : TTWState, walkparams : S1TTWParams, accdesc : AccessDescriptor) => S1AccessControls begin var r, w, x, gcs, wxn, overlay : bit; var pr, pw, px, pgcs, pwxn, p_overlay : bit; var ur, uw, ux, ugcs, uwxn, u_overlay : bit; let permissions : Permissions = walkstate.permissions; var s1perms : S1AccessControls; // Apply privileged indirect permissions case permissions.ppi of when '0000' => (pr,pw,px,pgcs) = ('0','0','0','0'); // No access when '0001' => (pr,pw,px,pgcs) = ('1','0','0','0'); // Privileged read when '0010' => (pr,pw,px,pgcs) = ('0','0','1','0'); // Privileged execute when '0011' => (pr,pw,px,pgcs) = ('1','0','1','0'); // Privileged read and execute when '0100' => (pr,pw,px,pgcs) = ('0','0','0','0'); // Reserved when '0101' => (pr,pw,px,pgcs) = ('1','1','0','0'); // Privileged read and write when '0110' => (pr,pw,px,pgcs) = ('1','1','1','0'); // Privileged read, write and execute when '0111' => (pr,pw,px,pgcs) = ('1','1','1','0'); // Privileged read, write and execute when '1000' => (pr,pw,px,pgcs) = ('1','0','0','0'); // Privileged read when '1001' => (pr,pw,px,pgcs) = ('1','0','0','1'); // Privileged read and gcs when '1010' => (pr,pw,px,pgcs) = ('1','0','1','0'); // Privileged read and execute when '1011' => (pr,pw,px,pgcs) = ('0','0','0','0'); // Reserved when '1100' => (pr,pw,px,pgcs) = ('1','1','0','0'); // Privileged read and write when '1101' => (pr,pw,px,pgcs) = ('0','0','0','0'); // Reserved when '1110' => (pr,pw,px,pgcs) = ('1','1','1','0'); // Privileged read, write and execute when '1111' => (pr,pw,px,pgcs) = ('0','0','0','0'); // Reserved end; p_overlay = NOT(permissions.ppi[3]); pwxn = if permissions.ppi == '0110' then '1' else '0'; if HasUnprivileged(regime) then // Apply unprivileged indirect permissions case permissions.upi of when '0000' => (ur,uw,ux,ugcs) = ('0','0','0','0'); // No access when '0001' => (ur,uw,ux,ugcs) = ('1','0','0','0'); // Unprivileged read when '0010' => (ur,uw,ux,ugcs) = ('0','0','1','0'); // Unprivileged execute when '0011' => (ur,uw,ux,ugcs) = ('1','0','1','0'); // Unprivileged read and execute when '0100' => (ur,uw,ux,ugcs) = ('0','0','0','0'); // Reserved when '0101' => (ur,uw,ux,ugcs)=('1','1','0','0');// Unprivileged read and write when '0110' => (ur,uw,ux,ugcs)=('1','1','1','0');// Unprivileged read, write and execute when '0111' => (ur,uw,ux,ugcs)=('1','1','1','0');// Unprivileged read, write and execute when '1000' => (ur,uw,ux,ugcs)=('1','0','0','0');// Unprivileged read when '1001' => (ur,uw,ux,ugcs)=('1','0','0','1');// Unprivileged read and gcs when '1010' => (ur,uw,ux,ugcs)=('1','0','1','0');// Unprivileged read and execute when '1011' => (ur,uw,ux,ugcs) = ('0','0','0','0');// Reserved when '1100' => (ur,uw,ux,ugcs) =('1','1','0','0');// Unprivileged read and write when '1101' => (ur,uw,ux,ugcs) =('0','0','0','0');// Reserved when '1110' => (ur,uw,ux,ugcs) =('1','1','1','0');// Unprivileged read,write and execute when '1111' => (ur,uw,ux,ugcs) =('0','0','0','0');// Reserved end; u_overlay = NOT(permissions.upi[3]); uwxn = if permissions.upi == '0110' then '1' else '0'; // If the decoded permissions has either px or pgcs along with either uw or ugcs, // then all effective Stage 1 Base Permissions are set to 0 if ((px == '1' || pgcs == '1') && (uw == '1' || ugcs == '1')) then (pr,pw,px,pgcs) = ('0','0','0','0'); (ur,uw,ux,ugcs) = ('0','0','0','0'); elsifend; if (IsFeatureImplemented(FEAT_PAN) && accdesc.pan && !(regime == Regime_EL10 && walkparams.nv1 == '1')) then if PSTATE.PAN == '1' && (ImpDefBool("Realmpermissions.upi EL2&0!= regime'0000') affectsthen (pr,pw) EPAN")= &&('0','0'); end; end; end; if accdesc.ssaccdesc.el == SS_Realm && regime == Regime_EL20 && walkstate.baseaddress.paspace != PAS_Realm) then ux = '0'; end; if (ImpDefBool("SCR_EL3.SIF affects EPAN") && accdesc.ss == SS_Secure && walkstate.baseaddress.paspace == PAS_NonSecure && walkparams.sif == '1') then ux = '0'; end; if PSTATE.PAN == '1' && (!IsZero(ur::uw::ux::ugcs) || (!IsZero(permissions.upi) && ImpDefBool("PAN applies when S1UnprivBasePerm is reserved"))) then (pr,pw) = ('0','0'); end; end; end; if accdesc.el == EL0 then (r,w,x,gcs,wxn,overlay) = (ur,uw,ux,ugcs,uwxn,u_overlay); else (r,w,x,gcs,wxn,overlay) = (pr,pw,px,pgcs,pwxn,p_overlay); end; // Prevent execution from Non-secure space by PE in secure state if SIF is set if accdesc.ss == SS_Secure && walkstate.baseaddress.paspace == PAS_NonSecure then x = x AND NOT(walkparams.sif); gcs = '0'; end; // Prevent execution from non-Root space by Root if accdesc.ss == SS_Root && walkstate.baseaddress.paspace != PAS_Root then x = '0'; gcs = '0'; end; // Prevent execution from non-Realm space by Realm EL2 and Realm EL2&0 if (accdesc.ss == SS_Realm && regime IN {Regime_EL2, Regime_EL20} && walkstate.baseaddress.paspace != PAS_Realm) then x = '0'; gcs = '0'; end; s1perms.r = r; s1perms.w = w; s1perms.x = x; s1perms.gcs = gcs; s1perms.wxn = wxn; s1perms.overlay = overlay == '1'; return s1perms; end;

Library pseudocode for aarch64/translation/vmsa_faults/AArch64_S2CheckPermissions

// AArch64_S2CheckPermissions() // ============================ // Verifies memory access with available permissions. func AArch64_S2CheckPermissions(fault_in : FaultRecord, walkstate : TTWState, walkparams : S2TTWParams, ipa : AddressDescriptor, accdesc : AccessDescriptor) => (FaultRecord, boolean) begin let memtype : MemType = walkstate.memattrs.memtype; let permissions : Permissions = walkstate.permissions; var fault : FaultRecord = fault_in; let s2perms : S2AccessControls = AArch64_S2ComputePermissions(permissions, walkparams, accdesc); var r, w : bit; var or, ow : bit; if accdesc.acctype == AccessType_TTW then r = s2perms.r_mmu; w = s2perms.w_mmu; or = s2perms.or_mmu; ow = s2perms.ow_mmu; elsif accdesc.rcw then r = s2perms.r_rcw; w = s2perms.w_rcw; or = s2perms.or_rcw; ow = s2perms.ow_rcw; else r = s2perms.r; w = s2perms.w; or = s2perms.or; ow = s2perms.ow; end; if accdesc.acctype == AccessType_TTW then if (accdesc.toplevel && accdesc.varange == VARange_LOWER && ((walkparams.tl0 == '1' && s2perms.toplevel0 == '0') || (walkparams.tl1 == '1' && s2perms.[toplevel1,toplevel0] == '10'))) then fault.statuscode = Fault_Permission; fault.toplevel = TRUE; elsif (accdesc.toplevel && accdesc.varange == VARange_UPPER && ((walkparams.tl1 == '1' && s2perms.toplevel1 == '0') || (walkparams.tl0 == '1' && s2perms.[toplevel1,toplevel0] == '01'))) then fault.statuscode = Fault_Permission; fault.toplevel = TRUE; // Stage 2 Permission fault due to AssuredOnly check elsif (walkstate.s2assuredonly == '1' && !ipa.s1assured) then fault.statuscode = Fault_Permission; fault.assuredonly = TRUE; elsif s2perms.overlay && or == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif accdesc.write && s2perms.overlay && ow == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif walkparams.ptw == '1' && memtype == MemType_Device then fault.statuscode = Fault_Permission; // Prevent translation table walks in Non-secure space by Realm state elsif accdesc.ss == SS_Realm && walkstate.baseaddress.paspace != PAS_Realm then fault.statuscode = Fault_Permission; elsif r == '0' then fault.statuscode = Fault_Permission; elsif accdesc.write && w == '0' then fault.statuscode = Fault_Permission; fault.hdbssf = walkparams.hdbss == '1' && !CanAppendToHDBSS() && permissions.dbm == '1'; elsif (accdesc.write && (walkparams.hd walkparams.s2pie!= == '1' &&|| permissions.s2dirty(walkparams.hdbss == '01' && (walkparams.hd !=!CanAppendToHDBSS())) '1' || (accdesc.acctype != AccessType_AT && walkparams.hdbsswalkparams.s2pie == '1' && !CanAppendToHDBSS())))permissions.s2dirty == '0') then fault.statuscode = Fault_Permission; fault.dirtybit = TRUE; fault.hdbssf = walkparams.hdbss == '1' && !CanAppendToHDBSS(); end; // Stage 2 Permission fault due to AssuredOnly check elsif ((walkstate.s2assuredonly == '1' && !ipa.s1assured) || (walkstate.s2assuredonly != '1' && IsFeatureImplemented(FEAT_GCS) && VTCR_EL2().GCSH == '1' && accdesc.acctype == AccessType_GCS && accdesc.el != EL0)) then fault.statuscode = Fault_Permission; fault.assuredonly = TRUE; elsif accdesc.acctype == AccessType_IFETCH then if s2perms.overlay && s2perms.ox == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif (memtype == MemType_Device && ConstrainUnpredictable(Unpredictable_INSTRDEVICE) == Constraint_FAULT) then fault.statuscode = Fault_Permission; // Prevent execution from Non-secure space by Realm state elsif accdesc.ss == SS_Realm && walkstate.baseaddress.paspace != PAS_Realm then fault.statuscode = Fault_Permission; elsif s2perms.x == '0' then fault.statuscode = Fault_Permission; end; elsif accdesc.acctype == AccessType_DC then if accdesc.cacheop == CacheOp_Invalidate then if !ELUsingAArch32(EL1) && s2perms.overlay && ow == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif !ELUsingAArch32(EL1) && w == '0' then fault.statuscode = Fault_Permission; elsif (walkparams.hd != '1' && walkparams.s2pie == '1' && permissions.s2dirty == '0') then fault.statuscode = Fault_Permission; fault.dirtybit = TRUE; end; elsif !ELUsingAArch32(EL1) && accdesc.el == EL0 && s2perms.overlay && or == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif (walkparams.cmow == '1' && accdesc.cacheop == CacheOp_CleanInvalidate && s2perms.overlay && ow == '0') then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif !ELUsingAArch32(EL1) && accdesc.el == EL0 && r == '0' then fault.statuscode = Fault_Permission; elsif (walkparams.cmow == '1' && accdesc.cacheop == CacheOp_CleanInvalidate && w == '0') then fault.statuscode = Fault_Permission; elsif (walkparams.cmow == '1' && accdesc.cacheop == CacheOp_CleanInvalidate && walkparams.hd != '1' && walkparams.s2pie == '1' && permissions.s2dirty == '0') then fault.statuscode = Fault_Permission; fault.dirtybit = TRUE; end; elsif accdesc.acctype == AccessType_IC then if (!ELUsingAArch32(EL1) && accdesc.el == EL0 && s2perms.overlay && or == '0' && ImpDefBool("Permission fault on EL0 IC_IVAU execution")) then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif walkparams.cmow == '1' && s2perms.overlay && ow == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; elsif (!ELUsingAArch32(EL1) && accdesc.el == EL0 && r == '0' && ImpDefBool("Permission fault on EL0 IC_IVAU execution")) then fault.statuscode = Fault_Permission; elsif walkparams.cmow == '1' && w == '0' then fault.statuscode = Fault_Permission; elsif (walkparams.cmow == '1' && walkparams.hd != '1' && walkparams.s2pie == '1' && permissions.s2dirty == '0') then fault.statuscode = Fault_Permission; fault.dirtybit = TRUE; end; elsif accdesc.read && s2perms.overlay && or == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; fault.write = FALSE; elsif accdesc.write && s2perms.overlay && ow == '0' then fault.statuscode = Fault_Permission; fault.overlay = TRUE; fault.write = TRUE; elsif accdesc.read && r == '0' then fault.statuscode = Fault_Permission; fault.write = FALSE; elsif accdesc.write && w == '0' then fault.statuscode = Fault_Permission; fault.write = TRUE; fault.hdbssf = walkparams.hdbss == '1' && !CanAppendToHDBSS() && permissions.dbm == '1'; elsif (IsFeatureImplemented(FEAT_MTE_PERM) && ((accdesc.tagchecked && AArch64_EffectiveTCF(accdesc.el, accdesc.read) != TCFType_Ignore) || accdesc.tagaccess) && ipa.memattrs.tags == MemTag_AllocationTagged && permissions.s2tag_na == '1' && S2DCacheEnabled()) then fault.statuscode = Fault_Permission; fault.tagaccess = TRUE; fault.write = accdesc.tagaccess && accdesc.write; elsif (accdesc.write && (walkparams.hd != '1' || (walkparams.hdbss == '1' && !CanAppendToHDBSS())) && walkparams.s2pie == '1' && permissions.s2dirty == '0') then fault.statuscode = Fault_Permission; fault.dirtybit = TRUE; fault.write = TRUE; fault.hdbssf = walkparams.hdbss == '1' && !CanAppendToHDBSS(); end; // MRO* allows only RCW and MMU writes var mro : boolean; if s2perms.overlay then mro = (s2perms.[w,w_rcw,w_mmu] AND s2perms.[ow,ow_rcw,ow_mmu]) == '011'; else mro = s2perms.[w,w_rcw,w_mmu] == '011'; end; return (fault, mro); end;

Library pseudocode for aarch64/translation/vmsa_faults/AArch64_S2HasAlignmentFaultDueToMemType

// AArch64_S2HasAlignmentFaultDueToMemType() // ========================================= // Returns whether stage 2 output fails alignment requirement on data accesses due to memory type func AArch64_S2HasAlignmentFaultDueToMemType(accdesc : AccessDescriptor, aligned : boolean, memattrs : MemoryAttributes) => boolean begin if accdesc.exclusive || accdesc.atomicop || accdesc.acqsc || accdesc.acqpc || accdesc.relsc then if (!aligned && !(IsWBShareable(memattrs) && S2DCacheEnabled()) && ConstrainUnpredictableBool(Unpredictable_LSE2_ALIGNMENT_FAULT)) then return TRUE; end; end; if memattrs.memtype != MemType_Device then return FALSE; elsif ((accdesc.acctype == AccessType_DCZero && accdesc.cachetype IN {==CacheType_Tag,) || accdesc.stzgm) then return ConstrainUnpredictable( CacheType_TagWrite, CacheType_TagZero}) || accdesc.stzgm) then return ConstrainUnpredictable(Unpredictable_DEVICETAGSTORE) == Constraint_FAULT; elsif accdesc.acctype == AccessType_DCZero then return TRUE; elsif !aligned then return !(ImpDefBool("Device location supports unaligned access")); else return FALSE; end; end;

Library pseudocode for aarch64/translation/vmsa_translation/AArch64_S1Translate

// AArch64_S1Translate() // ===================== // Translate VA to IPA/PA depending on the regime func AArch64_S1Translate(fault_in : FaultRecord, regime : Regime, va : bits(64), size : integer, aligned : boolean, accdesc : AccessDescriptor) => (FaultRecord, AddressDescriptor) recurselimit Unbounded_DescriptorUpdate begin var fault : FaultRecord = fault_in; // Prepare fault fields in case a fault is detected fault.secondstage = FALSE; fault.s2fs1walk = FALSE; if !AArch64_S1Enabled(regime, accdesc.acctype) then return AArch64_S1DisabledOutput(fault, regime, va, accdesc, aligned); end; var walkparams : S1TTWParams = AArch64_GetS1TTWParams(regime, accdesc.el, accdesc.ss, va); let s1mintxsz : integer = AArch64_S1MinTxSZ(regime, walkparams); let s1maxtxsz : integer = AArch64_MaxTxSZ(walkparams.tgx); if AArch64_S1TxSZFaults(regime, walkparams) then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); elsif UInt(walkparams.txsz) < s1mintxsz then walkparams.txsz = s1mintxsz[5:0]; elsif UInt(walkparams.txsz) > s1maxtxsz then walkparams.txsz = s1maxtxsz[5:0]; end; if AArch64_VAIsOutOfRange(va, accdesc.acctype, regime, walkparams) then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); end; if accdesc.el == EL0 && walkparams.e0pd == '1' then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); end; if (IsFeatureImplemented(FEAT_SVE) && accdesc.el == EL0 && walkparams.nfd == '1' && ((accdesc.nonfault && accdesc.contiguous) || (accdesc.firstfault && !accdesc.first && !accdesc.contiguous))) then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); end; var descipaddr : AddressDescriptor; var walkstate : TTWState; var descriptor : bits(128); if walkparams.d128 == '1' then (fault, descipaddr, walkstate, descriptor) = AArch64_S1Walk{128}(fault, walkparams, va, regime, accdesc); else (fault, descipaddr, walkstate, descriptor[63:0]) = AArch64_S1Walk{64}(fault, walkparams, va, regime, accdesc); descriptor[127:64] = Zeros{64}; end; if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor); end; if AArch64_S1HasAlignmentFaultDueToMemType(regime, accdesc, aligned, walkparams.ntlsmd, walkstate.memattrs) then fault.statuscode = Fault_Alignment; end; let fault_perm : FaultRecord = AArch64_S1CheckPermissions(fault, va, size, regime, walkstate, walkparams, accdesc); var mem_desc : bits(128); var new_desc : bits(128) = descriptor; if AArch64_SetAccessFlag(walkparams.ha, accdesc, fault) then // Set descriptor AF bit new_desc[10] = '1'; end; // If HW update of dirty bit is enabled, the walk state permissions // will already reflect a configuration permitting writes. // The update of the descriptor occurs only if the descriptor bits in // memory do not reflect that and the access instigates a write. if AArch64_SetDirtyState(walkparams.hd, (walkparams.pie OR descriptor[51]), accdesc, fault, fault_perm) then // Clear descriptor AP[2]/nDirty bit permitting stage 1 writes new_desc[7] = '0'; end; if fault.statuscode == Fault_None && fault_perm.statuscode != Fault_None then fault = fault_perm; end; // Either the access flag was clear or AP[2]/nDirty wasis set if new_desc != descriptor then ifvar (!descpaddr :IsWBShareable(descipaddr.memattrs) && ConstrainUnpredictableBool(Unpredictable_Unsupported_Atomic_HW_Update)) then fault.statuscode = Fault_HWUpdateAccessFlag; return (fault, ARBITRARY : AddressDescriptor); end; var descpaddr : AddressDescriptor; let descaccess : AccessDescriptor = CreateAccDescTTEUpdate(accdesc); if regime == Regime_EL10 && EL2Enabled() then var s2fault : FaultRecord; let s1aarch64 : boolean = TRUE; let s2aligned : boolean = TRUE; (s2fault, descpaddr) = AArch64_S2Translate(fault, descipaddr, s1aarch64, s2aligned, descaccess); if s2fault.statuscode != Fault_None then return (s2fault, ARBITRARY : AddressDescriptor); end; else descpaddr = descipaddr; end; if walkparams.d128 == '1' then (fault, mem_desc) = AArch64_MemSwapTableDesc{128}(fault, descriptor, new_desc, walkparams.ee, descaccess, descpaddr); else (fault, mem_desc[63:0]) = AArch64_MemSwapTableDesc{64}(fault, descriptor[63:0], new_desc[63:0], walkparams.ee, descaccess, descpaddr); mem_desc[127:64] = Zeros{64}; end; if fault.statuscode != Fault_None then if (accdesc.acctype == AccessType_AT && !(ImpDefBool("AT reports the HW update fault"))) then // Mask the fault fault.statuscode = Fault_None; else return (fault, ARBITRARY : AddressDescriptor); end; elsif new_desc != descriptor && mem_desc != new_desc then // HW update of Dirty state or AF was not successful due to the descriptor being updated // not matching the descriptor used for translation. Due to this, the walk is restarted. return AArch64_S1Translate(fault_in, regime, va, size, aligned, accdesc); end; end; if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor); end; // Output Address let oa : FullAddress = StageOA(va, walkparams.d128, walkparams.tgx, walkstate); var memattrs : MemoryAttributes; if AArch64_S1TreatAsNormalNC(walkstate, regime, accdesc) then // Treat memory attributes as Normal Non-Cacheable memattrs = NormalNCMemAttr(); memattrs.xs = walkstate.memattrs.xs; // The effect of SCTLR_ELx.C when '0' is Constrained UNPREDICTABLE on the Tagged attribute // when the memory region is Allocation Tagged. if (IsFeatureImplemented(FEAT_MTE2) && walkstate.memattrs.tags == MemTag_AllocationTagged && ConstrainUnpredictableBool(Unpredictable_S1CTAGGED)) then memattrs.tags = MemTag_AllocationTagged; // SCTLR_ELx.C has no effect on whether the memory region is treated as Canonically Tagged. elsif (IsFeatureImplemented(FEAT_MTE_CANONICAL_TAGS) && walkstate.memattrs.tags == MemTag_CanonicallyTagged) then memattrs.tags = MemTag_CanonicallyTagged; end; else memattrs = walkstate.memattrs; end; // Shareability value of stage 1 translation subject to stage 2 is IMPLEMENTATION DEFINED // to be either effective value or descriptor value if (regime == Regime_EL10 && EL2Enabled() && HCR_EL2().VM == '1' && !(ImpDefBool("Apply effective shareability at stage 1"))) then memattrs.shareability = walkstate.memattrs.shareability; else memattrs.shareability = EffectiveShareability(memattrs); end; var ipa : AddressDescriptor = CreateAddressDescriptor(va, oa, memattrs, accdesc); ipa.s1assured = walkstate.s1assured; let varange : VARange = AArch64_GetVARange(va); ipa.mecid = AArch64_S1OutputMECID{128}(walkparams, regime, varange, ipa.paddress.paspace, descriptor); if (accdesc.atomicop && !IsWBShareable(memattrs) && ConstrainUnpredictableBool(Unpredictable_Atomic_MMU_IMPDEF_FAULT)) then fault.statuscode = Fault_Exclusive; return (fault, ipa); end; if accdesc.ls64 && memattrs.memtype == MemType_Normal then if IsFeatureImplemented(FEAT_LS64WB) && !accdesc.withstatus then if (!IsWBShareable(memattrs) && !(memattrs.inner.attrs == MemAttr_NC && memattrs.outer.attrs == MemAttr_NC) && (ImpDefBool( "LD64B or ST64B faults to cacheable non-iWBoWB memory"))) then fault.statuscode = Fault_Exclusive; return (fault, ipa); end; elsif !(memattrs.inner.attrs == MemAttr_NC && memattrs.outer.attrs == MemAttr_NC) then fault.statuscode = Fault_Exclusive; return (fault, ipa); end; end; return (fault, ipa); end;

Library pseudocode for aarch64/translation/vmsa_translation/AArch64_S2Translate

// AArch64_S2Translate() // ===================== // Translate stage 1 IPA to PA and combine memory attributes func AArch64_S2Translate(fault_in : FaultRecord, ipa : AddressDescriptor, s1aarch64 : boolean, aligned : boolean, accdesc : AccessDescriptor) => (FaultRecord, AddressDescriptor) recurselimit Unbounded_DescriptorUpdate begin var walkparams : S2TTWParams = AArch64_GetS2TTWParams(accdesc.ss, ipa.paddress.paspace, s1aarch64); var fault : FaultRecord = fault_in; var s2fs1mro : boolean; // Prepare fault fields in case a fault is detected fault.statuscode = Fault_None; // Ignore any faults from stage 1 fault.dirtybit = FALSE; fault.overlay = FALSE; fault.tagaccess = FALSE; fault.s1tagnotdata = FALSE; fault.secondstage = TRUE; fault.s2fs1walk = accdesc.acctype == AccessType_TTW; fault.ipaddress = ipa.paddress; if walkparams.vm != '1' then // Stage 2 translation is disabled return (fault, ipa); end; let s2mintxsz : integer = AArch64_S2MinTxSZ(walkparams, s1aarch64); let s2maxtxsz : integer = AArch64_MaxTxSZ(walkparams.tgx); if AArch64_S2TxSZFaults(walkparams, s1aarch64) then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); elsif UInt(walkparams.txsz) < s2mintxsz then walkparams.txsz = s2mintxsz[5:0]; elsif UInt(walkparams.txsz) > s2maxtxsz then walkparams.txsz = s2maxtxsz[5:0]; end; if (walkparams.d128 == '0' && (AArch64_S2InvalidSL(walkparams) || AArch64_S2InconsistentSL(walkparams))) then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); end; if AArch64_IPAIsOutOfRange(ipa.paddress.address, walkparams) then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor); end; var descpaddr : AddressDescriptor; var walkstate : TTWState; var descriptor : bits(128); if walkparams.d128 == '1' then (fault, descpaddr, walkstate, descriptor) = AArch64_S2Walk{128}(fault, ipa, walkparams, accdesc); else (fault, descpaddr, walkstate, descriptor[63:0]) = AArch64_S2Walk{64}(fault, ipa, walkparams, accdesc); descriptor[127:64] = Zeros{64}; end; if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor); end; if AArch64_S2HasAlignmentFaultDueToMemType(accdesc, aligned, walkstate.memattrs) then fault.statuscode = Fault_Alignment; end; var fault_perm : FaultRecord; (fault_perm, s2fs1mro) = AArch64_S2CheckPermissions(fault, walkstate, walkparams, ipa, accdesc); var mem_desc : bits(128); var new_desc : bits(128) = descriptor; if AArch64_SetAccessFlag(walkparams.ha, accdesc, fault) then // Set descriptor AF bit new_desc[10] = '1'; end; // If HW update of dirty bit is enabled, the walk state permissions // will already reflect a configuration permitting writes. // The update of the descriptor occurs only if the descriptor bits in // memory do not reflect that and the access instigates a write. if AArch64_SetDirtyState(walkparams.hd, (walkparams.s2pie OR descriptor[51]), accdesc, fault, fault_perm) then // Set descriptor S2AP[1]/Dirty bit permitting stage 2 writes new_desc[7] = '1'; end; if fault.statuscode == Fault_None && fault_perm.statuscode != Fault_None then fault = fault_perm; end; // Either the access flag was clear or S2AP[1]/Dirty wasis clear if new_desc != descriptor then if walkparams.hdbss == '1' && descriptor[7] == '0' && new_desc[7] == '1' then fault = AppendToHDBSS(fault, ipa.paddress, accdesc, walkparams, walkstate.level); end; // If an error, other than a synchronous External abort, occurred on the HDBSS update, // stage 2 hardware update of dirty state is not permitted. if (HDBSSPROD_EL2().FSC != '101000' && (!fault.hdbssf ||IsWBShareable(descpaddr.memattrs) && ConstrainUnpredictableBool(Unpredictable_Unsupported_Atomic_HW_Update)) then fault.statuscode = Fault_HWUpdateAccessFlag; return (fault, ARBITRARY : AddressDescriptor); end; if walkparams.hdbss == '1' && descriptor[7] == '0' && new_desc[7] == '1' then fault = AppendToHDBSS(fault, ipa.paddress, accdesc, walkparams, walkstate.level); end; // If an error, other than a synchronous External abort, occurred on the HDBSS update, // stage 2 hardware update of dirty state is not permitted. if (!(walkparams.hdbss == '1' && descriptor[7] != new_desc[7]) || (HDBSSPROD_EL2().FSC != '101000' && (!fault.hdbssf || IsExternalAbort(fault.statuscode))))))) then let descaccess : AccessDescriptor = CreateAccDescTTEUpdate(accdesc); if walkparams.d128 == '1' then (fault, mem_desc) = AArch64_MemSwapTableDesc{128}(fault, descriptor, new_desc, walkparams.ee, descaccess, descpaddr); else (fault, mem_desc[63:0]) = AArch64_MemSwapTableDesc{64}(fault, descriptor[63:0], new_desc[63:0], walkparams.ee, descaccess, descpaddr); mem_desc[127:64] = Zeros{64}; end; end; if fault.statuscode != Fault_None then if (accdesc.acctype == AccessType_AT && !(ImpDefBool("AT reports the HW update fault"))) then // Mask the fault fault.statuscode = Fault_None; else return (fault, ARBITRARY : AddressDescriptor); end; elsif new_desc != descriptor && mem_desc != new_desc then // HW update of Dirty state or AF was not successful due to the descriptor being updated // not matching the descriptor used for translation. Due to this, the walk is restarted. return AArch64_S2Translate(fault_in, ipa, s1aarch64, aligned, accdesc); end; end; if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor); end; let ipa_64 : bits(64) = ZeroExtend{}(ipa.paddress.address); // Output Address let oa : FullAddress = StageOA(ipa_64, walkparams.d128, walkparams.tgx, walkstate); var s2_memattrs : MemoryAttributes; if AArch64_S2TreatAsNormalNC(walkstate, walkparams, accdesc) then // Treat memory attributes as Normal Non-Cacheable s2_memattrs = NormalNCMemAttr(); s2_memattrs.xs = walkstate.memattrs.xs; if walkstate.memattrs.tags == MemTag_CanonicallyTagged then s2_memattrs.tags = MemTag_CanonicallyTagged; end; else s2_memattrs = walkstate.memattrs; end; let s2aarch64 : boolean = TRUE; var memattrs : MemoryAttributes; if walkparams.fwb == '0' then memattrs = S2CombineS1MemAttrs(ipa.memattrs, s2_memattrs, s2aarch64); else memattrs = s2_memattrs; end; var pa : AddressDescriptor = CreateAddressDescriptor(ipa.vaddress, oa, memattrs, accdesc); pa.s2fs1mro = s2fs1mro; pa.mecid = AArch64_S2OutputMECID{128}(walkparams, pa.paddress.paspace, descriptor); if (accdesc.acctype == AccessType_TTW && accdesc.atomicop && !IsWBShareable(pa.memattrs) && ConstrainUnpredictableBool(Unpredictable_Unsupported_Atomic_HW_Update)) then fault.statuscode = Fault_HWUpdateAccessFlag; return (fault, pa); end; if (accdesc.acctype != AccessType_TTW &&{128}(walkparams, pa.paddress.paspace, descriptor); if (accdesc.atomicop && !IsWBShareable(pa.memattrss2_memattrs) && ConstrainUnpredictableBool(Unpredictable_Atomic_MMU_IMPDEF_FAULT)) then fault.statuscode = Fault_Exclusive; return (fault, pa); end; if accdesc.ls64 && s2_memattrs.memtype == MemType_Normal then if IsFeatureImplemented(FEAT_LS64WB) && !accdesc.withstatus then if (!IsWBShareable(s2_memattrs) && !(s2_memattrs.inner.attrs == MemAttr_NC && s2_memattrs.outer.attrs == MemAttr_NC) && (ImpDefBool( "LD64B or ST64B faults to cacheable non-iWBoWB memory"))) then fault.statuscode = Fault_Exclusive; return (fault, ipa); end; elsif !(s2_memattrs.inner.attrs == MemAttr_NC && s2_memattrs.outer.attrs == MemAttr_NC) then fault.statuscode = Fault_Exclusive; return (fault, ipa); end; end; return (fault, pa); end;

Library pseudocode for aarch64/translation/vmsa_walk/AArch64_S1Walk

// AArch64_S1Walk() // ================ // Traverse stage 1 translation tables obtaining the final descriptor // as well as the address leading to that descriptor func AArch64_S1Walk{N : integer{64, 128}}(fault_in : FaultRecord, walkparams : S1TTWParams, va : bits(64), regime : Regime, accdesc : AccessDescriptor ) => (FaultRecord, AddressDescriptor, TTWState, bits(N)) begin var fault : FaultRecord = fault_in; var aligned : boolean; if HasUnprivileged(regime) && AArch64_S1EPD(regime, va) == '1' then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; var walkstate : TTWState = AArch64_S1InitialTTWState(walkparams, va, regime, accdesc.ss); let startlevel : integer = walkstate.level; if startlevel > 3 then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; var descriptor : bits(N); var walkaddress : AddressDescriptor; var skl : bits(2) = '00'; walkaddress.vaddress = va; walkaddress.mecid = AArch64_S1TTWalkMECID(walkparams.emec, regime, accdesc.ss); if !AArch64_S1DCacheEnabled(regime) then walkaddress.memattrs = NormalNCMemAttr(); walkaddress.memattrs.xs = walkstate.memattrs.xs; else walkaddress.memattrs = walkstate.memattrs; end; // Shareability value of stage 1 translation subject to stage 2 is IMPLEMENTATION DEFINED // to be either effective value or descriptor value if (regime == Regime_EL10 && EL2Enabled() && HCR_EL2().VM == '1' && !(ImpDefBool("Apply effective shareability at stage 1"))) then walkaddress.memattrs.shareability = walkstate.memattrs.shareability; else walkaddress.memattrs.shareability = EffectiveShareability(walkaddress.memattrs); end; var s2fs1mro : boolean = FALSE; var desctype : DescriptorType; var descaddress : FullAddress = AArch64_S1SLTTEntryAddress(walkstate.level, walkparams, va, walkstate.baseaddress); // Detect Address Size Fault by Descriptor Address if AArch64_S1OAOutOfRange(descaddress.address, walkparams) then fault.statuscode = Fault_AddressSize; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; repeat fault.level = walkstate.level; walkaddress.paddress = descaddress; walkaddress.s1assured = walkstate.s1assured; let toplevel : boolean = walkstate.level == startlevel; let varange : VARange = AArch64_GetVARange(va); let walkaccess : AccessDescriptor = CreateAccDescS1TTW(toplevel, varange, accdesc); var s2fault : FaultRecord; var s2walkaddress : AddressDescriptor; if regime == Regime_EL10 && EL2Enabled() then let s1aarch64 : boolean = TRUE; aligned = TRUE; (s2fault, s2walkaddress) = AArch64_S2Translate(fault, walkaddress, s1aarch64, aligned, walkaccess); if s2fault.statuscode != Fault_None then return (s2fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; s2fs1mro = s2walkaddress.s2fs1mro; (fault, descriptor) = FetchDescriptor{N}(walkparams.ee, s2walkaddress, walkaccess, fault); else (fault, descriptor) = FetchDescriptor{N}(walkparams.ee, walkaddress, walkaccess, fault); end; if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; var new_descriptor : bits(N); repeat new_descriptor = descriptor; desctype = AArch64_DecodeDescriptorType{N}(descriptor, walkparams.d128, walkparams.ds, walkparams.tgx, walkstate.level); case desctype of when DescriptorType_Table => walkstate = AArch64_S1NextWalkStateTable{N}(walkstate, s2fs1mro, regime, walkparams, descriptor); skl = if walkparams.d128 == '1' then descriptor[110:109] else '00'; descaddress = AArch64_S1TTEntryAddress{N}(walkstate.level, walkparams, skl, va, walkstate.baseaddress, descriptor); // Detect Address Size Fault by Descriptor Address if AArch64_S1OAOutOfRange(descaddress.address, walkparams) then fault.statuscode = Fault_AddressSize; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; if walkparams.haft == '1' then new_descriptor[10] = '1'; end; if (walkparams.d128 == '1' && skl != '00' && AArch64_nTFaults{N}(walkparams.d128, descriptor)) then fault.statuscode = Fault_Translation; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; when DescriptorType_Leaf => walkstate = AArch64_S1NextWalkStateLeaf{N}(walkstate, s2fs1mro, regime, accdesc, walkparams, descriptor); when DescriptorType_Invalid => fault.statuscode = Fault_Translation; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); otherwise => unreachable; end; if new_descriptor != descriptor then if var (!descpaddr :IsWBShareable(walkaddress.memattrs) && ConstrainUnpredictableBool(Unpredictable_Unsupported_Atomic_HW_Update)) then fault.statuscode = Fault_HWUpdateAccessFlag; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; var descpaddr : AddressDescriptor; let descaccess : AccessDescriptor = CreateAccDescTTEUpdate(accdesc); if regime == Regime_EL10 && EL2Enabled() then let s1aarch64 : boolean = TRUE; aligned = TRUE; (s2fault, descpaddr) = AArch64_S2Translate(fault, walkaddress, s1aarch64, aligned, descaccess); if s2fault.statuscode != Fault_None then return (s2fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; else descpaddr = walkaddress; end; (fault, descriptor) = AArch64_MemSwapTableDesc{N}(fault, descriptor, new_descriptor, walkparams.ee, descaccess, descpaddr); if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; end; until new_descriptor == descriptor looplimit Unbounded_DescriptorUpdate; until desctype == DescriptorType_Leaf looplimit MAX_WALK_LEVELS; let oa : FullAddress = StageOA(va, walkparams.d128, walkparams.tgx, walkstate); if (walkstate.contiguous == '1' && AArch64_ContiguousBitFaults(walkparams.d128, walkparams.txsz, walkparams.tgx, walkstate.level)) then fault.statuscode = Fault_Translation; elsif walkstate.level < FINAL_LEVEL && AArch64_nTFaults{N}(walkparams.d128, descriptor) then fault.statuscode = Fault_Translation; elsif AArch64_S1AMECFault{N}(walkparams, walkstate.baseaddress.paspace, regime, descriptor) then fault.statuscode = Fault_Translation; // Detect Address Size Fault by final output elsif AArch64_S1OAOutOfRange(oa.address, walkparams) then fault.statuscode = Fault_AddressSize; // Check descriptor AF bit elsif (descriptor[10] == '0' && walkparams.ha == '0' && (!accdesc.acctype IN {AccessType_DC, AccessType_IC} || ImpDefBool("Generate access flag fault on IC/DC operations"))) then fault.statuscode = Fault_AccessFlag; end; if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; return (fault, walkaddress, walkstate, descriptor); end;

Library pseudocode for aarch64/translation/vmsa_walk/AArch64_S2Walk

// AArch64_S2Walk() // ================ // Traverse stage 2 translation tables obtaining the final descriptor // as well as the address leading to that descriptor func AArch64_S2Walk{N : integer{64, 128}}(fault_in : FaultRecord, ipa : AddressDescriptor, walkparams : S2TTWParams, accdesc : AccessDescriptor) => (FaultRecord, AddressDescriptor, TTWState, bits(N)) begin var fault : FaultRecord = fault_in; let ipa_64 : bits(64) = ZeroExtend{}(ipa.paddress.address); var walkstate : TTWState; if accdesc.ss == SS_Secure then walkstate = AArch64_SS2InitialTTWState(walkparams, ipa.paddress.paspace); else walkstate = AArch64_S2InitialTTWState(accdesc.ss, walkparams); end; let startlevel : integer = walkstate.level; if startlevel > 3 then fault.statuscode = Fault_Translation; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; var descriptor : bits(N); let walkaccess : AccessDescriptor = CreateAccDescS2TTW(accdesc); var walkaddress : AddressDescriptor; var skl : bits(2) = '00'; walkaddress.vaddress = ipa.vaddress; walkaddress.mecid = AArch64_S2TTWalkMECID(walkparams.emec, accdesc.ss); if !S2DCacheEnabled() then walkaddress.memattrs = NormalNCMemAttr(); walkaddress.memattrs.xs = walkstate.memattrs.xs; else walkaddress.memattrs = walkstate.memattrs; end; walkaddress.memattrs.shareability = EffectiveShareability(walkaddress.memattrs); var desctype : DescriptorType; // Initial lookup might index into concatenated tables var descaddress : FullAddress = AArch64_S2SLTTEntryAddress(walkparams, ipa.paddress.address, walkstate.baseaddress); // Detect Address Size Fault by Descriptor Address if AArch64_S2OAOutOfRange(descaddress.address, walkparams) then fault.statuscode = Fault_AddressSize; fault.level = 0; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; repeat fault.level = walkstate.level; walkaddress.paddress = descaddress; (fault, descriptor) = FetchDescriptor{N}(walkparams.ee, walkaddress, walkaccess, fault); if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; var new_descriptor : bits(N); repeat new_descriptor = descriptor; desctype = AArch64_DecodeDescriptorType{N}(descriptor, walkparams.d128, walkparams.ds, walkparams.tgx, walkstate.level); case desctype of when DescriptorType_Table => walkstate = AArch64_S2NextWalkStateTable{N}(walkstate, walkparams, descriptor); skl = if walkparams.d128 == '1' then descriptor[110:109] else '00'; descaddress = AArch64_S2TTEntryAddress(walkstate.level, walkparams, skl, ipa.paddress.address, walkstate.baseaddress); // Detect Address Size Fault by table descriptor if AArch64_S2OAOutOfRange(descaddress.address, walkparams) then fault.statuscode = Fault_AddressSize; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; if walkparams.haft == '1' then new_descriptor[10] = '1'; end; if (walkparams.d128 == '1' && skl != '00' && AArch64_nTFaults{N}(walkparams.d128, descriptor)) then fault.statuscode = Fault_Translation; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; when DescriptorType_Leaf => walkstate = AArch64_S2NextWalkStateLeaf{N}(walkstate, accdesc.ss, walkparams, ipa, descriptor); when DescriptorType_Invalid => fault.statuscode = Fault_Translation; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); otherwise => unreachable; end; if new_descriptor != descriptor then if let (!descaccess :IsWBShareable(walkaddress.memattrs) && ConstrainUnpredictableBool(Unpredictable_Unsupported_Atomic_HW_Update)) then fault.statuscode = Fault_HWUpdateAccessFlag; return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; let descaccess : AccessDescriptor = CreateAccDescTTEUpdate(accdesc); (fault, descriptor) = AArch64_MemSwapTableDesc{N}(fault, descriptor, new_descriptor, walkparams.ee, descaccess, walkaddress); if fault.statuscode != Fault_None then return (fault, ARBITRARY : AddressDescriptor, ARBITRARY : TTWState, ARBITRARY : bits(N)); end; end; until new_descriptor == descriptor looplimit Unbounded_DescriptorUpdate; until desctype == DescriptorType_Leaf looplimit MAX_WALK_LEVELS; let oa : FullAddress = StageOA(ipa_64, walkparams.d128, walkparams.tgx, walkstate); if (walkstate.contiguous == '1' && AArch64_ContiguousBitFaults(walkparams.d128, walkparams.txsz, walkparams.tgx, walkstate.level)) then fault.statuscode = Fault_Translation; elsif walkstate.level < FINAL_LEVEL && AArch64_nTFaults{N}(walkparams.d128, descriptor) then fault.statuscode = Fault_Translation; // Detect Address Size Fault by final output elsif AArch64_S2OAOutOfRange(oa.address, walkparams) then fault.statuscode = Fault_AddressSize; // Check descriptor AF bit elsif (descriptor[10] == '0' && walkparams.ha == '0' && (!accdesc.acctype IN {AccessType_DC, AccessType_IC} || ImpDefBool("Generate access flag fault on IC/DC operations"))) then fault.statuscode = Fault_AccessFlag; end; return (fault, walkaddress, walkstate, descriptor); end;

Library pseudocode for shared/debug/SoftwareLockStatus/Component

// Component // ========= // Component Types. type Component of enumeration { Component_AMUComponent_ETE, Component_ETEComponent_TRBE, Component_TRBEComponent_RAS, Component_RASComponent_GIC, Component_GICComponent_PMU, Component_PMUComponent_Debug, Component_Debug,Component_CTI }; Component_CTI };

Library pseudocode for shared/debug/SoftwareLockStatus/GetAccessComponent

// GetAccessComponent() // ==================== // DeterminesReturns the componentaccessed by decoding the physical address in the address descriptor.component. impdef func GetAccessComponent(addrdesc() :=> AddressDescriptor) => Component begin return Component_Debug; end;

Library pseudocode for shared/debug/SoftwareLockStatus/SoftwareLockStatus

// SoftwareLockStatus() // ==================== // Returns the state of the Software Lock. func SoftwareLockStatus(addrdesc() => boolean begin let component : AddressDescriptor) => boolean begin let component : Component = GetAccessComponent(addrdesc);(); if !HaveSoftwareLock(component) then return FALSE; end; case component of when Component_ETE => return TRCLSR().SLK == '1'; when Component_Debug => return EDLSR().SLK == '1'; when Component_PMU => return PMLSR().SLK == '1'; when Component_CTI => return CTILSR().SLK == '1'; otherwise => return FALSE; end; end;

Library pseudocode for shared/debug/authentication/AllowExternalDebugAccess

// AllowExternalDebugAccess() // ========================== // Returns TRUE if an external debug interface access to the External DBGBVR<DBGBVR_EL1(n>_EL1,), // DBGBCR<DBGBCR_EL1(n>_EL1,), DBGWVR<DBGWVR_EL1(n>_EL1,), DBGWCR<DBGWCR_EL1(n>_EL1) registers, and, from Armv8.2, the // OSLAR_EL1 register is allowed for the access. Returns FALSE otherwise. func AllowExternalDebugAccess(addrdesc : AddressDescriptor) => boolean begin // The access may also be subject to OS Lock, power-down, etc. if IsFeatureImplemented(FEAT_RME) then case MDCR_EL3().[EDADE,EDAD] of when '00' => return TRUE; when '01' => return addrdesc.paddress.paspace IN {PAS_Root, PAS_Secure}; when '10' => return addrdesc.paddress.paspace IN {PAS_Root, PAS_Realm}; when '11' => return addrdesc.paddress.paspace == PAS_Root; end; end; if IsFeatureImplemented(FEAT_Debugv8p4) then if addrdesc.paddress.paspace == PAS_Secure then return TRUE; end; else if !ExternalInvasiveDebugEnabled() then return FALSE; end; if ExternalSecureInvasiveDebugEnabled() then return TRUE; end; end; if HaveEL(EL3) then let EDAD_bit : bit = if ELUsingAArch32(EL3) then SDCR().EDAD else MDCR_EL3().EDAD; return EDAD_bit == '0'; else return NonSecureOnlyImplementation(); end; end;

Library pseudocode for shared/debug/authentication/ExternalInvasiveDebugEnabled

// ExternalInvasiveDebugEnabled() // ============================== // The definition of this function is IMPLEMENTATION DEFINED. // In the recommended interface, this function returns the state of the DBGEN signal. readonly func ExternalInvasiveDebugEnabled() => boolean begin return DBGEN == HIGH; end;

Library pseudocode for shared/debug/authentication/ExternalNoninvasiveDebugEnabled

// ExternalNoninvasiveDebugEnabled() // ================================= // This function returns TRUE if the FEAT_Debugv8p4 is implemented. // Otherwise, this function is IMPLEMENTATION DEFINED, and, in the // recommended interface, ExternalNoninvasiveDebugEnabled returns // the state of the (DBGEN OR NIDEN) signal. readonly func ExternalNoninvasiveDebugEnabled() => boolean begin return (IsFeatureImplemented(FEAT_Debugv8p4) || ExternalInvasiveDebugEnabled() || NIDEN == HIGH); end;

Library pseudocode for shared/debug/authentication/ExternalRealmInvasiveDebugEnabled

// ExternalRealmInvasiveDebugEnabled() // =================================== // The definition of this function is IMPLEMENTATION DEFINED. // In the recommended interface, this function returns the state of the // (DBGEN AND RLPIDEN) signal. readonly func ExternalRealmInvasiveDebugEnabled() => boolean begin if !IsFeatureImplemented(FEAT_RME) then return FALSE; end; return ExternalInvasiveDebugEnabled() && RLPIDEN == HIGH; end;

Library pseudocode for shared/debug/authentication/ExternalRealmNoninvasiveDebugEnabled

// ExternalRealmNoninvasiveDebugEnabled() // ====================================== // The definition of this function is IMPLEMENTATION DEFINED. // In the recommended interface, this function returns the state of the // (DBGEN AND RLPIDEN) signal. readonly func ExternalRealmNoninvasiveDebugEnabled() => boolean begin if !IsFeatureImplemented(FEAT_RME) then return FALSE; end; return ExternalRealmInvasiveDebugEnabled(); end;

Library pseudocode for shared/debug/authentication/ExternalSecureInvasiveDebugEnabled

// ExternalSecureInvasiveDebugEnabled() // ==================================== // The definition of this function is IMPLEMENTATION DEFINED. // In the recommended interface, this function returns the state of the (DBGEN AND SPIDEN) signal. // CoreSight allows asserting SPIDEN without also asserting DBGEN, but this is not recommended. readonly func ExternalSecureInvasiveDebugEnabled() => boolean begin if !HaveSecureState() then return (!IsFeatureImplemented(FEAT_RME)FALSE; || RTPIDEN == HIGH); end; return ExternalInvasiveDebugEnabled() && SPIDEN == HIGH; end;

Library pseudocode for shared/debug/authentication/ExternalSecureNoninvasiveDebugEnabled

// ExternalSecureNoninvasiveDebugEnabled() // ======================================= // This function returns the value of ExternalSecureInvasiveDebugEnabled() when FEAT_Debugv8p4 // is implemented. Otherwise, the definition of this function is IMPLEMENTATION DEFINED. // In the recommended interface, this function returns the state of the (DBGEN OR NIDEN) AND // (SPIDEN OR SPNIDEN) signal. readonly func ExternalSecureNoninvasiveDebugEnabled() => boolean begin if !HaveSecureState() then return FALSE; end; if !IsFeatureImplemented(FEAT_Debugv8p4) then return (ExternalNoninvasiveDebugEnabled() && (SPIDEN == HIGH || SPNIDEN == HIGH)); else return ExternalSecureInvasiveDebugEnabled(); end; end;

Library pseudocode for shared/debug/halting/ExitDebugState

// ExitDebugState() // ================ func ExitDebugState() begin assert Halted(); SynchronizeContext(); // Although EDSCR.STATUS signals that the PE is restarting, debuggers must use EDPRSR.SDR to // detect that the PE has restarted. EDSCR().STATUS = '000001'; // Signal restarting // Clear any pending Halting debug events if IsFeatureImplemented(FEAT_Debugv8p8) then EDESR()[3:0] = '0000'; else EDESR()[2:0] = '000'; end; var new_pc : bits(64); var spsr : bits(64); if UsingAArch32() then new_pc = ZeroExtend{64}(DLR()); if IsFeatureImplemented(FEAT_Debugv8p9) then spsr = DSPSR2() :: DSPSR(); else spsr = ZeroExtend{64}(DSPSR()); end; else new_pc = DLR_EL0(); spsr = DSPSR_EL0(); end; let illegal_psr_state : boolean = IllegalExceptionReturn{64}(spsr); // If this is an illegal return, SetPSTATEFromPSR() will set PSTATE.IL. SetPSTATEFromPSR{64}(spsr); // Can update privileged bits, even at EL0 let branch_conditional : boolean = FALSE; if UsingAArch32() then if ConstrainUnpredictableBool(Unpredictable_RESTARTALIGNPC) then new_pc[0] = '0'; end; // AArch32 branch BranchTo{32}(new_pc[31:0], BranchType_DBGEXIT, branch_conditional); else // If targeting AArch32 then PC[63:32,1:0] might be set to UNKNOWN. if illegal_psr_state && spsr[4] == '1' then new_pc[63:32] = ARBITRARY : bits(32); new_pc[1:0] = ARBITRARY : bits(2); end; if IsFeatureImplemented(FEAT_BRBE) then BRBEDebugStateExit(new_pc); end; // A type of branch that is never predicted BranchTo{64}(new_pc,AArch64_BranchAddr(new_pc,PSTATE.EL)); end; // A type of branch that is never predicted BranchTo{64}(new_pc, BranchType_DBGEXIT, branch_conditional); end; // Atomically signal restarted EDSCR().STATUS = '000010'; EDPRSR().SDR = '1'; // End of atomically signal EDPRSR().HALTED = '0'; UpdateEDSCRFields(); // Stop signalling PE state DisableITRAndResumeInstructionPrefetch(); return; end;

Library pseudocode for shared/debug/halting/Halt

// Halt() // ====== func Halt(reason : bits(6)) begin let is_async : boolean = FALSE; let fault : FaultRecord = NoFault(); Halt(reason, is_async, fault); end; // Halt() // ====== func Halt(reason : bits(6), is_async : boolean, fault : FaultRecord) begin CTI_SignalEvent(CrossTriggerIn_CrossHalt); // Trigger other cores to halt let preferred_restart_address : bits(64) = ThisInstrAddr{}(); var spsr : bits(64) = GetPSRFromPSTATE{}( GetPSRFromPSTATE{64}(DebugState); if (IsFeatureImplemented(FEAT_BTI) && !is_async && ! reason IN {DebugHalt_Step_Normal, DebugHalt_Step_Exclusive, DebugHalt_Step_NoSyndrome, DebugHalt_Breakpoint, DebugHalt_HaltInstruction} && ConstrainUnpredictableBool(Unpredictable_ZEROBTYPE)) then spsr[11:10] = '00'; end; if UsingAArch32() then DLR() = preferred_restart_address[31:0]; DSPSR() = spsr[31:0]; if IsFeatureImplemented(FEAT_Debugv8p9) then DSPSR2() = spsr[63:32]; end; else DLR_EL0() = preferred_restart_address; DSPSR_EL0() = spsr; end; EDSCR().ITE = '1'; EDSCR().ITO = '0'; if IsFeatureImplemented(FEAT_RME) then if PSTATE.EL == PSTATE.EL == EL3 then EDSCR().SDD = '0'; else EDSCR().SDD = if ExternalRootInvasiveDebugEnabled() then '0' else '1'; end; elsif CurrentSecurityState() == SS_Secure then EDSCR().SDD = '0'; // If entered in Secure state, allow debug elsif HaveEL(EL3) then EDSCR().SDD = if ExternalSecureInvasiveDebugEnabled() then '0' else '1'; else EDSCR().SDD = '1'; // Otherwise EDSCR.SDD is RES1 end; EDSCR().MA = '0'; // In Debug state: // * PSTATE.[SS,SSBS,D,A,I,F] are not observable and ignored so behave-as-if UNKNOWN. // * PSTATE.[N,Z,C,V,Q,GE,E,M,nRW,EL,SP,DIT] are also not observable, but since these // are not changed on exception entry, this function also leaves them unchanged. // * PSTATE.[IT,T] are ignored. // * PSTATE.IL is ignored and behave-as-if 0. // * PSTATE.BTYPE is ignored and behave-as-if 0. // * PSTATE.TCO is set 1. // * PSTATE.PACM is ignored and behave-as-if 0. // * PSTATE.[UAO,PAN] are observable and not changed on entry into Debug state. // * PSTATE.UINJ is set to 0. if UsingAArch32() then PSTATE.[IT,SS,SSBS,A,I,F,T] = ARBITRARY : bits(14); else PSTATE.[SS,SSBS,D,A,I,F] = ARBITRARY : bits(6); end; if IsFeatureImplemented(FEAT_MTE) then PSTATE.TCO = '1'; end; if IsFeatureImplemented(FEAT_BTI) then PSTATE.BTYPE = '00'; end; if IsFeatureImplemented(FEAT_PAuth_LR) then PSTATE.PACM = '0'; end; PSTATE.IL = '0'; if IsFeatureImplemented(FEAT_UINJ) then PSTATE.UINJ() then PSTATE.[IT,SS,SSBS,A,I,F,T] = ARBITRARY : bits(14); else PSTATE.[SS,SSBS,D,A,I,F] = ARBITRARY : bits(6); end; if IsFeatureImplemented(FEAT_MTE) then PSTATE.TCO = '1'; end; if IsFeatureImplemented(FEAT_BTI) then PSTATE.BTYPE = '00'; end; if IsFeatureImplemented(FEAT_PAuth_LR) then PSTATE.PACM = '0'; end; PSTATE.IL = '0'; if IsFeatureImplemented(FEAT_UINJ) then PSTATE.UINJ = '0'; end; if IsFeatureImplemented(FEAT_BRBE) then BRBEDebugStateEntry(preferred_restart_address); end; StopInstructionPrefetchAndEnableITR(); // atomic write EDSCR().STATUS = reason; EDPRSR().HALTED = '1'; // end of atomic write UpdateEDSCRFields(); // Update EDSCR PE state flags. if IsFeatureImplemented(FEAT_EDHSR) then UpdateEDHSR(reason, fault); // Update EDHSR fields. end; if !is_async then EndOfInstruction(); end; return; end;

Library pseudocode for shared/debug/halting/UpdateEDSCRFields

// UpdateEDSCRFields() // =================== // Update EDSCR PE state fields func UpdateEDSCRFields() begin if !Halted() then EDSCR().EL = '00'; if IsFeatureImplemented(FEAT_RME) then // SDD bit. EDSCR().SDD = if ExternalRootInvasiveDebugEnabled() then '0' else '1'; EDSCR().[NSE,NS] = ARBITRARY : bits(2); else // SDD bit. EDSCR().SDD = if ExternalSecureInvasiveDebugEnabled() then '0' else '1'; EDSCR().NS = ARBITRARY : bit; end; EDSCR().RW = '1111'; else EDSCR().EL = PSTATE.EL; // SError Pending. if PSTATE.EL; // SError Pending. if EL2Enabled() && HCR_EL2().[AMO,TGE] == '10' && PSTATE.EL IN { PSTATE.EL IN {EL0,EL1} then EDSCR().A = if IsVirtualSErrorPending() then '1' else '0'; elsif (IsFeatureImplemented(FEAT_E3DSE) && SCR_EL3().EnDSE == '1' && PSTATE.EL IN {EffectiveSCR_EL3_EnDSE() == '1' && PSTATE.EL IN {EL0,EL1,EL2}) then EDSCR().A = if IsDelegatedSErrorPending() then '1' else '0'; else EDSCR().A = if IsPhysicalSErrorPending() then '1' else '0'; end; let ss : SecurityState = CurrentSecurityState(); if IsFeatureImplemented(FEAT_RME) then case ss of when SS_Secure => EDSCR().[NSE,NS] = '00'; when SS_NonSecure => EDSCR().[NSE,NS] = '01'; when SS_Root => EDSCR().[NSE,NS] = '10'; when SS_Realm => EDSCR().[NSE,NS] = '11'; end; else EDSCR().NS = if ss == SS_Secure then '0' else '1'; end; var RW : bits(4); RW[1] = if ELUsingAArch32(EL1) then '0' else '1'; if PSTATE.EL) then '0' else '1'; if PSTATE.EL != EL0 then RW[0] = RW[1]; else RW[0] = if UsingAArch32() then '0' else '1'; end; if !EL2Enabled() then RW[2] = RW[1]; else RW[2] = if ELUsingAArch32(EL2) then '0' else '1'; end; if !HaveEL(EL3) then RW[3] = RW[2]; else RW[3] = if ELUsingAArch32(EL3) then '0' else '1'; end; // The least-significant bits of EDSCR.RW are UNKNOWN if any higher EL is using AArch32.AArch32_ if RW[3] == '0' then RW[2:0] = ARBITRARY : bits(3); elsif RW[2] == '0' then RW[1:0] = ARBITRARY : bits(2); elsif RW[1] == '0' then RW[0] = ARBITRARY : bit; end; EDSCR().RW = RW; end; return; end;

Library pseudocode for shared/debug/pmu

var PMUEventAccumulator : array [[31]] of integer; // Accumulates PMU events for a cycle var PMULastThresholdValue : array [[31]] of boolean; //;// A record of the threshold result for each // Constant used in PMU functions to represent actions on the cycle counter. constant CYCLE_COUNTER_ID : integer = 31; // Constant used in PMU functions to represent actions on the instruction counter. constant INSTRUCTION_COUNTER_ID : integer = 32;

Library pseudocode for shared/functions/aborts/EncodeLDFSC

// EncodeLDFSC() // ============= // Function that gives the Long-descriptor FSC code for types of Fault func EncodeLDFSC(statuscode : Fault, level : integer) => bits(6) begin var result : bits(6); // 128-bit descriptors will start from level -2 for 4KB to resolve bits IA[55:51] if level == -2 then assert IsFeatureImplemented(FEAT_D128); case statuscode of when Fault_AddressSize => result = '101100'; when Fault_Translation => result = '101010'; when Fault_SyncExternalOnWalk => result = '010010'; when Fault_SyncParityOnWalk => result = '011010'; assert !IsFeatureImplemented(FEAT_RAS); when Fault_GPCFOnWalk => result = '100010'; otherwise => unreachable; end; return result; end; if level == -1 then assert IsFeatureImplemented(FEAT_LPA2); case statuscode of when Fault_AddressSize => result = '101001'; when Fault_Translation => result = '101011'; when Fault_SyncExternalOnWalk => result = '010011'; when Fault_SyncParityOnWalk => result = '011011'; assert !IsFeatureImplemented(FEAT_RAS); when Fault_GPCFOnWalk => result = '100011'; otherwise => unreachable; end; return result; end; case statuscode of when Fault_AddressSize => result = '0000'::level[1:0]; assert level IN {0,1,2,3}; when Fault_AccessFlag => result = '0010'::level[1:0]; assert level IN {0,1,2,3}; when Fault_Permission => result = '0011'::level[1:0]; assert level IN {0,1,2,3}; when Fault_Translation => result = '0001'::level[1:0]; assert level IN {0,1,2,3}; when Fault_AsyncExternal => result = '010001'; assert UsingAArch32(); when Fault_SyncExternal => result = '010000'; when Fault_SyncExternalOnWalk => result = '0101'::level[1:0]; assert level IN {0,1,2,3}; when Fault_SyncParity => result = '011000'; when Fault_SyncParityOnWalk => result = '0111'::level[1:0]; assert level IN {0,1,2,3}; when Fault_AsyncParity => result = '011001'; when Fault_AsyncExternal => result = '010001'; assert UsingAArch32 => result = '011001';(); when Fault_TagCheck => result = '010001'; assert IsFeatureImplemented(FEAT_MTE2); when Fault_Alignment => result = '100001'; when Fault_Debug => result = '100010'; when Fault_GPCFOnWalk => result = '1001'::level[1:0]; assert level IN {0,1,2,3}; when Fault_GPCFOnOutput => result = '101000'; when Fault_TLBConflict => result = '110000'; when Fault_HWUpdateAccessFlag => result = '110001'; when Fault_Lockdown => result = '110100'; // IMPLEMENTATION DEFINED when Fault_Exclusive => result = '110101'; // IMPLEMENTATION DEFINED otherwise => unreachable; end; return result; end;

Library pseudocode for shared/functions/extension/HaveTraceExt

// HaveTraceExt() // ============== // Returns TRUE if Trace functionality as described by the Trace Architecture // is implemented. readonly func HaveTraceExt() => boolean begin return IsFeatureImplemented(FEAT_ETE) || IsFeatureImplemented(FEAT_ETMv4); end;

Library pseudocode for shared/functions/memory/CreateAccDescDCZero

// CreateAccDescDCZero() // ===================== // Access descriptor for data cache zero operations func CreateAccDescDCZero(cachetype : CacheType) => AccessDescriptor begin var accdesc : AccessDescriptor = NewAccDesc(AccessType_DCZero); accdesc.write = TRUE; accdesc.pan = TRUE; accdesc.tagchecked = cachetype == CacheType_Data; accdesc.tagaccess = cachetype IN {CacheType_Tag, CacheType_TagWrite, CacheType_TagZero, CacheType_Data_Tag}; accdesc.cachetype = cachetype; return accdesc; end;

Library pseudocode for shared/functions/memory/IsContiguousSVEAccess

// IsContiguousSVEAccess() // ======================= // Return TRUE if memory access is contiguous load/stores in an SVE mode. func IsContiguousSVEAccess(accdesc : AccessDescriptor) => boolean begin return (IsFeatureImplemented(FEAT_SVE) && accdesc.acctype == AccessType_SVE && accdesc.contiguous;); end;

Library pseudocode for shared/functions/memory/IsSMEAccess

// IsSMEAccess() // ============= // Return TRUE if access is of SME load/stores. func IsSMEAccess(accdesc : AccessDescriptor) => boolean begin return IsFeatureImplemented(FEAT_SME) && accdesc.acctype == AccessType_SME; end;

Library pseudocode for shared/functions/mpam/ReportVIDFault

// ReportVIDFault() // ================ // Report a GPCF or External abort on an MVMS or MITT access. func ReportVIDFault(mpamdata : MPAMdata, el : bits(2), fault_address : bits(56), fsc : bits(2)) begin assert el == '0x'; MPAMVIDSR_EL2().FADDR = fault_address; MPAMVIDSR_EL2().FSC = fsc; MPAMVIDSR_EL2().FIR = if mpamdata.sm then '10' else el; end;

Library pseudocode for shared/functions/sysregisters/SPSR_ELx

// SPSR_ELx - accessor // =================== accessor SPSR_ELx() <=> value : bits(64) begin getter var result : bits(64); case PSTATE.EL of when PSTATE.EL of when EL1 => result = SPSR_EL1()[63:0]; when EL2 => result = SPSR_EL2()[63:0]; when EL3 => result = SPSR_EL3()[63:0]; otherwise => unreachable; end; return result; end; setter case PSTATE.EL=> result = SPSR_EL3()[63:0]; otherwise => unreachable; end; return result; end; setter case PSTATE.EL of when EL1 => SPSR_EL1()[63:0] = value[63:0]; when EL2 => SPSR_EL2()[63:0] = value[63:0]; when EL3 => SPSR_EL3()[63:0] = value[63:0]; otherwise => unreachable; end; return; end; end;

Library pseudocode for shared/functions/system/ELStateUsingAArch32K

// ELStateUsingAArch32K() // ====================== // Returns (known, aarch32): // 'known' is FALSE for EL0 if the current Exception level is not EL0 and EL1 is // using AArch64, since it cannot determine the state of EL0; TRUE otherwise. // 'aarch32' is TRUE if the specified Exception level is using AArch32; FALSE otherwise. readonly func ELStateUsingAArch32K(el : bits(2), secure : boolean) => (boolean, boolean) begin assert HaveEL(el); if !HaveAArch32EL(el) then return (TRUE, FALSE); // Exception level is using AArch64 elsif secure && el == EL2 then return (TRUE, FALSE); // Secure EL2 is using AArch64 elsif !HaveAArch64() then return (TRUE, TRUE); // Highest Exception level, therefore all levels are using AArch32 end; // Remainder of function deals with the interprocessing cases when highest // Exception level is using AArch64.AArch64_ if el == EL3 then return (TRUE, FALSE); end; if (HaveEL(EL3) && SCR_EL3().RW == '0' && (!secure || !IsFeatureImplemented(FEAT_SEL2) || SCR_EL3().EEL2 == '0')) then // AArch32 below EL3. return (TRUE, TRUE); end; if el == EffectiveSCR_EL3_RW() == '0' && (!secure || !IsFeatureImplemented(FEAT_SEL2) || SCR_EL3().EEL2 == '0')) then // AArch32 below EL3. return (TRUE, TRUE); end; if el == EL2 then return (TRUE, FALSE); end; if (HaveEL(EL2) && !ELIsInHost(EL0) && HCR_EL2().RW == '0' && (!secure || (IsFeatureImplemented(FEAT_SEL2) && SCR_EL3().EEL2 == '1'))) then // AArch32 below EL2. return (TRUE, TRUE); end; if el == EL1 then return (TRUE, FALSE); end; // The execution state of EL0 is only known from PSTATE.nRW when executing at EL0. if PSTATE.EL == PSTATE.EL == EL0 then return (TRUE, PSTATE.nRWthen return (TRUE, PSTATE.nRW == '1'); else return (FALSE, ARBITRARY : boolean); end; end;

Library pseudocode for shared/functions/system/EffectiveEA

// EffectiveEA() // ============= // Returns effective SCR_EL3.EA value readonly func EffectiveEA() => bit begin if !HaveEL(EL3) || Halted() then return '0'; else return if HaveAArch64() then SCR_EL3().EA else SCR().EA; end; end;

Library pseudocode for shared/functions/system/EffectiveHCR_EL2_NVx

// EffectiveHCR_EL2_NVx() // ====================== // Return the Effective value of HCR_EL2.[HCR_EL2().[NV2,NV1,NV]. func EffectiveHCR_EL2_NVx() => bits(3) begin if !EL2Enabled() || !IsFeatureImplemented(FEAT_NV) then return '000'; end; var nv1 : bit = HCR_EL2().NV1; if (!IsFeatureImplemented(FEAT_E2H0) && ImpDefBool("HCR_EL2.NV1 is implemented as RAZ")) then nv1 = '0'; end; if HCR_EL2().NV == '0' then if nv1 == '1' then case ConstrainUnpredictable(Unpredictable_NVNV1) of when Constraint_NVNV1_00 => return '000'; when Constraint_NVNV1_01 => return '010'; when Constraint_NVNV1_11 => return '011'; end; else return '000'; end; end; if !IsFeatureImplemented(FEAT_NV2) then return '0' :: nv1 :: '1'; end; var nv2 : bit = HCR_EL2().NV2; if (nv2 == '0' && ImpDefBool( "Programming HCR_EL2.<NV,NV2> to '10' behaves as '11'")) then nv2 = '1'; end; return nv2 :: nv1 :: '1'; end;

Library pseudocode for shared/functions/system/EffectiveSCR_EL3_FIQ

// EffectiveSCR_EL3_FIQ() // ====================== // Returns effective SCR_EL3().FIQ value readonly func EffectiveSCR_EL3_FIQ() => bit begin if !HaveEL(EL3) || ELUsingAArch32(EL3) then return '0'; end; if IsFeatureImplemented(FEAT_GCIE) && IsFeatureImplemented(FEAT_EL3) then return '1'; end; return SCR_EL3().FIQ; end;

Library pseudocode for shared/functions/system/EffectiveSCR_EL3_IRQ

// EffectiveSCR_EL3_IRQ() // ====================== // Returns effective SCR_EL3().IRQ value readonly func EffectiveSCR_EL3_IRQ() => bit begin if !HaveEL(EL3) || ELUsingAArch32(EL3) then return '0'; end; if IsFeatureImplemented(FEAT_GCIE) then return '0'; end; return SCR_EL3().IRQ; end;

Library pseudocode for shared/functions/system/EffectiveSCR_EL3_RW

// EffectiveSCR_EL3_RW() // ===================== // Returns effective SCR_EL3.RW value readonly func EffectiveSCR_EL3_RW() => bit begin if !HaveAArch64() then return '0'; end; if !HaveAArch32EL(EL2) && !HaveAArch32EL(EL1) then return '1'; end; if HaveAArch32EL(EL1) then if !HaveAArch32EL(EL2) && EffectiveSCR_EL3_NS() == '1' then return '1'; end; if (IsFeatureImplemented(FEAT_SEL2) && SCR_EL3().EEL2 == '1' && EffectiveSCR_EL3_NS() == '0') then return '1'; end; end; return SCR_EL3().RW; end;

Library pseudocode for shared/functions/system/IllegalExceptionReturn

// IllegalExceptionReturn() // ======================== func IllegalExceptionReturn{N}(spsr : bits(N)) => boolean begin // Check for illegal return: // * To an unimplemented Exception level. // * To EL2 in Secure state, when SecureEL2 is not enabled. // * To EL0 using AArch64 state, with SPSR.M[0]==1. // * To AArch64 state with SPSR.M[1]==1. // * To AArch32 state with an illegal value of SPSR.M. let (valid, target) : (boolean, bits(2)) = ELFromSPSR{N}(spsr); if !valid then return TRUE; end; // Check for return to higher Exception level. if UInt(target) > UInt(PSTATE.EL) then return TRUE; end; let spsr_mode_is_aarch32 : boolean = (spsr[4] == '1'); // Check for illegal return: // * To EL1, EL2 or EL3 with register width specified in the SPSR different from the // Execution state used in the Exception level being returned to, as determined by // the SCR_EL3.RW or HCR_EL2.RW bits, or as configured from reset. // * To EL0 using AArch64 state when EL1 is using AArch32 state as determined by the // SCR_EL3.RW or HCR_EL2.RW bits or as configured from reset. // * To AArch64 state from AArch32 state (should be caught by above). let (known, target_el_is_aarch32) : (boolean, boolean) =PSTATE.EL) then return TRUE; end; let spsr_mode_is_aarch32 : boolean = (spsr[4] == '1'); // Check for illegal return: // * To EL1, EL2 or EL3 with register width specified in the SPSR different from the // Execution state used in the Exception level being returned to, as determined by // the SCR_EL3.RW or HCR_EL2.RW bits, or as configured from reset. // * To EL0 using AArch64 state when EL1 is using AArch32 state as determined by the // SCR_EL3.RW or HCR_EL2.RW bits or as configured from reset. // * To AArch64 state from AArch32 state (should be caught by above). let (known, target_el_is_aarch32) : (boolean, boolean) = ELUsingAArch32K(target); assert known || (target == EL0 && !ELUsingAArch32(EL1)); if known && spsr_mode_is_aarch32 != target_el_is_aarch32 then return TRUE; end; // Check for illegal return from AArch32 to AArch64.AArch64_ if UsingAArch32() && !spsr_mode_is_aarch32 then return TRUE; end; // Check for illegal return to EL1 when HCR_EL2.TGE is set and when either of // * SecureEL2 is enabled. // * SecureEL2 is not enabled and EL1 is in Non-secure state. if EL2Enabled() && target == EL1 && HCR_EL2().TGE == '1' then if (!IsSecureBelowEL3() || IsSecureEL2Enabled()) then return TRUE; end; end; // Check for an illegal return to EL1 by a Guest Hypervisor at EL1 when HCRX_EL2.NVTGE is set. if (IsFeatureImplemented(FEAT_NV3) && PSTATE.EL == PSTATE.EL == EL1 && spsr[3:2] == '01' && EffectiveHCR_EL2_NVx() == '101' && IsHCRXEL2Enabled() && HCRX_EL2().NVTGE == '1' && NVHCR_EL2().TGE == '1') then return TRUE; end; if (IsFeatureImplemented(FEAT_GCS) && PSTATE.EXLOCK == '0' && PSTATE.EL() && HCRX_EL2().NVTGE == '1' && NVHCR_EL2().TGE == '1') then return TRUE; end; if (IsFeatureImplemented(FEAT_GCS) && PSTATE.EXLOCK == '0' && PSTATE.EL == target && GetCurrentEXLOCKEN()) then return TRUE; end; return FALSE; end;

Library pseudocode for shared/functions/system/PSTATE

// PSTATE // ====== // PE state bits. // There is no significance to the field order. var PSTATE : collection { N : bits (1), // Negative condition flag Z : bits (1), // Zero condition flag C : bits (1), // Carry condition flag V : bits (1), // Overflow condition flag D : bits (1), // Debug mask bit [AArch64 only] A : bits (1), // SError interrupt mask bit I : bits (1), // IRQ mask bit F : bits (1), // FIQ mask bit EXLOCK : bits (1), // Lock exception return state PAN : bits (1), // Privileged Access Never Bit [v8.1] UAO : bits (1), // User Access Override [v8.2] DIT : bits (1), // Data Independent Timing [v8.4] TCO : bits (1), // Tag Check Override [v8.5, AArch64 only] PM : bits (1), // PMU exception Mask PPEND : bits (1), // synchronous PMU exception to be observed BTYPE : bits (2), // Branch Type [v8.5] PACM : bits (1), // PAC instruction modifier ZA : bits (1), // Accumulation array enabled [SME] SM : bits (1), // Streaming SVE mode enabled [SME] ALLINT : bits (1), // Interrupt mask bit UINJ : bits (1), // Undefined Exception Injection SS : bits (1), // Software step bit IL : bits (1), // Illegal Execution state bit EL : bits (2), // Exception level nRW : bits (1), // Execution state: 0=AArch64, 1=AArch32 SP : bits (1), // Stack pointer select: 0=SP0, 1=SPx [AArch64 only] Q : bits (1), // Cumulative saturation flag [AArch32 only] GE : bits (4), // Greater than or Equal flags [AArch32 only] SSBS : bits (1), // Speculative Store Bypass Safe IT : bits (8), // If-then bits, RES0 in CPSR [AArch32 only] J : bits (1), // J bit, RES0 [AArch32 only, RES0 in SPSR and CPSR] T : bits (1), // T32 bit, RES0 in CPSR [AArch32 only] E : bits (1), // Endianness bit [AArch32 only] M : bits (5); // Mode field [AArch32 only] }; PSTATE : collection { N : bits (1), // Negative condition flag Z : bits (1), // Zero condition flag C : bits (1), // Carry condition flag V : bits (1), // Overflow condition flag D : bits (1), // Debug mask bit [AArch64 only] A : bits (1), // SError interrupt mask bit I : bits (1), // IRQ mask bit F : bits (1), // FIQ mask bit EXLOCK : bits (1), // Lock exception return state PAN : bits (1), // Privileged Access Never Bit [v8.1] UAO : bits (1), // User Access Override [v8.2] DIT : bits (1), // Data Independent Timing [v8.4] TCO : bits (1), // Tag Check Override [v8.5, AArch64 only] PM : bits (1), // PMU exception Mask PPEND : bits (1), // synchronous PMU exception to be observed BTYPE : bits (2), // Branch Type [v8.5] PACM : bits (1), // PAC instruction modifier ZA : bits (1), // Accumulation array enabled [SME] SM : bits (1), // Streaming SVE mode enabled [SME] ALLINT : bits (1), // Interrupt mask bit UINJ : bits (1), // Undefined Exception Injection SS : bits (1), // Software step bit IL : bits (1), // Illegal Execution state bit EL : bits (2), // Exception level nRW : bits (1), // Execution state: 0=AArch64, 1=AArch32 SP : bits (1), // Stack pointer select: 0=SP0, 1=SPx [AArch64 only] Q : bits (1), // Cumulative saturation flag [AArch32 only] GE : bits (4), // Greater than or Equal flags [AArch32 only] SSBS : bits (1), // Speculative Store Bypass Safe IT : bits (8), // If-then bits, RES0 in CPSR [AArch32 only] J : bits (1), // J bit, RES0 [AArch32 only, RES0 in SPSR and CPSR] T : bits (1), // T32 bit, RES0 in CPSR [AArch32 only] E : bits (1), // Endianness bit [AArch32 only] M : bits (5) // Mode field [AArch32 only] };

Library pseudocode for shared/functions/tlbi/ExcludeXS

// ExcludeXS() // =========== // Returns TRUE if a TLBI maintenance instruction without the nXS qualifier executed at EL1 // behaves in the same way as the corresponding TLBI maintenance instruction with the nXS qualifier. func ExcludeXS() => boolean begin return (IsFeatureImplemented(FEAT_XS) && PSTATE.EL == EL1 && IsHCRXEL2Enabled() && HCRX_EL2().FnXS == '1'); end;

Library pseudocode for shared/functions/unpredictable/ConstrainUnpredictable

// ConstrainUnpredictable() // ======================== // Return the appropriate Constraint result to control the caller's behavior. // The return value is IMPLEMENTATION DEFINED within a permitted list for each // UNPREDICTABLE case. // (The permitted list is determined by an assert or case statement at the call site.) readonly impdef func ConstrainUnpredictable(which : Unpredictable) => Constraint begin case which of when Unpredictable_VMSR => return Constraint_UNDEF; when Unpredictable_WBOVERLAPLD => return Constraint_WBSUPPRESS; // return loaded value when Unpredictable_WBOVERLAPST => return Constraint_NONE; // store pre-writeback value when Unpredictable_LDPOVERLAP => return Constraint_UNDEF; // instruction is UNDEFINED when Unpredictable_BASEOVERLAP => return Constraint_UNKNOWN; // use UNKNOWN address when Unpredictable_DATAOVERLAP => return Constraint_UNKNOWN; // store UNKNOWN value when Unpredictable_DEVPAGE2 => return Constraint_FAULT; // take an alignment fault when Unpredictable_RESTCF => return Constraint_UNKNOWN; // Do not take a fault when Unpredictable_DEVICETAGSTORE => return Constraint_NONE; // Do not take a fault when Unpredictable_INSTRDEVICE => return Constraint_NONE; // Do not take a fault when Unpredictable_RESCPACR => return Constraint_TRUE; // Map to UNKNOWN value when Unpredictable_RESMAIR => return Constraint_UNKNOWN; // Map to UNKNOWN value when Unpredictable_S1CTAGGED => return Constraint_FALSE; // SCTLR_ELx.C == '0' marks address as untagged when Unpredictable_S2RESMEMATTR => return Constraint_NC; // Map to Noncacheable value when Unpredictable_RESTEXCB => return Constraint_UNKNOWN; // Map to UNKNOWN value when Unpredictable_RESDACR => return Constraint_UNKNOWN; // Map to UNKNOWN value when Unpredictable_RESPRRR => return Constraint_UNKNOWN; // Map to UNKNOWN value when Unpredictable_RESVTCRS => return Constraint_UNKNOWN; // Map to UNKNOWN value when Unpredictable_RESTnSZ => return Constraint_FORCE; // Map to the limit value when Unpredictable_OORTnSZ => return Constraint_FORCE; // Map to the limit value when Unpredictable_LARGEIPA => return Constraint_FORCE; // Restrict the IA size to the PAMax value when Unpredictable_ESRCONDPASS => return Constraint_FALSE; // Report as "AL" when Unpredictable_ILZEROIT => return Constraint_FALSE; // Do not zero PSTATE.IT when Unpredictable_ILZEROT => return Constraint_FALSE; // Do not zero PSTATE.T when Unpredictable_BPVECTORCATCHPRI => return Constraint_TRUE; // Debug Vector Catch: match on 2nd halfword when Unpredictable_VCMATCHHALF => return Constraint_FALSE; // No match when Unpredictable_VCMATCHDAPA => return Constraint_FALSE; // No match on Data Abort or Prefetch abort when Unpredictable_WPMASKANDBAS => return Constraint_FALSE; // Watchpoint disabled when Unpredictable_WPBASCONTIGUOUS => return Constraint_FALSE; // Watchpoint disabled when Unpredictable_RESWPMASK => return Constraint_DISABLED; // Watchpoint disabled when Unpredictable_WPMASKEDBITS => return Constraint_FALSE; // Watchpoint disabled when Unpredictable_RESBPWPCTRL => return Constraint_DISABLED; // Breakpoint/watchpoint disabled when Unpredictable_BPNOTIMPL => return Constraint_DISABLED; // Breakpoint disabled when Unpredictable_RESBPTYPE => return Constraint_DISABLED; // Breakpoint disabled when Unpredictable_BPNOTCTXCMP => return Constraint_DISABLED; // Breakpoint disabled when Unpredictable_RESMDSELR => return Constraint_UNKNOWN; // Map to UNKNOWN value when Unpredictable_BPMATCHHALF => return Constraint_FALSE; // No match when Unpredictable_BPMISMATCHHALF => return Constraint_FALSE; // No match when Unpredictable_BPLINKINGDISABLED => return Constraint_FALSE; // Breakpoint does not match when Unpredictable_RESTARTALIGNPC => return Constraint_FALSE; // Do not force alignment when Unpredictable_RESTARTZEROUPPERPC => return Constraint_TRUE; // Force zero extension when Unpredictable_ZEROUPPER => return Constraint_TRUE; // zero top halves of X registers when Unpredictable_ERETZEROUPPERPC => return Constraint_TRUE; // zero top half of PC when Unpredictable_A32FORCEALIGNPC => return Constraint_FALSE; // Do not force alignment when Unpredictable_SMD => return Constraint_UNDEF; // disabled SMC is Unallocated when Unpredictable_NONFAULT => return Constraint_FALSE; // Speculation enabled when Unpredictable_SVEZEROUPPER => return Constraint_TRUE; // zero top bits of Z registers when Unpredictable_SVELDNFDATA => return Constraint_TRUE; // Load mem data in NF loads when Unpredictable_SVELDNFZERO => return Constraint_TRUE; // Write zeros in NF loads when Unpredictable_CHECKSPNONEACTIVE => return Constraint_TRUE; // Check SP alignment when Unpredictable_SMEZEROUPPER => return Constraint_TRUE; // zero top bits of ZA registers when Unpredictable_NVNV1 => return Constraint_NVNV1_00; // Map unpredictable configuration of HCR_EL2[NV,NV1] // to NV = 0 and NV1 = 0 when Unpredictable_BADDR_RESS => return Constraint_RESS; // Values behave as RESS when Unpredictable_Shareability => return Constraint_OSH; // Map reserved encoding of shareability to Outer Shareable when Unpredictable_AFUPDATE => // AF update for alignment or Permission fault return Constraint_TRUE; when Unpredictable_DBUPDATE => // DB State update for alignment fault return Constraint_TRUE; when Unpredictable_Unsupported_Atomic_HW_Update => return Constraint_FALSE; // Do not raise Unsupported Atomic HW Update fault // when encountering unsupported memory attributes when Unpredictable_IESBinDebug => // Use SCTLR_ELx[].IESB in Debug state return Constraint_TRUE; when Unpredictable_BADPMSFCR => // Bad settings for PMSFCR_EL1/PMSEVFR_EL1/PMSLATFR_EL1 return Constraint_TRUE; when Unpredictable_RES_PMU_VS => // Bad setting for SVE Streaming mode filter return Constraint_FALSE; when Unpredictable_COUNT_CHAIN => // Chained PMU counters idx, idx+1 are not in same range return Constraint_FALSE; when Unpredictable_EL1TIMESTAMP => // Bad settings for TRFCR_EL1 return Constraint_EL1TIMESTAMP; when Unpredictable_EL2TIMESTAMP => // Bad settings for TRFCR_EL2 return Constraint_EL2TIMESTAMP; when Unpredictable_ZEROBTYPE => return Constraint_TRUE; // Save BTYPE in SPSR_ELx/DPSR_EL0 as '00' when Unpredictable_CLEARERRITEZERO => // Clearing sticky errors when instruction in flight return Constraint_FALSE; when Unpredictable_ALUEXCEPTIONRETURN => return Constraint_UNDEF; when Unpredictable_DBGxVR_RESS => return Constraint_FALSE; when Unpredictable_PMSCR_PCT => return Constraint_PMSCR_PCT_VIRT; when Unpredictable_WFxTDEBUG => return Constraint_FALSE; // WFxT in Debug state does not execute as a NOP // Accesses are not single-copy atomic above the byte level when Unpredictable_LS64UNSUPPORTED => return Constraint_LIMITED_ATOMICITY; // Unaligned exclusives, atomics, acquire/release // to a region that is not to Normal inner write-back // outer write-back shareable generate an Alignment fault. when Unpredictable_LSE2_ALIGNMENT_FAULT => return Constraint_FALSE; when Unpredictable_LSE128OVERLAP => return Constraint_UNDEF; // instruction is UNDEFINED when Unpredictable_IGNORETRAPINDEBUG => return Constraint_FALSE; // Trap to register access in debug state is enabled when Unpredictable_PMUEVENTCOUNTER => return Constraint_UNDEF; // Accesses to the register are UNDEFINED when Unpredictable_RES_HPMN => return Constraint_UNKNOWN; // The counter is reserved for EL2 use when Unpredictable_RES_EPMN => return Constraint_UNKNOWN; // The counter is reserved for external use when Unpredictable_BRBFILTRATE => return Constraint_FALSE; // BRB_FILTRATE event not generated on BRB injection when Unpredictable_PMUSNAPSHOTEVENT => // PMU_SNAPSHOT event not generated in Debug state return Constraint_FALSE; when Unpredictable_RESEPMSSAD => // External access to PMUv3 Snapshot extension allowed in Secure state // when FEAT_RME is not implemented or Root state otherwise return Constraint_UNKNOWN; when Unpredictable_RESPMSSE => return Constraint_DISABLED; // PMU capture events disabled when Unpredictable_RESPMEE => return Constraint_DISABLED; // PMU Profiling exception disabled, PMUIRQ enabled when Unpredictable_RESPMSEE => return Constraint_DISABLED; // SPE Profiling exception disabled when Unpredictable_RESTRFEE => return Constraint_DISABLED; // TRBE Profiling exception disabled when Unpredictable_RESTC => return Constraint_DISABLED; // Threshold features disabled when Unpredictable_MOPSOVERLAP => // Instruction is UNDEFINED return Constraint_UNDEF; when Unpredictable_MOPS_R31 => // Instruction is UNDEFINED return Constraint_UNDEF; when Unpredictable_CASRETURNOLDVALUE => return Constraint_TRUE; when Unpredictable_WRITEFAILEDCAS => return Constraint_FALSE; when Unpredictable_STRONLYTAGCHECKEDCAS => return Constraint_TRUE; // CAS with compare fail does a Tag Check when Unpredictable_STRONLYTAGCHECKEDRCWSCAS => return Constraint_TRUE; // RCW(S)CAS with RCW(S) fail/compare fail does a Tag Check when Unpredictable_RESERVEDNSxB => return Constraint_MAPTOALLOCATED; when Unpredictable_RESERVEDNSxB_Trap => return Constraint_TRUE; when Unpredictable_RES_ETBAD => // ExternalTracebufferaccess disabled for res values return Constraint_DISABLED; when Unpredictable_RESBPMASK => return Constraint_DISABLED; // Mask set to 0 when Unpredictable_BPMASK => return Constraint_FALSE; // Breakpoint match will fail when Unpredictable_BPMASKEDBITS => return Constraint_FALSE; // Breakpoint match will fail when Unpredictable_BPLINKEDADDRMATCH => return Constraint_FALSE; // Breakpoint match will fail when Unpredictable_16BYTEROUNDEDUPACCESS => // Watchpoint match of 16 byte rounded range in case of SVE access return Constraint_TRUE; when Unpredictable_16BYTEROUNDEDDOWNACCESS => // Watchpoint match of 16 byte rounded range in case of SVE access return Constraint_TRUE; when Unpredictable_NODTRTAGCHK => // The load or store operation does not perform the Tag check in Debug state return Constraint_TRUE; when Unpredictable_CPACHECK => // Do not perform Checked Pointer Arithmetic return Constraint_FALSE; when Unpredictable_Atomic_SYNC_ABORT => return Constraint_FALSE; when Unpredictable_Atomic_SERROR => return Constraint_FALSE; when Unpredictable_Atomic_NOP => return Constraint_FALSE; when Unpredictable_Atomic_MMU_IMPDEF_FAULT => return Constraint_FALSE; when Unpredictable_MPAM_TRUNCATE_VID => return Constraint_TRUE; when Unpredictable_USE_DEFAULT_PMG => return Constraint_TRUE; when Unpredictable_BankedRegister => return Constraint_NOP; when Unpredictable_UnimplementedRegister => return Constraint_NOP; otherwise => unreachable; end; end;

Library pseudocode for shared/functions/unpredictable/Unpredictable

// Unpredictable // ============= // List of Constrained Unpredictable situations. type Unpredictable of enumeration { // VMSR on MVFR Unpredictable_VMSR, // Writeback/transfer register overlap (load) Unpredictable_WBOVERLAPLD, // Writeback/transfer register overlap (store) Unpredictable_WBOVERLAPST, // Load Pair transfer register overlap Unpredictable_LDPOVERLAP, // Store-exclusive base/status register overlap Unpredictable_BASEOVERLAP, // Store-exclusive data/status register overlap Unpredictable_DATAOVERLAP, // Load-store alignment checks Unpredictable_DEVPAGE2, // Instruction fetch from Device memory Unpredictable_INSTRDEVICE, // Reserved CPACR value Unpredictable_RESCPACR, // Reserved MAIR value Unpredictable_RESMAIR, // Effect of SCTLR_ELx.C on Tagged attribute Unpredictable_S1CTAGGED, // Reserved Stage 2 MemAttr value Unpredictable_S2RESMEMATTR, // Reserved TEX:::C:::B value Unpredictable_RESTEXCB, // Reserved PRRR value Unpredictable_RESPRRR, // Reserved DACR field Unpredictable_RESDACR, // Reserved VTCR.S value Unpredictable_RESVTCRS, // Reserved TCR.TnSZ value Unpredictable_RESTnSZ, // Reserved SCTLR_ELx.TCF value Unpredictable_RESTCF, // Tag stored to Device memory Unpredictable_DEVICETAGSTORE, // Out-of-range TCR.TnSZ value Unpredictable_OORTnSZ, // IPA size exceeds PA size Unpredictable_LARGEIPA, // Syndrome for a known-passing conditional A32 instruction Unpredictable_ESRCONDPASS, // Illegal State exception: zero PSTATE.IT Unpredictable_ILZEROIT, // Illegal State exception: zero PSTATE.T Unpredictable_ILZEROT, // Debug: prioritization of Vector Catch Unpredictable_BPVECTORCATCHPRI, // Debug Vector Catch: match on 2nd halfword Unpredictable_VCMATCHHALF, // Debug Vector Catch: match on Data Abort // or Prefetch abort Unpredictable_VCMATCHDAPA, // Debug watchpoints: nonzero MASK and non-ones BAS Unpredictable_WPMASKANDBAS, // Debug watchpoints: non-contiguous BAS Unpredictable_WPBASCONTIGUOUS, // Debug watchpoints: reserved MASK Unpredictable_RESWPMASK, // Debug watchpoints: nonzero MASKed bits of address Unpredictable_WPMASKEDBITS, // Debug breakpoints and watchpoints: reserved control bits Unpredictable_RESBPWPCTRL, // Debug breakpoints: not implemented Unpredictable_BPNOTIMPL, // Debug breakpoints: reserved type Unpredictable_RESBPTYPE, // Debug breakpoints and watchpoints: reserved MDSELR_EL1.BANK Unpredictable_RESMDSELR, // Debug breakpoints: not-context-aware breakpoint Unpredictable_BPNOTCTXCMP, // Debug breakpoints: match on 2nd halfword of instruction Unpredictable_BPMATCHHALF, // Debug breakpoints: mismatch on 2nd halfword of instruction Unpredictable_BPMISMATCHHALF, // Debug breakpoints: a breakpoint is linked to that is not // programmed with linking enabled Unpredictable_BPLINKINGDISABLED, // Debug breakpoints: reserved MASK Unpredictable_RESBPMASK, // Debug breakpoints: MASK is set for a Context matching // breakpoint or when DBGBCR_EL1([n).].BAS != '1111' Unpredictable_BPMASK, // Debug breakpoints: nonzero MASKed bits of address Unpredictable_BPMASKEDBITS, // Debug breakpoints: A linked breakpoint is // linked to an address matching breakpoint Unpredictable_BPLINKEDADDRMATCH, // Debug: restart to a misaligned AArch32 PC value Unpredictable_RESTARTALIGNPC, // Debug: restart to a not-zero-extended AArch32 PC value Unpredictable_RESTARTZEROUPPERPC, // Zero top 32 bits of X registers in AArch32 state Unpredictable_ZEROUPPER, // Zero top 32 bits of PC on illegal return to // AArch32 state Unpredictable_ERETZEROUPPERPC, // Force address to be aligned when interworking // branch to A32 state Unpredictable_A32FORCEALIGNPC, // SMC disabled Unpredictable_SMD, // FF speculation Unpredictable_NONFAULT, // Zero top bits of Z registers in EL change Unpredictable_SVEZEROUPPER, // Load mem data in NF loads Unpredictable_SVELDNFDATA, // Write zeros in NF loads Unpredictable_SVELDNFZERO, // SP alignment fault when predicate is all zero Unpredictable_CHECKSPNONEACTIVE, // Zero top bits of ZA registers in EL change Unpredictable_SMEZEROUPPER, // Watchpoint match of last rounded up memory access in case of // 16 byte rounding Unpredictable_16BYTEROUNDEDUPACCESS, // Watchpoint match of first rounded down memory access in case of // 16 byte rounding Unpredictable_16BYTEROUNDEDDOWNACCESS, // HCR_EL2.[HCR_EL2().[NV,NV1] == '01' Unpredictable_NVNV1, // Upper bits of a BADDR are not RESS Unpredictable_BADDR_RESS, // Reserved shareability encoding Unpredictable_Shareability, // Access Flag Update by HW Unpredictable_AFUPDATE, // Dirty Bit State Update by HW Unpredictable_DBUPDATE, // UnsupportedConsider memorySCTLR_ELx[].IESB attributesin forDebug HW updatestate Unpredictable_Unsupported_Atomic_HW_UpdateUnpredictable_IESBinDebug, // ConsiderBad SCTLR_ELx().IESBsettings infor Debug statePMSFCR_EL1/PMSEVFR_EL1/PMSLATFR_EL1 Unpredictable_IESBinDebugUnpredictable_BADPMSFCR, // TheZero HCR_EL2.TERRsaved /BType HCR2.TERRvalue andin SCR_EL3.TERR SPSR_ELx/ SCR.TERR // trap control can be treated as RES0.DPSR_EL0 Unpredictable_MINIMALRASv2Unpredictable_ZEROBTYPE, // BadTimestamp settingsconstrained forto PMSFCR_EL1/PMSEVFR_EL1/PMSLATFR_EL1virtual or physical Unpredictable_BADPMSFCRUnpredictable_EL2TIMESTAMP, // Zero saved BType value in SPSR_ELx/DPSR_EL0 Unpredictable_ZEROBTYPEUnpredictable_EL1TIMESTAMP, // TimestampReserved constrainedMDCR_EL3().[NSTBE,NSTB] toor virtualMDCR_EL3().[NSPBE,NSPB] or physicalvalue Unpredictable_EL2TIMESTAMPUnpredictable_RESERVEDNSxB, Unpredictable_EL1TIMESTAMPUnpredictable_RESERVEDNSxB_Trap, // ReservedWFET MDCR_EL3.[NSTBE,NSTB] or MDCR_EL3.[NSPBE,NSPB]WFIT valueinstruction in Debug state Unpredictable_RESERVEDNSxBUnpredictable_WFxTDEBUG, // Address does not support LS64 instructions Unpredictable_RESERVEDNSxB_TrapUnpredictable_LS64UNSUPPORTED, // WFETUnaligned orexclusives, WFITatomics, instructionacquire/release // into Debuga stateregion that is not to Normal inner write-back // outer write-back shareable generate an Alignment fault. Unpredictable_WFxTDEBUGUnpredictable_LSE2_ALIGNMENT_FAULT, // Address128-bit doesAtomic notor support128-bit LS64RCW{S} instructionstransfer register overlap Unpredictable_LS64UNSUPPORTEDUnpredictable_LSE128OVERLAP, // UnalignedClearing exclusives, atomics, acquireDCC/release //ITR tosticky aflags regionwhen thatinstruction is notin to Normal inner write-back // outer write-back shareable generate an Alignment fault.flight Unpredictable_LSE2_ALIGNMENT_FAULTUnpredictable_CLEARERRITEZERO, // 128-bitALUEXCEPTIONRETURN Atomicwhen orin 128-bituser/system RCW{S}mode transferin // registerA32 overlapinstructions Unpredictable_LSE128OVERLAPUnpredictable_ALUEXCEPTIONRETURN, // ClearingTrap DCC/ITRto stickyregister flagsin whendebug instructionstate isare in flightignored Unpredictable_CLEARERRITEZEROUnpredictable_IGNORETRAPINDEBUG, // ALUEXCEPTIONRETURNCompare whenDBGBVR.RESS infor userBP/system mode in // A32 instructionsWP Unpredictable_ALUEXCEPTIONRETURNUnpredictable_DBGxVR_RESS, // TrapInaccessible toevent register in debug state are ignoredcounter Unpredictable_IGNORETRAPINDEBUGUnpredictable_PMUEVENTCOUNTER, // CompareReserved DBGBVR.RESSPMSCR.PCT for BP/WPbehavior Unpredictable_DBGxVR_RESSUnpredictable_PMSCR_PCT, // InaccessibleMDCR_EL2.HPMN eventor counterHDCR.HPMN is larger than PMCR.N or // FEAT_HPMN0 is not implemented and HPMN is 0. Unpredictable_PMUEVENTCOUNTERUnpredictable_RES_HPMN, // ReservedChained PMSCR.PCTPMU behaviorcounters idx and idx+1 are not in same range Unpredictable_PMSCR_PCTUnpredictable_COUNT_CHAIN, // MDCR_EL2.HPMNPMCCR.EPMN or HDCR.HPMN is larger than PMCR.N or // FEAT_HPMN0 is not implemented and HPMN is 0. Unpredictable_RES_HPMNUnpredictable_RES_EPMN, // ChainedGenerate PMUBRB_FILTRATE countersevent idxon andBRB idx+1 are not in same rangeinjection Unpredictable_COUNT_CHAINUnpredictable_BRBFILTRATE, // PMCCR.EPMNGenerate isPMU_SNAPSHOT largerevent thanin PMCR.NDebug state Unpredictable_RES_EPMNUnpredictable_PMUSNAPSHOTEVENT, // GenerateReserved BRB_FILTRATEMDCR_EL3.EPMSSAD event on BRB injectionvalue Unpredictable_BRBFILTRATEUnpredictable_RESEPMSSAD, // GenerateReserved PMU_SNAPSHOTPMECR_EL1.SSE event in Debug statevalue Unpredictable_PMUSNAPSHOTEVENTUnpredictable_RESPMSSE, // ReservedEnable MDCR_EL3.EPMSSADfor valuePMU Profiling exception and PMUIRQ Unpredictable_RESEPMSSADUnpredictable_RESPMEE, // ReservedEnables PMECR_EL1.SSEfor valueSPE Profiling exceptions and PMSIRQ Unpredictable_RESPMSSEUnpredictable_RESPMSEE, // EnableEnables for PMUTRBE Profiling exceptionexceptions and PMUIRQPMSIRQ Unpredictable_RESPMEEUnpredictable_RESTRFEE, // EnablesOperands for SPECPY*/SET* Profilinginstructions exceptions and PMSIRQoverlap Unpredictable_RESPMSEEUnpredictable_MOPSOVERLAP, // EnablesOperands for TRBECPY*/SET* Profilinginstructions exceptionsuse and0b11111 // PMSIRQas a register specifier Unpredictable_RESTRFEEUnpredictable_MOPS_R31, // OperandsChooses forwhich CPY*/SET*value instructionsto overlapreturn in a non failed Atomic Compare and Swap Unpredictable_MOPSOVERLAPUnpredictable_CASRETURNOLDVALUE, // OperandsEnables forwrite CPY*/SET*of instructionsthe usenewvalue 0b11111 //in as a registerfailed specifierAtomic Compare and Swap Unpredictable_MOPS_R31Unpredictable_WRITEFAILEDCAS, // ChoosesStore-only whichTag valuechecking toon return in a non failed Atomic Compare and Swap Unpredictable_CASRETURNOLDVALUEUnpredictable_STRONLYTAGCHECKEDCAS, // EnablesStore-only writeTag ofchecking theon newvaluea infailed aRCW(S) failedchecks // or RCW(S) Atomic Compare and Swap Unpredictable_WRITEFAILEDCASUnpredictable_STRONLYTAGCHECKEDRCWSCAS, // Store-onlyReserved TagMDCR_EL3.ETBAD checking on a failed Atomic Compare and Swapvalue Unpredictable_STRONLYTAGCHECKEDCASUnpredictable_RES_ETBAD, // Store-onlyInvalid TagStreaming checkingMode onfilter a failed RCW(S) checks // or RCW(S) Atomic Compare and Swapbits Unpredictable_STRONLYTAGCHECKEDRCWSCASUnpredictable_RES_PMU_VS, // ReservedApply MDCR_EL3.ETBADChecked valuePointer Arithmetic on a sequential access to bytes // that cross the 0xXXFF_FFFF_FFFF_FFFF boundary. Unpredictable_RES_ETBADUnpredictable_CPACHECK, // InvalidReserved StreamingPMEVTYPER_EL0(n).[TC,TE,TC2] Mode filter bitsvalues Unpredictable_RES_PMU_VSUnpredictable_RESTC, // ApplyWhen CheckedFEAT_MTE Pointeris Arithmeticimplemented, onif aMemory sequential access tomode bytesis enabled // thatand crossPSTATE.TCO is 0, Reads and writes to the 0xXXFF_FFFF_FFFF_FFFFexternal boundary.debug // interface DTR registers are CONSTRAINED UNPREDICTABLE for tagcheck Unpredictable_CPACHECKUnpredictable_NODTRTAGCHK, // ReservedUse PMEVTYPER[n]_EL0.[TC,TE,TC2]the valuesdefault PMG when the default PARTID is generated // due to MPAM error Unpredictable_RESTCUnpredictable_USE_DEFAULT_PMG, // WhenIf FEAT_MTEthe isatomic implemented,instructions ifare Memorynot accessatomic modein isregard enabledto other // andagents PSTATE.TCOthat isaccess 0memory, Reads andthen writesthe toinstruction thecan externalhave debugone or // interfacemore DTRof registersthe arefollowing CONSTRAINED UNPREDICTABLE for tagcheckeffects Unpredictable_NODTRTAGCHKUnpredictable_Atomic_SYNC_ABORT, // Use the default PMG when the default PARTID is generated // due to MPAM error Unpredictable_USE_DEFAULT_PMGUnpredictable_Atomic_SERROR, // If the atomic instructions are not atomic in regard to other // agents that access memory, then the instruction can have one or // more of the following effects Unpredictable_Atomic_SYNC_ABORTUnpredictable_Atomic_NOP, Unpredictable_Atomic_SERRORUnpredictable_Atomic_MMU_IMPDEF_FAULT, // Truncate virtual identifier to bottom 12 bits if it exceeds 2^12 Unpredictable_Atomic_NOPUnpredictable_MPAM_TRUNCATE_VID, // Accessing DBGDSCRint via MRC in debug state Unpredictable_Atomic_MMU_IMPDEF_FAULTUnpredictable_MRC_APSR_TARGET, // TruncateAccessing virtualBanked identifierregister tonot bottomaccessible 12from bitsthe ifPE it exceeds 2^12mode Unpredictable_MPAM_TRUNCATE_VIDUnpredictable_BankedRegister, // Accessing DBGDSCRintunimplemented viaBanked MRC in debug stateregister Unpredictable_MRC_APSR_TARGETUnpredictable_UnimplementedRegister, // Accessing Banked register not accessible from the PE mode }; Unpredictable_BankedRegister, // Accessing unimplemented Banked register Unpredictable_UnimplementedRegister, };

Library pseudocode for shared/trace/TraceBuffer/CheckMDCR_EL3_NSTBTrap

// CheckMDCR_EL3_NSTBTrap() // ======================== // Check if the register access is trappable by MDCR_EL3.[NSTBE, NSTB] func CheckMDCR_EL3_NSTBTrap() => boolean begin var state_bits : bits(3); var reserved : boolean; (state_bits, reserved) = EffectiveMDCR_EL3_NSTB(); return ((reserved && ConstrainUnpredictableBool(Unpredictable_RESERVEDNSxB_Trap)) || state_bits[0] == '0' || state_bits[1] != SCR_EL3().NS || (IsFeatureImplemented(FEAT_RME) && state_bits[2] != SCR_EL3().NSE)); end; EffectiveSCR_EL3_NS() || (IsFeatureImplemented(FEAT_RME) && state_bits[2] != EffectiveSCR_EL3_NSE())); end;

Library pseudocode for shared/trace/selfhosted/SelfHostedTraceEnabled

// SelfHostedTraceEnabled() // ======================== // Returns TRUE if Self-hosted Trace is enabled. readonly func SelfHostedTraceEnabled() => boolean begin var secure_trace_enable : bit = '0'; if !(HaveTraceExt() && IsFeatureImplemented(FEAT_TRF)) then return FALSE; end; if EDSCR().TFO == '0' then return TRUE; end; if IsFeatureImplemented(FEAT_RME) then secure_trace_enable = if IsFeatureImplemented(FEAT_SEL2) then MDCR_EL3().STE else '0'; return ((secure_trace_enable == '1' && !ExternalSecureNoninvasiveDebugEnabled()) || (MDCR_EL3().RLTE == '1' && !ExternalRealmNoninvasiveDebugEnabled())); end; if HaveEL(EL3) then secure_trace_enable = if ELUsingAArch32(EL3) then SDCR().STE else MDCR_EL3().STE; else secure_trace_enable = if SecureOnlyImplementation() then '1' else '0'; end; if secure_trace_enable == '1' && !ExternalSecureNoninvasiveDebugEnabled() then return TRUE; end; return FALSE; end;

Library pseudocode for shared/translation/gpc/DecodeGPTBlock

// DecodeGPTBlock() // ================ // Decode a GPT Block descriptor. func DecodeGPTBlock(pgs : PGSe, gpt_entry : bits(64)) => GPTEntry begin assert gpt_entry[3:0] == GPT_Block; var result : GPTEntry; result.gpi = gpt_entry[7:4]; result.level = 0; result.istable = FALSE; // GPT information from a level 0 GPT Block descriptor is permitted // to be cached in a TLB as though the Block is a contiguous region // of granules each of the size configured in GPCCR_EL3.PGS. case pgs of when PGS_4KB => result.size = GPTRange_4KB; when PGS_16KB => result.size = GPTRange_16KB; when PGS_64KB => result.size = GPTRange_64KB; otherwise => unreachable; end; result.contig_size = GPTL0Size(); return result; end;

Library pseudocode for shared/translation/gpc/DecodeGPTContiguous

// DecodeGPTContiguous() // ===================== // Decode a GPT Contiguous descriptor. func DecodeGPTContiguous(pgs : PGSe, gpt_entry : bits(64)) => GPTEntry begin assert gpt_entry[3:0] == GPT_Contig; var result : GPTEntry; result.gpi = gpt_entry[7:4]; case pgs of when PGS_4KB => result.size = GPTRange_4KB; when PGS_16KB => result.size = GPTRange_16KB; when PGS_64KB => result.size = GPTRange_64KB; otherwise => unreachable; end; case gpt_entry[9:8] of when '01' => result.contig_size = GPTRange_2MB; when '10' => result.contig_size = GPTRange_32MB; when '11' => result.contig_size = GPTRange_512MB; otherwise => unreachable; end; result.level = 1; result.istable = FALSE; return result; end;

Library pseudocode for shared/translation/gpc/DecodeGPTGranules

// DecodeGPTGranules() // =================== // Decode a GPT Granules descriptor. func DecodeGPTGranules(pgs : PGSe, index : integer, gpt_entry : bits(64)) => GPTEntry begin var result : GPTEntry; result.gpi = gpt_entry[index*4 +:4]; case pgs of when PGS_4KB => result.size = GPTRange_4KB; when PGS_16KB => result.size = GPTRange_16KB; when PGS_64KB => result.size = GPTRange_64KB; otherwise => unreachable; end; result.contig_size = result.size; // No contiguity result.level = 1; result.istable = FALSE; return result; end;

Library pseudocode for shared/translation/gpc/DecodeGPTTable

// DecodeGPTTable() // ================ // Decode a GPT Table descriptor. func DecodeGPTTable(pgs : PGSe, gpt_entry : bits(64)) => GPTTable begin assert gpt_entry[3:0] == GPT_Table; var result : GPTTable; // Descriptor bits [L0GPTSZ-PGS-2:12] are RES0 var s : integer{30, 34, 36, 39}; case GPTL0Size() of when GPTRange_1GB => s = 30; when GPTRange_16GB => s = 34; when GPTRange_64GB => s = 36; when GPTRange_512GB => s = 39; otherwise => unreachable; end; var p : integer{12, 14, 16}; case pgs of when PGS_4KB => presult.address = 12;gpt_entry[55:17]::Zeros{17}; when PGS_16KB => presult.address = 14;gpt_entry[55:15]::Zeros{15}; when PGS_64KB => presult.address = 16;gpt_entry[55:13]::Zeros{13}; otherwise => unreachable; end; let align_bits : integer{} = (s - p) - 1; result.address = AlignDownP2(gpt_entry[55:0],align_bits); return result; end;

Library pseudocode for shared/translation/gpc/GPTEntry

// GPTEntry // ======== type GPTEntry of record { gpi : bits(4), // GPI value for this region size : AddressSize, // Region size contig_size : AddressSize, // Contiguous region size istable :level boolean, // Flag a table entry level : integer, // Level of GPT lookup pa : bits(56) // PA uniquely identifying the GPT entry };

Library pseudocode for shared/translation/gpc/GPTTableDescriptorValid

// GPTTableDescriptorValid() // ========================= // Returns TRUE if the given GPT Table descriptor is valid, and FALSE otherwise. func GPTTableDescriptorValid(level_0_entry : bits(64)) => boolean begin assert level_0_entry[3:0] == GPT_Table; let l0sz : integer{} = GPTL0Size(); let pgs : PGSe = DecodePGS(GPCCR_EL3().PGS); let p : integer{} = DecodePGSRange(pgs); let top : integer{} = if DecodePPS() == 56 then 56 else 52; return IsZero(level_0_entry[63:top52,11:4]) && IsZero(level_0_entry[(l0sz-p)-2:12]); end;

Library pseudocode for srmask/EffectiveACTLRMASK_EL1

// EffectiveACTLRMASK_EL1() // ======================== // Return the effective value of ACTLRMASK_EL1. func EffectiveACTLRMASK_EL1() => ACTLR_EL1_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; if EL2Enabled() && (!IsHCRXEL2Enabled() || HCRX_EL2().SRMASKEn == '0') then return Zeros{64}; end; let mask : ACTLR_EL1_Type = ImpDefBits{64}("ACTLR_EL1 layout"); return mask; end;

Library pseudocode for srmask/EffectiveACTLRMASK_EL2

// EffectiveACTLRMASK_EL2() // ======================== // Return the effective value of ACTLRMASK_EL2. func EffectiveACTLRMASK_EL2() => ACTLR_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; let mask : ACTLR_EL2_Type = ImpDefBits{64}("ACTLR_EL2 layout"); return mask; end;

Library pseudocode for srmask/EffectiveCPACRMASK_EL1

// EffectiveCPACRMASK_EL1() // ======================== // Return the effective value of CPACRMASK_EL1. func EffectiveCPACRMASK_EL1() => CPACR_EL1_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; if EL2Enabled() && (!IsHCRXEL2Enabled() || HCRX_EL2().SRMASKEn == '0') then return Zeros{64}; end; var mask : CPACR_EL1_Type = Ones{64}; let mask_reg : CPACRMASK_EL1_Type = CPACRMASK_EL1(); mask.TCPAC = mask_reg.TCPAC; mask.TAM = mask_reg.TAM; mask.E0POE = mask_reg.E0POE; mask.TTA = mask_reg.TTA; mask.SMEN = SignExtend{2}(mask_reg.SMEN); mask.FPEN = SignExtend{2}(mask_reg.FPEN); mask.ZEN = SignExtend{2}(mask_reg.ZEN); mask[32+: 32] = Zeros{32}; mask[26+: 2] = Zeros{2}; mask[22+: 2] = Zeros{2}; mask[18+: 2] = Zeros{2}; mask[0+: 16] = Zeros{16}; return mask; end;

Library pseudocode for srmask/EffectiveCPTRMASK_EL2

// EffectiveCPTRMASK_EL2() // ======================= // Return the effective value of CPTRMASK_EL2. func EffectiveCPTRMASK_EL2() => CPTR_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : CPTR_EL2_Type = Ones{64}; let mask_reg : CPTRMASK_EL2_Type = CPTRMASK_EL2(); if ELIsInHost(EL2) then mask.TCPAC = mask_reg.TCPAC; mask.TAM = mask_reg.TAM; mask.E0POE = mask_reg.E0POE; mask.TTA = mask_reg.TTA; mask.SMEN = SignExtend{2}(mask_reg.SMEN); mask.FPEN = SignExtend{2}(mask_reg.FPEN); mask.ZEN = SignExtend{2}(mask_reg.ZEN); mask[32+: 32] = Zeros{32}; mask[26+: 2] = Zeros{2}; mask[22+: 2] = Zeros{2}; mask[18+: 2] = Zeros{2}; mask[0+: 16] = Zeros{16}; else mask.TCPAC = mask_reg.TCPAC; mask.TAM = mask_reg.TAM; mask.TTA = mask_reg.TTA; mask.TSM = mask_reg.TSM; mask.TFP = mask_reg.TFP; mask.TZ = mask_reg.TZ; mask[32+: 32] = Zeros{32}; mask[21+: 9] = Zeros{9}; mask[14+: 6] = Zeros{6}; mask[13+: 1] = '0'; mask[11+: 1] = '0'; mask[9+: 1] = '0'; mask[0+: 8] = Zeros{8}; end; return mask; end;

Library pseudocode for srmask/EffectiveHCRMASK_EL2

// EffectiveHCRMASK_EL2() // ====================== // Return the effective value of HCRMASK_EL2. func EffectiveHCRMASK_EL2() => HCR_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK2) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : HCR_EL2_Type = Ones{64}; let mask_reg : HCRMASK_EL2_Type = HCRMASK_EL2(); mask.TWEDEL = SignExtend{4}(mask_reg.TWEDEL); mask.TWEDEn = mask_reg.TWEDEn; mask.TID5 = mask_reg.TID5; mask.DCT = mask_reg.DCT; mask.ATA = mask_reg.ATA; mask.TTLBOS = mask_reg.TTLBOS; mask.TTLBIS = mask_reg.TTLBIS; mask.EnSCXT = mask_reg.EnSCXT; mask.TOCU = mask_reg.TOCU; mask.AMVOFFEN = mask_reg.AMVOFFEN; mask.TICAB = mask_reg.TICAB; mask.TID4 = mask_reg.TID4; mask.GPF = mask_reg.GPF; mask.FIEN = mask_reg.FIEN; mask.FWB = mask_reg.FWB; mask.NV2 = mask_reg.NV2; mask.AT = mask_reg.AT; mask.NV1 = mask_reg.NV1; mask.NV = mask_reg.NV; mask.API = mask_reg.API; mask.APK = mask_reg.APK; mask.TEA = mask_reg.TEA; mask.TERR = mask_reg.TERR; mask.TLOR = mask_reg.TLOR; mask.E2H = mask_reg.E2H; mask.ID = mask_reg.ID; mask.CD = mask_reg.CD; mask.RW = mask_reg.RW; mask.TRVM = mask_reg.TRVM; mask.HCD = mask_reg.HCD; mask.TDZ = mask_reg.TDZ; mask.TGE = mask_reg.TGE; mask.TVM = mask_reg.TVM; mask.TTLB = mask_reg.TTLB; mask.TPU = mask_reg.TPU; mask.TPCP = mask_reg.TPCP; mask.TSW = mask_reg.TSW; mask.TACR = mask_reg.TACR; mask.TIDCP = mask_reg.TIDCP; mask.TSC = mask_reg.TSC; mask.TID3 = mask_reg.TID3; mask.TID2 = mask_reg.TID2; mask.TID1 = mask_reg.TID1; mask.TID0 = mask_reg.TID0; mask.TWE = mask_reg.TWE; mask.TWI = mask_reg.TWI; mask.DC = mask_reg.DC; mask.BSU = SignExtend{2}(mask_reg.BSU); mask.FB = mask_reg.FB; mask.VSE = mask_reg.VSE; mask.VI = mask_reg.VI; mask.VF = mask_reg.VF; mask.AMO = mask_reg.AMO; mask.IMO = mask_reg.IMO; mask.FMO = mask_reg.FMO; mask.PTW = mask_reg.PTW; mask.SWIO = mask_reg.SWIO; mask.VM = mask_reg.VM; mask[38+: 2] = Zeros{2}; return mask; end;

Library pseudocode for srmask/EffectiveHCRXMASK_EL2

// EffectiveHCRXMASK_EL2() // ======================= // Return the effective value of HCRXMASK_EL2. func EffectiveHCRXMASK_EL2() => HCRX_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK2) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : HCRX_EL2_Type = Ones{64}; let mask_reg : HCRXMASK_EL2_Type = HCRXMASK_EL2(); mask.FNB = mask_reg.FNB; mask.VTLBIDOSEn = mask_reg.VTLBIDOSEn; mask.NVnTTLBOS = mask_reg.NVnTTLBOS; mask.NVnTTLBIS = mask_reg.NVnTTLBIS; mask.NVnTTLB = mask_reg.NVnTTLB; mask.FDIT = mask_reg.FDIT; mask.NVTGE = mask_reg.NVTGE; mask.SRMASKEn = mask_reg.SRMASKEn; mask.VTLBIDEn = mask_reg.VTLBIDEn; mask.PACMEn = mask_reg.PACMEn; mask.EnFPM = mask_reg.EnFPM; mask.GCSEn = mask_reg.GCSEn; mask.EnIDCP128 = mask_reg.EnIDCP128; mask.EnSDERR = mask_reg.EnSDERR; mask.TMEA = mask_reg.TMEA; mask.EnSNERR = mask_reg.EnSNERR; mask.D128En = mask_reg.D128En; mask.PTTWI = mask_reg.PTTWI; mask.SCTLR2En = mask_reg.SCTLR2En; mask.TCR2En = mask_reg.TCR2En; mask.MSCEn = mask_reg.MSCEn; mask.MCE2 = mask_reg.MCE2; mask.CMOW = mask_reg.CMOW; mask.VFNMI = mask_reg.VFNMI; mask.VINMI = mask_reg.VINMI; mask.TALLINT = mask_reg.TALLINT; mask.SMPME = mask_reg.SMPME; mask.FGTnXS = mask_reg.FGTnXS; mask.FnXS = mask_reg.FnXS; mask.EnASR = mask_reg.EnASR; mask.EnALS = mask_reg.EnALS; mask.EnAS0 = mask_reg.EnAS0; mask[37+: 27] = Zeros{27}; mask[28+: 3] = Zeros{3}; mask[12+: 2] = Zeros{2}; return mask; end;

Library pseudocode for srmask/EffectiveNVHCRMASK_EL2

// EffectiveNVHCRMASK_EL2() // ======================== // Return the effective value of NVHCRMASK_EL2. func EffectiveNVHCRMASK_EL2() => NVHCR_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK2) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : NVHCR_EL2_Type = Ones{64}; let mask_reg : NVHCRMASK_EL2_Type = NVHCRMASK_EL2(); mask.TWEDEL = mask_reg.TWEDEL; mask.TWEDEn = mask_reg.TWEDEn; mask.TID5 = mask_reg.TID5; mask.DCT = mask_reg.DCT; mask.ATA = mask_reg.ATA; mask.EnSCXT = mask_reg.EnSCXT; mask.TOCU = mask_reg.TOCU; mask.AMVOFFEN = mask_reg.AMVOFFEN; mask.TICAB = mask_reg.TICAB; mask.TID4 = mask_reg.TID4; mask.GPF = mask_reg.GPF; mask.FIEN = mask_reg.FIEN; mask.FWB = mask_reg.FWB; mask.NV2 = mask_reg.NV2; mask.AT = mask_reg.AT; mask.NV1 = mask_reg.NV1; mask.NV = mask_reg.NV; mask.API = mask_reg.API; mask.APK = mask_reg.APK; mask.TEA = mask_reg.TEA; mask.TERR = mask_reg.TERR; mask.TLOR = mask_reg.TLOR; mask.E2H = mask_reg.E2H; mask.ID = mask_reg.ID; mask.CD = mask_reg.CD; mask.RW = mask_reg.RW; mask.HCD = mask_reg.HCD; mask.TDZ = mask_reg.TDZ; mask.TGE = mask_reg.TGE; mask.TVM = mask_reg.TVM; mask.TTLB = mask_reg.TTLB; mask.TPU = mask_reg.TPU; mask.TPCP = mask_reg.TPCP; mask.TSW = mask_reg.TSW; mask.TACR = mask_reg.TACR; mask.TIDCP = mask_reg.TIDCP; mask.TSC = mask_reg.TSC; mask.TID3 = mask_reg.TID3; mask.TID2 = mask_reg.TID2; mask.TID1 = mask_reg.TID1; mask.TID0 = mask_reg.TID0; mask.TWE = mask_reg.TWE; mask.TWI = mask_reg.TWI; mask.DC = mask_reg.DC; mask.BSU = mask_reg.BSU; mask.FB = mask_reg.FB; mask.VSE = mask_reg.VSE; mask.VI = mask_reg.VI; mask.VF = mask_reg.VF; mask.AMO = mask_reg.AMO; mask.IMO = mask_reg.IMO; mask.FMO = mask_reg.FMO; mask.PTW = mask_reg.PTW; mask.SWIO = mask_reg.SWIO; mask.VM = mask_reg.VM; mask[61+: 3] = Zeros{3}; mask[38+: 2] = Zeros{2}; mask[11+: 1] = '0'; return mask; end;

Library pseudocode for srmask/EffectiveNVHCRXMASK_EL2

// EffectiveNVHCRXMASK_EL2() // ========================= // Return the effective value of NVHCRXMASK_EL2. func EffectiveNVHCRXMASK_EL2() => NVHCRX_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK2) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : NVHCRX_EL2_Type = Ones{64}; let mask_reg : NVHCRXMASK_EL2_Type = NVHCRXMASK_EL2(); mask.FNB = mask_reg.FNB; mask.VTLBIDOSEn = mask_reg.VTLBIDOSEn; mask.NVnTTLBOS = mask_reg.NVnTTLBOS; mask.NVnTTLBIS = mask_reg.NVnTTLBIS; mask.NVnTTLB = mask_reg.NVnTTLB; mask.FDIT = mask_reg.FDIT; mask.NVTGE = mask_reg.NVTGE; mask.SRMASKEn = mask_reg.SRMASKEn; mask.VTLBIDEn = mask_reg.VTLBIDEn; mask.PACMEn = mask_reg.PACMEn; mask.EnFPM = mask_reg.EnFPM; mask.GCSEn = mask_reg.GCSEn; mask.EnIDCP128 = mask_reg.EnIDCP128; mask.EnSDERR = mask_reg.EnSDERR; mask.TMEA = mask_reg.TMEA; mask.EnSNERR = mask_reg.EnSNERR; mask.D128En = mask_reg.D128En; mask.PTTWI = mask_reg.PTTWI; mask.SCTLR2En = mask_reg.SCTLR2En; mask.TCR2En = mask_reg.TCR2En; mask.MSCEn = mask_reg.MSCEn; mask.MCE2 = mask_reg.MCE2; mask.CMOW = mask_reg.CMOW; mask.VFNMI = mask_reg.VFNMI; mask.VINMI = mask_reg.VINMI; mask.TALLINT = mask_reg.TALLINT; mask.SMPME = mask_reg.SMPME; mask.FGTnXS = mask_reg.FGTnXS; mask.FnXS = mask_reg.FnXS; mask.EnASR = mask_reg.EnASR; mask.EnALS = mask_reg.EnALS; mask.EnAS0 = mask_reg.EnAS0; mask[37+: 27] = Zeros{27}; mask[28+: 3] = Zeros{3}; mask[12+: 2] = Zeros{2}; return mask; end;

Library pseudocode for srmask/EffectiveSCTLR2MASK_EL1

// EffectiveSCTLR2MASK_EL1() // ========================= // Return the effective value of SCTLR2MASK_EL1. func EffectiveSCTLR2MASK_EL1() => SCTLR2_EL1_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; if EL2Enabled() && (!IsHCRXEL2Enabled() || HCRX_EL2().SRMASKEn == '0') then return Zeros{64}; end; var mask : SCTLR2_EL1_Type = Ones{64}; let mask_reg : SCTLR2MASK_EL1_Type = SCTLR2MASK_EL1(); mask.TLBOSNIS = mask_reg.TLBOSNIS; mask.FDIT = mask_reg.FDIT; mask.BTD = mask_reg.BTD; mask.BTD0 = mask_reg.BTD0; mask.EnIA2 = mask_reg.EnIA2; mask.EnIB2 = mask_reg.EnIB2; mask.EnDA2 = mask_reg.EnDA2; mask.EnDB2 = mask_reg.EnDB2; mask.CPTM0 = mask_reg.CPTM0; mask.CPTM = mask_reg.CPTM; mask.CPTA0 = mask_reg.CPTA0; mask.CPTA = mask_reg.CPTA; mask.EnPACM0 = mask_reg.EnPACM0; mask.EnPACM = mask_reg.EnPACM; mask.EnIDCP128 = mask_reg.EnIDCP128; mask.EASE = mask_reg.EASE; mask.EnANERR = mask_reg.EnANERR; mask.EnADERR = mask_reg.EnADERR; mask.NMEA = mask_reg.NMEA; mask[27+: 37] = Zeros{37}; mask[13+: 6] = Zeros{6}; mask[0+: 2] = Zeros{2}; return mask; end;

Library pseudocode for srmask/EffectiveSCTLR2MASK_EL2

// EffectiveSCTLR2MASK_EL2() // ========================= // Return the effective value of SCTLR2MASK_EL2. func EffectiveSCTLR2MASK_EL2() => SCTLR2_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : SCTLR2_EL2_Type = Ones{64}; let mask_reg : SCTLR2MASK_EL2_Type = SCTLR2MASK_EL2(); mask.TLBOSNIS = mask_reg.TLBOSNIS; mask.FDIT = mask_reg.FDIT; mask.BTD = mask_reg.BTD; mask.BTD0 = mask_reg.BTD0; mask.EnIA2 = mask_reg.EnIA2; mask.EnIB2 = mask_reg.EnIB2; mask.EnDA2 = mask_reg.EnDA2; mask.EnDB2 = mask_reg.EnDB2; mask.CPTM0 = mask_reg.CPTM0; mask.CPTM = mask_reg.CPTM; mask.CPTA0 = mask_reg.CPTA0; mask.CPTA = mask_reg.CPTA; mask.EnPACM0 = mask_reg.EnPACM0; mask.EnPACM = mask_reg.EnPACM; mask.EnIDCP128 = mask_reg.EnIDCP128; mask.EASE = mask_reg.EASE; mask.EnANERR = mask_reg.EnANERR; mask.EnADERR = mask_reg.EnADERR; mask.NMEA = mask_reg.NMEA; mask.EMEC = mask_reg.EMEC; mask[27+: 37] = Zeros{37}; mask[13+: 6] = Zeros{6}; mask[0+: 1] = '0'; return mask; end;

Library pseudocode for srmask/EffectiveSCTLRMASK_EL1

// EffectiveSCTLRMASK_EL1() // ======================== // Return the effective value of SCTLRMASK_EL1. func EffectiveSCTLRMASK_EL1() => SCTLR_EL1_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; if EL2Enabled() && (!IsHCRXEL2Enabled() || HCRX_EL2().SRMASKEn == '0') then return Zeros{64}; end; var mask : SCTLR_EL1_Type = Ones{64}; let mask_reg : SCTLRMASK_EL1_Type = SCTLRMASK_EL1(); mask.TIDCP = mask_reg.TIDCP; mask.SPINTMASK = mask_reg.SPINTMASK; mask.NMI = mask_reg.NMI; mask.EnTP2 = mask_reg.EnTP2; mask.TCSO = mask_reg.TCSO; mask.TCSO0 = mask_reg.TCSO0; mask.EPAN = mask_reg.EPAN; mask.EnALS = mask_reg.EnALS; mask.EnAS0 = mask_reg.EnAS0; mask.EnASR = mask_reg.EnASR; mask.TWEDEL = SignExtend{4}(mask_reg.TWEDEL); mask.TWEDEn = mask_reg.TWEDEn; mask.DSSBS = mask_reg.DSSBS; mask.ATA = mask_reg.ATA; mask.ATA0 = mask_reg.ATA0; mask.TCF = SignExtend{2}(mask_reg.TCF); mask.TCF0 = SignExtend{2}(mask_reg.TCF0); mask.ITFSB = mask_reg.ITFSB; mask.BT1 = mask_reg.BT1; mask.BT0 = mask_reg.BT0; mask.EnFPM = mask_reg.EnFPM; mask.MSCEn = mask_reg.MSCEn; mask.CMOW = mask_reg.CMOW; mask.EnIA = mask_reg.EnIA; mask.EnIB = mask_reg.EnIB; mask.LSMAOE = mask_reg.LSMAOE; mask.nTLSMD = mask_reg.nTLSMD; mask.EnDA = mask_reg.EnDA; mask.UCI = mask_reg.UCI; mask.EE = mask_reg.EE; mask.E0E = mask_reg.E0E; mask.SPAN = mask_reg.SPAN; mask.EIS = mask_reg.EIS; mask.IESB = mask_reg.IESB; mask.TSCXT = mask_reg.TSCXT; mask.WXN = mask_reg.WXN; mask.nTWE = mask_reg.nTWE; mask.nTWI = mask_reg.nTWI; mask.UCT = mask_reg.UCT; mask.DZE = mask_reg.DZE; mask.EnDB = mask_reg.EnDB; mask.I = mask_reg.I; mask.EOS = mask_reg.EOS; mask.EnRCTX = mask_reg.EnRCTX; mask.UMA = mask_reg.UMA; mask.SED = mask_reg.SED; mask.ITD = mask_reg.ITD; mask.nAA = mask_reg.nAA; mask.CP15BEN = mask_reg.CP15BEN; mask.SA0 = mask_reg.SA0; mask.SA = mask_reg.SA; mask.C = mask_reg.C; mask.A = mask_reg.A; mask.M = mask_reg.M; mask[50+: 4] = Zeros{4}; mask[17+: 1] = '0'; return mask; end;

Library pseudocode for srmask/EffectiveSCTLRMASK_EL2

// EffectiveSCTLRMASK_EL2() // ======================== // Return the effective value of SCTLRMASK_EL2. func EffectiveSCTLRMASK_EL2() => SCTLR_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : SCTLR_EL2_Type = Ones{64}; let mask_reg : SCTLRMASK_EL2_Type = SCTLRMASK_EL2(); mask.TIDCP = mask_reg.TIDCP; mask.SPINTMASK = mask_reg.SPINTMASK; mask.NMI = mask_reg.NMI; mask.EnTP2 = mask_reg.EnTP2; mask.TCSO = mask_reg.TCSO; mask.TCSO0 = mask_reg.TCSO0; mask.EPAN = mask_reg.EPAN; mask.EnALS = mask_reg.EnALS; mask.EnAS0 = mask_reg.EnAS0; mask.EnASR = mask_reg.EnASR; mask.TWEDEL = SignExtend{4}(mask_reg.TWEDEL); mask.TWEDEn = mask_reg.TWEDEn; mask.DSSBS = mask_reg.DSSBS; mask.ATA = mask_reg.ATA; mask.ATA0 = mask_reg.ATA0; mask.TCF = SignExtend{2}(mask_reg.TCF); mask.TCF0 = SignExtend{2}(mask_reg.TCF0); mask.ITFSB = mask_reg.ITFSB; mask.BT = mask_reg.BT; mask.BT0 = mask_reg.BT0; mask.EnFPM = mask_reg.EnFPM; mask.MSCEn = mask_reg.MSCEn; mask.CMOW = mask_reg.CMOW; mask.EnIA = mask_reg.EnIA; mask.EnIB = mask_reg.EnIB; mask.LSMAOE = mask_reg.LSMAOE; mask.nTLSMD = mask_reg.nTLSMD; mask.EnDA = mask_reg.EnDA; mask.UCI = mask_reg.UCI; mask.EE = mask_reg.EE; mask.E0E = mask_reg.E0E; mask.SPAN = mask_reg.SPAN; mask.EIS = mask_reg.EIS; mask.IESB = mask_reg.IESB; mask.TSCXT = mask_reg.TSCXT; mask.WXN = mask_reg.WXN; mask.nTWE = mask_reg.nTWE; mask.nTWI = mask_reg.nTWI; mask.UCT = mask_reg.UCT; mask.DZE = mask_reg.DZE; mask.EnDB = mask_reg.EnDB; mask.I = mask_reg.I; mask.EOS = mask_reg.EOS; mask.EnRCTX = mask_reg.EnRCTX; mask.SED = mask_reg.SED; mask.ITD = mask_reg.ITD; mask.nAA = mask_reg.nAA; mask.CP15BEN = mask_reg.CP15BEN; mask.SA0 = mask_reg.SA0; mask.SA = mask_reg.SA; mask.C = mask_reg.C; mask.A = mask_reg.A; mask.M = mask_reg.M; mask[50+: 4] = Zeros{4}; mask[17+: 1] = '0'; mask[9+: 1] = '0'; return mask; end;

Library pseudocode for srmask/EffectiveTCR2MASK_EL1

// EffectiveTCR2MASK_EL1() // ======================= // Return the effective value of TCR2MASK_EL1. func EffectiveTCR2MASK_EL1() => TCR2_EL1_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; if EL2Enabled() && (!IsHCRXEL2Enabled() || HCRX_EL2().SRMASKEn == '0') then return Zeros{64}; end; var mask : TCR2_EL1_Type = Ones{64}; let mask_reg : TCR2MASK_EL1_Type = TCR2MASK_EL1(); mask.FNGNA1 = mask_reg.FNGNA1; mask.FNGNA0 = mask_reg.FNGNA0; mask.FNG1 = mask_reg.FNG1; mask.FNG0 = mask_reg.FNG0; mask.A2 = mask_reg.A2; mask.DisCH1 = mask_reg.DisCH1; mask.DisCH0 = mask_reg.DisCH0; mask.HAFT = mask_reg.HAFT; mask.PTTWI = mask_reg.PTTWI; mask.D128 = mask_reg.D128; mask.AIE = mask_reg.AIE; mask.POE = mask_reg.POE; mask.E0POE = mask_reg.E0POE; mask.PIE = mask_reg.PIE; mask.PnCH = mask_reg.PnCH; mask[22+: 42] = Zeros{42}; mask[19+: 1] = '0'; mask[12+: 2] = Zeros{2}; mask[6+: 4] = Zeros{4}; return mask; end;

Library pseudocode for srmask/EffectiveTCR2MASK_EL2

// EffectiveTCR2MASK_EL2() // ======================= // Return the effective value of TCR2MASK_EL2. func EffectiveTCR2MASK_EL2() => TCR2_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : TCR2_EL2_Type = Ones{64}; let mask_reg : TCR2MASK_EL2_Type = TCR2MASK_EL2(); if !ELIsInHost(EL2) then mask.AMEC0 = mask_reg.AMEC0; mask.HAFT = mask_reg.HAFT; mask.PTTWI = mask_reg.PTTWI; mask.AIE = mask_reg.AIE; mask.POE = mask_reg.POE; mask.PIE = mask_reg.PIE; mask.PnCH = mask_reg.PnCH; mask[13+: 51] = Zeros{51}; mask[5+: 5] = Zeros{5}; mask[2+: 1] = '0'; else mask.FNG1 = mask_reg.FNG1; mask.FNG0 = mask_reg.FNG0; mask.A2 = mask_reg.A2; mask.DisCH1 = mask_reg.DisCH1; mask.DisCH0 = mask_reg.DisCH0; mask.AMEC1 = mask_reg.AMEC1; mask.AMEC0 = mask_reg.AMEC0; mask.HAFT = mask_reg.HAFT; mask.PTTWI = mask_reg.PTTWI; mask.D128 = mask_reg.D128; mask.AIE = mask_reg.AIE; mask.POE = mask_reg.POE; mask.E0POE = mask_reg.E0POE; mask.PIE = mask_reg.PIE; mask.PnCH = mask_reg.PnCH; mask[19+: 45] = Zeros{45}; mask[6+: 4] = Zeros{4}; end; return mask; end;

Library pseudocode for srmask/EffectiveTCRMASK_EL1

// EffectiveTCRMASK_EL1() // ====================== // Return the effective value of TCRMASK_EL1. func EffectiveTCRMASK_EL1() => TCR_EL1_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; if EL2Enabled() && (!IsHCRXEL2Enabled() || HCRX_EL2().SRMASKEn == '0') then return Zeros{64}; end; var mask : TCR_EL1_Type = Ones{64}; let mask_reg : TCRMASK_EL1_Type = TCRMASK_EL1(); mask.MTX1 = mask_reg.MTX1; mask.MTX0 = mask_reg.MTX0; mask.DS = mask_reg.DS; mask.TCMA1 = mask_reg.TCMA1; mask.TCMA0 = mask_reg.TCMA0; mask.E0PD1 = mask_reg.E0PD1; mask.E0PD0 = mask_reg.E0PD0; mask.NFD1 = mask_reg.NFD1; mask.NFD0 = mask_reg.NFD0; mask.TBID1 = mask_reg.TBID1; mask.TBID0 = mask_reg.TBID0; mask.HWU162 = mask_reg.HWU162; mask.HWU161 = mask_reg.HWU161; mask.HWU160 = mask_reg.HWU160; mask.HWU159 = mask_reg.HWU159; mask.HWU062 = mask_reg.HWU062; mask.HWU061 = mask_reg.HWU061; mask.HWU060 = mask_reg.HWU060; mask.HWU059 = mask_reg.HWU059; mask.HPD1 = mask_reg.HPD1; mask.HPD0 = mask_reg.HPD0; mask.HD = mask_reg.HD; mask.HA = mask_reg.HA; mask.TBI1 = mask_reg.TBI1; mask.TBI0 = mask_reg.TBI0; mask.AS = mask_reg.AS; mask.IPS = SignExtend{3}(mask_reg.IPS); mask.TG1 = SignExtend{2}(mask_reg.TG1); mask.SH1 = SignExtend{2}(mask_reg.SH1); mask.ORGN1 = SignExtend{2}(mask_reg.ORGN1); mask.IRGN1 = SignExtend{2}(mask_reg.IRGN1); mask.EPD1 = mask_reg.EPD1; mask.A1 = mask_reg.A1; mask.T1SZ = SignExtend{6}(mask_reg.T1SZ); mask.TG0 = SignExtend{2}(mask_reg.TG0); mask.SH0 = SignExtend{2}(mask_reg.SH0); mask.ORGN0 = SignExtend{2}(mask_reg.ORGN0); mask.IRGN0 = SignExtend{2}(mask_reg.IRGN0); mask.EPD0 = mask_reg.EPD0; mask.T0SZ = SignExtend{6}(mask_reg.T0SZ); mask[62+: 2] = Zeros{2}; mask[35+: 1] = '0'; mask[6+: 1] = '0'; return mask; end;

Library pseudocode for srmask/EffectiveTCRMASK_EL2

// EffectiveTCRMASK_EL2() // ====================== // Return the effective value of TCRMASK_EL2. func EffectiveTCRMASK_EL2() => TCR_EL2_Type begin if !IsFeatureImplemented(FEAT_SRMASK) then return Zeros{64}; end; if HaveEL(EL3) && SCR_EL3().SRMASKEn == '0' then return Zeros{64}; end; var mask : TCR_EL2_Type = Ones{64}; let mask_reg : TCRMASK_EL2_Type = TCRMASK_EL2(); if !ELIsInHost(EL2) then mask.MTX = mask_reg.MTX; mask.DS = mask_reg.DS; mask.TCMA = mask_reg.TCMA; mask.TBID = mask_reg.TBID; mask.HWU62 = mask_reg.HWU62; mask.HWU61 = mask_reg.HWU61; mask.HWU60 = mask_reg.HWU60; mask.HWU59 = mask_reg.HWU59; mask.HPD = mask_reg.HPD; mask.HD = mask_reg.HD; mask.HA = mask_reg.HA; mask.TBI = mask_reg.TBI; mask.PS = SignExtend{3}(mask_reg.PS); mask.TG0 = SignExtend{2}(mask_reg.TG0); mask.SH0 = SignExtend{2}(mask_reg.SH0); mask.ORGN0 = SignExtend{2}(mask_reg.ORGN0); mask.IRGN0 = SignExtend{2}(mask_reg.IRGN0); mask.T0SZ = SignExtend{6}(mask_reg.T0SZ); mask[34+: 30] = Zeros{30}; mask[31+: 1] = '0'; mask[23+: 1] = '0'; mask[19+: 1] = '0'; mask[6+: 2] = Zeros{2}; else mask.MTX1 = mask_reg.MTX1; mask.MTX0 = mask_reg.MTX0; mask.DS = mask_reg.DS; mask.TCMA1 = mask_reg.TCMA1; mask.TCMA0 = mask_reg.TCMA0; mask.E0PD1 = mask_reg.E0PD1; mask.E0PD0 = mask_reg.E0PD0; mask.NFD1 = mask_reg.NFD1; mask.NFD0 = mask_reg.NFD0; mask.TBID1 = mask_reg.TBID1; mask.TBID0 = mask_reg.TBID0; mask.HWU162 = mask_reg.HWU162; mask.HWU161 = mask_reg.HWU161; mask.HWU160 = mask_reg.HWU160; mask.HWU159 = mask_reg.HWU159; mask.HWU062 = mask_reg.HWU062; mask.HWU061 = mask_reg.HWU061; mask.HWU060 = mask_reg.HWU060; mask.HWU059 = mask_reg.HWU059; mask.HPD1 = mask_reg.HPD1; mask.HPD0 = mask_reg.HPD0; mask.HD = mask_reg.HD; mask.HA = mask_reg.HA; mask.TBI1 = mask_reg.TBI1; mask.TBI0 = mask_reg.TBI0; mask.AS = mask_reg.AS; mask.IPS = SignExtend{3}(mask_reg.IPS); mask.TG1 = SignExtend{2}(mask_reg.TG1); mask.SH1 = SignExtend{2}(mask_reg.SH1); mask.ORGN1 = SignExtend{2}(mask_reg.ORGN1); mask.IRGN1 = SignExtend{2}(mask_reg.IRGN1); mask.EPD1 = mask_reg.EPD1; mask.A1 = mask_reg.A1; mask.T1SZ = SignExtend{6}(mask_reg.T1SZ); mask.TG0 = SignExtend{2}(mask_reg.TG0); mask.SH0 = SignExtend{2}(mask_reg.SH0); mask.ORGN0 = SignExtend{2}(mask_reg.ORGN0); mask.IRGN0 = SignExtend{2}(mask_reg.IRGN0); mask.EPD0 = mask_reg.EPD0; mask.T0SZ = SignExtend{6}(mask_reg.T0SZ); mask[62+: 2] = Zeros{2}; mask[35+: 1] = '0'; mask[6+: 1] = '0'; end; return mask; end;


2025-12_rel2025-09_diff_tag 2025-12-102025-11-28 16:4129:4505

Copyright © 2010-2025 Arm Limited or its affiliates. All rights reserved. This document is Non-Confidential.

(old) htmldiff from-(new)