* [PATCH 1/2] openrisc: Add text patching API support [not found] <20250805084114.4125333-1-chenmiao.ku@gmail.com> @ 2025-08-05 8:40 ` ChenMiao 2025-08-05 9:15 ` Stafford Horne 2025-08-05 8:40 ` [PATCH 2/2] openrisc: Add jump label support ChenMiao 1 sibling, 1 reply; 6+ messages in thread From: ChenMiao @ 2025-08-05 8:40 UTC (permalink / raw) To: Stafford Horne Cc: chenmiao, Jonas Bonn, Stefan Kristiansson, Arnd Bergmann, Mike Rapoport (Microsoft), Geert Uytterhoeven, Luis Chamberlain, Sahil Siddiq, Johannes Berg, Masahiro Yamada, Dave Hansen, Andrew Morton, open list:OPENRISC ARCHITECTURE, open list 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. 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..4c3d8a6a906a --- /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, const void *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..2b979a0bc584 --- /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, const void *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, const void *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] 6+ messages in thread
* Re: [PATCH 1/2] openrisc: Add text patching API support 2025-08-05 8:40 ` [PATCH 1/2] openrisc: Add text patching API support ChenMiao @ 2025-08-05 9:15 ` Stafford Horne 2025-08-05 9:29 ` Miao Chen 2025-08-05 9:38 ` Geert Uytterhoeven 0 siblings, 2 replies; 6+ messages in thread From: Stafford Horne @ 2025-08-05 9:15 UTC (permalink / raw) To: ChenMiao Cc: Jonas Bonn, Stefan Kristiansson, Arnd Bergmann, Mike Rapoport (Microsoft), Geert Uytterhoeven, Luis Chamberlain, Sahil Siddiq, Johannes Berg, Masahiro Yamada, Dave Hansen, Andrew Morton, open list:OPENRISC ARCHITECTURE, open list On Tue, Aug 05, 2025 at 08:40:57AM +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. > > 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..4c3d8a6a906a > --- /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, const void *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..2b979a0bc584 > --- /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, const void *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); If you change *insn to unsigned long insn, you can do: ret = copy_to_kernel_nofault(waddr, &insn, iszeof(insn)); > + 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, const void *insn) Does insn need to be void *? It think it could be just unsigned long. See comment above. > +{ > + 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 [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] openrisc: Add text patching API support 2025-08-05 9:15 ` Stafford Horne @ 2025-08-05 9:29 ` Miao Chen 2025-08-05 9:38 ` Geert Uytterhoeven 1 sibling, 0 replies; 6+ messages in thread From: Miao Chen @ 2025-08-05 9:29 UTC (permalink / raw) To: Stafford Horne Cc: Jonas Bonn, Stefan Kristiansson, Arnd Bergmann, Mike Rapoport (Microsoft), Geert Uytterhoeven, Luis Chamberlain, Sahil Siddiq, Johannes Berg, Masahiro Yamada, Dave Hansen, Andrew Morton, open list:OPENRISC ARCHITECTURE, open list I also considered this approach. In the initial design, there was a size_t len parameter, but since OpenRISC doesn't support it yet, it was removed to only support single instructions. If there are plans to support modifying multiple instructions in the future, we can simply add size_t lento this API and replace OPENRISC_INSN_SIZE with len. That's why I didn't change it to unsigned long and kept it as const void*, while using OPENRISC_INSN_SIZE to fix the length of a single instruction. Stafford Horne <shorne@gmail.com> 于2025年8月5日周二 17:15写道: > > On Tue, Aug 05, 2025 at 08:40:57AM +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. > > > > 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..4c3d8a6a906a > > --- /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, const void *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..2b979a0bc584 > > --- /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, const void *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); > > If you change *insn to unsigned long insn, you can do: > > ret = copy_to_kernel_nofault(waddr, &insn, iszeof(insn)); > > > + 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, const void *insn) > > Does insn need to be void *? It think it could be just unsigned long. See > comment above. > > > +{ > > + 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 [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] openrisc: Add text patching API support 2025-08-05 9:15 ` Stafford Horne 2025-08-05 9:29 ` Miao Chen @ 2025-08-05 9:38 ` Geert Uytterhoeven 2025-08-05 13:11 ` Stafford Horne 1 sibling, 1 reply; 6+ messages in thread From: Geert Uytterhoeven @ 2025-08-05 9:38 UTC (permalink / raw) To: Stafford Horne Cc: ChenMiao, Jonas Bonn, Stefan Kristiansson, Arnd Bergmann, Mike Rapoport (Microsoft), Luis Chamberlain, Sahil Siddiq, Johannes Berg, Masahiro Yamada, Dave Hansen, Andrew Morton, open list:OPENRISC ARCHITECTURE, open list Hi Stafford, On Tue, 5 Aug 2025 at 11:15, Stafford Horne <shorne@gmail.com> wrote: > On Tue, Aug 05, 2025 at 08:40:57AM +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. > > > > Signed-off-by: chenmiao <chenmiao.ku@gmail.com> > > --- /dev/null > > +++ b/arch/openrisc/include/asm/insn-def.h > > +/* or1k instructions are always 32 bits. */ > > +#define OPENRISC_INSN_SIZE 4 > > --- /dev/null > > +++ b/arch/openrisc/kernel/patching.c > > +static int __patch_insn_write(void *addr, const void *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); > > If you change *insn to unsigned long insn, you can do: > > ret = copy_to_kernel_nofault(waddr, &insn, iszeof(insn)); sizeof(*insn)? > > > + 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, const void *insn) > > Does insn need to be void *? It think it could be just unsigned long. See > comment above. u32? unsigned long would be 64-bit on 64-bit platforms. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] openrisc: Add text patching API support 2025-08-05 9:38 ` Geert Uytterhoeven @ 2025-08-05 13:11 ` Stafford Horne 0 siblings, 0 replies; 6+ messages in thread From: Stafford Horne @ 2025-08-05 13:11 UTC (permalink / raw) To: Geert Uytterhoeven Cc: ChenMiao, Jonas Bonn, Stefan Kristiansson, Arnd Bergmann, Mike Rapoport (Microsoft), Luis Chamberlain, Sahil Siddiq, Johannes Berg, Masahiro Yamada, Dave Hansen, Andrew Morton, open list:OPENRISC ARCHITECTURE, open list On Tue, Aug 05, 2025 at 11:38:07AM +0200, Geert Uytterhoeven wrote: > Hi Stafford, > > On Tue, 5 Aug 2025 at 11:15, Stafford Horne <shorne@gmail.com> wrote: > > On Tue, Aug 05, 2025 at 08:40:57AM +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. > > > > > > Signed-off-by: chenmiao <chenmiao.ku@gmail.com> > > > > --- /dev/null > > > +++ b/arch/openrisc/include/asm/insn-def.h > > > > +/* or1k instructions are always 32 bits. */ > > > +#define OPENRISC_INSN_SIZE 4 > > > > --- /dev/null > > > +++ b/arch/openrisc/kernel/patching.c > > > > +static int __patch_insn_write(void *addr, const void *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); > > > > If you change *insn to unsigned long insn, you can do: > > > > ret = copy_to_kernel_nofault(waddr, &insn, iszeof(insn)); > > sizeof(*insn)? Yes, typo, thanks. > > > > > + 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, const void *insn) > > > > Does insn need to be void *? It think it could be just unsigned long. See > > comment above. > > u32? > > unsigned long would be 64-bit on 64-bit platforms. Thanks, yes for us it's more correct to use u32. I always thing unsigned long is OK in openrisc as we have no 64-bit implementations. But might as well have it correct in case we ever add the 64-bit implementation. -Stafford ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] openrisc: Add jump label support [not found] <20250805084114.4125333-1-chenmiao.ku@gmail.com> 2025-08-05 8:40 ` [PATCH 1/2] openrisc: Add text patching API support ChenMiao @ 2025-08-05 8:40 ` ChenMiao 1 sibling, 0 replies; 6+ messages in thread From: ChenMiao @ 2025-08-05 8:40 UTC (permalink / raw) To: Stafford Horne Cc: chenmiao, Jonathan Corbet, Jonas Bonn, Stefan Kristiansson, Peter Zijlstra, Josh Poimboeuf, Jason Baron, Steven Rostedt, Ard Biesheuvel, Masahiro Yamada, Nicolas Schier, Johannes Berg, Sahil Siddiq, open list:DOCUMENTATION, open list, open list:OPENRISC ARCHITECTURE 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. 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..2cda900dd33e --- /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] 6+ messages in thread
end of thread, other threads:[~2025-08-05 13:11 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250805084114.4125333-1-chenmiao.ku@gmail.com>
2025-08-05 8:40 ` [PATCH 1/2] openrisc: Add text patching API support ChenMiao
2025-08-05 9:15 ` Stafford Horne
2025-08-05 9:29 ` Miao Chen
2025-08-05 9:38 ` Geert Uytterhoeven
2025-08-05 13:11 ` Stafford Horne
2025-08-05 8:40 ` [PATCH 2/2] openrisc: Add jump label support ChenMiao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).