Skip to content

Commit 62217be

Browse files
committed
parisc: Add static branch and JUMP_LABEL feature
Signed-off-by: Helge Deller <[email protected]>
1 parent bdca5d6 commit 62217be

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

arch/parisc/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ config PARISC
4545
select HAVE_DEBUG_STACKOVERFLOW
4646
select HAVE_ARCH_AUDITSYSCALL
4747
select HAVE_ARCH_HASH
48+
select HAVE_ARCH_JUMP_LABEL
49+
select HAVE_ARCH_JUMP_LABEL_RELATIVE
4850
select HAVE_ARCH_SECCOMP_FILTER
4951
select HAVE_ARCH_TRACEHOOK
5052
select HAVE_REGS_AND_STACK_ACCESS_API
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
12+
static __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;
23+
l_yes:
24+
return true;
25+
}
26+
27+
static __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;
38+
l_yes:
39+
return true;
40+
}
41+
42+
#endif /* __ASSEMBLY__ */
43+
#endif

arch/parisc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ obj-$(CONFIG_64BIT) += perf.o perf_asm.o $(obj64-y)
3333
obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o
3434
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
3535
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
36+
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
3637
obj-$(CONFIG_KGDB) += kgdb.o
3738
obj-$(CONFIG_KPROBES) += kprobes.o

arch/parisc/kernel/jump_label.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) 2019 Helge Deller <[email protected]>
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+
13+
static 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+
21+
void 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+
46+
void 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+
}

arch/parisc/kernel/vmlinux.lds.S

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
*(.data..vm0.pgd) \
1919
*(.data..vm0.pte)
2020

21+
/* No __ro_after_init data in the .rodata section - which will always be ro */
22+
#define RO_AFTER_INIT_DATA
23+
2124
#include <asm-generic/vmlinux.lds.h>
2225

2326
/* needed for the processor specific cache alignment size */

0 commit comments

Comments
 (0)