• Mark Rutland's avatar
    arm64: irqflags: use alternative branches for pseudo-NMI logic · a5f61cc6
    Mark Rutland authored
    Due to the way we use alternatives in the irqflags code, even when
    CONFIG_ARM64_PSEUDO_NMI=n, we generate unused alternative code for
    pseudo-NMI management. This patch reworks the irqflags code to remove
    the redundant code when CONFIG_ARM64_PSEUDO_NMI=n, which benefits the
    more common case, and will permit further rework of our DAIF management
    (e.g. in preparation for ARMv8.8-A's NMI feature).
    
    Prior to this patch a defconfig kernel has hundreds of redundant
    instructions to access ICC_PMR_EL1 (which should only need to be
    manipulated in setup code), which this patch removes:
    
    | [mark@lakrids:~/src/linux]% usekorg 12.1.0 aarch64-linux-objdump -d vmlinux-before-defconfig | grep icc_pmr_el1 | wc -l
    | 885
    | [mark@lakrids:~/src/linux]% usekorg 12.1.0 aarch64-linux-objdump -d vmlinux-after-defconfig | grep icc_pmr_el1 | wc -l
    | 5
    
    Those instructions alone account for more than 3KiB of kernel text, and
    will be associated with additional alt_instr entries, padding and
    branches, etc.
    
    These redundant instructions exist because we use alternative sequences
    for to choose between DAIF / PMR management in irqflags.h, and even when
    CONFIG_ARM64_PSEUDO_NMI=n, those alternative sequences will generate the
    code for PMR management, along with alt_instr entries. We use
    alternatives here as this was necessary to ensure that we never
    encounter a mismatched local_irq_save() ... local_irq_restore() sequence
    in the middle of patching, which was possible to see if we used static
    keys to choose between DAIF and PMR management.
    
    Since commit:
    
      21fb26bf ("arm64: alternatives: add alternative_has_feature_*()")
    
    ... we have a mechanism to use alternatives similarly to static keys,
    allowing us to write the bulk of the logic in C code while also being
    able to rely on all sites being patched in one go, and avoiding a
    mismatched mismatched local_irq_save() ... local_irq_restore() sequence
    during patching.
    
    This patch rewrites arm64's local_irq_*() functions to use alternative
    branches. This allows for the pseudo-NMI code to be entirely elided when
    CONFIG_ARM64_PSEUDO_NMI=n, making a defconfig Image 64KiB smaller, and
    not affectint the size of an Image with CONFIG_ARM64_PSEUDO_NMI=y:
    
    | [mark@lakrids:~/src/linux]% ls -al vmlinux-*
    | -rwxr-xr-x 1 mark mark 137473432 Jan 18 11:11 vmlinux-after-defconfig
    | -rwxr-xr-x 1 mark mark 137918776 Jan 18 11:15 vmlinux-after-pnmi
    | -rwxr-xr-x 1 mark mark 137380152 Jan 18 11:03 vmlinux-before-defconfig
    | -rwxr-xr-x 1 mark mark 137523704 Jan 18 11:08 vmlinux-before-pnmi
    | [mark@lakrids:~/src/linux]% ls -al Image-*
    | -rw-r--r-- 1 mark mark 38646272 Jan 18 11:11 Image-after-defconfig
    | -rw-r--r-- 1 mark mark 38777344 Jan 18 11:14 Image-after-pnmi
    | -rw-r--r-- 1 mark mark 38711808 Jan 18 11:03 Image-before-defconfig
    | -rw-r--r-- 1 mark mark 38777344 Jan 18 11:08 Image-before-pnmi
    
    Some sensitive code depends on being run with interrupts enabled or with
    interrupts disabled, and so when enabling or disabling interrupts we
    must ensure that the compiler does not move such code around the actual
    enable/disable. Before this patch, that was ensured by the combined asm
    volatile blocks having memory clobbers (and any sensitive code either
    being asm volatile, or touching memory). This patch consistently uses
    explicit barrier() operations before and after the enable/disable, which
    allows us to use the usual sysreg accessors (which are asm volatile) to
    manipulate the interrupt masks. The use of pmr_sync() is pulled within
    this critical section for consistency.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Reviewed-by: default avatarMarc Zyngier <maz@kernel.org>
    Cc: Mark Brown <broonie@kernel.org>
    Cc: Will Deacon <will@kernel.org>
    Link: https://lore.kernel.org/r/20230130145429.903791-6-mark.rutland@arm.comSigned-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    a5f61cc6
irqflags.h 4.45 KB