arch/arm64/kvm/pkvm.c
Source file repositories/reference/linux-study-clean/arch/arm64/kvm/pkvm.c
File Facts
- System
- Linux kernel
- Corpus path
arch/arm64/kvm/pkvm.c- Extension
.c- Size
- 15495 bytes
- Lines
- 593
- Domain
- Architecture Layer
- Bucket
- arch/arm64
- 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.
- 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/init.hlinux/interval_tree_generic.hlinux/kmemleak.hlinux/kvm_host.hasm/kvm_mmu.hlinux/memblock.hlinux/mutex.hasm/kvm_pkvm.hhyp_constants.h
Detected Declarations
function register_memblock_regionsfunction for_each_mem_regionfunction kvm_hyp_reservefunction __pkvm_destroy_hyp_vmfunction __pkvm_create_hyp_vcpufunction __pkvm_create_hyp_vmfunction pkvm_hyp_vm_is_createdfunction pkvm_create_hyp_vmfunction pkvm_create_hyp_vcpufunction pkvm_destroy_hyp_vmfunction pkvm_init_host_vmfunction _kvm_host_prot_finalizefunction pkvm_drop_host_privilegesfunction finalize_pkvmfunction __pkvm_mapping_startfunction __pkvm_mapping_endfunction pkvm_pgtable_stage2_initfunction __pkvm_pgtable_stage2_reclaimfunction for_each_mapping_in_range_safefunction __pkvm_pgtable_stage2_unsharefunction for_each_mapping_in_range_safefunction pkvm_pgtable_stage2_destroy_rangefunction pkvm_pgtable_stage2_destroy_pgdfunction pkvm_pgtable_stage2_mapfunction relax_permsfunction pkvm_pgtable_stage2_unmapfunction pkvm_pgtable_stage2_wrprotectfunction pkvm_pgtable_stage2_flushfunction pkvm_pgtable_stage2_test_clear_youngfunction pkvm_pgtable_stage2_relax_permsfunction pkvm_pgtable_stage2_mkyoungfunction pkvm_pgtable_stage2_free_unlinkedfunction pkvm_pgtable_stage2_splitfunction pkvm_force_reclaim_guest_page
Annotated Snippet
if (mapping) {
ret = kvm_call_hyp_nvhe(__pkvm_vcpu_in_poison_fault);
return ret ? -EFAULT : -EAGAIN;
}
ret = kvm_call_hyp_nvhe(__pkvm_host_donate_guest, pfn, gfn);
} else {
if (WARN_ON_ONCE(size != PAGE_SIZE && size != PMD_SIZE))
return -EINVAL;
/*
* We either raced with another vCPU or we're changing between
* page and block mappings. As per user_mem_abort(), same-size
* permission faults are handled in the relax_perms() path.
*/
if (mapping) {
if (size == (mapping->nr_pages * PAGE_SIZE))
return -EAGAIN;
/*
* Remove _any_ pkvm_mapping overlapping with the range,
* bigger or smaller.
*/
ret = __pkvm_pgtable_stage2_unshare(pgt, addr, end);
if (ret)
return ret;
mapping = NULL;
}
ret = kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn,
size / PAGE_SIZE, prot);
}
if (WARN_ON(ret))
return ret;
swap(mapping, cache->mapping);
mapping->gfn = gfn;
mapping->pfn = pfn;
mapping->nr_pages = size / PAGE_SIZE;
pkvm_mapping_insert(mapping, &pgt->pkvm_mappings);
return ret;
}
int pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
{
struct kvm *kvm = kvm_s2_mmu_to_kvm(pgt->mmu);
if (WARN_ON(kvm_vm_is_protected(kvm)))
return -EPERM;
lockdep_assert_held_write(&kvm->mmu_lock);
return __pkvm_pgtable_stage2_unshare(pgt, addr, addr + size);
}
int pkvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
{
struct kvm *kvm = kvm_s2_mmu_to_kvm(pgt->mmu);
pkvm_handle_t handle = kvm->arch.pkvm.handle;
struct pkvm_mapping *mapping;
int ret = 0;
if (WARN_ON(kvm_vm_is_protected(kvm)))
return -EPERM;
lockdep_assert_held(&kvm->mmu_lock);
for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping) {
ret = kvm_call_hyp_nvhe(__pkvm_host_wrprotect_guest, handle, mapping->gfn,
mapping->nr_pages);
if (WARN_ON(ret))
break;
}
return ret;
}
int pkvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size)
{
struct kvm *kvm = kvm_s2_mmu_to_kvm(pgt->mmu);
struct pkvm_mapping *mapping;
lockdep_assert_held(&kvm->mmu_lock);
for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping)
__clean_dcache_guest_page(pfn_to_kaddr(mapping->pfn),
PAGE_SIZE * mapping->nr_pages);
return 0;
Annotation
- Immediate include surface: `linux/init.h`, `linux/interval_tree_generic.h`, `linux/kmemleak.h`, `linux/kvm_host.h`, `asm/kvm_mmu.h`, `linux/memblock.h`, `linux/mutex.h`, `asm/kvm_pkvm.h`.
- Detected declarations: `function register_memblock_regions`, `function for_each_mem_region`, `function kvm_hyp_reserve`, `function __pkvm_destroy_hyp_vm`, `function __pkvm_create_hyp_vcpu`, `function __pkvm_create_hyp_vm`, `function pkvm_hyp_vm_is_created`, `function pkvm_create_hyp_vm`, `function pkvm_create_hyp_vcpu`, `function pkvm_destroy_hyp_vm`.
- Atlas domain: Architecture Layer / arch/arm64.
- 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.