Skip to content

Commit 97e4d77

Browse files
mairacanalpopcornmix
authored andcommitted
drm/v3d: Support Big/Super Pages when writing out PTEs
Commit e4c1772 upstream 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@igalia.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240923141348.2422499-9-mcanal@igalia.com
1 parent 79ac512 commit 97e4d77

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

drivers/gpu/drm/v3d/v3d_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct platform_device;
2020
struct reset_control;
2121

2222
#define V3D_MMU_PAGE_SHIFT 12
23+
#define V3D_PAGE_FACTOR (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT)
2324

2425
#define V3D_MAX_QUEUES (V3D_CPU + 1)
2526

drivers/gpu/drm/v3d/v3d_mmu.c

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,16 @@
2525
* superpage bit set.
2626
*/
2727
#define V3D_PTE_SUPERPAGE BIT(31)
28+
#define V3D_PTE_BIGPAGE BIT(30)
2829
#define V3D_PTE_WRITEABLE BIT(29)
2930
#define V3D_PTE_VALID BIT(28)
3031

32+
static bool v3d_mmu_is_aligned(u32 page, u32 page_address, size_t alignment)
33+
{
34+
return IS_ALIGNED(page, alignment >> V3D_MMU_PAGE_SHIFT) &&
35+
IS_ALIGNED(page_address, alignment >> V3D_MMU_PAGE_SHIFT);
36+
}
37+
3138
int v3d_mmu_flush_all(struct v3d_dev *v3d)
3239
{
3340
int ret;
@@ -78,19 +85,40 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo)
7885
struct drm_gem_shmem_object *shmem_obj = &bo->base;
7986
struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev);
8087
u32 page = bo->node.start;
81-
u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID;
82-
struct sg_dma_page_iter dma_iter;
83-
84-
for_each_sgtable_dma_page(shmem_obj->sgt, &dma_iter, 0) {
85-
dma_addr_t dma_addr = sg_page_iter_dma_address(&dma_iter);
86-
u32 page_address = dma_addr >> V3D_MMU_PAGE_SHIFT;
87-
u32 pte = page_prot | page_address;
88-
u32 i;
89-
90-
BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >=
91-
BIT(24));
92-
for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++)
93-
v3d->pt[page++] = pte + i;
88+
struct scatterlist *sgl;
89+
unsigned int count;
90+
91+
for_each_sgtable_dma_sg(shmem_obj->sgt, sgl, count) {
92+
dma_addr_t dma_addr = sg_dma_address(sgl);
93+
u32 pfn = dma_addr >> V3D_MMU_PAGE_SHIFT;
94+
unsigned int len = sg_dma_len(sgl);
95+
96+
while (len > 0) {
97+
u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID;
98+
u32 page_address = page_prot | pfn;
99+
unsigned int i, page_size;
100+
101+
BUG_ON(pfn + V3D_PAGE_FACTOR >= BIT(24));
102+
103+
if (len >= SZ_1M &&
104+
v3d_mmu_is_aligned(page, page_address, SZ_1M)) {
105+
page_size = SZ_1M;
106+
page_address |= V3D_PTE_SUPERPAGE;
107+
} else if (len >= SZ_64K &&
108+
v3d_mmu_is_aligned(page, page_address, SZ_64K)) {
109+
page_size = SZ_64K;
110+
page_address |= V3D_PTE_BIGPAGE;
111+
} else {
112+
page_size = SZ_4K;
113+
}
114+
115+
for (i = 0; i < page_size >> V3D_MMU_PAGE_SHIFT; i++) {
116+
v3d->pt[page++] = page_address + i;
117+
pfn++;
118+
}
119+
120+
len -= page_size;
121+
}
94122
}
95123

96124
WARN_ON_ONCE(page - bo->node.start !=

0 commit comments

Comments
 (0)