blob: b2b50c78bf62f2c90da8507cc2426645d508f3f7 [file] [log] [blame] [edit]
From 0e4c1a4392bcf58bac954c023ba9b2da48bc0dbe Mon Sep 17 00:00:00 2001
From: Raffaele Aquilone <raffaele.aquilone@arm.com>
Date: Wed, 27 Mar 2024 16:59:34 +0000
Subject: [PATCH] GPUCORE-41547 Improve handling of page metadata after migration
Handling of page metadata after migration in kbase_mmu_migrate_page()
has been made slightly safer. Only if the page is still in the
ALLOCATED_MAPPED state is it safe to access and update the
metadata. There's no problem if the page became NOT_MOVABLE.
It is an error, instead, if the page has changed to any other
state.
The kbase_set_phy_alloc_page_status() helper must be called
while keeping the region lock to prevent race conditions where
the pages of a GPU VA region could be set to NOT_MOVABLE
while a page migration is in progress.
TI2: 1151297 (page migration tests, ps 7)
TI2: 1151300 (DDK precommit, ps 7)
Change-Id: I062431075fcd29fcd13e65acd779ab03315f51d0
---
diff --git a/product/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c b/product/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c
index a0d9789..5a5a4c3 100644
--- a/product/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c
+++ b/product/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c
@@ -351,13 +351,14 @@
}
remove_external_chunk_mappings(kctx, chunk);
- kbase_gpu_vm_unlock(kctx);
/* If page migration is enabled, we don't want to migrate tiler heap pages.
* This does not change if the constituent pages are already marked as isolated.
*/
if (kbase_is_page_migration_enabled())
- kbase_set_phy_alloc_page_status(chunk->region->gpu_alloc, NOT_MOVABLE);
+ kbase_set_phy_alloc_page_status(kctx, chunk->region->gpu_alloc, NOT_MOVABLE);
+
+ kbase_gpu_vm_unlock(kctx);
return chunk;
@@ -738,7 +739,7 @@
KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING);
if (kbase_is_page_migration_enabled())
- kbase_set_phy_alloc_page_status(buf_desc_reg->gpu_alloc, NOT_MOVABLE);
+ kbase_set_phy_alloc_page_status(kctx, buf_desc_reg->gpu_alloc, NOT_MOVABLE);
kbase_gpu_vm_unlock(kctx);
diff --git a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c
index 1a0b9fa..76886ea 100644
--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c
+++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c
@@ -2027,11 +2027,13 @@
}
KBASE_EXPORT_TEST_API(kbase_alloc_phy_pages);
-void kbase_set_phy_alloc_page_status(struct kbase_mem_phy_alloc *alloc,
+void kbase_set_phy_alloc_page_status(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc,
enum kbase_page_status status)
{
u32 i = 0;
+ lockdep_assert_held(&kctx->reg_lock);
+
for (; i < alloc->nents; i++) {
struct tagged_addr phys = alloc->pages[i];
struct kbase_page_metadata *page_md = kbase_page_private(as_page(phys));
@@ -3293,7 +3295,8 @@
if (kbase_is_page_migration_enabled()) {
kbase_gpu_vm_lock(kctx);
mutex_lock(&kctx->jit_evict_lock);
- kbase_set_phy_alloc_page_status(reg->gpu_alloc, ALLOCATED_MAPPED);
+ kbase_set_phy_alloc_page_status(kctx, reg->gpu_alloc,
+ ALLOCATED_MAPPED);
mutex_unlock(&kctx->jit_evict_lock);
kbase_gpu_vm_unlock(kctx);
}
@@ -3443,9 +3446,18 @@
kbase_mem_evictable_mark_reclaim(reg->gpu_alloc);
kbase_gpu_vm_lock(kctx);
+
reg->flags |= KBASE_REG_DONT_NEED;
reg->flags &= ~KBASE_REG_ACTIVE_JIT_ALLOC;
kbase_mem_shrink_cpu_mapping(kctx, reg, 0, reg->gpu_alloc->nents);
+
+ /* Inactive JIT regions should be freed by the shrinker and not impacted
+ * by page migration. Once freed, they will enter into the page migration
+ * state machine via the mempools.
+ */
+ if (kbase_is_page_migration_enabled())
+ kbase_set_phy_alloc_page_status(kctx, reg->gpu_alloc, NOT_MOVABLE);
+
kbase_gpu_vm_unlock(kctx);
/*
@@ -3461,12 +3473,6 @@
list_move(&reg->jit_node, &kctx->jit_pool_head);
- /* Inactive JIT regions should be freed by the shrinker and not impacted
- * by page migration. Once freed, they will enter into the page migration
- * state machine via the mempools.
- */
- if (kbase_is_page_migration_enabled())
- kbase_set_phy_alloc_page_status(reg->gpu_alloc, NOT_MOVABLE);
mutex_unlock(&kctx->jit_evict_lock);
}
diff --git a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
index 59b6ddc0..e35f47e 100644
--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
+++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
@@ -530,6 +530,7 @@
/**
* kbase_set_phy_alloc_page_status - Set the page migration status of the underlying
* physical allocation.
+ * @kctx: Pointer to Kbase context.
* @alloc: the physical allocation containing the pages whose metadata is going
* to be modified
* @status: the status the pages should end up in
@@ -538,7 +539,7 @@
* proper states are set. Instead, it is only used when we change the allocation
* to NOT_MOVABLE or from NOT_MOVABLE to ALLOCATED_MAPPED
*/
-void kbase_set_phy_alloc_page_status(struct kbase_mem_phy_alloc *alloc,
+void kbase_set_phy_alloc_page_status(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc,
enum kbase_page_status status);
static inline void kbase_mem_phy_alloc_gpu_mapped(struct kbase_mem_phy_alloc *alloc)
diff --git a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
index 70b7163..925bc1d 100644
--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
+++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
@@ -885,7 +885,7 @@
/* Indicate to page migration that the memory can be reclaimed by the shrinker.
*/
if (kbase_is_page_migration_enabled())
- kbase_set_phy_alloc_page_status(gpu_alloc, NOT_MOVABLE);
+ kbase_set_phy_alloc_page_status(kctx, gpu_alloc, NOT_MOVABLE);
mutex_unlock(&kctx->jit_evict_lock);
kbase_mem_evictable_mark_reclaim(gpu_alloc);
@@ -943,7 +943,7 @@
* from.
*/
if (kbase_is_page_migration_enabled())
- kbase_set_phy_alloc_page_status(gpu_alloc, ALLOCATED_MAPPED);
+ kbase_set_phy_alloc_page_status(kctx, gpu_alloc, ALLOCATED_MAPPED);
}
}
diff --git a/product/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c b/product/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c
index c6f96a81..ab0d85b 100644
--- a/product/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c
+++ b/product/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c
@@ -4003,13 +4003,24 @@
/* Undertaking metadata transfer, while we are holding the mmu_lock */
spin_lock(&page_md->migrate_lock);
if (level == MIDGARD_MMU_BOTTOMLEVEL) {
- size_t page_array_index = (page_md->data.mapped.vpfn / GPU_PAGES_PER_CPU_PAGE) -
- page_md->data.mapped.reg->start_pfn;
+ enum kbase_page_status page_status = PAGE_STATUS_GET(page_md->status);
- WARN_ON(PAGE_STATUS_GET(page_md->status) != ALLOCATED_MAPPED);
+ if (page_status == ALLOCATED_MAPPED) {
+ /* Replace page in array of pages of the physical allocation. */
+ size_t page_array_index =
+ div_u64(page_md->data.mapped.vpfn, GPU_PAGES_PER_CPU_PAGE) -
+ page_md->data.mapped.reg->start_pfn;
- /* Replace page in array of pages of the physical allocation. */
- page_md->data.mapped.reg->gpu_alloc->pages[page_array_index] = new_phys;
+ page_md->data.mapped.reg->gpu_alloc->pages[page_array_index] = new_phys;
+ } else if (page_status == NOT_MOVABLE) {
+ dev_dbg(kbdev->dev,
+ "%s: migration completed and page has become NOT_MOVABLE.",
+ __func__);
+ } else {
+ dev_WARN(kbdev->dev,
+ "%s: migration completed but page has moved to status %d.",
+ __func__, page_status);
+ }
}
/* Update the new page dma_addr with the transferred metadata from the old_page */
page_md->dma_addr = new_dma_addr;