mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
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
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
| microblaze: | TODO |
|
| microblaze: | TODO |
|
||||||
| mips: | ok |
|
| mips: | ok |
|
||||||
| nios2: | TODO |
|
| nios2: | TODO |
|
||||||
| openrisc: | TODO |
|
| openrisc: | ok |
|
||||||
| parisc: | ok |
|
| parisc: | ok |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | ok |
|
| riscv: | ok |
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ config OPENRISC
|
|||||||
select GENERIC_PCI_IOMAP
|
select GENERIC_PCI_IOMAP
|
||||||
select GENERIC_IOREMAP
|
select GENERIC_IOREMAP
|
||||||
select GENERIC_CPU_DEVICES
|
select GENERIC_CPU_DEVICES
|
||||||
|
select HAVE_ARCH_JUMP_LABEL
|
||||||
|
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||||
select HAVE_PCI
|
select HAVE_PCI
|
||||||
select HAVE_UID16
|
select HAVE_UID16
|
||||||
select HAVE_PAGE_SIZE_8KB
|
select HAVE_PAGE_SIZE_8KB
|
||||||
|
|||||||
@@ -3,26 +3,23 @@ CONFIG_LOG_BUF_SHIFT=14
|
|||||||
CONFIG_BLK_DEV_INITRD=y
|
CONFIG_BLK_DEV_INITRD=y
|
||||||
# CONFIG_RD_GZIP is not set
|
# CONFIG_RD_GZIP is not set
|
||||||
CONFIG_EXPERT=y
|
CONFIG_EXPERT=y
|
||||||
# CONFIG_KALLSYMS is not set
|
|
||||||
# CONFIG_EPOLL is not set
|
# CONFIG_EPOLL is not set
|
||||||
# CONFIG_TIMERFD is not set
|
# CONFIG_TIMERFD is not set
|
||||||
# CONFIG_EVENTFD is not set
|
# CONFIG_EVENTFD is not set
|
||||||
# CONFIG_AIO is not set
|
# CONFIG_AIO is not set
|
||||||
# CONFIG_VM_EVENT_COUNTERS is not set
|
# CONFIG_KALLSYMS 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_BUILTIN_DTB_NAME="or1ksim"
|
CONFIG_BUILTIN_DTB_NAME="or1ksim"
|
||||||
CONFIG_HZ_100=y
|
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_NET=y
|
||||||
CONFIG_PACKET=y
|
CONFIG_PACKET=y
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
CONFIG_INET=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_INET_DIAG is not set
|
||||||
CONFIG_TCP_CONG_ADVANCED=y
|
CONFIG_TCP_CONG_ADVANCED=y
|
||||||
# CONFIG_TCP_CONG_BIC is not set
|
# CONFIG_TCP_CONG_BIC is not set
|
||||||
@@ -35,7 +32,6 @@ CONFIG_DEVTMPFS=y
|
|||||||
CONFIG_DEVTMPFS_MOUNT=y
|
CONFIG_DEVTMPFS_MOUNT=y
|
||||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||||
# CONFIG_FW_LOADER is not set
|
# CONFIG_FW_LOADER is not set
|
||||||
CONFIG_PROC_DEVICETREE=y
|
|
||||||
CONFIG_NETDEVICES=y
|
CONFIG_NETDEVICES=y
|
||||||
CONFIG_ETHOC=y
|
CONFIG_ETHOC=y
|
||||||
CONFIG_MICREL_PHY=y
|
CONFIG_MICREL_PHY=y
|
||||||
@@ -53,4 +49,3 @@ CONFIG_SERIAL_OF_PLATFORM=y
|
|||||||
# CONFIG_DNOTIFY is not set
|
# CONFIG_DNOTIFY is not set
|
||||||
CONFIG_TMPFS=y
|
CONFIG_TMPFS=y
|
||||||
CONFIG_NFS_FS=y
|
CONFIG_NFS_FS=y
|
||||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ CONFIG_NR_CPUS=8
|
|||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
CONFIG_HZ_100=y
|
CONFIG_HZ_100=y
|
||||||
# CONFIG_OPENRISC_NO_SPR_SR_DSX is not set
|
# CONFIG_OPENRISC_NO_SPR_SR_DSX is not set
|
||||||
|
CONFIG_JUMP_LABEL=y
|
||||||
# CONFIG_COMPAT_BRK is not set
|
# CONFIG_COMPAT_BRK is not set
|
||||||
CONFIG_NET=y
|
CONFIG_NET=y
|
||||||
CONFIG_PACKET=y
|
CONFIG_PACKET=y
|
||||||
@@ -55,7 +56,6 @@ CONFIG_DRM=y
|
|||||||
# CONFIG_DRM_FBDEV_EMULATION is not set
|
# CONFIG_DRM_FBDEV_EMULATION is not set
|
||||||
CONFIG_DRM_VIRTIO_GPU=y
|
CONFIG_DRM_VIRTIO_GPU=y
|
||||||
CONFIG_FB=y
|
CONFIG_FB=y
|
||||||
CONFIG_FIRMWARE_EDID=y
|
|
||||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||||
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
|
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
|
||||||
CONFIG_LOGO=y
|
CONFIG_LOGO=y
|
||||||
|
|||||||
@@ -9,4 +9,3 @@ generic-y += spinlock.h
|
|||||||
generic-y += qrwlock_types.h
|
generic-y += qrwlock_types.h
|
||||||
generic-y += qrwlock.h
|
generic-y += qrwlock.h
|
||||||
generic-y += user.h
|
generic-y += user.h
|
||||||
generic-y += text-patching.h
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
enum fixed_addresses {
|
enum fixed_addresses {
|
||||||
FIX_EARLYCON_MEM_BASE,
|
FIX_EARLYCON_MEM_BASE,
|
||||||
|
FIX_TEXT_POKE0,
|
||||||
__end_of_fixed_addresses
|
__end_of_fixed_addresses
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
15
arch/openrisc/include/asm/insn-def.h
Normal file
15
arch/openrisc/include/asm/insn-def.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Chen Miao
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASM_OPENRISC_INSN_DEF_H
|
||||||
|
#define __ASM_OPENRISC_INSN_DEF_H
|
||||||
|
|
||||||
|
/* or1k instructions are always 32 bits. */
|
||||||
|
#define OPENRISC_INSN_SIZE 4
|
||||||
|
|
||||||
|
/* or1k nop instruction code */
|
||||||
|
#define OPENRISC_INSN_NOP 0x15000000U
|
||||||
|
|
||||||
|
#endif /* __ASM_OPENRISC_INSN_DEF_H */
|
||||||
72
arch/openrisc/include/asm/jump_label.h
Normal file
72
arch/openrisc/include/asm/jump_label.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Chen Miao
|
||||||
|
*
|
||||||
|
* Based on arch/arm/include/asm/jump_label.h
|
||||||
|
*/
|
||||||
|
#ifndef __ASM_OPENRISC_JUMP_LABEL_H
|
||||||
|
#define __ASM_OPENRISC_JUMP_LABEL_H
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/insn-def.h>
|
||||||
|
|
||||||
|
#define HAVE_JUMP_LABEL_BATCH
|
||||||
|
|
||||||
|
#define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUMP_TABLE_ENTRY - Create a jump table entry
|
||||||
|
* @key: Jump key identifier (typically a symbol address)
|
||||||
|
* @label: Target label address
|
||||||
|
*
|
||||||
|
* This macro creates a jump table entry in the dedicated kernel section (__jump_table).
|
||||||
|
* Each entry contains the following information:
|
||||||
|
* Offset from current instruction to jump instruction (1b - .)
|
||||||
|
* Offset from current instruction to target label (label - .)
|
||||||
|
* Offset from current instruction to key identifier (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 /* __ASSEMBLER__ */
|
||||||
|
#endif /* __ASM_OPENRISC_JUMP_LABEL_H */
|
||||||
13
arch/openrisc/include/asm/text-patching.h
Normal file
13
arch/openrisc/include/asm/text-patching.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Chen Miao
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_OPENRISC_PATCHING_H
|
||||||
|
#define _ASM_OPENRISC_PATCHING_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
int patch_insn_write(void *addr, u32 insn);
|
||||||
|
|
||||||
|
#endif /* _ASM_OPENRISC_PATCHING_H */
|
||||||
@@ -9,9 +9,11 @@ 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 \
|
traps.o time.o irq.o entry.o ptrace.o signal.o \
|
||||||
sys_call_table.o unwinder.o cacheinfo.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_SMP) += smp.o sync-timer.o
|
||||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||||
obj-$(CONFIG_MODULES) += module.o
|
obj-$(CONFIG_MODULES) += module.o
|
||||||
obj-$(CONFIG_OF) += prom.o
|
obj-$(CONFIG_OF) += prom.o
|
||||||
|
obj-y += patching.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
51
arch/openrisc/kernel/jump_label.c
Normal file
51
arch/openrisc/kernel/jump_label.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// 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.
|
||||||
|
*/
|
||||||
|
WARN_ON_ONCE(offset < -134217728 || offset > 134217724);
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
kick_all_cpus_sync();
|
||||||
|
}
|
||||||
@@ -55,6 +55,10 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
|||||||
value |= *location & 0xfc000000;
|
value |= *location & 0xfc000000;
|
||||||
*location = value;
|
*location = value;
|
||||||
break;
|
break;
|
||||||
|
case R_OR1K_32_PCREL:
|
||||||
|
value -= (uint32_t)location;
|
||||||
|
*location = value;
|
||||||
|
break;
|
||||||
case R_OR1K_AHI16:
|
case R_OR1K_AHI16:
|
||||||
/* Adjust the operand to match with a signed LO16. */
|
/* Adjust the operand to match with a signed LO16. */
|
||||||
value += 0x8000;
|
value += 0x8000;
|
||||||
|
|||||||
79
arch/openrisc/kernel/patching.c
Normal file
79
arch/openrisc/kernel/patching.c
Normal file
@@ -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 __always_inline void *patch_map(void *addr, int fixmap)
|
||||||
|
{
|
||||||
|
uintptr_t uaddr = (uintptr_t) addr;
|
||||||
|
phys_addr_t phys;
|
||||||
|
|
||||||
|
if (core_kernel_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* patch_insn_write - Write a single instruction to a specified memory location
|
||||||
|
* This API provides a single-instruction patching, primarily used for runtime
|
||||||
|
* code modification.
|
||||||
|
* By the way, the insn size must be 4 bytes.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -249,6 +249,8 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
initrd_below_start_ok = 1;
|
initrd_below_start_ok = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#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() sets up the MMU and marks all pages as reserved */
|
||||||
paging_init();
|
paging_init();
|
||||||
|
|||||||
@@ -226,7 +226,11 @@ static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init __set_fixmap(enum fixed_addresses idx,
|
/*
|
||||||
|
* __set_fix must now support both EARLYCON and TEXT_POKE mappings,
|
||||||
|
* which are used at different stages of kernel execution.
|
||||||
|
*/
|
||||||
|
void __set_fixmap(enum fixed_addresses idx,
|
||||||
phys_addr_t phys, pgprot_t prot)
|
phys_addr_t phys, pgprot_t prot)
|
||||||
{
|
{
|
||||||
unsigned long address = __fix_to_virt(idx);
|
unsigned long address = __fix_to_virt(idx);
|
||||||
|
|||||||
Reference in New Issue
Block a user