arch/powerpc/kernel/module_32.c
Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/module_32.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/kernel/module_32.c- Extension
.c- Size
- 9620 bytes
- Lines
- 341
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/moduleloader.hlinux/elf.hlinux/vmalloc.hlinux/fs.hlinux/string.hlinux/kernel.hlinux/ftrace.hlinux/cache.hlinux/bug.hlinux/sort.hasm/setup.hasm/text-patching.h
Detected Declarations
function Copyrightfunction relacmpfunction get_plt_sizefunction module_frob_arch_sectionsfunction entry_matchesfunction do_plt_callfunction patch_location_16function apply_relocate_addfunction module_trampoline_targetfunction module_finalize_ftrace
Annotated Snippet
if (sechdrs[i].sh_type == SHT_RELA) {
pr_debug("Found relocations in section %u\n", i);
pr_debug("Ptr: %p. Number: %u\n",
(void *)hdr + sechdrs[i].sh_offset,
sechdrs[i].sh_size / sizeof(Elf32_Rela));
/* Sort the relocation information based on a symbol and
* addend key. This is a stable O(n*log n) complexity
* algorithm but it will reduce the complexity of
* count_relocs() to linear complexity O(n)
*/
sort((void *)hdr + sechdrs[i].sh_offset,
sechdrs[i].sh_size / sizeof(Elf32_Rela),
sizeof(Elf32_Rela), relacmp, NULL);
ret += count_relocs((void *)hdr
+ sechdrs[i].sh_offset,
sechdrs[i].sh_size
/ sizeof(Elf32_Rela))
* sizeof(struct ppc_plt_entry);
}
}
return ret;
}
int module_frob_arch_sections(Elf32_Ehdr *hdr,
Elf32_Shdr *sechdrs,
char *secstrings,
struct module *me)
{
unsigned int i;
/* Find .plt and .init.plt sections */
for (i = 0; i < hdr->e_shnum; i++) {
if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
me->arch.init_plt_section = i;
else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
me->arch.core_plt_section = i;
}
if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
pr_err("Module doesn't contain .plt or .init.plt sections.\n");
return -ENOEXEC;
}
/* Override their sizes */
sechdrs[me->arch.core_plt_section].sh_size
= get_plt_size(hdr, sechdrs, secstrings, 0);
sechdrs[me->arch.init_plt_section].sh_size
= get_plt_size(hdr, sechdrs, secstrings, 1);
return 0;
}
static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
{
if (entry->jump[0] != PPC_RAW_LIS(_R12, PPC_HA(val)))
return 0;
if (entry->jump[1] != PPC_RAW_ADDI(_R12, _R12, PPC_LO(val)))
return 0;
return 1;
}
/* Set up a trampoline in the PLT to bounce us to the distant function */
static uint32_t do_plt_call(void *location,
Elf32_Addr val,
const Elf32_Shdr *sechdrs,
struct module *mod)
{
struct ppc_plt_entry *entry;
pr_debug("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
/* Init, or core PLT? */
if (within_module_core((unsigned long)location, mod))
entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
else
entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
/* Find this entry, or if that fails, the next avail. entry */
while (entry->jump[0]) {
if (entry_matches(entry, val)) return (uint32_t)entry;
entry++;
}
if (patch_instruction(&entry->jump[0], ppc_inst(PPC_RAW_LIS(_R12, PPC_HA(val)))))
return 0;
if (patch_instruction(&entry->jump[1], ppc_inst(PPC_RAW_ADDI(_R12, _R12, PPC_LO(val)))))
return 0;
if (patch_instruction(&entry->jump[2], ppc_inst(PPC_RAW_MTCTR(_R12))))
return 0;
if (patch_instruction(&entry->jump[3], ppc_inst(PPC_RAW_BCTR())))
Annotation
- Immediate include surface: `linux/module.h`, `linux/moduleloader.h`, `linux/elf.h`, `linux/vmalloc.h`, `linux/fs.h`, `linux/string.h`, `linux/kernel.h`, `linux/ftrace.h`.
- Detected declarations: `function Copyright`, `function relacmp`, `function get_plt_size`, `function module_frob_arch_sections`, `function entry_matches`, `function do_plt_call`, `function patch_location_16`, `function apply_relocate_add`, `function module_trampoline_target`, `function module_finalize_ftrace`.
- 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.