[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:59:30 UTC 2024


On 22/04/2024 10:57, Tvrtko Ursulin wrote:
> 
> 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>

Ooops muscle memory strikes again! I guess reviewing patches for 10+ 
years can do that.. :)

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at igalia.com>

Regards,

Tvrtko


More information about the dri-devel mailing list