aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/parisc/Kconfig2
-rw-r--r--arch/parisc/include/asm/jump_label.h43
-rw-r--r--arch/parisc/kernel/Makefile1
-rw-r--r--arch/parisc/kernel/jump_label.c55
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S3
5 files changed, 104 insertions, 0 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 26c215570adf..c971256a74d2 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -45,6 +45,8 @@ config PARISC
45 select HAVE_DEBUG_STACKOVERFLOW 45 select HAVE_DEBUG_STACKOVERFLOW
46 select HAVE_ARCH_AUDITSYSCALL 46 select HAVE_ARCH_AUDITSYSCALL
47 select HAVE_ARCH_HASH 47 select HAVE_ARCH_HASH
48 select HAVE_ARCH_JUMP_LABEL
49 select HAVE_ARCH_JUMP_LABEL_RELATIVE
48 select HAVE_ARCH_SECCOMP_FILTER 50 select HAVE_ARCH_SECCOMP_FILTER
49 select HAVE_ARCH_TRACEHOOK 51 select HAVE_ARCH_TRACEHOOK
50 select HAVE_REGS_AND_STACK_ACCESS_API 52 select HAVE_REGS_AND_STACK_ACCESS_API
diff --git a/arch/parisc/include/asm/jump_label.h b/arch/parisc/include/asm/jump_label.h
new file mode 100644
index 000000000000..7efb1aa2f7f8
--- /dev/null
+++ b/arch/parisc/include/asm/jump_label.h
@@ -0,0 +1,43 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _ASM_PARISC_JUMP_LABEL_H
3#define _ASM_PARISC_JUMP_LABEL_H
4
5#ifndef __ASSEMBLY__
6
7#include <linux/types.h>
8#include <asm/assembly.h>
9
10#define JUMP_LABEL_NOP_SIZE 4
11
12static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
13{
14 asm_volatile_goto("1:\n\t"
15 "nop\n\t"
16 ".pushsection __jump_table, \"aw\"\n\t"
17 ".word 1b - ., %l[l_yes] - .\n\t"
18 __stringify(ASM_ULONG_INSN) " %c0 - .\n\t"
19 ".popsection\n\t"
20 : : "i" (&((char *)key)[branch]) : : l_yes);
21
22 return false;
23l_yes:
24 return true;
25}
26
27static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
28{
29 asm_volatile_goto("1:\n\t"
30 "b,n %l[l_yes]\n\t"
31 ".pushsection __jump_table, \"aw\"\n\t"
32 ".word 1b - ., %l[l_yes] - .\n\t"
33 __stringify(ASM_ULONG_INSN) " %c0 - .\n\t"
34 ".popsection\n\t"
35 : : "i" (&((char *)key)[branch]) : : l_yes);
36
37 return false;
38l_yes:
39 return true;
40}
41
42#endif /* __ASSEMBLY__ */
43#endif
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)
33obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o 33obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o
34obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o 34obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
35obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o 35obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
36obj-$(CONFIG_JUMP_LABEL) += jump_label.o
36obj-$(CONFIG_KGDB) += kgdb.o 37obj-$(CONFIG_KGDB) += kgdb.o
37obj-$(CONFIG_KPROBES) += kprobes.o 38obj-$(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 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Helge Deller <deller@gmx.de>
4 *
5 * Based on arch/arm64/kernel/jump_label.c
6 */
7#include <linux/kernel.h>
8#include <linux/jump_label.h>
9#include <linux/bug.h>
10#include <asm/alternative.h>
11#include <asm/patch.h>
12
13static inline int reassemble_17(int as17)
14{
15 return (((as17 & 0x10000) >> 16) |
16 ((as17 & 0x0f800) << 5) |
17 ((as17 & 0x00400) >> 8) |
18 ((as17 & 0x003ff) << 3));
19}
20
21void arch_jump_label_transform(struct jump_entry *entry,
22 enum jump_label_type type)
23{
24 void *addr = (void *)jump_entry_code(entry);
25 u32 insn;
26
27 if (type == JUMP_LABEL_JMP) {
28 void *target = (void *)jump_entry_target(entry);
29 int distance = target - addr;
30 /*
31 * Encode the PA1.1 "b,n" instruction with a 17-bit
32 * displacement. In case we hit the BUG(), we could use
33 * another branch instruction with a 22-bit displacement on
34 * 64-bit CPUs instead. But this seems sufficient for now.
35 */
36 distance -= 8;
37 BUG_ON(distance > 262143 || distance < -262144);
38 insn = 0xe8000002 | reassemble_17(distance >> 2);
39 } else {
40 insn = INSN_NOP;
41 }
42
43 patch_text(addr, insn);
44}
45
46void arch_jump_label_transform_static(struct jump_entry *entry,
47 enum jump_label_type type)
48{
49 /*
50 * We use the architected NOP in arch_static_branch, so there's no
51 * need to patch an identical NOP over the top of it here. The core
52 * will call arch_jump_label_transform from a module notifier if the
53 * NOP needs to be replaced by a branch.
54 */
55}
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 @@
18 *(.data..vm0.pgd) \ 18 *(.data..vm0.pgd) \
19 *(.data..vm0.pte) 19 *(.data..vm0.pte)
20 20
21/* No __ro_after_init data in the .rodata section - which will always be ro */
22#define RO_AFTER_INIT_DATA
23
21#include <asm-generic/vmlinux.lds.h> 24#include <asm-generic/vmlinux.lds.h>
22 25
23/* needed for the processor specific cache alignment size */ 26/* needed for the processor specific cache alignment size */