arch/powerpc/lib/test-code-patching.c
Source file repositories/reference/linux-study-clean/arch/powerpc/lib/test-code-patching.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/lib/test-code-patching.c- Extension
.c- Size
- 14419 bytes
- Lines
- 496
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- Inferred role
- Architecture Layer: implementation source
- Status
- source implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
Dependency Surface
linux/vmalloc.hlinux/init.hasm/text-patching.h
Detected Declarations
function instr_is_branch_to_addrfunction test_trampolinefunction test_branch_iformfunction test_create_function_callfunction test_branch_bformfunction test_translate_branchfunction test_prefixed_patchingfunction test_multi_instruction_patchingfunction test_data_patchingfunction test_code_patching
Annotated Snippet
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2008 Michael Ellerman, IBM Corporation.
*/
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <asm/text-patching.h>
static int __init instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
{
if (instr_is_branch_iform(ppc_inst_read(instr)) ||
instr_is_branch_bform(ppc_inst_read(instr)))
return branch_target(instr) == addr;
return 0;
}
static void __init test_trampoline(void)
{
asm ("nop;nop;\n");
}
#define check(x) do { \
if (!(x)) \
pr_err("code-patching: test failed at line %d\n", __LINE__); \
} while (0)
static void __init test_branch_iform(void)
{
int err;
ppc_inst_t instr;
u32 tmp[2];
u32 *iptr = tmp;
unsigned long addr = (unsigned long)tmp;
/* The simplest case, branch to self, no flags */
check(instr_is_branch_iform(ppc_inst(0x48000000)));
/* All bits of target set, and flags */
check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
/* High bit of opcode set, which is wrong */
check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
/* Middle bits of opcode set, which is wrong */
check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
/* Simplest case, branch to self with link */
check(instr_is_branch_iform(ppc_inst(0x48000001)));
/* All bits of targets set */
check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
/* Some bits of targets set */
check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
/* Must be a valid branch to start with */
check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
/* Absolute branch to 0x100 */
ppc_inst_write(iptr, ppc_inst(0x48000103));
check(instr_is_branch_to_addr(iptr, 0x100));
/* Absolute branch to 0x420fc */
ppc_inst_write(iptr, ppc_inst(0x480420ff));
check(instr_is_branch_to_addr(iptr, 0x420fc));
/* Maximum positive relative branch, + 20MB - 4B */
ppc_inst_write(iptr, ppc_inst(0x49fffffc));
check(instr_is_branch_to_addr(iptr, addr + 0x1FFFFFC));
/* Smallest negative relative branch, - 4B */
ppc_inst_write(iptr, ppc_inst(0x4bfffffc));
check(instr_is_branch_to_addr(iptr, addr - 4));
/* Largest negative relative branch, - 32 MB */
ppc_inst_write(iptr, ppc_inst(0x4a000000));
check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
/* Branch to self, with link */
err = create_branch(&instr, iptr, addr, BRANCH_SET_LINK);
ppc_inst_write(iptr, instr);
check(instr_is_branch_to_addr(iptr, addr));
/* Branch to self - 0x100, with link */
err = create_branch(&instr, iptr, addr - 0x100, BRANCH_SET_LINK);
ppc_inst_write(iptr, instr);
check(instr_is_branch_to_addr(iptr, addr - 0x100));
/* Branch to self + 0x100, no link */
err = create_branch(&instr, iptr, addr + 0x100, 0);
ppc_inst_write(iptr, instr);
check(instr_is_branch_to_addr(iptr, addr + 0x100));
/* Maximum relative negative offset, - 32 MB */
err = create_branch(&instr, iptr, addr - 0x2000000, BRANCH_SET_LINK);
ppc_inst_write(iptr, instr);
check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
Annotation
- Immediate include surface: `linux/vmalloc.h`, `linux/init.h`, `asm/text-patching.h`.
- Detected declarations: `function instr_is_branch_to_addr`, `function test_trampoline`, `function test_branch_iform`, `function test_create_function_call`, `function test_branch_bform`, `function test_translate_branch`, `function test_prefixed_patching`, `function test_multi_instruction_patching`, `function test_data_patching`, `function test_code_patching`.
- Atlas domain: Architecture Layer / arch/powerpc.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.