mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-06 17:35:20 +02:00
ANDROID: KVM: arm64: iommu: Allow driver to flush cached refcount
commit "a737b7d0e721 (ANDROID: KVM: arm64: iommu: Reduce the logic in generic code)" move unmap_walk logic to the SMMUv3 driver to abstract the unmap operation. When that was moved, to avoid exposing the kvm_iommu_flush_unmap_cache() a WARN_ON was added on the assumption that it is enough to limit the pgcount called into the driver to KVM_IOMMU_PADDR_CACHE_MAX. As it turns out, that IOMMU layer in the kernel can map pages with at page level and unmap them at the block level, so 1 page in a block expands to 512 enteries in the cache. So, we need to expose this function to the driver. Bug: 277989609 Bug: 278749606 Change-Id: Ic3815bdf2f96fd086a7b7c5c5a2ff32478fbf2d3 Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
parent
65ea117650
commit
21f5282377
|
@ -12,6 +12,7 @@ typedef void (*dyn_hcall_t)(struct user_pt_regs *);
|
||||||
struct kvm_hyp_iommu;
|
struct kvm_hyp_iommu;
|
||||||
struct iommu_iotlb_gather;
|
struct iommu_iotlb_gather;
|
||||||
struct kvm_hyp_iommu_domain;
|
struct kvm_hyp_iommu_domain;
|
||||||
|
struct kvm_iommu_paddr_cache;
|
||||||
|
|
||||||
#ifdef CONFIG_MODULES
|
#ifdef CONFIG_MODULES
|
||||||
enum pkvm_psci_notification {
|
enum pkvm_psci_notification {
|
||||||
|
@ -213,7 +214,7 @@ struct pkvm_module_ops {
|
||||||
void (*iommu_reclaim_pages_atomic)(void *p, u8 order);
|
void (*iommu_reclaim_pages_atomic)(void *p, u8 order);
|
||||||
int (*iommu_snapshot_host_stage2)(struct kvm_hyp_iommu_domain *domain);
|
int (*iommu_snapshot_host_stage2)(struct kvm_hyp_iommu_domain *domain);
|
||||||
int (*hyp_smp_processor_id)(void);
|
int (*hyp_smp_processor_id)(void);
|
||||||
ANDROID_KABI_RESERVE(1);
|
ANDROID_KABI_USE(1, void (*iommu_flush_unmap_cache)(struct kvm_iommu_paddr_cache *cache));
|
||||||
ANDROID_KABI_RESERVE(2);
|
ANDROID_KABI_RESERVE(2);
|
||||||
ANDROID_KABI_RESERVE(3);
|
ANDROID_KABI_RESERVE(3);
|
||||||
ANDROID_KABI_RESERVE(4);
|
ANDROID_KABI_RESERVE(4);
|
||||||
|
|
|
@ -70,6 +70,8 @@ struct kvm_iommu_paddr_cache {
|
||||||
size_t pgsize[KVM_IOMMU_PADDR_CACHE_MAX];
|
size_t pgsize[KVM_IOMMU_PADDR_CACHE_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void kvm_iommu_flush_unmap_cache(struct kvm_iommu_paddr_cache *cache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct kvm_iommu_ops - KVM iommu ops
|
* struct kvm_iommu_ops - KVM iommu ops
|
||||||
* @init: init the driver called once before the kernel de-privilege
|
* @init: init the driver called once before the kernel de-privilege
|
||||||
|
|
|
@ -380,7 +380,7 @@ void kvm_iommu_iotlb_gather_add_page(struct kvm_hyp_iommu_domain *domain,
|
||||||
kvm_iommu_iotlb_gather_add_range(gather, iova, size);
|
kvm_iommu_iotlb_gather_add_range(gather, iova, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_iommu_flush_unmap_cache(struct kvm_iommu_paddr_cache *cache)
|
void kvm_iommu_flush_unmap_cache(struct kvm_iommu_paddr_cache *cache)
|
||||||
{
|
{
|
||||||
while (cache->ptr) {
|
while (cache->ptr) {
|
||||||
cache->ptr--;
|
cache->ptr--;
|
||||||
|
|
|
@ -152,6 +152,7 @@ const struct pkvm_module_ops module_ops = {
|
||||||
.iommu_reclaim_pages_atomic = kvm_iommu_reclaim_pages_atomic,
|
.iommu_reclaim_pages_atomic = kvm_iommu_reclaim_pages_atomic,
|
||||||
.iommu_snapshot_host_stage2 = kvm_iommu_snapshot_host_stage2,
|
.iommu_snapshot_host_stage2 = kvm_iommu_snapshot_host_stage2,
|
||||||
.hyp_smp_processor_id = _hyp_smp_processor_id,
|
.hyp_smp_processor_id = _hyp_smp_processor_id,
|
||||||
|
.iommu_flush_unmap_cache = kvm_iommu_flush_unmap_cache,
|
||||||
};
|
};
|
||||||
|
|
||||||
int __pkvm_init_module(void *module_init)
|
int __pkvm_init_module(void *module_init)
|
||||||
|
|
|
@ -41,6 +41,7 @@ extern const struct pkvm_module_ops *mod_ops;
|
||||||
#define kvm_iommu_donate_pages_atomic(x) CALL_FROM_OPS(iommu_donate_pages_atomic, x)
|
#define kvm_iommu_donate_pages_atomic(x) CALL_FROM_OPS(iommu_donate_pages_atomic, x)
|
||||||
#define kvm_iommu_reclaim_pages_atomic(x, y) CALL_FROM_OPS(iommu_reclaim_pages_atomic, x, y)
|
#define kvm_iommu_reclaim_pages_atomic(x, y) CALL_FROM_OPS(iommu_reclaim_pages_atomic, x, y)
|
||||||
#define kvm_iommu_snapshot_host_stage2(x) CALL_FROM_OPS(iommu_snapshot_host_stage2, x)
|
#define kvm_iommu_snapshot_host_stage2(x) CALL_FROM_OPS(iommu_snapshot_host_stage2, x)
|
||||||
|
#define kvm_iommu_flush_unmap_cache(x) CALL_FROM_OPS(iommu_flush_unmap_cache, x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __ARM_SMMU_V3_MODULE__ */
|
#endif /* __ARM_SMMU_V3_MODULE__ */
|
||||||
|
|
|
@ -1300,14 +1300,20 @@ static void kvm_iommu_unmap_walker(struct io_pgtable_ctxt *ctxt)
|
||||||
struct kvm_iommu_walk_data *data = (struct kvm_iommu_walk_data *)ctxt->arg;
|
struct kvm_iommu_walk_data *data = (struct kvm_iommu_walk_data *)ctxt->arg;
|
||||||
struct kvm_iommu_paddr_cache *cache = data->cache;
|
struct kvm_iommu_paddr_cache *cache = data->cache;
|
||||||
|
|
||||||
cache->paddr[cache->ptr] = ctxt->addr;
|
|
||||||
cache->pgsize[cache->ptr++] = ctxt->size;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is guaranteed unmap is called with max of the cache size,
|
* It is guaranteed unmap is called with max of the cache size,
|
||||||
* see kvm_iommu_unmap_pages()
|
* see kvm_iommu_unmap_pages()
|
||||||
*/
|
*/
|
||||||
WARN_ON(cache->ptr == KVM_IOMMU_PADDR_CACHE_MAX);
|
cache->paddr[cache->ptr] = ctxt->addr;
|
||||||
|
cache->pgsize[cache->ptr++] = ctxt->size;
|
||||||
|
|
||||||
|
/* Make more space. */
|
||||||
|
if(cache->ptr == KVM_IOMMU_PADDR_CACHE_MAX) {
|
||||||
|
/* Must invalidate TLB first. */
|
||||||
|
smmu_iotlb_sync(data->cookie, data->iotlb_gather);
|
||||||
|
iommu_iotlb_gather_init(data->iotlb_gather);
|
||||||
|
kvm_iommu_flush_unmap_cache(cache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t smmu_unmap_pages(struct kvm_hyp_iommu_domain *domain, unsigned long iova,
|
static size_t smmu_unmap_pages(struct kvm_hyp_iommu_domain *domain, unsigned long iova,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user