forked from Minki/linux
f2545b2d4c
The conversion of the hotplug locking to a percpu rwsem unearthed lock ordering issues all over the place. The jump_label code has two issues: 1) Nested get_online_cpus() invocations 2) Ordering problems vs. the cpus rwsem and the jump_label_mutex To cure these, the following lock order has been established; cpus_rwsem -> jump_label_lock -> text_mutex Even if not all architectures need protection against CPU hotplug, taking cpus_rwsem before jump_label_lock is now mandatory in code pathes which actually modify code and therefor need text_mutex protection. Move the get_online_cpus() invocations into the core jump label code and establish the proper lock order where required. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ingo Molnar <mingo@kernel.org> Acked-by: "David S. Miller" <davem@davemloft.net> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Chris Metcalf <cmetcalf@mellanox.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sebastian Siewior <bigeasy@linutronix.de> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Jason Baron <jbaron@akamai.com> Cc: Ralf Baechle <ralf@linux-mips.org> Link: http://lkml.kernel.org/r/20170524081549.025830817@linutronix.de
51 lines
1.0 KiB
C
51 lines
1.0 KiB
C
#include <linux/kernel.h>
|
|
#include <linux/types.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/cpu.h>
|
|
|
|
#include <linux/jump_label.h>
|
|
#include <linux/memory.h>
|
|
|
|
#include <asm/cacheflush.h>
|
|
|
|
#ifdef HAVE_JUMP_LABEL
|
|
|
|
void arch_jump_label_transform(struct jump_entry *entry,
|
|
enum jump_label_type type)
|
|
{
|
|
u32 *insn = (u32 *) (unsigned long) entry->code;
|
|
u32 val;
|
|
|
|
if (type == JUMP_LABEL_JMP) {
|
|
s32 off = (s32)entry->target - (s32)entry->code;
|
|
bool use_v9_branch = false;
|
|
|
|
BUG_ON(off & 3);
|
|
|
|
#ifdef CONFIG_SPARC64
|
|
if (off <= 0xfffff && off >= -0x100000)
|
|
use_v9_branch = true;
|
|
#endif
|
|
if (use_v9_branch) {
|
|
/* WDISP19 - target is . + immed << 2 */
|
|
/* ba,pt %xcc, . + off */
|
|
val = 0x10680000 | (((u32) off >> 2) & 0x7ffff);
|
|
} else {
|
|
/* WDISP22 - target is . + immed << 2 */
|
|
BUG_ON(off > 0x7fffff);
|
|
BUG_ON(off < -0x800000);
|
|
/* ba . + off */
|
|
val = 0x10800000 | (((u32) off >> 2) & 0x3fffff);
|
|
}
|
|
} else {
|
|
val = 0x01000000;
|
|
}
|
|
|
|
mutex_lock(&text_mutex);
|
|
*insn = val;
|
|
flushi(insn);
|
|
mutex_unlock(&text_mutex);
|
|
}
|
|
|
|
#endif
|