Commit f6cc0c50 authored by Will Deacon's avatar Will Deacon

arm64: Avoid calling stop_machine() when patching jump labels

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>
parent 3c4d9137
...@@ -36,7 +36,7 @@ void arch_jump_label_transform(struct jump_entry *entry, ...@@ -36,7 +36,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
insn = aarch64_insn_gen_nop(); insn = aarch64_insn_gen_nop();
} }
aarch64_insn_patch_text(&addr, &insn, 1); aarch64_insn_patch_text_nosync(addr, insn);
} }
void arch_jump_label_transform_static(struct jump_entry *entry, void arch_jump_label_transform_static(struct jump_entry *entry,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment