arch/s390/kvm/gmap.c
Source file repositories/reference/linux-study-clean/arch/s390/kvm/gmap.c
File Facts
- System
- Linux kernel
- Corpus path
arch/s390/kvm/gmap.c- Extension
.c- Size
- 37813 bytes
- Lines
- 1378
- Domain
- Architecture Layer
- Bucket
- arch/s390
- 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.
- 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/compiler.hlinux/kvm.hlinux/kvm_host.hlinux/pgtable.hlinux/pagemap.hasm/lowcore.hasm/uv.hasm/gmap_helpers.hdat.hgmap.hkvm-s390.hfaultin.h
Detected Declarations
struct clear_young_pte_privstruct gmap_unmap_privstruct gmap_protect_asce_top_levelfunction Authorfunction gmap_limit_to_typefunction gmap_newfunction gmap_add_childfunction gmap_set_limitfunction gmap_rmap_radix_tree_freefunction radix_tree_for_each_slotfunction gmap_remove_childfunction gmap_disposefunction s390_replace_ascefunction _gmap_unmap_prefixfunction gmap_clear_young_ptefunction gmap_clear_young_crstefunction gmap_age_gfnfunction _gmap_unmap_ptefunction _gmap_unmap_crstefunction gmap_unmap_gfn_rangefunction __pte_test_and_clear_softdirtyfunction _pte_test_and_clear_softdirtyfunction _crste_test_and_clear_softdirtyfunction gmap_sync_dirty_logfunction gmap_handle_minor_crste_faultfunction _gmap_handle_minor_pte_faultfunction gmap_try_fixup_minorfunction gmap_2g_allowedfunction gmap_1m_allowedfunction _gmap_linkfunction gmap_linkfunction gmap_ucas_map_onefunction gmap_ucas_translate_simplefunction gmap_ucas_translatefunction scoped_guardfunction scoped_guardfunction gmap_ucas_mapfunction gmap_ucas_unmap_onefunction gmap_ucas_unmapfunction _gmap_split_crstefunction gmap_split_huge_pagesfunction _gmap_enable_skeysfunction gmap_enable_skeysfunction _destroy_pages_ptefunction _destroy_pages_crstefunction gmap_pv_destroy_rangefunction gmap_insert_rmapfunction gmap_protect_rmap
Annotated Snippet
struct clear_young_pte_priv {
struct gmap *gmap;
bool young;
};
static long gmap_clear_young_pte(union pte *ptep, gfn_t gfn, gfn_t end, struct dat_walk *walk)
{
struct clear_young_pte_priv *p = walk->priv;
union pgste pgste;
union pte pte, new;
pte = READ_ONCE(*ptep);
if (!pte.s.pr || (!pte.s.y && pte.h.i))
return 0;
pgste = pgste_get_lock(ptep);
if (!pgste.prefix_notif || gmap_mkold_prefix(p->gmap, gfn, end)) {
new = pte;
new.h.i = 1;
new.s.y = 0;
if ((new.s.d || !new.h.p) && !new.s.s)
folio_set_dirty(pfn_folio(pte.h.pfra));
new.s.d = 0;
new.h.p = 1;
pgste.prefix_notif = 0;
pgste = __dat_ptep_xchg(ptep, pgste, new, gfn, walk->asce, uses_skeys(p->gmap));
}
p->young = 1;
pgste_set_unlock(ptep, pgste);
return 0;
}
static long gmap_clear_young_crste(union crste *crstep, gfn_t gfn, gfn_t end, struct dat_walk *walk)
{
struct clear_young_pte_priv *priv = walk->priv;
union crste crste, new;
do {
crste = READ_ONCE(*crstep);
if (!crste.h.fc)
return 0;
if (!crste.s.fc1.y && crste.h.i)
return 0;
if (crste_prefix(crste) && !gmap_mkold_prefix(priv->gmap, gfn, end))
break;
new = crste;
new.h.i = 1;
new.s.fc1.y = 0;
new.s.fc1.prefix_notif = 0;
if (new.s.fc1.d || !new.h.p)
folio_set_dirty(phys_to_folio(crste_origin_large(crste)));
new.s.fc1.d = 0;
new.h.p = 1;
} while (!dat_crstep_xchg_atomic(crstep, crste, new, gfn, walk->asce));
priv->young = 1;
return 0;
}
/**
* gmap_age_gfn() - Clear young.
* @gmap: The guest gmap.
* @start: The first gfn to test.
* @end: The gfn after the last one to test.
*
* Context: Called with the kvm mmu write lock held.
* Return: 1 if any page in the given range was young, otherwise 0.
*/
bool gmap_age_gfn(struct gmap *gmap, gfn_t start, gfn_t end)
{
const struct dat_walk_ops ops = {
.pte_entry = gmap_clear_young_pte,
.pmd_entry = gmap_clear_young_crste,
.pud_entry = gmap_clear_young_crste,
};
struct clear_young_pte_priv priv = {
.gmap = gmap,
.young = false,
};
_dat_walk_gfn_range(start, end, gmap->asce, &ops, 0, &priv);
return priv.young;
}
struct gmap_unmap_priv {
Annotation
- Immediate include surface: `linux/compiler.h`, `linux/kvm.h`, `linux/kvm_host.h`, `linux/pgtable.h`, `linux/pagemap.h`, `asm/lowcore.h`, `asm/uv.h`, `asm/gmap_helpers.h`.
- Detected declarations: `struct clear_young_pte_priv`, `struct gmap_unmap_priv`, `struct gmap_protect_asce_top_level`, `function Author`, `function gmap_limit_to_type`, `function gmap_new`, `function gmap_add_child`, `function gmap_set_limit`, `function gmap_rmap_radix_tree_free`, `function radix_tree_for_each_slot`.
- Atlas domain: Architecture Layer / arch/s390.
- Implementation status: source 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.