arch/powerpc/mm/book3s64/subpage_prot.c
Source file repositories/reference/linux-study-clean/arch/powerpc/mm/book3s64/subpage_prot.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/mm/book3s64/subpage_prot.c- Extension
.c- Size
- 6586 bytes
- Lines
- 282
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- Inferred role
- Architecture Layer: syscall or user/kernel boundary
- Status
- core 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.
- Defines or participates in a user/kernel boundary; inspect argument validation, copy_from_user/copy_to_user, credentials, and dispatch target.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- 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/errno.hlinux/kernel.hlinux/gfp.hlinux/types.hlinux/pagewalk.hlinux/hugetlb.hlinux/syscalls.hlinux/pgtable.hlinux/uaccess.h
Detected Declarations
syscall subpage_protfunction subpage_prot_freefunction hpte_flush_rangefunction subpage_prot_clearfunction subpage_walk_pmd_entryfunction subpage_mark_vma_nohugefunction subpage_mark_vma_nohuge
Annotated Snippet
SYSCALL_DEFINE3(subpage_prot, unsigned long, addr,
unsigned long, len, u32 __user *, map)
{
struct mm_struct *mm = current->mm;
struct subpage_prot_table *spt;
u32 **spm, *spp;
unsigned long i;
size_t nw;
unsigned long next, limit;
int err;
if (radix_enabled())
return -ENOENT;
/* Check parameters */
if ((addr & ~PAGE_MASK) || (len & ~PAGE_MASK) ||
addr >= mm->task_size || len >= mm->task_size ||
addr + len > mm->task_size)
return -EINVAL;
if (is_hugepage_only_range(mm, addr, len))
return -EINVAL;
if (!map) {
/* Clear out the protection map for the address range */
subpage_prot_clear(addr, len);
return 0;
}
if (!access_ok(map, (len >> PAGE_SHIFT) * sizeof(u32)))
return -EFAULT;
mmap_write_lock(mm);
spt = mm_ctx_subpage_prot(&mm->context);
if (!spt) {
/*
* Allocate subpage prot table if not already done.
* Do this with mmap_lock held
*/
spt = kzalloc_obj(struct subpage_prot_table);
if (!spt) {
err = -ENOMEM;
goto out;
}
mm->context.hash_context->spt = spt;
}
subpage_mark_vma_nohuge(mm, addr, len);
for (limit = addr + len; addr < limit; addr = next) {
next = pmd_addr_end(addr, limit);
err = -ENOMEM;
if (addr < 0x100000000UL) {
spm = spt->low_prot;
} else {
spm = spt->protptrs[addr >> SBP_L3_SHIFT];
if (!spm) {
spm = (u32 **)get_zeroed_page(GFP_KERNEL);
if (!spm)
goto out;
spt->protptrs[addr >> SBP_L3_SHIFT] = spm;
}
}
spm += (addr >> SBP_L2_SHIFT) & (SBP_L2_COUNT - 1);
spp = *spm;
if (!spp) {
spp = (u32 *)get_zeroed_page(GFP_KERNEL);
if (!spp)
goto out;
*spm = spp;
}
spp += (addr >> PAGE_SHIFT) & (SBP_L1_COUNT - 1);
local_irq_disable();
demote_segment_4k(mm, addr);
local_irq_enable();
i = (addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
nw = PTRS_PER_PTE - i;
if (addr + (nw << PAGE_SHIFT) > next)
nw = (next - addr) >> PAGE_SHIFT;
mmap_write_unlock(mm);
if (__copy_from_user(spp, map, nw * sizeof(u32)))
return -EFAULT;
map += nw;
mmap_write_lock(mm);
/* now flush any existing HPTEs for the range */
hpte_flush_range(mm, addr, nw);
Annotation
- Immediate include surface: `linux/errno.h`, `linux/kernel.h`, `linux/gfp.h`, `linux/types.h`, `linux/pagewalk.h`, `linux/hugetlb.h`, `linux/syscalls.h`, `linux/pgtable.h`.
- Detected declarations: `syscall subpage_prot`, `function subpage_prot_free`, `function hpte_flush_range`, `function subpage_prot_clear`, `function subpage_walk_pmd_entry`, `function subpage_mark_vma_nohuge`, `function subpage_mark_vma_nohuge`.
- Atlas domain: Architecture Layer / arch/powerpc.
- Implementation status: core implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
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.