• Will Deacon's avatar
    arm64: Avoid calling stop_machine() when patching jump labels · f6cc0c50
    Will Deacon authored
    Patching a jump label involves patching a single instruction at a time,
    swizzling between a branch and a NOP. The architecture treats these
    instructions specially, so a concurrently executing CPU is guaranteed to
    see either the NOP or the branch, rather than an amalgamation of the two
    instruction encodings.
    
    However, in order to guarantee that the new instruction is visible, it
    is necessary to send an IPI to the concurrently executing CPU so that it
    discards any previously fetched instructions from its pipeline. This
    operation therefore cannot be completed from a context with IRQs
    disabled, but this is exactly what happens on the jump label path where
    the hotplug lock is held and irqs are subsequently disabled by
    stop_machine_cpuslocked(). This results in a deadlock during boot on
    Hikey-960.
    
    Due to the architectural guarantees around patching NOPs and branches,
    we don't actually need to stop_machine() at all on the jump label path,
    so we can avoid the deadlock by using the "nosync" variant of our
    instruction patching routine.
    
    Fixes: 693350a7 ("arm64: insn: Don't fallback on nosync path for general insn patching")
    Reported-by: default avatarTuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
    Reported-by: default avatarJohn Stultz <john.stultz@linaro.org>
    Tested-by: default avatarValentin Schneider <valentin.schneider@arm.com>
    Tested-by: default avatarTuomas Tynkkynen <tuomas@tuxera.com>
    Tested-by: default avatarJohn Stultz <john.stultz@linaro.org>
    Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
    f6cc0c50
jump_label.c 1.56 KB