diff options
author | Helge Deller <deller@gmx.de> | 2019-05-03 23:51:00 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2019-05-06 00:10:03 +0200 |
commit | 62217beb394e654bbd2bb87c533dadd2d8bf62c6 (patch) | |
tree | 3adcd75c34fa8d4aa3836a5e30e0d8a72995a95a /arch/parisc/kernel | |
parent | bdca5d64ee92abeacd6dada0bc6f6f8e6350dd67 (diff) |
parisc: Add static branch and JUMP_LABEL feature
Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/parisc/kernel/jump_label.c | 55 | ||||
-rw-r--r-- | arch/parisc/kernel/vmlinux.lds.S | 3 |
3 files changed, 59 insertions, 0 deletions
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index b818b28c8a99..fc0df5c44468 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -33,5 +33,6 @@ obj-$(CONFIG_64BIT) += perf.o perf_asm.o $(obj64-y) obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o +obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/arch/parisc/kernel/jump_label.c b/arch/parisc/kernel/jump_label.c new file mode 100644 index 000000000000..d2f3cb12e282 --- /dev/null +++ b/arch/parisc/kernel/jump_label.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Helge Deller <deller@gmx.de> + * + * Based on arch/arm64/kernel/jump_label.c + */ +#include <linux/kernel.h> +#include <linux/jump_label.h> +#include <linux/bug.h> +#include <asm/alternative.h> +#include <asm/patch.h> + +static inline int reassemble_17(int as17) +{ + return (((as17 & 0x10000) >> 16) | + ((as17 & 0x0f800) << 5) | + ((as17 & 0x00400) >> 8) | + ((as17 & 0x003ff) << 3)); +} + +void arch_jump_label_transform(struct jump_entry *entry, + enum jump_label_type type) +{ + void *addr = (void *)jump_entry_code(entry); + u32 insn; + + if (type == JUMP_LABEL_JMP) { + void *target = (void *)jump_entry_target(entry); + int distance = target - addr; + /* + * Encode the PA1.1 "b,n" instruction with a 17-bit + * displacement. In case we hit the BUG(), we could use + * another branch instruction with a 22-bit displacement on + * 64-bit CPUs instead. But this seems sufficient for now. + */ + distance -= 8; + BUG_ON(distance > 262143 || distance < -262144); + insn = 0xe8000002 | reassemble_17(distance >> 2); + } else { + insn = INSN_NOP; + } + + patch_text(addr, insn); +} + +void arch_jump_label_transform_static(struct jump_entry *entry, + enum jump_label_type type) +{ + /* + * We use the architected NOP in arch_static_branch, so there's no + * need to patch an identical NOP over the top of it here. The core + * will call arch_jump_label_transform from a module notifier if the + * NOP needs to be replaced by a branch. + */ +} diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index c3b1b9c24ede..a8be7a47fcc0 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -18,6 +18,9 @@ *(.data..vm0.pgd) \ *(.data..vm0.pte) +/* No __ro_after_init data in the .rodata section - which will always be ro */ +#define RO_AFTER_INIT_DATA + #include <asm-generic/vmlinux.lds.h> /* needed for the processor specific cache alignment size */ |