* [PATCH v2 0/2] Support fixmap and jump_label for openrisc @ 2025-08-06 2:05 ChenMiao 2025-08-06 2:05 ` [PATCH v2 1/2] openrisc: Add text patching API support ChenMiao 2025-08-06 2:05 ` [PATCH v2 2/2] openrisc: Add jump label support ChenMiao 0 siblings, 2 replies; 7+ messages in thread From: ChenMiao @ 2025-08-06 2:05 UTC (permalink / raw) To: Linux Kernel; +Cc: Linux OpenRISC, chenmiao From: chenmiao <chenmiao.ku@gmail.com> Hello everyone, This implements a basic text patching mechanism and a complete jump_label implementation for OpenRISC. 1. Implement the patch_map interface and the patch_insn_write single insn write API by providing FIX_TEXT_POKE0. And create a new insn-def.h to record openrisc's instruction macro definition which only have OPENRISC_INSN_SIZE now. - V2: modify the patch_insn_write API from const void* to u32 insn. 2. Based on the previously implemented patch_insn_write, achieve a complete jump_label implementation, directly supporting arch_jump_label_transform_queue. And add a new macro OPENRISC_INSN_NOP in insn-def.h. - V2: using the modified patch_insn_write API in arch_jump_label_transform_queue. Link: https://lore.kernel.org/openrisc/20250805084926.4125564-1-chenmiao.ku@gmail.com/T/#u Thanks, Chen Miao chenmiao (2): openrisc: Add text patching API support openrisc: Add jump label support .../core/jump-labels/arch-support.txt | 2 +- arch/openrisc/Kconfig | 2 + arch/openrisc/configs/or1ksim_defconfig | 19 ++--- arch/openrisc/configs/virt_defconfig | 1 + arch/openrisc/include/asm/Kbuild | 1 - arch/openrisc/include/asm/fixmap.h | 1 + arch/openrisc/include/asm/insn-def.h | 15 ++++ arch/openrisc/include/asm/jump_label.h | 68 ++++++++++++++++ arch/openrisc/include/asm/text-patching.h | 13 +++ arch/openrisc/kernel/Makefile | 2 + arch/openrisc/kernel/jump_label.c | 53 +++++++++++++ arch/openrisc/kernel/patching.c | 79 +++++++++++++++++++ arch/openrisc/kernel/setup.c | 2 + arch/openrisc/mm/init.c | 2 +- 14 files changed, 245 insertions(+), 15 deletions(-) create mode 100644 arch/openrisc/include/asm/insn-def.h create mode 100644 arch/openrisc/include/asm/jump_label.h create mode 100644 arch/openrisc/include/asm/text-patching.h create mode 100644 arch/openrisc/kernel/jump_label.c create mode 100644 arch/openrisc/kernel/patching.c -- 2.45.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] openrisc: Add text patching API support 2025-08-06 2:05 [PATCH v2 0/2] Support fixmap and jump_label for openrisc ChenMiao @ 2025-08-06 2:05 ` ChenMiao 2025-08-09 8:25 ` Stafford Horne 2025-08-06 2:05 ` [PATCH v2 2/2] openrisc: Add jump label support ChenMiao 1 sibling, 1 reply; 7+ messages in thread From: ChenMiao @ 2025-08-06 2:05 UTC (permalink / raw) To: Linux Kernel Cc: Linux OpenRISC, chenmiao, Jonas Bonn, Stefan Kristiansson, Stafford Horne, Mike Rapoport (Microsoft), Geert Uytterhoeven, Arnd Bergmann, Luis Chamberlain, Sahil Siddiq, Johannes Berg, Nicolas Schier, Masahiro Yamada, Dave Hansen, Andrew Morton From: chenmiao <chenmiao.ku@gmail.com> We need a text patching mechanism to ensure that in the subsequent implementation of jump_label, the code can be modified to the correct location. Therefore, FIX_TEXT_POKE0 has been added as a mapping area. And, I create a new file named insn-def.h to define the or1k insn macro size and more define in the future. Among these changes, we implement patch_map and support the patch_insn_write API for single instruction writing. - V2: We modify the patch_insn_write(void *addr, const void *insn) API to patch_insn_write(void *addr, u32 insn), derectly support a single u32 instruction write to map memory. Link: https://lore.kernel.org/openrisc/aJIC8o1WmVHol9RY@antec/T/#t Signed-off-by: chenmiao <chenmiao.ku@gmail.com> --- arch/openrisc/include/asm/Kbuild | 1 - arch/openrisc/include/asm/fixmap.h | 1 + arch/openrisc/include/asm/insn-def.h | 12 ++++ arch/openrisc/include/asm/text-patching.h | 13 ++++ arch/openrisc/kernel/Makefile | 1 + arch/openrisc/kernel/patching.c | 79 +++++++++++++++++++++++ arch/openrisc/mm/init.c | 2 +- 7 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 arch/openrisc/include/asm/insn-def.h create mode 100644 arch/openrisc/include/asm/text-patching.h create mode 100644 arch/openrisc/kernel/patching.c diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index 2b1a6b00cdac..cef49d60d74c 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -9,4 +9,3 @@ generic-y += spinlock.h generic-y += qrwlock_types.h generic-y += qrwlock.h generic-y += user.h -generic-y += text-patching.h diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h index aaa6a26a3e92..74000215064d 100644 --- a/arch/openrisc/include/asm/fixmap.h +++ b/arch/openrisc/include/asm/fixmap.h @@ -28,6 +28,7 @@ enum fixed_addresses { FIX_EARLYCON_MEM_BASE, + FIX_TEXT_POKE0, __end_of_fixed_addresses }; diff --git a/arch/openrisc/include/asm/insn-def.h b/arch/openrisc/include/asm/insn-def.h new file mode 100644 index 000000000000..dc8d16db1579 --- /dev/null +++ b/arch/openrisc/include/asm/insn-def.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025 Chen Miao + */ + +#ifndef __ASM_INSN_DEF_H +#define __ASM_INSN_DEF_H + +/* or1k instructions are always 32 bits. */ +#define OPENRISC_INSN_SIZE 4 + +#endif /* __ASM_INSN_DEF_H */ diff --git a/arch/openrisc/include/asm/text-patching.h b/arch/openrisc/include/asm/text-patching.h new file mode 100644 index 000000000000..bffe828288c3 --- /dev/null +++ b/arch/openrisc/include/asm/text-patching.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025 Chen Miao + */ + +#ifndef _ASM_PATCHING_H_ +#define _ASM_PATCHING_H_ + +#include <linux/types.h> + +int patch_insn_write(void *addr, u32 insn); + +#endif /* _ASM_PATCHING_H_ */ diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile index 58e6a1b525b7..f0957ce16d6b 100644 --- a/arch/openrisc/kernel/Makefile +++ b/arch/openrisc/kernel/Makefile @@ -13,5 +13,6 @@ obj-$(CONFIG_SMP) += smp.o sync-timer.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_OF) += prom.o +obj-y += patching.o clean: diff --git a/arch/openrisc/kernel/patching.c b/arch/openrisc/kernel/patching.c new file mode 100644 index 000000000000..c9a30f0d1193 --- /dev/null +++ b/arch/openrisc/kernel/patching.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (C) 2020 SiFive + * Copyright (C) 2025 Chen Miao + */ + +#include <linux/mm.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/uaccess.h> + +#include <asm/insn-def.h> +#include <asm/cacheflush.h> +#include <asm/page.h> +#include <asm/fixmap.h> +#include <asm/text-patching.h> +#include <asm/sections.h> + +static DEFINE_RAW_SPINLOCK(patch_lock); + +static inline bool is_exit_text(uintptr_t addr) +{ + /* Now Have NO Mechanism to do */ + return true; +} + +static __always_inline void *patch_map(void *addr, int fixmap) +{ + uintptr_t uaddr = (uintptr_t) addr; + phys_addr_t phys; + + if (core_kernel_text(uaddr) || is_exit_text(uaddr)) { + phys = __pa_symbol(addr); + } else { + struct page *page = vmalloc_to_page(addr); + BUG_ON(!page); + phys = page_to_phys(page) + offset_in_page(addr); + } + + return (void *)set_fixmap_offset(fixmap, phys); +} + +static void patch_unmap(int fixmap) +{ + clear_fixmap(fixmap); +} + +static int __patch_insn_write(void *addr, u32 insn) +{ + void *waddr = addr; + unsigned long flags = 0; + int ret; + + raw_spin_lock_irqsave(&patch_lock, flags); + + waddr = patch_map(addr, FIX_TEXT_POKE0); + + ret = copy_to_kernel_nofault(waddr, &insn, OPENRISC_INSN_SIZE); + local_icache_range_inv((unsigned long)waddr, + (unsigned long)waddr + OPENRISC_INSN_SIZE); + + patch_unmap(FIX_TEXT_POKE0); + + raw_spin_unlock_irqrestore(&patch_lock, flags); + + return ret; +} + +int patch_insn_write(void *addr, u32 insn) +{ + u32 *tp = addr; + int ret; + + if ((uintptr_t) tp & 0x3) + return -EINVAL; + + ret = __patch_insn_write(tp, insn); + + return ret; +} diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c index e4904ca6f0a0..b5925710f954 100644 --- a/arch/openrisc/mm/init.c +++ b/arch/openrisc/mm/init.c @@ -226,7 +226,7 @@ static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot) return 0; } -void __init __set_fixmap(enum fixed_addresses idx, +void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) { unsigned long address = __fix_to_virt(idx); -- 2.45.2 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] openrisc: Add text patching API support 2025-08-06 2:05 ` [PATCH v2 1/2] openrisc: Add text patching API support ChenMiao @ 2025-08-09 8:25 ` Stafford Horne 2025-08-10 14:52 ` Miao Chen 0 siblings, 1 reply; 7+ messages in thread From: Stafford Horne @ 2025-08-09 8:25 UTC (permalink / raw) To: ChenMiao Cc: Linux Kernel, Linux OpenRISC, Jonas Bonn, Stefan Kristiansson, Mike Rapoport (Microsoft), Geert Uytterhoeven, Arnd Bergmann, Luis Chamberlain, Sahil Siddiq, Johannes Berg, Nicolas Schier, Masahiro Yamada, Dave Hansen, Andrew Morton On Wed, Aug 06, 2025 at 02:05:03AM +0000, ChenMiao wrote: > From: chenmiao <chenmiao.ku@gmail.com> > > We need a text patching mechanism to ensure that in the subsequent > implementation of jump_label, the code can be modified to the correct > location. Therefore, FIX_TEXT_POKE0 has been added as a mapping area. > > And, I create a new file named insn-def.h to define the or1k insn macro > size and more define in the future. > > Among these changes, we implement patch_map and support the > patch_insn_write API for single instruction writing. > > - V2: We modify the patch_insn_write(void *addr, const void *insn) API to > patch_insn_write(void *addr, u32 insn), derectly support a single u32 > instruction write to map memory. > > Link: https://lore.kernel.org/openrisc/aJIC8o1WmVHol9RY@antec/T/#t > > Signed-off-by: chenmiao <chenmiao.ku@gmail.com> > --- The v2, notes should go in this part of the patch (after ---), this way it does not show up when I queue the patches. > arch/openrisc/include/asm/Kbuild | 1 - > arch/openrisc/include/asm/fixmap.h | 1 + > arch/openrisc/include/asm/insn-def.h | 12 ++++ > arch/openrisc/include/asm/text-patching.h | 13 ++++ > arch/openrisc/kernel/Makefile | 1 + > arch/openrisc/kernel/patching.c | 79 +++++++++++++++++++++++ > arch/openrisc/mm/init.c | 2 +- > 7 files changed, 107 insertions(+), 2 deletions(-) > create mode 100644 arch/openrisc/include/asm/insn-def.h > create mode 100644 arch/openrisc/include/asm/text-patching.h > create mode 100644 arch/openrisc/kernel/patching.c > > diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild > index 2b1a6b00cdac..cef49d60d74c 100644 > --- a/arch/openrisc/include/asm/Kbuild > +++ b/arch/openrisc/include/asm/Kbuild > @@ -9,4 +9,3 @@ generic-y += spinlock.h > generic-y += qrwlock_types.h > generic-y += qrwlock.h > generic-y += user.h > -generic-y += text-patching.h > diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h > index aaa6a26a3e92..74000215064d 100644 > --- a/arch/openrisc/include/asm/fixmap.h > +++ b/arch/openrisc/include/asm/fixmap.h > @@ -28,6 +28,7 @@ > > enum fixed_addresses { > FIX_EARLYCON_MEM_BASE, > + FIX_TEXT_POKE0, > __end_of_fixed_addresses > }; > > diff --git a/arch/openrisc/include/asm/insn-def.h b/arch/openrisc/include/asm/insn-def.h > new file mode 100644 > index 000000000000..dc8d16db1579 > --- /dev/null > +++ b/arch/openrisc/include/asm/insn-def.h > @@ -0,0 +1,12 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2025 Chen Miao > + */ > + > +#ifndef __ASM_INSN_DEF_H > +#define __ASM_INSN_DEF_H > + > +/* or1k instructions are always 32 bits. */ > +#define OPENRISC_INSN_SIZE 4 Is this used outside of the usage below? Why do we need a header for it? > +#endif /* __ASM_INSN_DEF_H */ > diff --git a/arch/openrisc/include/asm/text-patching.h b/arch/openrisc/include/asm/text-patching.h > new file mode 100644 > index 000000000000..bffe828288c3 > --- /dev/null > +++ b/arch/openrisc/include/asm/text-patching.h > @@ -0,0 +1,13 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2025 Chen Miao > + */ > + > +#ifndef _ASM_PATCHING_H_ > +#define _ASM_PATCHING_H_ > + > +#include <linux/types.h> > + > +int patch_insn_write(void *addr, u32 insn); > + > +#endif /* _ASM_PATCHING_H_ */ > diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile > index 58e6a1b525b7..f0957ce16d6b 100644 > --- a/arch/openrisc/kernel/Makefile > +++ b/arch/openrisc/kernel/Makefile > @@ -13,5 +13,6 @@ obj-$(CONFIG_SMP) += smp.o sync-timer.o > obj-$(CONFIG_STACKTRACE) += stacktrace.o > obj-$(CONFIG_MODULES) += module.o > obj-$(CONFIG_OF) += prom.o > +obj-y += patching.o > > clean: > diff --git a/arch/openrisc/kernel/patching.c b/arch/openrisc/kernel/patching.c > new file mode 100644 > index 000000000000..c9a30f0d1193 > --- /dev/null > +++ b/arch/openrisc/kernel/patching.c > @@ -0,0 +1,79 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* Copyright (C) 2020 SiFive > + * Copyright (C) 2025 Chen Miao > + */ > + > +#include <linux/mm.h> > +#include <linux/kernel.h> > +#include <linux/spinlock.h> > +#include <linux/uaccess.h> > + > +#include <asm/insn-def.h> > +#include <asm/cacheflush.h> > +#include <asm/page.h> > +#include <asm/fixmap.h> > +#include <asm/text-patching.h> > +#include <asm/sections.h> > + > +static DEFINE_RAW_SPINLOCK(patch_lock); > + > +static inline bool is_exit_text(uintptr_t addr) > +{ > + /* Now Have NO Mechanism to do */ > + return true; > +} Is this needed? OpenRISC doesn't seem to have any sections to support __exit annotated cleanup functions. Ref: https://kernelnewbies.org/FAQ/InitExitMacros Returning true here means that all of the patch_map calls will be treated as kernel pages below though, which is wrong, please remove this. > + > +static __always_inline void *patch_map(void *addr, int fixmap) > +{ > + uintptr_t uaddr = (uintptr_t) addr; > + phys_addr_t phys; > + > + if (core_kernel_text(uaddr) || is_exit_text(uaddr)) { > + phys = __pa_symbol(addr); > + } else { > + struct page *page = vmalloc_to_page(addr); > + BUG_ON(!page); > + phys = page_to_phys(page) + offset_in_page(addr); > + } > + > + return (void *)set_fixmap_offset(fixmap, phys); > +} > + > +static void patch_unmap(int fixmap) > +{ > + clear_fixmap(fixmap); > +} > + > +static int __patch_insn_write(void *addr, u32 insn) > +{ > + void *waddr = addr; > + unsigned long flags = 0; > + int ret; > + > + raw_spin_lock_irqsave(&patch_lock, flags); > + > + waddr = patch_map(addr, FIX_TEXT_POKE0); > + > + ret = copy_to_kernel_nofault(waddr, &insn, OPENRISC_INSN_SIZE); > + local_icache_range_inv((unsigned long)waddr, > + (unsigned long)waddr + OPENRISC_INSN_SIZE); Instead of OPENRISC_INSN_SIZE, can you use sizeof(insn)? > + patch_unmap(FIX_TEXT_POKE0); > + > + raw_spin_unlock_irqrestore(&patch_lock, flags); > + > + return ret; > +} > + > +int patch_insn_write(void *addr, u32 insn) > +{ > + u32 *tp = addr; > + int ret; > + > + if ((uintptr_t) tp & 0x3) > + return -EINVAL; > + > + ret = __patch_insn_write(tp, insn); > + > + return ret; > +} > diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c > index e4904ca6f0a0..b5925710f954 100644 > --- a/arch/openrisc/mm/init.c > +++ b/arch/openrisc/mm/init.c > @@ -226,7 +226,7 @@ static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot) > return 0; > } > > -void __init __set_fixmap(enum fixed_addresses idx, > +void __set_fixmap(enum fixed_addresses idx, Can you put a comment about this bit in the commit description? > phys_addr_t phys, pgprot_t prot) > { > unsigned long address = __fix_to_virt(idx); > -- > 2.45.2 -Stafford ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] openrisc: Add text patching API support 2025-08-09 8:25 ` Stafford Horne @ 2025-08-10 14:52 ` Miao Chen 0 siblings, 0 replies; 7+ messages in thread From: Miao Chen @ 2025-08-10 14:52 UTC (permalink / raw) To: Stafford Horne Cc: Linux Kernel, Linux OpenRISC, Jonas Bonn, Stefan Kristiansson, Mike Rapoport (Microsoft), Geert Uytterhoeven, Arnd Bergmann, Luis Chamberlain, Sahil Siddiq, Johannes Berg, Nicolas Schier, Masahiro Yamada, Dave Hansen, Andrew Morton Stafford Horne <shorne@gmail.com> 于2025年8月9日周六 16:25写道: > > On Wed, Aug 06, 2025 at 02:05:03AM +0000, ChenMiao wrote: > > From: chenmiao <chenmiao.ku@gmail.com> > > > > We need a text patching mechanism to ensure that in the subsequent > > implementation of jump_label, the code can be modified to the correct > > location. Therefore, FIX_TEXT_POKE0 has been added as a mapping area. > > > > And, I create a new file named insn-def.h to define the or1k insn macro > > size and more define in the future. > > > > Among these changes, we implement patch_map and support the > > patch_insn_write API for single instruction writing. > > > > - V2: We modify the patch_insn_write(void *addr, const void *insn) API to > > patch_insn_write(void *addr, u32 insn), derectly support a single u32 > > instruction write to map memory. > > > > Link: https://lore.kernel.org/openrisc/aJIC8o1WmVHol9RY@antec/T/#t > > > > Signed-off-by: chenmiao <chenmiao.ku@gmail.com> > > --- > > The v2, notes should go in this part of the patch (after ---), this way > it does not show up when I queue the patches. well, I'll be care of the next version > > > arch/openrisc/include/asm/Kbuild | 1 - > > arch/openrisc/include/asm/fixmap.h | 1 + > > arch/openrisc/include/asm/insn-def.h | 12 ++++ > > arch/openrisc/include/asm/text-patching.h | 13 ++++ > > arch/openrisc/kernel/Makefile | 1 + > > arch/openrisc/kernel/patching.c | 79 +++++++++++++++++++++++ > > arch/openrisc/mm/init.c | 2 +- > > 7 files changed, 107 insertions(+), 2 deletions(-) > > create mode 100644 arch/openrisc/include/asm/insn-def.h > > create mode 100644 arch/openrisc/include/asm/text-patching.h > > create mode 100644 arch/openrisc/kernel/patching.c > > > > diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild > > index 2b1a6b00cdac..cef49d60d74c 100644 > > --- a/arch/openrisc/include/asm/Kbuild > > +++ b/arch/openrisc/include/asm/Kbuild > > @@ -9,4 +9,3 @@ generic-y += spinlock.h > > generic-y += qrwlock_types.h > > generic-y += qrwlock.h > > generic-y += user.h > > -generic-y += text-patching.h > > diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h > > index aaa6a26a3e92..74000215064d 100644 > > --- a/arch/openrisc/include/asm/fixmap.h > > +++ b/arch/openrisc/include/asm/fixmap.h > > @@ -28,6 +28,7 @@ > > > > enum fixed_addresses { > > FIX_EARLYCON_MEM_BASE, > > + FIX_TEXT_POKE0, > > __end_of_fixed_addresses > > }; > > > > diff --git a/arch/openrisc/include/asm/insn-def.h b/arch/openrisc/include/asm/insn-def.h > > new file mode 100644 > > index 000000000000..dc8d16db1579 > > --- /dev/null > > +++ b/arch/openrisc/include/asm/insn-def.h > > @@ -0,0 +1,12 @@ > > +/* SPDX-License-Identifier: GPL-2.0-only */ > > +/* > > + * Copyright (C) 2025 Chen Miao > > + */ > > + > > +#ifndef __ASM_INSN_DEF_H > > +#define __ASM_INSN_DEF_H > > + > > +/* or1k instructions are always 32 bits. */ > > +#define OPENRISC_INSN_SIZE 4 > > Is this used outside of the usage below? Why do we need a header for it? I think we need the header, although it seems redundant. Although we only added one line here, I think as development progresses, we might need more macro definitions related to the instruction set, possibly including jump_label, ftrace, and potentially bpf. > > > +#endif /* __ASM_INSN_DEF_H */ > > diff --git a/arch/openrisc/include/asm/text-patching.h b/arch/openrisc/include/asm/text-patching.h > > new file mode 100644 > > index 000000000000..bffe828288c3 > > --- /dev/null > > +++ b/arch/openrisc/include/asm/text-patching.h > > @@ -0,0 +1,13 @@ > > +/* SPDX-License-Identifier: GPL-2.0-only */ > > +/* > > + * Copyright (C) 2025 Chen Miao > > + */ > > + > > +#ifndef _ASM_PATCHING_H_ > > +#define _ASM_PATCHING_H_ > > + > > +#include <linux/types.h> > > + > > +int patch_insn_write(void *addr, u32 insn); > > + > > +#endif /* _ASM_PATCHING_H_ */ > > diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile > > index 58e6a1b525b7..f0957ce16d6b 100644 > > --- a/arch/openrisc/kernel/Makefile > > +++ b/arch/openrisc/kernel/Makefile > > @@ -13,5 +13,6 @@ obj-$(CONFIG_SMP) += smp.o sync-timer.o > > obj-$(CONFIG_STACKTRACE) += stacktrace.o > > obj-$(CONFIG_MODULES) += module.o > > obj-$(CONFIG_OF) += prom.o > > +obj-y += patching.o > > > > clean: > > diff --git a/arch/openrisc/kernel/patching.c b/arch/openrisc/kernel/patching.c > > new file mode 100644 > > index 000000000000..c9a30f0d1193 > > --- /dev/null > > +++ b/arch/openrisc/kernel/patching.c > > @@ -0,0 +1,79 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* Copyright (C) 2020 SiFive > > + * Copyright (C) 2025 Chen Miao > > + */ > > + > > +#include <linux/mm.h> > > +#include <linux/kernel.h> > > +#include <linux/spinlock.h> > > +#include <linux/uaccess.h> > > + > > +#include <asm/insn-def.h> > > +#include <asm/cacheflush.h> > > +#include <asm/page.h> > > +#include <asm/fixmap.h> > > +#include <asm/text-patching.h> > > +#include <asm/sections.h> > > + > > +static DEFINE_RAW_SPINLOCK(patch_lock); > > + > > +static inline bool is_exit_text(uintptr_t addr) > > +{ > > + /* Now Have NO Mechanism to do */ > > + return true; > > +} > > Is this needed? OpenRISC doesn't seem to have any sections to support __exit > annotated cleanup functions. > > Ref: https://kernelnewbies.org/FAQ/InitExitMacros > > Returning true here means that all of the patch_map calls will be treated as > kernel pages below though, which is wrong, please remove this. > I'll remove it. > > + > > +static __always_inline void *patch_map(void *addr, int fixmap) > > +{ > > + uintptr_t uaddr = (uintptr_t) addr; > > + phys_addr_t phys; > > + > > + if (core_kernel_text(uaddr) || is_exit_text(uaddr)) { > > + phys = __pa_symbol(addr); > > + } else { > > + struct page *page = vmalloc_to_page(addr); > > + BUG_ON(!page); > > + phys = page_to_phys(page) + offset_in_page(addr); > > + } > > + > > + return (void *)set_fixmap_offset(fixmap, phys); > > +} > > + > > +static void patch_unmap(int fixmap) > > +{ > > + clear_fixmap(fixmap); > > +} > > + > > +static int __patch_insn_write(void *addr, u32 insn) > > +{ > > + void *waddr = addr; > > + unsigned long flags = 0; > > + int ret; > > + > > + raw_spin_lock_irqsave(&patch_lock, flags); > > + > > + waddr = patch_map(addr, FIX_TEXT_POKE0); > > + > > + ret = copy_to_kernel_nofault(waddr, &insn, OPENRISC_INSN_SIZE); > > + local_icache_range_inv((unsigned long)waddr, > > + (unsigned long)waddr + OPENRISC_INSN_SIZE); > > Instead of OPENRISC_INSN_SIZE, can you use sizeof(insn)? I think not using sizeof(insn)here would be better. In fact, using the OPENRISC_INSN_SIZE macro might be more appropriate. Here we are modifying a single instruction, so it must be 4 bytes—the length of one OPENRISC INSN. > > > + patch_unmap(FIX_TEXT_POKE0); > > + > > + raw_spin_unlock_irqrestore(&patch_lock, flags); > > + > > + return ret; > > +} > > + > > +int patch_insn_write(void *addr, u32 insn) > > +{ > > + u32 *tp = addr; > > + int ret; > > + > > + if ((uintptr_t) tp & 0x3) > > + return -EINVAL; > > + > > + ret = __patch_insn_write(tp, insn); > > + > > + return ret; > > +} > > diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c > > index e4904ca6f0a0..b5925710f954 100644 > > --- a/arch/openrisc/mm/init.c > > +++ b/arch/openrisc/mm/init.c > > @@ -226,7 +226,7 @@ static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot) > > return 0; > > } > > > > -void __init __set_fixmap(enum fixed_addresses idx, > > +void __set_fixmap(enum fixed_addresses idx, > > Can you put a comment about this bit in the commit description? I'll do the next version > > > phys_addr_t phys, pgprot_t prot) > > { > > unsigned long address = __fix_to_virt(idx); > > -- > > 2.45.2 > > -Stafford > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] openrisc: Add jump label support 2025-08-06 2:05 [PATCH v2 0/2] Support fixmap and jump_label for openrisc ChenMiao 2025-08-06 2:05 ` [PATCH v2 1/2] openrisc: Add text patching API support ChenMiao @ 2025-08-06 2:05 ` ChenMiao 2025-08-09 8:37 ` Stafford Horne 1 sibling, 1 reply; 7+ messages in thread From: ChenMiao @ 2025-08-06 2:05 UTC (permalink / raw) To: Linux Kernel Cc: Linux OpenRISC, chenmiao, Jonathan Corbet, Jonas Bonn, Stefan Kristiansson, Stafford Horne, Peter Zijlstra, Josh Poimboeuf, Jason Baron, Steven Rostedt, Ard Biesheuvel, Masahiro Yamada, Sahil Siddiq, Nicolas Schier, Johannes Berg, linux-doc From: chenmiao <chenmiao.ku@gmail.com> Implemented the full functionality of jump_label, of course, with text patching supported by just one API. By the way, add new macro OPENRISC_INSN_NOP in insn-def.h to use. - V2: using the patch_insn_write(void *addr, u32 insn) not the const void *insn. Link: https://lore.kernel.org/openrisc/aJIC8o1WmVHol9RY@antec/T/#t Signed-off-by: chenmiao <chenmiao.ku@gmail.com> --- .../core/jump-labels/arch-support.txt | 2 +- arch/openrisc/Kconfig | 2 + arch/openrisc/configs/or1ksim_defconfig | 19 ++---- arch/openrisc/configs/virt_defconfig | 1 + arch/openrisc/include/asm/insn-def.h | 3 + arch/openrisc/include/asm/jump_label.h | 68 +++++++++++++++++++ arch/openrisc/kernel/Makefile | 1 + arch/openrisc/kernel/jump_label.c | 53 +++++++++++++++ arch/openrisc/kernel/setup.c | 2 + 9 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 arch/openrisc/include/asm/jump_label.h create mode 100644 arch/openrisc/kernel/jump_label.c diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt index ccada815569f..683de7c15058 100644 --- a/Documentation/features/core/jump-labels/arch-support.txt +++ b/Documentation/features/core/jump-labels/arch-support.txt @@ -17,7 +17,7 @@ | microblaze: | TODO | | mips: | ok | | nios2: | TODO | - | openrisc: | TODO | + | openrisc: | ok | | parisc: | ok | | powerpc: | ok | | riscv: | ok | diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index b38fee299bc4..9156635dd264 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -24,6 +24,8 @@ config OPENRISC select GENERIC_PCI_IOMAP select GENERIC_IOREMAP select GENERIC_CPU_DEVICES + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_PCI select HAVE_UID16 select HAVE_PAGE_SIZE_8KB diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig index 59fe33cefba2..769705ac24d5 100644 --- a/arch/openrisc/configs/or1ksim_defconfig +++ b/arch/openrisc/configs/or1ksim_defconfig @@ -3,26 +3,23 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_GZIP is not set CONFIG_EXPERT=y -# CONFIG_KALLSYMS is not set # CONFIG_EPOLL is not set # CONFIG_TIMERFD is not set # CONFIG_EVENTFD is not set # CONFIG_AIO is not set -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLUB=y -CONFIG_SLUB_TINY=y -CONFIG_MODULES=y -# CONFIG_BLOCK is not set +# CONFIG_KALLSYMS is not set CONFIG_BUILTIN_DTB_NAME="or1ksim" CONFIG_HZ_100=y +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +# CONFIG_BLOCK is not set +CONFIG_SLUB_TINY=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_VM_EVENT_COUNTERS is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set CONFIG_TCP_CONG_ADVANCED=y # CONFIG_TCP_CONG_BIC is not set @@ -35,7 +32,6 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FW_LOADER is not set -CONFIG_PROC_DEVICETREE=y CONFIG_NETDEVICES=y CONFIG_ETHOC=y CONFIG_MICREL_PHY=y @@ -53,4 +49,3 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_DNOTIFY is not set CONFIG_TMPFS=y CONFIG_NFS_FS=y -# CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/openrisc/configs/virt_defconfig b/arch/openrisc/configs/virt_defconfig index c1b69166c500..4a80c5794877 100644 --- a/arch/openrisc/configs/virt_defconfig +++ b/arch/openrisc/configs/virt_defconfig @@ -12,6 +12,7 @@ CONFIG_NR_CPUS=8 CONFIG_SMP=y CONFIG_HZ_100=y # CONFIG_OPENRISC_NO_SPR_SR_DSX is not set +CONFIG_JUMP_LABEL=y # CONFIG_COMPAT_BRK is not set CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/openrisc/include/asm/insn-def.h b/arch/openrisc/include/asm/insn-def.h index dc8d16db1579..2ccdbb37c27c 100644 --- a/arch/openrisc/include/asm/insn-def.h +++ b/arch/openrisc/include/asm/insn-def.h @@ -9,4 +9,7 @@ /* or1k instructions are always 32 bits. */ #define OPENRISC_INSN_SIZE 4 +/* or1k nop instruction code */ +#define OPENRISC_INSN_NOP 0x15000000U + #endif /* __ASM_INSN_DEF_H */ diff --git a/arch/openrisc/include/asm/jump_label.h b/arch/openrisc/include/asm/jump_label.h new file mode 100644 index 000000000000..03afca9c3a1f --- /dev/null +++ b/arch/openrisc/include/asm/jump_label.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025 Chen Miao + * + * Based on arch/arm/include/asm/jump_label.h + */ +#ifndef __ASM_JUMP_LABEL_H +#define __ASM_JUMP_LABEL_H + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <asm/insn-def.h> + +#define HAVE_JUMP_LABEL_BATCH + +#define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE + +/* + * should aligned 4 + * for jump_label relative + * entry.code = nop.addr - . -> return false + * entry.target = l_yes - . -> return true + * entry.key = key - . + */ +#define JUMP_TABLE_ENTRY(key, label) \ + ".pushsection __jump_table, \"aw\" \n\t" \ + ".align 4 \n\t" \ + ".long 1b - ., " label " - . \n\t" \ + ".long " key " - . \n\t" \ + ".popsection \n\t" + +#define ARCH_STATIC_BRANCH_ASM(key, label) \ + ".align 4 \n\t" \ + "1: l.nop \n\t" \ + " l.nop \n\t" \ + JUMP_TABLE_ENTRY(key, label) + +static __always_inline bool arch_static_branch(struct static_key *const key, + const bool branch) +{ + asm goto (ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]") + ::"i"(&((char *)key)[branch])::l_yes); + + return false; +l_yes: + return true; +} + +#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \ + ".align 4 \n\t" \ + "1: l.j " label " \n\t" \ + " l.nop \n\t" \ + JUMP_TABLE_ENTRY(key, label) + +static __always_inline bool +arch_static_branch_jump(struct static_key *const key, const bool branch) +{ + asm goto (ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[l_yes]") + ::"i"(&((char *)key)[branch])::l_yes); + + return false; +l_yes: + return true; +} + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_JUMP_LABEL_H */ diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile index f0957ce16d6b..19e0eb94f2eb 100644 --- a/arch/openrisc/kernel/Makefile +++ b/arch/openrisc/kernel/Makefile @@ -9,6 +9,7 @@ obj-y := head.o setup.o or32_ksyms.o process.o dma.o \ traps.o time.o irq.o entry.o ptrace.o signal.o \ sys_call_table.o unwinder.o cacheinfo.o +obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_SMP) += smp.o sync-timer.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/openrisc/kernel/jump_label.c b/arch/openrisc/kernel/jump_label.c new file mode 100644 index 000000000000..ce259ba30258 --- /dev/null +++ b/arch/openrisc/kernel/jump_label.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 Chen Miao + * + * Based on arch/arm/kernel/jump_label.c + */ +#include <linux/jump_label.h> +#include <linux/kernel.h> +#include <linux/memory.h> +#include <asm/bug.h> +#include <asm/cacheflush.h> +#include <asm/text-patching.h> + +bool arch_jump_label_transform_queue(struct jump_entry *entry, + enum jump_label_type type) +{ + void *addr = (void *)jump_entry_code(entry); + u32 insn; + + if (type == JUMP_LABEL_JMP) { + long offset; + + offset = jump_entry_target(entry) - jump_entry_code(entry); + /* + * The actual maximum range of the l.j instruction's offset is -134,217,728 + * ~ 134,217,724 (sign 26-bit imm). + * For the original jump range, we need to right-shift N by 2 to obtain the + * instruction's offset. + */ + if (unlikely(offset < -134217728 || offset > 134217724)) { + WARN_ON_ONCE(true); + } + /* 26bit imm mask */ + offset = (offset >> 2) & 0x03ffffff; + + insn = offset; + } else { + insn = OPENRISC_INSN_NOP; + } + + if (early_boot_irqs_disabled) { + copy_to_kernel_nofault(addr, &insn, sizeof(insn)); + } else { + patch_insn_write(addr, insn); + } + return true; +} + +void arch_jump_label_transform_apply(void) +{ + // flush + kick_all_cpus_sync(); +} diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c index a9fb9cc6779e..000a9cc10e6f 100644 --- a/arch/openrisc/kernel/setup.c +++ b/arch/openrisc/kernel/setup.c @@ -249,6 +249,8 @@ void __init setup_arch(char **cmdline_p) initrd_below_start_ok = 1; } #endif + /* perform jump_table sorting before paging_init locks down read only memory */ + jump_label_init(); /* paging_init() sets up the MMU and marks all pages as reserved */ paging_init(); -- 2.45.2 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] openrisc: Add jump label support 2025-08-06 2:05 ` [PATCH v2 2/2] openrisc: Add jump label support ChenMiao @ 2025-08-09 8:37 ` Stafford Horne 2025-08-10 15:09 ` Miao Chen 0 siblings, 1 reply; 7+ messages in thread From: Stafford Horne @ 2025-08-09 8:37 UTC (permalink / raw) To: ChenMiao Cc: Linux Kernel, Linux OpenRISC, Jonathan Corbet, Jonas Bonn, Stefan Kristiansson, Peter Zijlstra, Josh Poimboeuf, Jason Baron, Steven Rostedt, Ard Biesheuvel, Masahiro Yamada, Sahil Siddiq, Nicolas Schier, Johannes Berg, linux-doc On Wed, Aug 06, 2025 at 02:05:04AM +0000, ChenMiao wrote: > From: chenmiao <chenmiao.ku@gmail.com> > > Implemented the full functionality of jump_label, of course, > with text patching supported by just one API. > > By the way, add new macro OPENRISC_INSN_NOP in insn-def.h to use. > > - V2: using the patch_insn_write(void *addr, u32 insn) not the > const void *insn. > > Link: https://lore.kernel.org/openrisc/aJIC8o1WmVHol9RY@antec/T/#t > > Signed-off-by: chenmiao <chenmiao.ku@gmail.com> > --- > .../core/jump-labels/arch-support.txt | 2 +- > arch/openrisc/Kconfig | 2 + > arch/openrisc/configs/or1ksim_defconfig | 19 ++---- > arch/openrisc/configs/virt_defconfig | 1 + > arch/openrisc/include/asm/insn-def.h | 3 + > arch/openrisc/include/asm/jump_label.h | 68 +++++++++++++++++++ > arch/openrisc/kernel/Makefile | 1 + > arch/openrisc/kernel/jump_label.c | 53 +++++++++++++++ > arch/openrisc/kernel/setup.c | 2 + > 9 files changed, 138 insertions(+), 13 deletions(-) > create mode 100644 arch/openrisc/include/asm/jump_label.h > create mode 100644 arch/openrisc/kernel/jump_label.c > > diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt > index ccada815569f..683de7c15058 100644 > --- a/Documentation/features/core/jump-labels/arch-support.txt > +++ b/Documentation/features/core/jump-labels/arch-support.txt > @@ -17,7 +17,7 @@ > | microblaze: | TODO | > | mips: | ok | > | nios2: | TODO | > - | openrisc: | TODO | > + | openrisc: | ok | > | parisc: | ok | > | powerpc: | ok | > | riscv: | ok | > diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig > index b38fee299bc4..9156635dd264 100644 > --- a/arch/openrisc/Kconfig > +++ b/arch/openrisc/Kconfig > @@ -24,6 +24,8 @@ config OPENRISC > select GENERIC_PCI_IOMAP > select GENERIC_IOREMAP > select GENERIC_CPU_DEVICES > + select HAVE_ARCH_JUMP_LABEL > + select HAVE_ARCH_JUMP_LABEL_RELATIVE > select HAVE_PCI > select HAVE_UID16 > select HAVE_PAGE_SIZE_8KB > diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig > index 59fe33cefba2..769705ac24d5 100644 > --- a/arch/openrisc/configs/or1ksim_defconfig > +++ b/arch/openrisc/configs/or1ksim_defconfig > @@ -3,26 +3,23 @@ CONFIG_LOG_BUF_SHIFT=14 > CONFIG_BLK_DEV_INITRD=y > # CONFIG_RD_GZIP is not set > CONFIG_EXPERT=y > -# CONFIG_KALLSYMS is not set > # CONFIG_EPOLL is not set > # CONFIG_TIMERFD is not set > # CONFIG_EVENTFD is not set > # CONFIG_AIO is not set > -# CONFIG_VM_EVENT_COUNTERS is not set > -# CONFIG_COMPAT_BRK is not set > -CONFIG_SLUB=y > -CONFIG_SLUB_TINY=y > -CONFIG_MODULES=y > -# CONFIG_BLOCK is not set > +# CONFIG_KALLSYMS is not set > CONFIG_BUILTIN_DTB_NAME="or1ksim" > CONFIG_HZ_100=y > +CONFIG_JUMP_LABEL=y > +CONFIG_MODULES=y > +# CONFIG_BLOCK is not set > +CONFIG_SLUB_TINY=y > +# CONFIG_COMPAT_BRK is not set > +# CONFIG_VM_EVENT_COUNTERS is not set > CONFIG_NET=y > CONFIG_PACKET=y > CONFIG_UNIX=y > CONFIG_INET=y > -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set > -# CONFIG_INET_XFRM_MODE_TUNNEL is not set > -# CONFIG_INET_XFRM_MODE_BEET is not set > # CONFIG_INET_DIAG is not set > CONFIG_TCP_CONG_ADVANCED=y > # CONFIG_TCP_CONG_BIC is not set > @@ -35,7 +32,6 @@ CONFIG_DEVTMPFS=y > CONFIG_DEVTMPFS_MOUNT=y > # CONFIG_PREVENT_FIRMWARE_BUILD is not set > # CONFIG_FW_LOADER is not set > -CONFIG_PROC_DEVICETREE=y > CONFIG_NETDEVICES=y > CONFIG_ETHOC=y > CONFIG_MICREL_PHY=y > @@ -53,4 +49,3 @@ CONFIG_SERIAL_OF_PLATFORM=y > # CONFIG_DNOTIFY is not set > CONFIG_TMPFS=y > CONFIG_NFS_FS=y > -# CONFIG_ENABLE_MUST_CHECK is not set > diff --git a/arch/openrisc/configs/virt_defconfig b/arch/openrisc/configs/virt_defconfig > index c1b69166c500..4a80c5794877 100644 > --- a/arch/openrisc/configs/virt_defconfig > +++ b/arch/openrisc/configs/virt_defconfig > @@ -12,6 +12,7 @@ CONFIG_NR_CPUS=8 > CONFIG_SMP=y > CONFIG_HZ_100=y > # CONFIG_OPENRISC_NO_SPR_SR_DSX is not set > +CONFIG_JUMP_LABEL=y > # CONFIG_COMPAT_BRK is not set > CONFIG_NET=y > CONFIG_PACKET=y The defconfig updates look quite different. Did you use savedefconfig for both of them? > diff --git a/arch/openrisc/include/asm/insn-def.h b/arch/openrisc/include/asm/insn-def.h > index dc8d16db1579..2ccdbb37c27c 100644 > --- a/arch/openrisc/include/asm/insn-def.h > +++ b/arch/openrisc/include/asm/insn-def.h > @@ -9,4 +9,7 @@ > /* or1k instructions are always 32 bits. */ > #define OPENRISC_INSN_SIZE 4 > > +/* or1k nop instruction code */ > +#define OPENRISC_INSN_NOP 0x15000000U I see you use this header again here, note that in arch/openrisc/kernel/signal.c. We write instructions to memory too for the sigreturn trampoline. Also, you use OPENRISC_INSN_SIZE below. Could you move this header to this patch completely? I don't think its needed in the patching patch. > #endif /* __ASM_INSN_DEF_H */ > diff --git a/arch/openrisc/include/asm/jump_label.h b/arch/openrisc/include/asm/jump_label.h > new file mode 100644 > index 000000000000..03afca9c3a1f > --- /dev/null > +++ b/arch/openrisc/include/asm/jump_label.h > @@ -0,0 +1,68 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2025 Chen Miao > + * > + * Based on arch/arm/include/asm/jump_label.h > + */ > +#ifndef __ASM_JUMP_LABEL_H > +#define __ASM_JUMP_LABEL_H Can this be __ASM_OPENRISC_JUMP_LABEL_H? > +#ifndef __ASSEMBLY__ Note upstream this is now __ASSEMBLER__. > +#include <linux/types.h> > +#include <asm/insn-def.h> > + > +#define HAVE_JUMP_LABEL_BATCH > + > +#define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE > + > +/* > + * should aligned 4 > + * for jump_label relative > + * entry.code = nop.addr - . -> return false > + * entry.target = l_yes - . -> return true > + * entry.key = key - . > + */ > +#define JUMP_TABLE_ENTRY(key, label) \ > + ".pushsection __jump_table, \"aw\" \n\t" \ > + ".align 4 \n\t" \ > + ".long 1b - ., " label " - . \n\t" \ > + ".long " key " - . \n\t" \ > + ".popsection \n\t" > + > +#define ARCH_STATIC_BRANCH_ASM(key, label) \ > + ".align 4 \n\t" \ > + "1: l.nop \n\t" \ > + " l.nop \n\t" \ > + JUMP_TABLE_ENTRY(key, label) > + > +static __always_inline bool arch_static_branch(struct static_key *const key, > + const bool branch) > +{ > + asm goto (ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]") > + ::"i"(&((char *)key)[branch])::l_yes); > + > + return false; > +l_yes: > + return true; > +} > + > +#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \ > + ".align 4 \n\t" \ > + "1: l.j " label " \n\t" \ > + " l.nop \n\t" \ > + JUMP_TABLE_ENTRY(key, label) > + > +static __always_inline bool > +arch_static_branch_jump(struct static_key *const key, const bool branch) > +{ > + asm goto (ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[l_yes]") > + ::"i"(&((char *)key)[branch])::l_yes); > + > + return false; > +l_yes: > + return true; > +} > + > +#endif /* __ASSEMBLY__ */ > +#endif /* __ASM_JUMP_LABEL_H */ > diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile > index f0957ce16d6b..19e0eb94f2eb 100644 > --- a/arch/openrisc/kernel/Makefile > +++ b/arch/openrisc/kernel/Makefile > @@ -9,6 +9,7 @@ obj-y := head.o setup.o or32_ksyms.o process.o dma.o \ > traps.o time.o irq.o entry.o ptrace.o signal.o \ > sys_call_table.o unwinder.o cacheinfo.o > > +obj-$(CONFIG_JUMP_LABEL) += jump_label.o > obj-$(CONFIG_SMP) += smp.o sync-timer.o > obj-$(CONFIG_STACKTRACE) += stacktrace.o > obj-$(CONFIG_MODULES) += module.o > diff --git a/arch/openrisc/kernel/jump_label.c b/arch/openrisc/kernel/jump_label.c > new file mode 100644 > index 000000000000..ce259ba30258 > --- /dev/null > +++ b/arch/openrisc/kernel/jump_label.c > @@ -0,0 +1,53 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2025 Chen Miao > + * > + * Based on arch/arm/kernel/jump_label.c > + */ > +#include <linux/jump_label.h> > +#include <linux/kernel.h> > +#include <linux/memory.h> > +#include <asm/bug.h> > +#include <asm/cacheflush.h> > +#include <asm/text-patching.h> > + > +bool arch_jump_label_transform_queue(struct jump_entry *entry, > + enum jump_label_type type) > +{ > + void *addr = (void *)jump_entry_code(entry); > + u32 insn; > + > + if (type == JUMP_LABEL_JMP) { > + long offset; > + > + offset = jump_entry_target(entry) - jump_entry_code(entry); > + /* > + * The actual maximum range of the l.j instruction's offset is -134,217,728 > + * ~ 134,217,724 (sign 26-bit imm). > + * For the original jump range, we need to right-shift N by 2 to obtain the > + * instruction's offset. > + */ > + if (unlikely(offset < -134217728 || offset > 134217724)) { > + WARN_ON_ONCE(true); > + } > + /* 26bit imm mask */ > + offset = (offset >> 2) & 0x03ffffff; > + > + insn = offset; > + } else { > + insn = OPENRISC_INSN_NOP; > + } > + > + if (early_boot_irqs_disabled) { > + copy_to_kernel_nofault(addr, &insn, sizeof(insn)); > + } else { > + patch_insn_write(addr, insn); > + } > + return true; > +} > + > +void arch_jump_label_transform_apply(void) > +{ > + // flush Could you use the /* */ comment style? Is this really flushing? > + kick_all_cpus_sync(); > +} > diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c > index a9fb9cc6779e..000a9cc10e6f 100644 > --- a/arch/openrisc/kernel/setup.c > +++ b/arch/openrisc/kernel/setup.c > @@ -249,6 +249,8 @@ void __init setup_arch(char **cmdline_p) > initrd_below_start_ok = 1; > } > #endif > + /* perform jump_table sorting before paging_init locks down read only memory */ > + jump_label_init(); > > /* paging_init() sets up the MMU and marks all pages as reserved */ > paging_init(); > -- > 2.45.2 > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] openrisc: Add jump label support 2025-08-09 8:37 ` Stafford Horne @ 2025-08-10 15:09 ` Miao Chen 0 siblings, 0 replies; 7+ messages in thread From: Miao Chen @ 2025-08-10 15:09 UTC (permalink / raw) To: Stafford Horne Cc: Linux Kernel, Linux OpenRISC, Jonathan Corbet, Jonas Bonn, Stefan Kristiansson, Peter Zijlstra, Josh Poimboeuf, Jason Baron, Steven Rostedt, Ard Biesheuvel, Masahiro Yamada, Sahil Siddiq, Nicolas Schier, Johannes Berg, linux-doc Stafford Horne <shorne@gmail.com> 于2025年8月9日周六 16:37写道: > > On Wed, Aug 06, 2025 at 02:05:04AM +0000, ChenMiao wrote: > > From: chenmiao <chenmiao.ku@gmail.com> > > > > Implemented the full functionality of jump_label, of course, > > with text patching supported by just one API. > > > > By the way, add new macro OPENRISC_INSN_NOP in insn-def.h to use. > > > > - V2: using the patch_insn_write(void *addr, u32 insn) not the > > const void *insn. > > > > Link: https://lore.kernel.org/openrisc/aJIC8o1WmVHol9RY@antec/T/#t > > > > Signed-off-by: chenmiao <chenmiao.ku@gmail.com> > > --- > > .../core/jump-labels/arch-support.txt | 2 +- > > arch/openrisc/Kconfig | 2 + > > arch/openrisc/configs/or1ksim_defconfig | 19 ++---- > > arch/openrisc/configs/virt_defconfig | 1 + > > arch/openrisc/include/asm/insn-def.h | 3 + > > arch/openrisc/include/asm/jump_label.h | 68 +++++++++++++++++++ > > arch/openrisc/kernel/Makefile | 1 + > > arch/openrisc/kernel/jump_label.c | 53 +++++++++++++++ > > arch/openrisc/kernel/setup.c | 2 + > > 9 files changed, 138 insertions(+), 13 deletions(-) > > create mode 100644 arch/openrisc/include/asm/jump_label.h > > create mode 100644 arch/openrisc/kernel/jump_label.c > > > > diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt > > index ccada815569f..683de7c15058 100644 > > --- a/Documentation/features/core/jump-labels/arch-support.txt > > +++ b/Documentation/features/core/jump-labels/arch-support.txt > > @@ -17,7 +17,7 @@ > > | microblaze: | TODO | > > | mips: | ok | > > | nios2: | TODO | > > - | openrisc: | TODO | > > + | openrisc: | ok | > > | parisc: | ok | > > | powerpc: | ok | > > | riscv: | ok | > > diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig > > index b38fee299bc4..9156635dd264 100644 > > --- a/arch/openrisc/Kconfig > > +++ b/arch/openrisc/Kconfig > > @@ -24,6 +24,8 @@ config OPENRISC > > select GENERIC_PCI_IOMAP > > select GENERIC_IOREMAP > > select GENERIC_CPU_DEVICES > > + select HAVE_ARCH_JUMP_LABEL > > + select HAVE_ARCH_JUMP_LABEL_RELATIVE > > select HAVE_PCI > > select HAVE_UID16 > > select HAVE_PAGE_SIZE_8KB > > diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig > > index 59fe33cefba2..769705ac24d5 100644 > > --- a/arch/openrisc/configs/or1ksim_defconfig > > +++ b/arch/openrisc/configs/or1ksim_defconfig > > @@ -3,26 +3,23 @@ CONFIG_LOG_BUF_SHIFT=14 > > CONFIG_BLK_DEV_INITRD=y > > # CONFIG_RD_GZIP is not set > > CONFIG_EXPERT=y > > -# CONFIG_KALLSYMS is not set > > # CONFIG_EPOLL is not set > > # CONFIG_TIMERFD is not set > > # CONFIG_EVENTFD is not set > > # CONFIG_AIO is not set > > -# CONFIG_VM_EVENT_COUNTERS is not set > > -# CONFIG_COMPAT_BRK is not set > > -CONFIG_SLUB=y > > -CONFIG_SLUB_TINY=y > > -CONFIG_MODULES=y > > -# CONFIG_BLOCK is not set > > +# CONFIG_KALLSYMS is not set > > CONFIG_BUILTIN_DTB_NAME="or1ksim" > > CONFIG_HZ_100=y > > +CONFIG_JUMP_LABEL=y > > +CONFIG_MODULES=y > > +# CONFIG_BLOCK is not set > > +CONFIG_SLUB_TINY=y > > +# CONFIG_COMPAT_BRK is not set > > +# CONFIG_VM_EVENT_COUNTERS is not set > > CONFIG_NET=y > > CONFIG_PACKET=y > > CONFIG_UNIX=y > > CONFIG_INET=y > > -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set > > -# CONFIG_INET_XFRM_MODE_TUNNEL is not set > > -# CONFIG_INET_XFRM_MODE_BEET is not set > > # CONFIG_INET_DIAG is not set > > CONFIG_TCP_CONG_ADVANCED=y > > # CONFIG_TCP_CONG_BIC is not set > > @@ -35,7 +32,6 @@ CONFIG_DEVTMPFS=y > > CONFIG_DEVTMPFS_MOUNT=y > > # CONFIG_PREVENT_FIRMWARE_BUILD is not set > > # CONFIG_FW_LOADER is not set > > -CONFIG_PROC_DEVICETREE=y > > CONFIG_NETDEVICES=y > > CONFIG_ETHOC=y > > CONFIG_MICREL_PHY=y > > @@ -53,4 +49,3 @@ CONFIG_SERIAL_OF_PLATFORM=y > > # CONFIG_DNOTIFY is not set > > CONFIG_TMPFS=y > > CONFIG_NFS_FS=y > > -# CONFIG_ENABLE_MUST_CHECK is not set > > diff --git a/arch/openrisc/configs/virt_defconfig b/arch/openrisc/configs/virt_defconfig > > index c1b69166c500..4a80c5794877 100644 > > --- a/arch/openrisc/configs/virt_defconfig > > +++ b/arch/openrisc/configs/virt_defconfig > > @@ -12,6 +12,7 @@ CONFIG_NR_CPUS=8 > > CONFIG_SMP=y > > CONFIG_HZ_100=y > > # CONFIG_OPENRISC_NO_SPR_SR_DSX is not set > > +CONFIG_JUMP_LABEL=y > > # CONFIG_COMPAT_BRK is not set > > CONFIG_NET=y > > CONFIG_PACKET=y > > The defconfig updates look quite different. Did you use savedefconfig for both > of them? Sure, it will do in the next version. > > > diff --git a/arch/openrisc/include/asm/insn-def.h b/arch/openrisc/include/asm/insn-def.h > > index dc8d16db1579..2ccdbb37c27c 100644 > > --- a/arch/openrisc/include/asm/insn-def.h > > +++ b/arch/openrisc/include/asm/insn-def.h > > @@ -9,4 +9,7 @@ > > /* or1k instructions are always 32 bits. */ > > #define OPENRISC_INSN_SIZE 4 > > > > +/* or1k nop instruction code */ > > +#define OPENRISC_INSN_NOP 0x15000000U > > I see you use this header again here, note that in > arch/openrisc/kernel/signal.c. We write instructions to memory too for the > sigreturn trampoline. > > Also, you use OPENRISC_INSN_SIZE below. Could you move this header to this > patch completely? I don't think its needed in the patching patch. > maybe... this patch we no need this header, but I think this header is meaningful, we can do this in another patch? modify the hard code insn to macro. > > #endif /* __ASM_INSN_DEF_H */ > > diff --git a/arch/openrisc/include/asm/jump_label.h b/arch/openrisc/include/asm/jump_label.h > > new file mode 100644 > > index 000000000000..03afca9c3a1f > > --- /dev/null > > +++ b/arch/openrisc/include/asm/jump_label.h > > @@ -0,0 +1,68 @@ > > +/* SPDX-License-Identifier: GPL-2.0-only */ > > +/* > > + * Copyright (C) 2025 Chen Miao > > + * > > + * Based on arch/arm/include/asm/jump_label.h > > + */ > > +#ifndef __ASM_JUMP_LABEL_H > > +#define __ASM_JUMP_LABEL_H > > Can this be __ASM_OPENRISC_JUMP_LABEL_H? > > > +#ifndef __ASSEMBLY__ > > Note upstream this is now __ASSEMBLER__. copy that. > > > +#include <linux/types.h> > > +#include <asm/insn-def.h> > > + > > +#define HAVE_JUMP_LABEL_BATCH > > + > > +#define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE > > + > > +/* > > + * should aligned 4 > > + * for jump_label relative > > + * entry.code = nop.addr - . -> return false > > + * entry.target = l_yes - . -> return true > > + * entry.key = key - . > > + */ > > +#define JUMP_TABLE_ENTRY(key, label) \ > > + ".pushsection __jump_table, \"aw\" \n\t" \ > > + ".align 4 \n\t" \ > > + ".long 1b - ., " label " - . \n\t" \ > > + ".long " key " - . \n\t" \ > > + ".popsection \n\t" > > + > > +#define ARCH_STATIC_BRANCH_ASM(key, label) \ > > + ".align 4 \n\t" \ > > + "1: l.nop \n\t" \ > > + " l.nop \n\t" \ > > + JUMP_TABLE_ENTRY(key, label) > > + > > +static __always_inline bool arch_static_branch(struct static_key *const key, > > + const bool branch) > > +{ > > + asm goto (ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]") > > + ::"i"(&((char *)key)[branch])::l_yes); > > + > > + return false; > > +l_yes: > > + return true; > > +} > > + > > +#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \ > > + ".align 4 \n\t" \ > > + "1: l.j " label " \n\t" \ > > + " l.nop \n\t" \ > > + JUMP_TABLE_ENTRY(key, label) > > + > > +static __always_inline bool > > +arch_static_branch_jump(struct static_key *const key, const bool branch) > > +{ > > + asm goto (ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[l_yes]") > > + ::"i"(&((char *)key)[branch])::l_yes); > > + > > + return false; > > +l_yes: > > + return true; > > +} > > + > > +#endif /* __ASSEMBLY__ */ > > +#endif /* __ASM_JUMP_LABEL_H */ > > diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile > > index f0957ce16d6b..19e0eb94f2eb 100644 > > --- a/arch/openrisc/kernel/Makefile > > +++ b/arch/openrisc/kernel/Makefile > > @@ -9,6 +9,7 @@ obj-y := head.o setup.o or32_ksyms.o process.o dma.o \ > > traps.o time.o irq.o entry.o ptrace.o signal.o \ > > sys_call_table.o unwinder.o cacheinfo.o > > > > +obj-$(CONFIG_JUMP_LABEL) += jump_label.o > > obj-$(CONFIG_SMP) += smp.o sync-timer.o > > obj-$(CONFIG_STACKTRACE) += stacktrace.o > > obj-$(CONFIG_MODULES) += module.o > > diff --git a/arch/openrisc/kernel/jump_label.c b/arch/openrisc/kernel/jump_label.c > > new file mode 100644 > > index 000000000000..ce259ba30258 > > --- /dev/null > > +++ b/arch/openrisc/kernel/jump_label.c > > @@ -0,0 +1,53 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Copyright (C) 2025 Chen Miao > > + * > > + * Based on arch/arm/kernel/jump_label.c > > + */ > > +#include <linux/jump_label.h> > > +#include <linux/kernel.h> > > +#include <linux/memory.h> > > +#include <asm/bug.h> > > +#include <asm/cacheflush.h> > > +#include <asm/text-patching.h> > > + > > +bool arch_jump_label_transform_queue(struct jump_entry *entry, > > + enum jump_label_type type) > > +{ > > + void *addr = (void *)jump_entry_code(entry); > > + u32 insn; > > + > > + if (type == JUMP_LABEL_JMP) { > > + long offset; > > + > > + offset = jump_entry_target(entry) - jump_entry_code(entry); > > + /* > > + * The actual maximum range of the l.j instruction's offset is -134,217,728 > > + * ~ 134,217,724 (sign 26-bit imm). > > + * For the original jump range, we need to right-shift N by 2 to obtain the > > + * instruction's offset. > > + */ > > + if (unlikely(offset < -134217728 || offset > 134217724)) { > > + WARN_ON_ONCE(true); > > + } > > + /* 26bit imm mask */ > > + offset = (offset >> 2) & 0x03ffffff; > > + > > + insn = offset; > > + } else { > > + insn = OPENRISC_INSN_NOP; > > + } > > + > > + if (early_boot_irqs_disabled) { > > + copy_to_kernel_nofault(addr, &insn, sizeof(insn)); > > + } else { > > + patch_insn_write(addr, insn); > > + } > > + return true; > > +} > > + > > +void arch_jump_label_transform_apply(void) > > +{ > > + // flush > > Could you use the /* */ comment style? Is this really flushing? sure, really flushing. > > > + kick_all_cpus_sync(); > > +} > > diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c > > index a9fb9cc6779e..000a9cc10e6f 100644 > > --- a/arch/openrisc/kernel/setup.c > > +++ b/arch/openrisc/kernel/setup.c > > @@ -249,6 +249,8 @@ void __init setup_arch(char **cmdline_p) > > initrd_below_start_ok = 1; > > } > > #endif > > + /* perform jump_table sorting before paging_init locks down read only memory */ > > + jump_label_init(); > > > > /* paging_init() sets up the MMU and marks all pages as reserved */ > > paging_init(); > > -- > > 2.45.2 > > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-08-10 15:09 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-08-06 2:05 [PATCH v2 0/2] Support fixmap and jump_label for openrisc ChenMiao 2025-08-06 2:05 ` [PATCH v2 1/2] openrisc: Add text patching API support ChenMiao 2025-08-09 8:25 ` Stafford Horne 2025-08-10 14:52 ` Miao Chen 2025-08-06 2:05 ` [PATCH v2 2/2] openrisc: Add jump label support ChenMiao 2025-08-09 8:37 ` Stafford Horne 2025-08-10 15:09 ` Miao Chen
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.