Skip to content

Commit 8c30b00

Browse files
ChenMiaoistffrdhrn
authored andcommitted
openrisc: Add jump label support
Supported a complete jump_label implementation based on the ARM64 and RV64 version and add the CONFIG_JUMP_LABEL=y to the defconfig. Testing was conducted using a dedicated test module jump-label-test, provided in the link below. For detailed steps, please refer to the README also at the provided link. Link: https://github.com/ChenMiaoi/GSoC-2025-Final-Report/tree/main/tests/jump-label-test Test Environment: - Hardware: QEMU emulated OR1K - Kernel Version: 6.17.0-rc3-dirty - Configs: CONFIG_MODULES=y,CONFIG_MODULE_UNLOAD=y - Toolchain: or1k-none-linux-musl-gcc 15.1.0 Test Results: $ insmod jump_label_test.ko [ 32.590000] Jump label performance test module loaded [ 35.250000] Normal branch time: 1241327150 ns (124 ns per iteration) [ 35.250000] Jump label (false) time: 706422700 ns (70 ns per iteration) [ 35.250000] Jump label (true) time: 708913450 ns (70 ns per iteration) $ rmmod jump_label_test.ko [ 72.210000] Jump label test module unloaded The results show approximately 43% improvement in branch performance when using jump labels compared to traditional branches. Link: https://lore.kernel.org/openrisc/aLsZ9S3X0OpKy1RM@antec/T/#u Signed-off-by: chenmiao <[email protected]> Signed-off-by: Stafford Horne <[email protected]>
1 parent 09a27fc commit 8c30b00

File tree

9 files changed

+134
-1
lines changed

9 files changed

+134
-1
lines changed

Documentation/features/core/jump-labels/arch-support.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
| microblaze: | TODO |
1818
| mips: | ok |
1919
| nios2: | TODO |
20-
| openrisc: | TODO |
20+
| openrisc: | ok |
2121
| parisc: | ok |
2222
| powerpc: | ok |
2323
| riscv: | ok |

arch/openrisc/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ config OPENRISC
2424
select GENERIC_PCI_IOMAP
2525
select GENERIC_IOREMAP
2626
select GENERIC_CPU_DEVICES
27+
select HAVE_ARCH_JUMP_LABEL
28+
select HAVE_ARCH_JUMP_LABEL_RELATIVE
2729
select HAVE_PCI
2830
select HAVE_UID16
2931
select HAVE_PAGE_SIZE_8KB

arch/openrisc/configs/or1ksim_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CONFIG_EXPERT=y
1010
# CONFIG_KALLSYMS is not set
1111
CONFIG_BUILTIN_DTB_NAME="or1ksim"
1212
CONFIG_HZ_100=y
13+
CONFIG_JUMP_LABEL=y
1314
CONFIG_MODULES=y
1415
# CONFIG_BLOCK is not set
1516
CONFIG_SLUB_TINY=y

arch/openrisc/configs/virt_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CONFIG_NR_CPUS=8
1212
CONFIG_SMP=y
1313
CONFIG_HZ_100=y
1414
# CONFIG_OPENRISC_NO_SPR_SR_DSX is not set
15+
CONFIG_JUMP_LABEL=y
1516
# CONFIG_COMPAT_BRK is not set
1617
CONFIG_NET=y
1718
CONFIG_PACKET=y

arch/openrisc/include/asm/insn-def.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@
99
/* or1k instructions are always 32 bits. */
1010
#define OPENRISC_INSN_SIZE 4
1111

