• Mark Rutland's avatar
    arm64: irqchip/gic-v3: Select priorities at boot time · 18fdb634
    Mark Rutland authored
    The distributor and PMR/RPR can present different views of the interrupt
    priority space dependent upon the values of GICD_CTLR.DS and
    SCR_EL3.FIQ. Currently we treat the distributor's view of the priority
    space as canonical, and when the two differ we change the way we handle
    values in the PMR/RPR, using the `gic_nonsecure_priorities` static key
    to decide what to do.
    
    This approach works, but it's sub-optimal. When using pseudo-NMI we
    manipulate the distributor rarely, and we manipulate the PMR/RPR
    registers very frequently in code spread out throughout the kernel (e.g.
    local_irq_{save,restore}()). It would be nicer if we could use fixed
    values for the PMR/RPR, and dynamically choose the values programmed
    into the distributor.
    
    This patch changes the GICv3 driver and arm64 code accordingly. PMR
    values are chosen at compile time, and the GICv3 driver determines the
    appropriate values to program into the distributor at boot time. This
    removes the need for the `gic_nonsecure_priorities` static key and
    results in smaller and better generated code for saving/restoring the
    irqflags.
    
    Before this patch, local_irq_disable() compiles to:
    
    | 0000000000000000 <outlined_local_irq_disable>:
    |    0:   d503201f        nop
    |    4:   d50343df        msr     daifset, #0x3
    |    8:   d65f03c0        ret
    |    c:   d503201f        nop
    |   10:   d2800c00        mov     x0, #0x60                       // #96
    |   14:   d5184600        msr     icc_pmr_el1, x0
    |   18:   d65f03c0        ret
    |   1c:   d2801400        mov     x0, #0xa0                       // #160
    |   20:   17fffffd        b       14 <outlined_local_irq_disable+0x14>
    
    After this patch, local_irq_disable() compiles to:
    
    | 0000000000000000 <outlined_local_irq_disable>:
    |    0:   d503201f        nop
    |    4:   d50343df        msr     daifset, #0x3
    |    8:   d65f03c0        ret
    |    c:   d2801800        mov     x0, #0xc0                       // #192
    |   10:   d5184600        msr     icc_pmr_el1, x0
    |   14:   d65f03c0        ret
    
    ... with 3 fewer instructions per call.
    
    For defconfig + CONFIG_PSEUDO_NMI=y, this results in a minor saving of
    ~4K of text, and will make it easier to make further improvements to the
    way we manipulate irqflags and DAIF bits.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Cc: Alexandru Elisei <alexandru.elisei@arm.com>
    Cc: Marc Zyngier <maz@kernel.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Will Deacon <will@kernel.org>
    Reviewed-by: default avatarMarc Zyngier <maz@kernel.org>
    Tested-by: default avatarMarc Zyngier <maz@kernel.org>
    Link: https://lore.kernel.org/r/20240617111841.2529370-6-mark.rutland@arm.comSigned-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
    18fdb634
irq-gic-v3.c 65.4 KB