arch/powerpc/lib/feature-fixups.c
Source file repositories/reference/linux-study-clean/arch/powerpc/lib/feature-fixups.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/lib/feature-fixups.c- Extension
.c- Size
- 31128 bytes
- Lines
- 1021
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- Inferred role
- Architecture Layer: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/types.hlinux/jump_label.hlinux/kernel.hlinux/string.hlinux/init.hlinux/sched/mm.hlinux/stop_machine.hasm/cputable.hasm/text-patching.hasm/interrupt.hasm/page.hasm/sections.hasm/setup.hasm/security_features.hasm/firmware.hasm/inst.h
Detected Declarations
struct fixup_entryfunction patch_alt_instructionfunction patch_feature_section_maskfunction do_feature_fixups_maskfunction do_feature_fixupsfunction is_fixup_addr_validfunction do_patch_fixupsfunction do_patch_entry_fixupsfunction do_stf_entry_barrier_fixupsfunction do_stf_exit_barrier_fixupsfunction __do_stf_barrier_fixupsfunction do_stf_barrier_fixupsfunction do_uaccess_flush_fixupsfunction __do_entry_flush_fixupsfunction do_entry_flush_fixupsfunction __do_rfi_flush_fixupsfunction do_rfi_flush_fixupsfunction do_barrier_nospec_fixups_rangefunction do_barrier_nospec_fixupsfunction do_barrier_nospec_fixups_rangefunction patch_btb_flush_sectionfunction do_btb_flush_fixupsfunction do_lwsync_fixupsfunction do_final_fixupsfunction apply_feature_fixupsfunction update_mmu_feature_fixupsfunction setup_feature_keysfunction check_featuresfunction patch_feature_sectionfunction calc_offsetfunction test_basic_patchingfunction test_alternative_patchingfunction test_alternative_case_too_bigfunction test_alternative_case_too_smallfunction test_alternative_case_with_branchfunction test_alternative_case_with_external_branchfunction test_alternative_case_with_branch_to_endfunction test_cpu_macrosfunction test_fw_macrosfunction test_lwsync_macrosfunction test_prefix_patchingfunction test_prefix_alt_patchingfunction test_prefix_word_alt_patchingfunction test_prefix_patchingexport static_key_feature_checks_initialized
Annotated Snippet
struct fixup_entry {
unsigned long mask;
unsigned long value;
long start_off;
long end_off;
long alt_start_off;
long alt_end_off;
};
static u32 *calc_addr(struct fixup_entry *fcur, long offset)
{
/*
* We store the offset to the code as a negative offset from
* the start of the alt_entry, to support the VDSO. This
* routine converts that back into an actual address.
*/
return (u32 *)((unsigned long)fcur + offset);
}
static int patch_alt_instruction(u32 *src, u32 *dest, u32 *alt_start, u32 *alt_end)
{
int err;
ppc_inst_t instr;
instr = ppc_inst_read(src);
if (instr_is_relative_branch(ppc_inst_read(src))) {
u32 *target = (u32 *)branch_target(src);
/* Branch within the section doesn't need translating */
if (target < alt_start || target > alt_end) {
err = translate_branch(&instr, dest, src);
if (err)
return 1;
}
}
raw_patch_instruction(dest, instr);
return 0;
}
static int patch_feature_section_mask(unsigned long value, unsigned long mask,
struct fixup_entry *fcur)
{
u32 *start, *end, *alt_start, *alt_end, *src, *dest;
start = calc_addr(fcur, fcur->start_off);
end = calc_addr(fcur, fcur->end_off);
alt_start = calc_addr(fcur, fcur->alt_start_off);
alt_end = calc_addr(fcur, fcur->alt_end_off);
if ((alt_end - alt_start) > (end - start))
return 1;
if ((value & fcur->mask & mask) == (fcur->value & mask))
return 0;
src = alt_start;
dest = start;
for (; src < alt_end; src = ppc_inst_next(src, src),
dest = ppc_inst_next(dest, dest)) {
if (patch_alt_instruction(src, dest, alt_start, alt_end))
return 1;
}
for (; dest < end; dest++)
raw_patch_instruction(dest, ppc_inst(PPC_RAW_NOP()));
return 0;
}
static void do_feature_fixups_mask(unsigned long value, unsigned long mask,
void *fixup_start, void *fixup_end)
{
struct fixup_entry *fcur, *fend;
fcur = fixup_start;
fend = fixup_end;
for (; fcur < fend; fcur++) {
if (patch_feature_section_mask(value, mask, fcur)) {
WARN_ON(1);
printk("Unable to patch feature section at %p - %p" \
" with %p - %p\n",
calc_addr(fcur, fcur->start_off),
calc_addr(fcur, fcur->end_off),
calc_addr(fcur, fcur->alt_start_off),
calc_addr(fcur, fcur->alt_end_off));
Annotation
- Immediate include surface: `linux/types.h`, `linux/jump_label.h`, `linux/kernel.h`, `linux/string.h`, `linux/init.h`, `linux/sched/mm.h`, `linux/stop_machine.h`, `asm/cputable.h`.
- Detected declarations: `struct fixup_entry`, `function patch_alt_instruction`, `function patch_feature_section_mask`, `function do_feature_fixups_mask`, `function do_feature_fixups`, `function is_fixup_addr_valid`, `function do_patch_fixups`, `function do_patch_entry_fixups`, `function do_stf_entry_barrier_fixups`, `function do_stf_exit_barrier_fixups`.
- Atlas domain: Architecture Layer / arch/powerpc.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.