linux-openrisc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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

* [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

* 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

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).