ANDROID: KVM: arm64: Add function to topup allocator with flags

The SMMUv3 driver might be called from an atomic context, which
requires to pass GFP_ATOMIC to the allocation function.
Add an extra function that accepts gfp flags that the driver can use.

Bug: 367702966
Bug: 277989609
Bug: 278749606

Change-Id: I99ed309d46a00d662e972e54ac63c5c96382d959
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh 2024-09-18 09:32:30 +00:00
parent f056913fae
commit 09b18ba6f8
3 changed files with 33 additions and 3 deletions

View File

@ -154,6 +154,8 @@ static inline void __free_hyp_memcache(struct kvm_hyp_memcache *mc,
void free_hyp_memcache(struct kvm_hyp_memcache *mc);
int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages, unsigned long order);
int topup_hyp_memcache_gfp(struct kvm_hyp_memcache *mc, unsigned long min_pages,
unsigned long order, gfp_t gfp);
static inline void init_hyp_memcache(struct kvm_hyp_memcache *mc)
{
@ -1346,5 +1348,6 @@ int kvm_iommu_register_driver(struct kvm_iommu_driver *kern_ops);
unsigned long __pkvm_reclaim_hyp_alloc_mgt(unsigned long nr_pages);
int __pkvm_topup_hyp_alloc_mgt(unsigned long id, unsigned long nr_pages,
unsigned long sz_alloc);
int __pkvm_topup_hyp_alloc_mgt_gfp(unsigned long id, unsigned long nr_pages,
unsigned long sz_alloc, gfp_t gfp);
#endif /* __ARM64_KVM_HOST_H__ */

View File

@ -1177,6 +1177,11 @@ static void *hyp_mc_alloc_fn(void *flags, unsigned long order)
return addr;
}
static void *hyp_mc_alloc_gfp_fn(void *flags, unsigned long order)
{
return (void *)__get_free_pages(*(gfp_t *)flags, order);
}
void free_hyp_memcache(struct kvm_hyp_memcache *mc)
{
unsigned long flags = mc->flags;
@ -1203,6 +1208,21 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages,
}
EXPORT_SYMBOL(topup_hyp_memcache);
int topup_hyp_memcache_gfp(struct kvm_hyp_memcache *mc, unsigned long min_pages,
unsigned long order, gfp_t gfp)
{
void *flags = &gfp;
if (!is_protected_kvm_enabled())
return 0;
if (order > PAGE_SHIFT)
return -E2BIG;
return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_gfp_fn,
kvm_host_pa, flags, order);
}
/**
* kvm_phys_addr_ioremap - map a device range to guest IPA
*

View File

@ -1019,14 +1019,15 @@ int __pkvm_register_el2_call(unsigned long hfn_hyp_va)
EXPORT_SYMBOL(__pkvm_register_el2_call);
#endif /* CONFIG_MODULES */
int __pkvm_topup_hyp_alloc_mgt(unsigned long id, unsigned long nr_pages, unsigned long sz_alloc)
int __pkvm_topup_hyp_alloc_mgt_gfp(unsigned long id, unsigned long nr_pages,
unsigned long sz_alloc, gfp_t gfp)
{
struct kvm_hyp_memcache mc;
int ret;
init_hyp_memcache(&mc);
ret = topup_hyp_memcache(&mc, nr_pages, get_order(sz_alloc));
ret = topup_hyp_memcache_gfp(&mc, nr_pages, get_order(sz_alloc), gfp);
if (ret)
return ret;
@ -1037,6 +1038,12 @@ int __pkvm_topup_hyp_alloc_mgt(unsigned long id, unsigned long nr_pages, unsigne
return ret;
}
EXPORT_SYMBOL(__pkvm_topup_hyp_alloc_mgt_gfp);
int __pkvm_topup_hyp_alloc_mgt(unsigned long id, unsigned long nr_pages, unsigned long sz_alloc)
{
return __pkvm_topup_hyp_alloc_mgt_gfp(id, nr_pages, sz_alloc, GFP_KERNEL);
}
EXPORT_SYMBOL(__pkvm_topup_hyp_alloc_mgt);
int __pkvm_topup_hyp_alloc(unsigned long nr_pages)