Merge tag 'for-linus' of https://github.com/openrisc/linux

Pull OpenRISC updates from Stafford Horne:
"I picked up one series from Chen Miao, our Google Summer of Code
contributor, which adds OpenRISC support for static keys"

* tag 'for-linus' of https://github.com/openrisc/linux:
openrisc: Add jump label support
openrisc: Regenerate defconfigs.
openrisc: Add R_OR1K_32_PCREL relocation type module support
openrisc: Add text patching API support

+255 -16
+1 -1
Documentation/features/core/jump-labels/arch-support.txt
··· 17 | microblaze: | TODO | 18 | mips: | ok | 19 | nios2: | TODO | 20 - | openrisc: | TODO | 21 | parisc: | ok | 22 | powerpc: | ok | 23 | riscv: | ok |
··· 17 | microblaze: | TODO | 18 | mips: | ok | 19 | nios2: | TODO | 20 + | openrisc: | ok | 21 | parisc: | ok | 22 | powerpc: | ok | 23 | riscv: | ok |
+2
arch/openrisc/Kconfig
··· 24 select GENERIC_PCI_IOMAP 25 select GENERIC_IOREMAP 26 select GENERIC_CPU_DEVICES 27 select HAVE_PCI 28 select HAVE_UID16 29 select HAVE_PAGE_SIZE_8KB
··· 24 select GENERIC_PCI_IOMAP 25 select GENERIC_IOREMAP 26 select GENERIC_CPU_DEVICES 27 + select HAVE_ARCH_JUMP_LABEL 28 + select HAVE_ARCH_JUMP_LABEL_RELATIVE 29 select HAVE_PCI 30 select HAVE_UID16 31 select HAVE_PAGE_SIZE_8KB
+7 -12
arch/openrisc/configs/or1ksim_defconfig
··· 3 CONFIG_BLK_DEV_INITRD=y 4 # CONFIG_RD_GZIP is not set 5 CONFIG_EXPERT=y 6 - # CONFIG_KALLSYMS is not set 7 # CONFIG_EPOLL is not set 8 # CONFIG_TIMERFD is not set 9 # CONFIG_EVENTFD is not set 10 # CONFIG_AIO is not set 11 - # CONFIG_VM_EVENT_COUNTERS is not set 12 - # CONFIG_COMPAT_BRK is not set 13 - CONFIG_SLUB=y 14 - CONFIG_SLUB_TINY=y 15 - CONFIG_MODULES=y 16 - # CONFIG_BLOCK is not set 17 CONFIG_BUILTIN_DTB_NAME="or1ksim" 18 CONFIG_HZ_100=y 19 CONFIG_NET=y 20 CONFIG_PACKET=y 21 CONFIG_UNIX=y 22 CONFIG_INET=y 23 - # CONFIG_INET_XFRM_MODE_TRANSPORT is not set 24 - # CONFIG_INET_XFRM_MODE_TUNNEL is not set 25 - # CONFIG_INET_XFRM_MODE_BEET is not set 26 # CONFIG_INET_DIAG is not set 27 CONFIG_TCP_CONG_ADVANCED=y 28 # CONFIG_TCP_CONG_BIC is not set ··· 32 CONFIG_DEVTMPFS_MOUNT=y 33 # CONFIG_PREVENT_FIRMWARE_BUILD is not set 34 # CONFIG_FW_LOADER is not set 35 - CONFIG_PROC_DEVICETREE=y 36 CONFIG_NETDEVICES=y 37 CONFIG_ETHOC=y 38 CONFIG_MICREL_PHY=y ··· 49 # CONFIG_DNOTIFY is not set 50 CONFIG_TMPFS=y 51 CONFIG_NFS_FS=y 52 - # CONFIG_ENABLE_MUST_CHECK is not set
··· 3 CONFIG_BLK_DEV_INITRD=y 4 # CONFIG_RD_GZIP is not set 5 CONFIG_EXPERT=y 6 # CONFIG_EPOLL is not set 7 # CONFIG_TIMERFD is not set 8 # CONFIG_EVENTFD is not set 9 # CONFIG_AIO is not set 10 + # CONFIG_KALLSYMS is not set 11 CONFIG_BUILTIN_DTB_NAME="or1ksim" 12 CONFIG_HZ_100=y 13 + CONFIG_JUMP_LABEL=y 14 + CONFIG_MODULES=y 15 + # CONFIG_BLOCK is not set 16 + CONFIG_SLUB_TINY=y 17 + # CONFIG_COMPAT_BRK is not set 18 + # CONFIG_VM_EVENT_COUNTERS is not set 19 CONFIG_NET=y 20 CONFIG_PACKET=y 21 CONFIG_UNIX=y 22 CONFIG_INET=y 23 # CONFIG_INET_DIAG is not set 24 CONFIG_TCP_CONG_ADVANCED=y 25 # CONFIG_TCP_CONG_BIC is not set ··· 35 CONFIG_DEVTMPFS_MOUNT=y 36 # CONFIG_PREVENT_FIRMWARE_BUILD is not set 37 # CONFIG_FW_LOADER is not set 38 CONFIG_NETDEVICES=y 39 CONFIG_ETHOC=y 40 CONFIG_MICREL_PHY=y ··· 53 # CONFIG_DNOTIFY is not set 54 CONFIG_TMPFS=y 55 CONFIG_NFS_FS=y
+1 -1
arch/openrisc/configs/virt_defconfig
··· 12 CONFIG_SMP=y 13 CONFIG_HZ_100=y 14 # CONFIG_OPENRISC_NO_SPR_SR_DSX is not set 15 # CONFIG_COMPAT_BRK is not set 16 CONFIG_NET=y 17 CONFIG_PACKET=y ··· 56 # CONFIG_DRM_FBDEV_EMULATION is not set 57 CONFIG_DRM_VIRTIO_GPU=y 58 CONFIG_FB=y 59 - CONFIG_FIRMWARE_EDID=y 60 CONFIG_FRAMEBUFFER_CONSOLE=y 61 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y 62 CONFIG_LOGO=y
··· 12 CONFIG_SMP=y 13 CONFIG_HZ_100=y 14 # CONFIG_OPENRISC_NO_SPR_SR_DSX is not set 15 + CONFIG_JUMP_LABEL=y 16 # CONFIG_COMPAT_BRK is not set 17 CONFIG_NET=y 18 CONFIG_PACKET=y ··· 55 # CONFIG_DRM_FBDEV_EMULATION is not set 56 CONFIG_DRM_VIRTIO_GPU=y 57 CONFIG_FB=y 58 CONFIG_FRAMEBUFFER_CONSOLE=y 59 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y 60 CONFIG_LOGO=y
-1
arch/openrisc/include/asm/Kbuild
··· 9 generic-y += qrwlock_types.h 10 generic-y += qrwlock.h 11 generic-y += user.h 12 - generic-y += text-patching.h
··· 9 generic-y += qrwlock_types.h 10 generic-y += qrwlock.h 11 generic-y += user.h
+1
arch/openrisc/include/asm/fixmap.h
··· 28 29 enum fixed_addresses { 30 FIX_EARLYCON_MEM_BASE, 31 __end_of_fixed_addresses 32 }; 33
··· 28 29 enum fixed_addresses { 30 FIX_EARLYCON_MEM_BASE, 31 + FIX_TEXT_POKE0, 32 __end_of_fixed_addresses 33 }; 34
+15
arch/openrisc/include/asm/insn-def.h
···
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2025 Chen Miao 4 + */ 5 + 6 + #ifndef __ASM_OPENRISC_INSN_DEF_H 7 + #define __ASM_OPENRISC_INSN_DEF_H 8 + 9 + /* or1k instructions are always 32 bits. */ 10 + #define OPENRISC_INSN_SIZE 4 11 + 12 + /* or1k nop instruction code */ 13 + #define OPENRISC_INSN_NOP 0x15000000U 14 + 15 + #endif /* __ASM_OPENRISC_INSN_DEF_H */
+72
arch/openrisc/include/asm/jump_label.h
···
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2025 Chen Miao 4 + * 5 + * Based on arch/arm/include/asm/jump_label.h 6 + */ 7 + #ifndef __ASM_OPENRISC_JUMP_LABEL_H 8 + #define __ASM_OPENRISC_JUMP_LABEL_H 9 + 10 + #ifndef __ASSEMBLER__ 11 + 12 + #include <linux/types.h> 13 + #include <asm/insn-def.h> 14 + 15 + #define HAVE_JUMP_LABEL_BATCH 16 + 17 + #define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE 18 + 19 + /** 20 + * JUMP_TABLE_ENTRY - Create a jump table entry 21 + * @key: Jump key identifier (typically a symbol address) 22 + * @label: Target label address 23 + * 24 + * This macro creates a jump table entry in the dedicated kernel section (__jump_table). 25 + * Each entry contains the following information: 26 + * Offset from current instruction to jump instruction (1b - .) 27 + * Offset from current instruction to target label (label - .) 28 + * Offset from current instruction to key identifier (key - .) 29 + */ 30 + #define JUMP_TABLE_ENTRY(key, label) \ 31 + ".pushsection __jump_table, \"aw\" \n\t" \ 32 + ".align 4 \n\t" \ 33 + ".long 1b - ., " label " - . \n\t" \ 34 + ".long " key " - . \n\t" \ 35 + ".popsection \n\t" 36 + 37 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 38 + ".align 4 \n\t" \ 39 + "1: l.nop \n\t" \ 40 + " l.nop \n\t" \ 41 + JUMP_TABLE_ENTRY(key, label) 42 + 43 + static __always_inline bool arch_static_branch(struct static_key *const key, 44 + const bool branch) 45 + { 46 + asm goto (ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]") 47 + ::"i"(&((char *)key)[branch])::l_yes); 48 + 49 + return false; 50 + l_yes: 51 + return true; 52 + } 53 + 54 + #define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \ 55 + ".align 4 \n\t" \ 56 + "1: l.j " label " \n\t" \ 57 + " l.nop \n\t" \ 58 + JUMP_TABLE_ENTRY(key, label) 59 + 60 + static __always_inline bool 61 + arch_static_branch_jump(struct static_key *const key, const bool branch) 62 + { 63 + asm goto (ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[l_yes]") 64 + ::"i"(&((char *)key)[branch])::l_yes); 65 + 66 + return false; 67 + l_yes: 68 + return true; 69 + } 70 + 71 + #endif /* __ASSEMBLER__ */ 72 + #endif /* __ASM_OPENRISC_JUMP_LABEL_H */
+13
arch/openrisc/include/asm/text-patching.h
···
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2025 Chen Miao 4 + */ 5 + 6 + #ifndef _ASM_OPENRISC_PATCHING_H 7 + #define _ASM_OPENRISC_PATCHING_H 8 + 9 + #include <linux/types.h> 10 + 11 + int patch_insn_write(void *addr, u32 insn); 12 + 13 + #endif /* _ASM_OPENRISC_PATCHING_H */
+2
arch/openrisc/kernel/Makefile
··· 9 traps.o time.o irq.o entry.o ptrace.o signal.o \ 10 sys_call_table.o unwinder.o cacheinfo.o 11 12 obj-$(CONFIG_SMP) += smp.o sync-timer.o 13 obj-$(CONFIG_STACKTRACE) += stacktrace.o 14 obj-$(CONFIG_MODULES) += module.o 15 obj-$(CONFIG_OF) += prom.o 16 17 clean:
··· 9 traps.o time.o irq.o entry.o ptrace.o signal.o \ 10 sys_call_table.o unwinder.o cacheinfo.o 11 12 + obj-$(CONFIG_JUMP_LABEL) += jump_label.o 13 obj-$(CONFIG_SMP) += smp.o sync-timer.o 14 obj-$(CONFIG_STACKTRACE) += stacktrace.o 15 obj-$(CONFIG_MODULES) += module.o 16 obj-$(CONFIG_OF) += prom.o 17 + obj-y += patching.o 18 19 clean:
+51
arch/openrisc/kernel/jump_label.c
···
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2025 Chen Miao 4 + * 5 + * Based on arch/arm/kernel/jump_label.c 6 + */ 7 + #include <linux/jump_label.h> 8 + #include <linux/kernel.h> 9 + #include <linux/memory.h> 10 + #include <asm/bug.h> 11 + #include <asm/cacheflush.h> 12 + #include <asm/text-patching.h> 13 + 14 + bool arch_jump_label_transform_queue(struct jump_entry *entry, 15 + enum jump_label_type type) 16 + { 17 + void *addr = (void *)jump_entry_code(entry); 18 + u32 insn; 19 + 20 + if (type == JUMP_LABEL_JMP) { 21 + long offset; 22 + 23 + offset = jump_entry_target(entry) - jump_entry_code(entry); 24 + /* 25 + * The actual maximum range of the l.j instruction's offset is -134,217,728 26 + * ~ 134,217,724 (sign 26-bit imm). 27 + * For the original jump range, we need to right-shift N by 2 to obtain the 28 + * instruction's offset. 29 + */ 30 + WARN_ON_ONCE(offset < -134217728 || offset > 134217724); 31 + 32 + /* 26bit imm mask */ 33 + offset = (offset >> 2) & 0x03ffffff; 34 + 35 + insn = offset; 36 + } else { 37 + insn = OPENRISC_INSN_NOP; 38 + } 39 + 40 + if (early_boot_irqs_disabled) 41 + copy_to_kernel_nofault(addr, &insn, sizeof(insn)); 42 + else 43 + patch_insn_write(addr, insn); 44 + 45 + return true; 46 + } 47 + 48 + void arch_jump_label_transform_apply(void) 49 + { 50 + kick_all_cpus_sync(); 51 + }
+4
arch/openrisc/kernel/module.c
··· 55 value |= *location & 0xfc000000; 56 *location = value; 57 break; 58 case R_OR1K_AHI16: 59 /* Adjust the operand to match with a signed LO16. */ 60 value += 0x8000;
··· 55 value |= *location & 0xfc000000; 56 *location = value; 57 break; 58 + case R_OR1K_32_PCREL: 59 + value -= (uint32_t)location; 60 + *location = value; 61 + break; 62 case R_OR1K_AHI16: 63 /* Adjust the operand to match with a signed LO16. */ 64 value += 0x8000;
+79
arch/openrisc/kernel/patching.c
···
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (C) 2020 SiFive 3 + * Copyright (C) 2025 Chen Miao 4 + */ 5 + 6 + #include <linux/mm.h> 7 + #include <linux/kernel.h> 8 + #include <linux/spinlock.h> 9 + #include <linux/uaccess.h> 10 + 11 + #include <asm/insn-def.h> 12 + #include <asm/cacheflush.h> 13 + #include <asm/page.h> 14 + #include <asm/fixmap.h> 15 + #include <asm/text-patching.h> 16 + #include <asm/sections.h> 17 + 18 + static DEFINE_RAW_SPINLOCK(patch_lock); 19 + 20 + static __always_inline void *patch_map(void *addr, int fixmap) 21 + { 22 + uintptr_t uaddr = (uintptr_t) addr; 23 + phys_addr_t phys; 24 + 25 + if (core_kernel_text(uaddr)) { 26 + phys = __pa_symbol(addr); 27 + } else { 28 + struct page *page = vmalloc_to_page(addr); 29 + BUG_ON(!page); 30 + phys = page_to_phys(page) + offset_in_page(addr); 31 + } 32 + 33 + return (void *)set_fixmap_offset(fixmap, phys); 34 + } 35 + 36 + static void patch_unmap(int fixmap) 37 + { 38 + clear_fixmap(fixmap); 39 + } 40 + 41 + static int __patch_insn_write(void *addr, u32 insn) 42 + { 43 + void *waddr = addr; 44 + unsigned long flags = 0; 45 + int ret; 46 + 47 + raw_spin_lock_irqsave(&patch_lock, flags); 48 + 49 + waddr = patch_map(addr, FIX_TEXT_POKE0); 50 + 51 + ret = copy_to_kernel_nofault(waddr, &insn, OPENRISC_INSN_SIZE); 52 + local_icache_range_inv((unsigned long)waddr, 53 + (unsigned long)waddr + OPENRISC_INSN_SIZE); 54 + 55 + patch_unmap(FIX_TEXT_POKE0); 56 + 57 + raw_spin_unlock_irqrestore(&patch_lock, flags); 58 + 59 + return ret; 60 + } 61 + 62 + /* 63 + * patch_insn_write - Write a single instruction to a specified memory location 64 + * This API provides a single-instruction patching, primarily used for runtime 65 + * code modification. 66 + * By the way, the insn size must be 4 bytes. 67 + */ 68 + int patch_insn_write(void *addr, u32 insn) 69 + { 70 + u32 *tp = addr; 71 + int ret; 72 + 73 + if ((uintptr_t) tp & 0x3) 74 + return -EINVAL; 75 + 76 + ret = __patch_insn_write(tp, insn); 77 + 78 + return ret; 79 + }
+2
arch/openrisc/kernel/setup.c
··· 249 initrd_below_start_ok = 1; 250 } 251 #endif 252 253 /* paging_init() sets up the MMU and marks all pages as reserved */ 254 paging_init();
··· 249 initrd_below_start_ok = 1; 250 } 251 #endif 252 + /* perform jump_table sorting before paging_init locks down read only memory */ 253 + jump_label_init(); 254 255 /* paging_init() sets up the MMU and marks all pages as reserved */ 256 paging_init();
+5 -1
arch/openrisc/mm/init.c
··· 226 return 0; 227 } 228 229 - void __init __set_fixmap(enum fixed_addresses idx, 230 phys_addr_t phys, pgprot_t prot) 231 { 232 unsigned long address = __fix_to_virt(idx);
··· 226 return 0; 227 } 228 229 + /* 230 + * __set_fix must now support both EARLYCON and TEXT_POKE mappings, 231 + * which are used at different stages of kernel execution. 232 + */ 233 + void __set_fixmap(enum fixed_addresses idx, 234 phys_addr_t phys, pgprot_t prot) 235 { 236 unsigned long address = __fix_to_virt(idx);