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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ config S390
	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
	select HAVE_ARCH_AUDITSYSCALL
	select HAVE_ARCH_JUMP_LABEL
	select HAVE_ARCH_JUMP_LABEL_RELATIVE
	select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
	select HAVE_ARCH_SECCOMP_FILTER
	select HAVE_ARCH_SOFT_DIRTY
+16 −24
Original line number Diff line number Diff line
@@ -14,41 +14,33 @@
 * We use a brcl 0,2 instruction for jump labels at compile time so it
 * 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"
			  ".pushsection __jump_table,\"aw\"\n"
			  ".balign	8\n"
		".quad 0b, %l[label], %0\n"
			  ".long	0b-.,%l[label]-.\n"
			  ".quad	%0-.\n"
			  ".popsection\n"
			  : : "X" (&((char *)key)[branch]) : : label);

	return false;
label:
	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"
			  ".pushsection __jump_table,\"aw\"\n"
			  ".balign	8\n"
		".quad 0b, %l[label], %0\n"
			  ".long	0b-.,%l[label]-.\n"
			  ".quad	%0-.\n"
			  ".popsection\n"
			  : : "X" (&((char *)key)[branch]) : : label);

	return false;
label:
	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
+6 −5
Original line number Diff line number Diff line
@@ -33,13 +33,13 @@ static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn)
{
	/* brcl 15,offset */
	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,
			   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 *ipn = (unsigned char *)new;

@@ -59,6 +59,7 @@ static void __jump_label_transform(struct jump_entry *entry,
				   enum jump_label_type type,
				   int init)
{
	void *code = (void *)jump_entry_code(entry);
	struct insn old, new;

	if (type == JUMP_LABEL_JMP) {
@@ -69,13 +70,13 @@ static void __jump_label_transform(struct jump_entry *entry,
		jump_label_make_nop(entry, &new);
	}
	if (init) {
		if (memcmp((void *)entry->code, &orignop, sizeof(orignop)))
		if (memcmp(code, &orignop, sizeof(orignop)))
			jump_label_bug(entry, &orignop, &new);
	} else {
		if (memcmp((void *)entry->code, &old, sizeof(old)))
		if (memcmp(code, &old, sizeof(old)))
			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)