msm: kgsl: Fix gpuaddr_in_range() to check upper bound

Currently gpuaddr_in_range() accepts only the gpuaddr & returns
true if it lies in valid range. But this does not mean that the
entire buffer is within range.
Modify the function to accept size as a parameter and check that
both starting & ending points of buffer lie within mmu range.

Change-Id: I1d722295b9a27e746bfdb6d3bf409ffe722193cb
Signed-off-by: Rohan Sethi <rohsethi@codeaurora.org>
This commit is contained in:
Rohan Sethi 2021-11-22 14:23:30 +05:30 • committed by Rohan Sethi
commit ac7349dd70
6 changed files with 17 additions and 15 deletions

View file

@ -1125,8 +1125,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv,
}
/* Make sure that the address is in range and dword aligned */
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr) ||
!IS_ALIGNED(ib->gpuaddr, 4)) {
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr,
ib->size) || !IS_ALIGNED(ib->gpuaddr, 4)) {
pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n",
context->id, ib->gpuaddr);
return false;

View file

@ -657,7 +657,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv,
}
/* Make sure that the address is mapped */
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr)) {
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr,
ib->size)) {
pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n",
context->id, ib->gpuaddr);
return false;

View file

@ -1302,9 +1302,9 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr)
if (!private)
return NULL;
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr) &&
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr, 0) &&
!kgsl_mmu_gpuaddr_in_range(
private->pagetable->mmu->securepagetable, gpuaddr))
private->pagetable->mmu->securepagetable, gpuaddr, 0))
return NULL;
spin_lock(&private->mem_lock);

View file

@ -2287,20 +2287,20 @@ static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable,
}
static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable,
uint64_t gpuaddr)
uint64_t gpuaddr, uint64_t size)
{
struct kgsl_iommu_pt *pt = pagetable->priv;
if (gpuaddr == 0)
return false;
if (gpuaddr >= pt->va_start && gpuaddr < pt->va_end)
if (gpuaddr >= pt->va_start && (gpuaddr + size) < pt->va_end)
return true;
if (gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end)
if (gpuaddr >= pt->compat_va_start && (gpuaddr + size) < pt->compat_va_end)
return true;
if (gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end)
if (gpuaddr >= pt->svm_start && (gpuaddr + size) < pt->svm_end)
return true;
return false;

View file

@ -529,10 +529,10 @@ enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device)
}
bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable,
uint64_t gpuaddr)
uint64_t gpuaddr, uint64_t size)
{
if (PT_OP_VALID(pagetable, addr_in_range))
return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr);
return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr, size);
return false;
}
@ -544,7 +544,7 @@ bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable,
*/
static bool nommu_gpuaddr_in_range(struct kgsl_pagetable *pagetable,
uint64_t gpuaddr)
uint64_t gpuaddr, uint64_t size)
{
return (gpuaddr != 0) ? true : false;
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved.
*/
#ifndef __KGSL_MMU_H
#define __KGSL_MMU_H
@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops {
int (*svm_range)(struct kgsl_pagetable *pt, uint64_t *lo, uint64_t *hi,
uint64_t memflags);
bool (*addr_in_range)(struct kgsl_pagetable *pagetable,
uint64_t gpuaddr);
uint64_t gpuaddr, uint64_t size);
};
enum kgsl_mmu_feature {
@ -174,7 +174,8 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
u64 ttbr0, uint64_t addr);
bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr);
bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr,
uint64_t size);
int kgsl_mmu_get_region(struct kgsl_pagetable *pagetable,
uint64_t gpuaddr, uint64_t size);