Commit 13ddb52c authored by Heiko Carstens's avatar Heiko Carstens Committed by Thomas Gleixner

s390/jump_label: Switch to relative references

Enable support for relative references in jump_label entries.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-s390@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Kees Cook <keescook@chromium.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Jessica Yu <jeyu@kernel.org>
Link: https://lkml.kernel.org/r/20180919065144.25010-10-ard.biesheuvel@linaro.org
parent e872267b
...@@ -120,6 +120,7 @@ config S390 ...@@ -120,6 +120,7 @@ config S390
select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_SOFT_DIRTY select HAVE_ARCH_SOFT_DIRTY
......
...@@ -14,41 +14,33 @@ ...@@ -14,41 +14,33 @@
* We use a brcl 0,2 instruction for jump labels at compile time so it * We use a brcl 0,2 instruction for jump labels at compile time so it
* can be easily distinguished from a hotpatch generated instruction. * can be easily distinguished from a hotpatch generated instruction.
*/ */
static __always_inline bool arch_static_branch(struct static_key *key, bool branch) static inline bool arch_static_branch(struct static_key *key, bool branch)
{ {
asm_volatile_goto("0: brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n" asm_volatile_goto("0: brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
".pushsection __jump_table, \"aw\"\n" ".pushsection __jump_table,\"aw\"\n"
".balign 8\n" ".balign 8\n"
".quad 0b, %l[label], %0\n" ".long 0b-.,%l[label]-.\n"
".quad %0-.\n"
".popsection\n" ".popsection\n"
: : "X" (&((char *)key)[branch]) : : label); : : "X" (&((char *)key)[branch]) : : label);
return false; return false;
label: label:
return true; return true;
} }
static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) static inline bool arch_static_branch_jump(struct static_key *key, bool branch)
{ {
asm_volatile_goto("0: brcl 15, %l[label]\n" asm_volatile_goto("0: brcl 15,%l[label]\n"
".pushsection __jump_table, \"aw\"\n" ".pushsection __jump_table,\"aw\"\n"
".balign 8\n" ".balign 8\n"
".quad 0b, %l[label], %0\n" ".long 0b-.,%l[label]-.\n"
".quad %0-.\n"
".popsection\n" ".popsection\n"
: : "X" (&((char *)key)[branch]) : : label); : : "X" (&((char *)key)[branch]) : : label);
return false; return false;
label: label:
return true; return true;
} }
typedef unsigned long jump_label_t;
struct jump_entry {
jump_label_t code;
jump_label_t target;
jump_label_t key;
};
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif #endif
...@@ -33,13 +33,13 @@ static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn) ...@@ -33,13 +33,13 @@ static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn)
{ {
/* brcl 15,offset */ /* brcl 15,offset */
insn->opcode = 0xc0f4; insn->opcode = 0xc0f4;
insn->offset = (entry->target - entry->code) >> 1; insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
} }
static void jump_label_bug(struct jump_entry *entry, struct insn *expected, static void jump_label_bug(struct jump_entry *entry, struct insn *expected,
struct insn *new) struct insn *new)
{ {
unsigned char *ipc = (unsigned char *)entry->code; unsigned char *ipc = (unsigned char *)jump_entry_code(entry);
unsigned char *ipe = (unsigned char *)expected; unsigned char *ipe = (unsigned char *)expected;
unsigned char *ipn = (unsigned char *)new; unsigned char *ipn = (unsigned char *)new;
...@@ -59,6 +59,7 @@ static void __jump_label_transform(struct jump_entry *entry, ...@@ -59,6 +59,7 @@ static void __jump_label_transform(struct jump_entry *entry,
enum jump_label_type type, enum jump_label_type type,
int init) int init)
{ {
void *code = (void *)jump_entry_code(entry);
struct insn old, new; struct insn old, new;
if (type == JUMP_LABEL_JMP) { if (type == JUMP_LABEL_JMP) {
...@@ -69,13 +70,13 @@ static void __jump_label_transform(struct jump_entry *entry, ...@@ -69,13 +70,13 @@ static void __jump_label_transform(struct jump_entry *entry,
jump_label_make_nop(entry, &new); jump_label_make_nop(entry, &new);
} }
if (init) { if (init) {
if (memcmp((void *)entry->code, &orignop, sizeof(orignop))) if (memcmp(code, &orignop, sizeof(orignop)))
jump_label_bug(entry, &orignop, &new); jump_label_bug(entry, &orignop, &new);
} else { } else {
if (memcmp((void *)entry->code, &old, sizeof(old))) if (memcmp(code, &old, sizeof(old)))
jump_label_bug(entry, &old, &new); jump_label_bug(entry, &old, &new);
} }
s390_kernel_write((void *)entry->code, &new, sizeof(new)); s390_kernel_write(code, &new, sizeof(new));
} }
static int __sm_arch_jump_label_transform(void *data) static int __sm_arch_jump_label_transform(void *data)
......
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