12+
/* or1k nop instruction code */
13+
#define OPENRISC_INSN_NOP 0x15000000U
14+
1215
#endif /* __ASM_OPENRISC_INSN_DEF_H */
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2025 Chen Miao
4+
*
5+
* Based on arch/arm/include/asm/jump_label.h
6+
*/
7+
#ifndef __ASM_OPENRISC_JUMP_LABEL_H
8+
#define __ASM_OPENRISC_JUMP_LABEL_H
9+
10+
#ifndef __ASSEMBLER__
11+
12+
#include <linux/types.h>
13+
#include <asm/insn-def.h>
14+
15+
#define HAVE_JUMP_LABEL_BATCH
16+
17+
#define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE
18+
19+
/**
20+
* JUMP_TABLE_ENTRY - Create a jump table entry
21+
* @key: Jump key identifier (typically a symbol address)
22+
* @label: Target label address
23+
*
24+
* This macro creates a jump table entry in the dedicated kernel section (__jump_table).
25+
* Each entry contains the following information:
26+
* Offset from current instruction to jump instruction (1b - .)
27+
* Offset from current instruction to target label (label - .)
28+
* Offset from current instruction to key identifier (key - .)
29+
*/
30+
#define JUMP_TABLE_ENTRY(key, label) \
31+
".pushsection __jump_table, \"aw\" \n\t" \
32+
".align 4 \n\t" \
33+
".long 1b - ., " label " - . \n\t" \
34+
".long " key " - . \n\t" \
35+
".popsection \n\t"
36+
37+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
38+
".align 4 \n\t" \
39+
"1: l.nop \n\t" \
40+
" l.nop \n\t" \
41+
JUMP_TABLE_ENTRY(key, label)
42+
43+
static __always_inline bool arch_static_branch(struct static_key *const key,
44+
const bool branch)
45+
{
46+
asm goto (ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
47+
::"i"(&((char *)key)[branch])::l_yes);
48+
49+
return false;
50+
l_yes:
51+
return true;
52+
}
53+
54+
#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \
55+
".align 4 \n\t" \
56+
"1: l.j " label " \n\t" \
57+
" l.nop \n\t" \
58+
JUMP_TABLE_ENTRY(key, label)
59+
60+
static __always_inline bool
61+
arch_static_branch_jump(struct static_key *const key, const bool branch)
62+
{
63+
asm goto (ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[l_yes]")
64+
::"i"(&((char *)key)[branch])::l_yes);
65+
66+
return false;
67+
l_yes:
68+
return true;
69+
}
70+
71+
#endif /* __ASSEMBLER__ */
72+
#endif /* __ASM_OPENRISC_JUMP_LABEL_H */

arch/openrisc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ obj-y := head.o setup.o or32_ksyms.o process.o dma.o \
99
traps.o time.o irq.o entry.o ptrace.o signal.o \
1010
sys_call_table.o unwinder.o cacheinfo.o
1111

12+
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
1213
obj-$(CONFIG_SMP) += smp.o sync-timer.o
1314
obj-$(CONFIG_STACKTRACE) += stacktrace.o
1415
obj-$(CONFIG_MODULES) += module.o

arch/openrisc/kernel/jump_label.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2025 Chen Miao
4+
*
5+
* Based on arch/arm/kernel/jump_label.c
6+
*/
7+
#include <linux/jump_label.h>
8+
#include <linux/kernel.h>
9+
#include <linux/memory.h>
10+
#include <asm/bug.h>
11+
#include <asm/cacheflush.h>
12+
#include <asm/text-patching.h>
13+
14+
bool arch_jump_label_transform_queue(struct jump_entry *entry,
15+
enum jump_label_type type)
16+
{
17+
void *addr = (void *)jump_entry_code(entry);
18+
u32 insn;
19+
20+
if (type == JUMP_LABEL_JMP) {
21+
long offset;
22+
23+
offset = jump_entry_target(entry) - jump_entry_code(entry);
24+
/*
25+
* The actual maximum range of the l.j instruction's offset is -134,217,728
26+
* ~ 134,217,724 (sign 26-bit imm).
27+
* For the original jump range, we need to right-shift N by 2 to obtain the
28+
* instruction's offset.
29+
*/
30+
WARN_ON_ONCE(offset < -134217728 || offset > 134217724);
31+
32+
/* 26bit imm mask */
33+
offset = (offset >> 2) & 0x03ffffff;
34+
35+
insn = offset;
36+
} else {
37+
insn = OPENRISC_INSN_NOP;
38+
}
39+
40+
if (early_boot_irqs_disabled)
41+
copy_to_kernel_nofault(addr, &insn, sizeof(insn));
42+
else
43+
patch_insn_write(addr, insn);
44+
45+
return true;
46+
}
47+
48+
void arch_jump_label_transform_apply(void)
49+
{
50+
kick_all_cpus_sync();
51+
}

arch/openrisc/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ void __init setup_arch(char **cmdline_p)
249249
initrd_below_start_ok = 1;
250250
}
251251
#endif
252+
/* perform jump_table sorting before paging_init locks down read only memory */
253+
jump_label_init();
252254

253255
/* paging_init() sets up the MMU and marks all pages as reserved */
254256
paging_init();

0 commit comments

Comments
 (0)