[Freedreno] [PATCH 6/6] drm/msm/a6xx: Add support for per-instance pagetables

Rob Clark robdclark at gmail.com
Fri Jun 12 03:22:29 UTC 2020


On Thu, Jun 11, 2020 at 3:29 PM Jordan Crouse <jcrouse at codeaurora.org> wrote:
>
> Add support for using per-instance pagetables if all the dependencies are
> available.
>
> Signed-off-by: Jordan Crouse <jcrouse at codeaurora.org>
> ---
>
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 69 ++++++++++++++++++++++++++-
>  drivers/gpu/drm/msm/msm_ringbuffer.h  |  1 +
>  2 files changed, 69 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index a1589e040c57..5e82b85d4d55 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -79,6 +79,58 @@ static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter,
>         OUT_RING(ring, upper_32_bits(iova));
>  }
>
> +static void a6xx_set_pagetable(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
> +               struct msm_file_private *ctx)
> +{
> +       phys_addr_t ttbr;
> +       u32 asid;
> +
> +       if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
> +               return;
> +
> +       OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
> +       OUT_RING(ring, 0);
> +
> +       /* Turn on APIV mode to access critical regions */
> +       OUT_PKT4(ring, REG_A6XX_CP_MISC_CNTL, 1);
> +       OUT_RING(ring, 1);
> +
> +       /* Make sure the ME is synchronized before staring the update */
> +       OUT_PKT7(ring, CP_WAIT_FOR_ME, 0);
> +
> +       /* Execute the table update */
> +       OUT_PKT7(ring, CP_SMMU_TABLE_UPDATE, 4);
> +       OUT_RING(ring, lower_32_bits(ttbr));
> +       OUT_RING(ring, (((u64) asid) << 48) | upper_32_bits(ttbr));
> +       /* CONTEXTIDR is currently unused */
> +       OUT_RING(ring, 0);
> +       /* CONTEXTBANK is currently unused */
> +       OUT_RING(ring, 0);

I can add this to xml (on userspace side, we've been describing packet
payload in xml and using the generated builders), and update generated
headers, if you agree to not add more open-coded pkt7 building ;-)

> +
> +       /*
> +        * Write the new TTBR0 to the memstore. This is good for debugging.
> +        */
> +       OUT_PKT7(ring, CP_MEM_WRITE, 4);
> +       OUT_RING(ring, lower_32_bits(rbmemptr(ring, ttbr0)));
> +       OUT_RING(ring, upper_32_bits(rbmemptr(ring, ttbr0)));
> +       OUT_RING(ring, lower_32_bits(ttbr));
> +       OUT_RING(ring, (((u64) asid) << 48) | upper_32_bits(ttbr));
> +
> +       /* Invalidate the draw state so we start off fresh */
> +       OUT_PKT7(ring, CP_SET_DRAW_STATE, 3);
> +       OUT_RING(ring, 0x40000);
> +       OUT_RING(ring, 1);
> +       OUT_RING(ring, 0);

Ie, this would look like:

    OUT_PKT7(ring, CP_SET_DRAW_STATE, 3);
    OUT_RING(ring, CP_SET_DRAW_STATE__0_COUNT(0) |
            CP_SET_DRAW_STATE__0_DISABLE_ALL_GROUPS |
            CP_SET_DRAW_STATE__0_GROUP_ID(0));
    OUT_RING(ring, CP_SET_DRAW_STATE__1_ADDR_LO(1));
    OUT_RING(ring, CP_SET_DRAW_STATE__2_ADDR_HI(0));

.. but written that way, I think you meant ADDR_LO to be zero?

(it is possible we need to regen headers for that to work, the kernel
headers are somewhat out of date by now)

BR,
-R

> +
> +       /* Turn off APRIV */
> +       OUT_PKT4(ring, REG_A6XX_CP_MISC_CNTL, 1);
> +       OUT_RING(ring, 0);
> +
> +       /* Turn off protected mode */
> +       OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
> +       OUT_RING(ring, 1);
> +}
> +
>  static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
>         struct msm_file_private *ctx)
>  {
> @@ -89,6 +141,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
>         struct msm_ringbuffer *ring = submit->ring;
>         unsigned int i;
>
> +       a6xx_set_pagetable(gpu, ring, ctx);
> +
>         get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP_0_LO,
>                 rbmemptr_stats(ring, index, cpcycles_start));
>
> @@ -872,6 +926,18 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
>         return (unsigned long)busy_time;
>  }
>
> +struct msm_gem_address_space *a6xx_address_space_instance(struct msm_gpu *gpu)
> +{
> +       struct msm_mmu *mmu;
> +
> +       mmu = msm_iommu_pagetable_create(gpu->aspace->mmu);
> +       if (IS_ERR(mmu))
> +               return msm_gem_address_space_get(gpu->aspace);
> +
> +       return msm_gem_address_space_create(mmu,
> +               "gpu", 0x100000000ULL, 0x1ffffffffULL);
> +}
> +
>  static const struct adreno_gpu_funcs funcs = {
>         .base = {
>                 .get_param = adreno_get_param,
> @@ -893,8 +959,9 @@ static const struct adreno_gpu_funcs funcs = {
>  #if defined(CONFIG_DRM_MSM_GPU_STATE)
>                 .gpu_state_get = a6xx_gpu_state_get,
>                 .gpu_state_put = a6xx_gpu_state_put,
> -               .create_address_space = adreno_iommu_create_address_space,
>  #endif
> +               .create_address_space = adreno_iommu_create_address_space,
> +               .address_space_instance = a6xx_address_space_instance,
>         },
>         .get_timestamp = a6xx_get_timestamp,
>  };
> diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h
> index 7764373d0ed2..0987d6bf848c 100644
> --- a/drivers/gpu/drm/msm/msm_ringbuffer.h
> +++ b/drivers/gpu/drm/msm/msm_ringbuffer.h
> @@ -31,6 +31,7 @@ struct msm_rbmemptrs {
>         volatile uint32_t fence;
>
>         volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT];
> +       volatile u64 ttbr0;
>  };
>
>  struct msm_ringbuffer {
> --
> 2.17.1
>


More information about the Freedreno mailing list