summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarshitha Sai Neelati <quic_hsaineel@quicinc.com>2023-02-15 23:07:29 +0530
committerHarshitha Sai Neelati <quic_hsaineel@quicinc.com>2023-02-28 14:01:07 +0530
commit4d87657af0d3159c77ab4c05b4c04e7869249c24 (patch)
tree4f04d9ef0140cdf74c387ad338d9debad7f33e5d
parent23fb0f089b60ff8564f7aff5cf5285e4c265769d (diff)
downloadgraphics-4d87657af0d3159c77ab4c05b4c04e7869249c24.tar.gz
msm: kgsl: Fix null pointer dereference in deferred_destroy
iommu->user_context can get detached in kgsl_iommu_close and later get accessed in the deferred_destroy path. Flush the workqueue to ensure pagetables are destroyed before proceeding for context detach. Also handle set_ttbr0_cfg properly in the close path. Change-Id: Idd936957e9c7617d978056604241e2e24dac8af4 Signed-off-by: Harshitha Sai Neelati <quic_hsaineel@quicinc.com>
-rw-r--r--kgsl_iommu.c63
1 files changed, 34 insertions, 29 deletions
diff --git a/kgsl_iommu.c b/kgsl_iommu.c
index 1dc1daf..d62626a 100644
--- a/kgsl_iommu.c
+++ b/kgsl_iommu.c
@@ -1125,6 +1125,24 @@ static u64 kgsl_iommu_get_ttbr0(struct kgsl_pagetable *pagetable)
return pt->ttbr0;
}
+/* Set TTBR0 for the given context with the specific configuration */
+static void kgsl_iommu_set_ttbr0(struct kgsl_iommu_context *context,
+ struct kgsl_mmu *mmu, const struct io_pgtable_cfg *pgtbl_cfg)
+{
+ struct adreno_smmu_priv *adreno_smmu;
+
+ /* Quietly return if the context doesn't have a domain */
+ if (!context->domain)
+ return;
+
+ adreno_smmu = dev_get_drvdata(&context->pdev->dev);
+
+ /* Enable CX and clocks before we call into SMMU to setup registers */
+ kgsl_iommu_enable_clk(mmu);
+ adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, pgtbl_cfg);
+ kgsl_iommu_disable_clk(mmu);
+}
+
static int kgsl_iommu_get_context_bank(struct kgsl_pagetable *pt, struct kgsl_context *context)
{
struct kgsl_iommu *iommu = to_kgsl_iommu(pt);
@@ -1154,9 +1172,6 @@ static int kgsl_iommu_get_asid(struct kgsl_pagetable *pt, struct kgsl_context *c
static void kgsl_iommu_destroy_default_pagetable(struct kgsl_pagetable *pagetable)
{
struct kgsl_device *device = KGSL_MMU_DEVICE(pagetable->mmu);
- struct kgsl_iommu *iommu = to_kgsl_iommu(pagetable);
- struct kgsl_iommu_context *context = &iommu->user_context;
- struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&context->pdev->dev);
struct kgsl_iommu_pt *pt = to_iommu_pt(pagetable);
struct kgsl_global_memdesc *md;
@@ -1167,8 +1182,6 @@ static void kgsl_iommu_destroy_default_pagetable(struct kgsl_pagetable *pagetabl
kgsl_iommu_default_unmap(pagetable, &md->memdesc);
}
- adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
-
kfree(pt);
}
@@ -1256,25 +1269,6 @@ static int kgsl_iopgtbl_alloc(struct kgsl_iommu_context *ctx, struct kgsl_iommu_
return 0;
}
-/* Enable TTBR0 for the given context with the specific configuration */
-static void kgsl_iommu_enable_ttbr0(struct kgsl_iommu_context *context,
- struct kgsl_iommu_pt *pt)
-{
- struct adreno_smmu_priv *adreno_smmu;
- struct kgsl_mmu *mmu = pt->base.mmu;
-
- /* Quietly return if the context doesn't have a domain */
- if (!context->domain)
- return;
-
- adreno_smmu = dev_get_drvdata(&context->pdev->dev);
-
- /* Enable CX and clocks before we call into SMMU to setup registers */
- kgsl_iommu_enable_clk(mmu);
- adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, &pt->cfg);
- kgsl_iommu_disable_clk(mmu);
-}
-
static struct kgsl_pagetable *kgsl_iommu_default_pagetable(struct kgsl_mmu *mmu)
{
struct kgsl_iommu *iommu = &mmu->iommu;
@@ -1457,11 +1451,21 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
/* First put away the default pagetables */
kgsl_mmu_putpagetable(mmu->defaultpagetable);
- mmu->defaultpagetable = NULL;
kgsl_mmu_putpagetable(mmu->securepagetable);
+
+ /*
+ * Flush the workqueue to ensure pagetables are
+ * destroyed before proceeding further
+ */
+ flush_workqueue(kgsl_driver.workqueue);
+
+ mmu->defaultpagetable = NULL;
mmu->securepagetable = NULL;
+ kgsl_iommu_set_ttbr0(&iommu->lpac_context, mmu, NULL);
+ kgsl_iommu_set_ttbr0(&iommu->user_context, mmu, NULL);
+
/* Next, detach the context banks */
kgsl_iommu_detach_context(&iommu->user_context);
kgsl_iommu_detach_context(&iommu->lpac_context);
@@ -2195,6 +2199,7 @@ static int iommu_probe_user_context(struct kgsl_device *device,
struct kgsl_iommu *iommu = KGSL_IOMMU(device);
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_mmu *mmu = &device->mmu;
+ struct kgsl_iommu_pt *pt;
int ret;
ret = kgsl_iommu_setup_context(mmu, node, &iommu->user_context,
@@ -2236,14 +2241,14 @@ static int iommu_probe_user_context(struct kgsl_device *device,
if (!test_bit(KGSL_MMU_IOPGTABLE, &mmu->features))
return 0;
+ pt = to_iommu_pt(mmu->defaultpagetable);
+
/* Enable TTBR0 on the default and LPAC contexts */
- kgsl_iommu_enable_ttbr0(&iommu->user_context,
- to_iommu_pt(mmu->defaultpagetable));
+ kgsl_iommu_set_ttbr0(&iommu->user_context, mmu, &pt->cfg);
kgsl_set_smmu_aperture(device, &iommu->user_context);
- kgsl_iommu_enable_ttbr0(&iommu->lpac_context,
- to_iommu_pt(mmu->defaultpagetable));
+ kgsl_iommu_set_ttbr0(&iommu->lpac_context, mmu, &pt->cfg);
ret = set_smmu_lpac_aperture(device, &iommu->lpac_context);
/* LPAC is optional, ignore setup failures in absence of LPAC feature */