Re: [PATCH v4 10/17] KVM: arm64: Add a shrinker for pKVM
Fuad Tabba <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,dev.linux.lists.kvmarm |
|---|---|
| Message-ID | <CA+EHjTxU2GCpSR587oR_EaMOvXfu+teCnfC2KCg=vpOtf4sgRA@mail.gmail.com> |
Hi Vincent, On Fri, 31 Jul 2026 at 15:36, 'Vincent Donnefort' via kernel-team <[email protected]> wrote: > > Integrate the pKVM memory reclaim interface with the host's memory > management subsystem. > > This allows the host to automatically recover unused memory fom the > hypervisor's heap allocator when the host is under memory pressure. > > Tested-by: Fuad Tabba <[email protected]> > Signed-off-by: Vincent Donnefort <[email protected]> > > diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c > index d28422f5c3d6..bfbb1266491d 100644 > --- a/arch/arm64/kvm/pkvm.c > +++ b/arch/arm64/kvm/pkvm.c > @@ -115,7 +115,7 @@ static int pkvm_hyp_topup(enum pkvm_topup_id id, unsigned long nr_pages) > return ret; > } > > -static __maybe_unused unsigned long pkvm_hyp_reclaim(enum pkvm_topup_id id, unsigned long target) > +static unsigned long pkvm_hyp_reclaim(enum pkvm_topup_id id, unsigned long target) This is the first caller of these, so it is where reclaim starts running against a concurrent top-up. Nothing marks the pages a top-up just put in allocator->mc as spoken for, and hyp_allocator_reclaim() ends with an unbounded drain of it, so a shrink with target 1 hands back the lot. Land that between a top-up and the retry it was for, and the retry asks again, and pkvm_call_hyp_req() goes round. Both are driven by memory pressure, so they are busiest together. Worth holding back what a pending request asked for? > { > struct kvm_hyp_memcache mc; > struct arm_smccc_res res; > @@ -133,7 +133,7 @@ static __maybe_unused unsigned long pkvm_hyp_reclaim(enum pkvm_topup_id id, unsi > return reclaimed; > } > > -static __maybe_unused unsigned long pkvm_hyp_reclaimable(enum pkvm_topup_id id) > +static unsigned long pkvm_hyp_reclaimable(enum pkvm_topup_id id) > { > return kvm_call_hyp_nvhe(__pkvm_hyp_reclaimable, id); > } > @@ -342,8 +342,19 @@ void __init pkvm_selftests(void) > #endif > } > > +static unsigned long pkvm_shrinker_count(struct shrinker *shrink, struct shrink_control *sc) > +{ > + return pkvm_hyp_reclaimable(PKVM_TOPUP_HYP_ALLOC) ?: SHRINK_EMPTY; > +} > + > +static unsigned long pkvm_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc) > +{ > + return pkvm_hyp_reclaim(PKVM_TOPUP_HYP_ALLOC, sc->nr_to_scan); > +} Returning 0 rather than SHRINK_STOP when reclaim comes back empty leaves do_shrink_slab() calling this until total_scan runs out, and each call is an HVC. count_objects() covers the case where there is nothing at all, but not the one where it goes stale between the two calls. Cheers, /fuad > + > static int __init finalize_pkvm(void) > { > + struct shrinker *pkvm_shrinker; > int ret; > > if (!is_protected_kvm_enabled() || !is_kvm_arm_initialised()) > @@ -359,10 +370,21 @@ static int __init finalize_pkvm(void) > kmemleak_free_part_phys(hyp_mem_base, hyp_mem_size); > > ret = pkvm_drop_host_privileges(); > - if (ret) > + if (ret) { > pr_err("Failed to finalize Hyp protection: %d\n", ret); > + return ret; > + } > > - return ret; > + pkvm_shrinker = shrinker_alloc(0, "pkvm"); > + if (pkvm_shrinker) { > + pkvm_shrinker->count_objects = pkvm_shrinker_count; > + pkvm_shrinker->scan_objects = pkvm_shrinker_scan; > + shrinker_register(pkvm_shrinker); > + } else { > + kvm_err("Failed to register shrinker for pKVM\n"); > + } > + > + return 0; > } > device_initcall_sync(finalize_pkvm); > > -- > 2.55.0.508.g3f0d502094-goog > > To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. >