[PATCH v3 6/8] drm/v3d: Support Big/Super Pages when writing out PTEs
Tvrtko Ursulin
tvrtko.ursulin at igalia.com
Mon Apr 22 09:57:10 UTC 2024
On 21/04/2024 22:44, Maíra Canal wrote:
> The V3D MMU also supports 64KB and 1MB pages, called big and super pages,
> respectively. In order to set a 64KB page or 1MB page in the MMU, we need
> to make sure that page table entries for all 4KB pages within a big/super
> page must be correctly configured.
>
> In order to create a big/super page, we need a contiguous memory region.
> That's why we use a separate mountpoint with THP enabled. In order to
> place the page table entries in the MMU, we iterate over the 16 4KB pages
> (for big pages) or 256 4KB pages (for super pages) and insert the PTE.
>
> Signed-off-by: Maíra Canal <mcanal at igalia.com>
> ---
> drivers/gpu/drm/v3d/v3d_drv.h | 1 +
> drivers/gpu/drm/v3d/v3d_mmu.c | 52 ++++++++++++++++++++++++++---------
> 2 files changed, 40 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
> index 17236ee23490..79d8a1a059aa 100644
> --- a/drivers/gpu/drm/v3d/v3d_drv.h
> +++ b/drivers/gpu/drm/v3d/v3d_drv.h
> @@ -18,6 +18,7 @@ struct platform_device;
> struct reset_control;
>
> #define V3D_MMU_PAGE_SHIFT 12
> +#define V3D_PAGE_FACTOR (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT)
>
> #define V3D_MAX_QUEUES (V3D_CPU + 1)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c
> index 14f3af40d6f6..2e0b31e373b2 100644
> --- a/drivers/gpu/drm/v3d/v3d_mmu.c
> +++ b/drivers/gpu/drm/v3d/v3d_mmu.c
> @@ -25,9 +25,16 @@
> * superpage bit set.
> */
> #define V3D_PTE_SUPERPAGE BIT(31)
> +#define V3D_PTE_BIGPAGE BIT(30)
> #define V3D_PTE_WRITEABLE BIT(29)
> #define V3D_PTE_VALID BIT(28)
>
> +static bool v3d_mmu_is_aligned(u32 page, u32 page_address, size_t alignment)
> +{
> + return IS_ALIGNED(page, alignment >> V3D_MMU_PAGE_SHIFT) &&
> + IS_ALIGNED(page_address, alignment >> V3D_MMU_PAGE_SHIFT);
> +}
> +
> static int v3d_mmu_flush_all(struct v3d_dev *v3d)
> {
> int ret;
> @@ -87,19 +94,38 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo)
> struct drm_gem_shmem_object *shmem_obj = &bo->base;
> struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev);
> u32 page = bo->node.start;
> - u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID;
> - struct sg_dma_page_iter dma_iter;
> -
> - for_each_sgtable_dma_page(shmem_obj->sgt, &dma_iter, 0) {
> - dma_addr_t dma_addr = sg_page_iter_dma_address(&dma_iter);
> - u32 page_address = dma_addr >> V3D_MMU_PAGE_SHIFT;
> - u32 pte = page_prot | page_address;
> - u32 i;
> -
> - BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >=
> - BIT(24));
> - for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++)
> - v3d->pt[page++] = pte + i;
> + struct scatterlist *sgl;
> + unsigned int count;
> +
> + for_each_sgtable_dma_sg(shmem_obj->sgt, sgl, count) {
> + dma_addr_t dma_addr = sg_dma_address(sgl);
> + u32 pfn = dma_addr >> V3D_MMU_PAGE_SHIFT;
> + unsigned int len = sg_dma_len(sgl);
> +
> + while (len > 0) {
> + u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID;
> + u32 page_address = page_prot | pfn;
> + unsigned int i, page_size;
> +
> + BUG_ON(pfn + V3D_PAGE_FACTOR >= BIT(24));
> +
> + if (len >= SZ_1M && v3d_mmu_is_aligned(page, page_address, SZ_1M)) {
> + page_size = SZ_1M;
> + page_address |= V3D_PTE_SUPERPAGE;
> + } else if (len >= SZ_64K && v3d_mmu_is_aligned(page, page_address, SZ_64K)) {
> + page_size = SZ_64K;
> + page_address |= V3D_PTE_BIGPAGE;
> + } else {
> + page_size = SZ_4K;
> + }
> +
> + for (i = 0; i < page_size >> V3D_MMU_PAGE_SHIFT; i++) {
> + v3d->pt[page++] = page_address + i;
> + pfn++;
> + }
> +
> + len -= page_size;
> + }
> }
>
> WARN_ON_ONCE(page - bo->node.start !=
It looks correct to me.
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Regards,
Tvrtko
More information about the dri-devel
mailing list