parisc: Add static branch / JUMP_LABEL feature
Subsystems (2)
Helge Deller
maintainerPATCH 1/1 parisc: Add static branch / JUMP_LABEL feature
arch/parisc/Kconfig +2 -0
@@ -45,6 +45,8 @@ config PARISC select HAVE_DEBUG_STACKOVERFLOW select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_HASH + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_REGS_AND_STACK_ACCESS_API
arch/parisc/include/asm/jump_label.h new file +43 -0
43 lines not on this page · raw message
arch/parisc/kernel/Makefile +1 -0
@@ -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
arch/parisc/kernel/jump_label.c new file +37 -0
@@ -0,0 +1,37 @@ +/* +* Copyright (C) 2019 Helge Deller <[email protected]> +* +* Based on arch/arm64/kernel/jump_label.c +*/ +#include <linux/kernel.h> +#include <linux/jump_label.h> +#include <asm/alternative.h> +#include <asm/patch.h> + +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); +unsigned len = target - addr; + insn =0xe8000002 + (len-2 )*8 ;/* "b,n .+8" */ + }else { + insn =INSN_NOP ; + } + +patch_text (addr, insn);// nosync ? +} + +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. +*/ +}
arch/parisc/kernel/vmlinux.lds.S +3 -0
@@ -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 */
Hi Helge,
Quoted 91 lines · Helge Deller
Signed-off-by Helge Deller <[email protected]>arch/parisc/Kconfig +2
-0@@ -45,6 +45,8 @@ config PARISC select HAVE_DEBUG_STACKOVERFLOW select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_HASH + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_REGS_AND_STACK_ACCESS_APIarch/parisc/include/asm/jump_label.h new file +43
-0@@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_PARISC_JUMP_LABEL_H +#define _ASM_PARISC_JUMP_LABEL_H + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <asm/assembly.h> + +#define JUMP_LABEL_NOP_SIZE 4 + +static __always_inline bool arch_static_branch(struct static_key *key, bool branch) +{ + asm_volatile_goto("1:\n\t" + "nop\n\t" + ".pushsection __jump_table, \"aw\"\n\t" + ".word 1b - ., %l[l_yes] - .\n\t" + __stringify(ASM_ULONG_INSN) " %c0\n\t" + ".popsection\n\t" + : : "i" (&((char *)key)[branch]) : : l_yes); + +return false; +l_yes: +return true; +} + +static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) +{ + asm_volatile_goto("1:\n\t" + "b,n %l[l_yes]\n\t" + ".pushsection __jump_table, \"aw\"\n\t" + ".word 1b - ., %l[l_yes] - .\n\t" + __stringify(ASM_ULONG_INSN) " %c0\n\t" + ".popsection\n\t" + : : "i" (&((char *)key)[branch]) : : l_yes); + +return false; +l_yes: +return true; +} + +#endif /* __ASSEMBLY__ */ +#endif arch/parisc/kernel/Makefile +1
-0@@ -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.oarch/parisc/kernel/jump_label.c new file +10
-0@@ -0,0 +1,37 @@ +/* +* Copyright (C) 2019 Helge Deller <[email protected]> +* +* Based on arch/arm64/kernel/jump_label.c +*/ +#include <linux/kernel.h> +#include <linux/jump_label.h> +#include <asm/alternative.h> +#include <asm/patch.h> +
arch/parisc/kernel/jump_label.c line 20
Quoted 10 lines
arch/parisc/kernel/jump_label.c new file +10
-0+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); +unsigned len = target - addr; + insn =0xe8000002 + (len-2 )*8 ;/* "b,n .+8" */
I don't know the maximum jump distance here that could be encountered, but this won't work for negative offsets and offsets > 2^11 bits due to the weird immediate encoding PA-RISC uses. I think this should use proper bit shifting to match the immediate encoding and have a BUG_ON(len < $MAX_NEG_DISTANCE || len > $MAX_POS_DISTANCE) to make sure we're not patching invalid branch instructions into the Kernel.
Quoted 31 lines
arch/parisc/kernel/jump_label.c new file +17
-0+ }else { + insn =INSN_NOP ; + } + +patch_text (addr, insn);// nosync ? +} + +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. +*/ +}arch/parisc/kernel/vmlinux.lds.S +3
-0@@ -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 */
Helge Deller
maintainerPATCH 1/1 parisc: Add static branch and JUMP_LABEL feature (v2)
v1: Initial patch
v2: Fixes, correctly encode branch instruction, check distance, check on 32-
and 64-bit kernel
arch/parisc/Kconfig +2 -0
@@ -45,6 +45,8 @@ config PARISC select HAVE_DEBUG_STACKOVERFLOW select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_HASH + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_REGS_AND_STACK_ACCESS_API
arch/parisc/include/asm/jump_label.h new file +43 -0
43 lines not on this page · raw message
arch/parisc/kernel/Makefile +1 -0
@@ -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
arch/parisc/kernel/jump_label.c new file +55 -0
55 lines not on this page · raw message
arch/parisc/kernel/vmlinux.lds.S +3 -0
@@ -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 */
Re: [PATCH] parisc: Add static branch and JUMP_LABEL feature (v2)
arch/parisc/kernel/jump_label.c line 35
Quoted 8 lines · Helge Deller
arch/parisc/kernel/jump_label.c new file +8
-0+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. +*/
Just a note on the comment. The branch instruction with 22-bit displacement uses the return pointer register %rp. It is available on 32 and 64-bit PA 2.0 machines but one would have to clobber %rp, or save and restore it on stack. The former would cause %rp to be saved and restored in the function's prologue and epilogue, respectively.
Dave
Signature · 1 line
John David Anglin [email protected]