diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index cd6b59190473..60970246523b 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -138,8 +138,12 @@ static inline void __free_hyp_memcache(struct kvm_hyp_memcache *mc, free_fn(pop_hyp_memcache(mc, to_va), arg); } -void free_hyp_memcache(struct kvm_hyp_memcache *mc); -int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages); +#define HYP_MEMCACHE_ACCOUNT_KMEMCG BIT(1) + +void free_hyp_memcache(struct kvm_hyp_memcache *mc, + unsigned long flags); +int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages, + unsigned long flags); struct kvm_vmid { atomic64_t id; diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index b5b407969aeb..ef382559ac49 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -528,7 +528,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) static_branch_dec(&userspace_irqchip_in_use); if (is_protected_kvm_enabled()) - free_hyp_memcache(&vcpu->arch.pkvm_memcache); + free_hyp_memcache(&vcpu->arch.pkvm_memcache, 0); else kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c index 379a8f45094c..08f76923776d 100644 --- a/arch/arm64/kvm/hypercalls.c +++ b/arch/arm64/kvm/hypercalls.c @@ -380,7 +380,8 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu) case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID: if (kvm_vm_is_protected(vcpu->kvm) && !topup_hyp_memcache(&vcpu->arch.pkvm_memcache, - kvm_mmu_cache_min_pages(&vcpu->kvm->arch.mmu))) + kvm_mmu_cache_min_pages(&vcpu->kvm->arch.mmu), + HYP_MEMCACHE_ACCOUNT_KMEMCG)) val[0] = SMCCC_RET_SUCCESS; break; case ARM_SMCCC_VENDOR_HYP_KVM_MEM_RELINQUISH_FUNC_ID: diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 70ac65c868ad..e2cdc65056e2 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1176,30 +1176,37 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu) } } -static void hyp_mc_free_fn(void *addr, void *unused) +static void hyp_mc_free_fn(void *addr, void *flags) { free_page((unsigned long)addr); } -static void *hyp_mc_alloc_fn(void *unused) +static void *hyp_mc_alloc_fn(void *flags) { - return (void *)__get_free_page(GFP_KERNEL_ACCOUNT); + unsigned long __flags = (unsigned long)flags; + gfp_t gfp_mask; + + gfp_mask = __flags & HYP_MEMCACHE_ACCOUNT_KMEMCG ? + GFP_KERNEL_ACCOUNT : GFP_KERNEL; + + return (void *)__get_free_page(gfp_mask); } -void free_hyp_memcache(struct kvm_hyp_memcache *mc) +void free_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long flags) { if (is_protected_kvm_enabled()) __free_hyp_memcache(mc, hyp_mc_free_fn, - kvm_host_va, NULL); + kvm_host_va, (void *)flags); } -int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages) +int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages, + unsigned long flags) { if (!is_protected_kvm_enabled()) return 0; return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn, - kvm_host_pa, NULL); + kvm_host_pa, (void *)flags); } /** @@ -1642,7 +1649,8 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, u64 pfn; int ret; - ret = topup_hyp_memcache(hyp_memcache, kvm_mmu_cache_min_pages(mmu)); + ret = topup_hyp_memcache(hyp_memcache, kvm_mmu_cache_min_pages(mmu), + HYP_MEMCACHE_ACCOUNT_KMEMCG); if (ret) return -ENOMEM; diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 4a951c61a5ac..4ff79b0dabd4 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -264,7 +264,7 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm) out_free: host_kvm->arch.pkvm.handle = 0; - free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc); + free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc, 0); } static void __pkvm_vcpu_hyp_created(struct kvm_vcpu *vcpu)