You copied the Doc URL to your clipboard.

AArch64 Debug.Pmu Pseudocode

Library pseudocode for aarch64/debug/pmu/AArch64.CheckForPMUOverflow

// AArch64.CheckForPMUOverflow()
// =============================
// Signal Performance Monitors overflow IRQ and CTI overflow events

boolean AArch64.CheckForPMUOverflow()

    pmuirq = PMCR_EL0.E == '1' && PMINTENSET_EL1<31> == '1' && PMOVSSET_EL0<31> == '1';
    for n = 0 to UInt(PMCR_EL0.N) - 1
        if HaveEL(EL2) then
            E = (if n < UInt(MDCR_EL2.HPMN) then PMCR_EL0.E else MDCR_EL2.HPME);
        else
            E = PMCR_EL0.E;
        if E == '1' && PMINTENSET_EL1<n> == '1' && PMOVSSET_EL0<n> == '1' then pmuirq = TRUE;

    SetInterruptRequestLevel(InterruptID_PMUIRQ, if pmuirq then HIGH else LOW);

    CTI_SetEventLevel(CrossTriggerIn_PMUOverflow, if pmuirq then HIGH else LOW);

    // The request remains set until the condition is cleared. (For example, an interrupt handler
    // or cross-triggered event handler clears the overflow status flag by writing to PMOVSCLR_EL0.)

    return pmuirq;

Library pseudocode for aarch64/debug/pmu/AArch64.CountEvents

// AArch64.CountEvents()
// =====================
// Return TRUE if counter "n" should count its event. For the cycle counter, n == 31.

boolean AArch64.CountEvents(integer n)
    assert n == 31 || n < UInt(PMCR_EL0.N);

    // Event counting is disabled in Debug state
    debug = Halted();

    // In Non-secure state, some counters are reserved for EL2
    if HaveEL(EL2) then
        resvd_for_el2 = n >= UInt(MDCR_EL2.HPMN) && n != 31;
    else
        resvd_for_el2 = FALSE;

    // Main enable controls
    E = if resvd_for_el2 then MDCR_EL2.HPME else PMCR_EL0.E;
    enabled = E == '1' && PMCNTENSET_EL0<n> == '1';

    // Event counting is allowed unless it is prohibited by any rule below
    prohibited = FALSE;
    // Event counting in Secure state is prohibited if all of:
    // * EL3 is implemented
    // * MDCR_EL3.SPME == 0, and either:
    //   - FEAT_PMUv3p7 is not implemented
    //   - MDCR_EL3.MPMX == 0
    if HaveEL(EL3) && IsSecure() then
        if HavePMUv3p7() then
            prohibited = MDCR_EL3.<SPME,MPMX> == '00';
        else
            prohibited = MDCR_EL3.SPME == '0';

    // Event counting at EL3 is prohibited if all of:
    // * FEAT_PMUv3p7 is implemented
    // * One of the following is true:
    //   - MDCR_EL3.SPME == 1
    //   - PMNx is not reserved for EL2
    // * MDCR_EL3.MPMX == 1
    if !prohibited && PSTATE.EL == EL3 && HavePMUv3p7() then
        prohibited = MDCR_EL3.MPMX == '1' && (MDCR_EL3.SPME == '1' || !resvd_for_el2);

    // Event counting at EL2 is prohibited if all of:
    // * The HPMD Extension is implemented
    // * PMNx is not reserved for EL2
    // * MDCR_EL2.HPMD == 1
    if !prohibited && PSTATE.EL == EL2 && HaveHPMDExt() && !resvd_for_el2 then
        prohibited = MDCR_EL2.HPMD == '1';

    // The IMPLEMENTATION DEFINED authentication interface might override software
    if prohibited && !HaveNoSecurePMUDisableOverride() then
        prohibited = !ExternalSecureNoninvasiveDebugEnabled();

    // PMCR_EL0.DP disables the cycle counter when event counting is prohibited
    if enabled && prohibited && n == 31 then
        enabled = PMCR_EL0.DP == '0';

    // If FEAT_PMUv3p5 is implemented, cycle counting can be prohibited.
    // This is not overridden by PMCR_EL0.DP.
    if Havev85PMU() && n == 31 then
        if HaveEL(EL3) && IsSecure() && MDCR_EL3.SCCD == '1' then
            prohibited = TRUE;
        if PSTATE.EL == EL2 && MDCR_EL2.HCCD == '1' then
            prohibited = TRUE;

    // If FEAT_PMUv3p7 is implemented, cycle counting an be prohibited at EL3.
    // This is not overriden by PMCR_EL0.DP.
    if HavePMUv3p7() && n == 31 then
        if PSTATE.EL == EL3 && MDCR_EL3.MCCD == '1' then
            prohibited = TRUE;

    // Event counting might be frozen
    frozen = FALSE;

    // If FEAT_PMUv3p7 is implemented, event counting can be frozen
    if HavePMUv3p7() && n != 31 then
        ovflw = PMOVSCLR_EL0<UInt(PMCR_EL0.N)-1:0>;
        if resvd_for_el2 then
            FZ = MDCR_EL2.HPMFZO;
            ovflw<UInt(MDCR_EL2.HPMN)-1:0> = Zeros();
        else
            FZ = PMCR_EL0.FZO;
            if HaveEL(EL2) then
                ovflw<UInt(PMCR_EL0.N)-1:UInt(MDCR_EL2.HPMN)> = Zeros();
        frozen = FZ == '1' && !IsZero(ovflw);

    // Event counting can be filtered by the {P, U, NSK, NSU, NSH, M, SH} bits
    filter = if n == 31 then PMCCFILTR_EL0[31:0] else PMEVTYPER_EL0[n]<31:0>;

    P   = filter<31>;
    U   = filter<30>;
    NSK = if HaveEL(EL3) then filter<29> else '0';
    NSU = if HaveEL(EL3) then filter<28> else '0';
    NSH = if HaveEL(EL2) then filter<27> else '0';
    M   = if HaveEL(EL3) then filter<26> else '0';
    SH  = if HaveEL(EL3) && HaveSecureEL2Ext() then filter<24> else '0';

    case PSTATE.EL of
        when EL0 filtered = if IsSecure() then U == '1' else U != NSU;
        when EL1 filtered = if IsSecure() then P == '1' else P != NSK;
        when EL2 filtered = if IsSecure() then NSH == SH else NSH == '0';
        when EL3 filtered = M != P;

    return !debug && enabled && !prohibited && !filtered && !frozen;