* [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers
@ 2023-11-24 14:24 Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 1/2] " Boris Brezillon
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Boris Brezillon @ 2023-11-24 14:24 UTC (permalink / raw)
To: Joerg Roedel, iommu, Will Deacon, Robin Murphy, linux-arm-kernel
Cc: Rob Clark, Gaurav Kohli, Steven Price, Jason Gunthorpe, kernel,
Boris Brezillon
Hello,
This patchset is an attempt at making page table allocation
customizable. This is useful to some GPU drivers for various reasons:
- speed-up upcoming page table allocations by managing a pool of free
pages
- batch page table allocation instead of allocating one page at a time
- pre-reserve pages for page tables needed for map/unmap operations and
return the unused page tables to some pool
The first and last reasons are particularly important for GPU drivers
wanting to implement asynchronous VM_BIND. Asynchronous VM_BIND requires
that any page table needed for a map/unmap operation to succeed be
allocated at VM_BIND job creation time. At the time of the job creation,
we don't know what the VM will look like when we get to execute the
map/unmap, and can't guess how many page tables we will need. Because
of that, we have to over-provision page tables for the worst case
scenario (page table tree is empty), which means we will allocate/free
a lot. Having pool a pool of free pages is crucial if we want to
speed-up VM_BIND requests.
There might also be other good reasons to want custom allocators, like
fine-grained memory accounting and resource limiting.
Regards,
Boris
Changes in v3:
- Add Robin's R-b
- Cosmetic changes
- Improve the allocator doc
- Stop passing GFP_ZERO to custom allocators
Changes in v2:
- Add Steven's R-b
- Expand on possible use-cases for custom allocators
- Add a caps field to io_pgtable_init_fns
Boris Brezillon (2):
iommu: Allow passing custom allocators to pgtable drivers
iommu: Extend LPAE page table format to support custom allocators
drivers/iommu/io-pgtable-arm.c | 55 ++++++++++++++++++++++++----------
drivers/iommu/io-pgtable.c | 23 ++++++++++++++
include/linux/io-pgtable.h | 34 +++++++++++++++++++++
3 files changed, 96 insertions(+), 16 deletions(-)
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/2] iommu: Allow passing custom allocators to pgtable drivers
2023-11-24 14:24 [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Boris Brezillon
@ 2023-11-24 14:24 ` Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 2/2] iommu: Extend LPAE page table format to support custom allocators Boris Brezillon
2023-11-27 10:10 ` [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Joerg Roedel
2 siblings, 0 replies; 5+ messages in thread
From: Boris Brezillon @ 2023-11-24 14:24 UTC (permalink / raw)
To: Joerg Roedel, iommu, Will Deacon, Robin Murphy, linux-arm-kernel
Cc: Rob Clark, Gaurav Kohli, Steven Price, Jason Gunthorpe, kernel,
Boris Brezillon
This will be useful for GPU drivers who want to keep page tables in a
pool so they can:
- keep freed page tables in a free pool and speed-up upcoming page
table allocations
- batch page table allocation instead of allocating one page at a time
- pre-reserve pages for page tables needed for map/unmap operations,
to ensure map/unmap operations don't try to allocate memory in paths
they're allowed to block or fail
It might also be valuable for other aspects of GPU and similar
use-cases, like fine-grained memory accounting and resource limiting.
We will extend the Arm LPAE format to support custom allocators in a
separate commit.
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
---
v3:
- Add Robin R-b
- Move caps definition around
- Add extra constraints to the ->alloc() callback documentation
v2:
- Add Steven R-b
- Expand on possible use-cases for custom allocators
- Add a caps fields to io_pgtable_init_fns so we can simplify the
check_custom_allocator() logic (Robin Murphy)
---
drivers/iommu/io-pgtable.c | 23 +++++++++++++++++++++++
include/linux/io-pgtable.h | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index b843fcd365d2..8841c1487f00 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -34,6 +34,26 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
#endif
};
+static int check_custom_allocator(enum io_pgtable_fmt fmt,
+ struct io_pgtable_cfg *cfg)
+{
+ /* No custom allocator, no need to check the format. */
+ if (!cfg->alloc && !cfg->free)
+ return 0;
+
+ /* When passing a custom allocator, both the alloc and free
+ * functions should be provided.
+ */
+ if (!cfg->alloc || !cfg->free)
+ return -EINVAL;
+
+ /* Make sure the format supports custom allocators. */
+ if (io_pgtable_init_table[fmt]->caps & IO_PGTABLE_CAP_CUSTOM_ALLOCATOR)
+ return 0;
+
+ return -EINVAL;
+}
+
struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
struct io_pgtable_cfg *cfg,
void *cookie)
@@ -44,6 +64,9 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
if (fmt >= IO_PGTABLE_NUM_FMTS)
return NULL;
+ if (check_custom_allocator(fmt, cfg))
+ return NULL;
+
fns = io_pgtable_init_table[fmt];
if (!fns)
return NULL;
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 25142a0e2fc2..86cf1f7ae389 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -100,6 +100,30 @@ struct io_pgtable_cfg {
const struct iommu_flush_ops *tlb;
struct device *iommu_dev;
+ /**
+ * @alloc: Custom page allocator.
+ *
+ * Optional hook used to allocate page tables. If this function is NULL,
+ * @free must be NULL too.
+ *
+ * Memory returned should be zeroed and suitable for dma_map_single() and
+ * virt_to_phys().
+ *
+ * Not all formats support custom page allocators. Before considering
+ * passing a non-NULL value, make sure the chosen page format supports
+ * this feature.
+ */
+ void *(*alloc)(void *cookie, size_t size, gfp_t gfp);
+
+ /**
+ * @free: Custom page de-allocator.
+ *
+ * Optional hook used to free page tables allocated with the @alloc
+ * hook. Must be non-NULL if @alloc is not NULL, must be NULL
+ * otherwise.
+ */
+ void (*free)(void *cookie, void *pages, size_t size);
+
/* Low-level data specific to the table format */
union {
struct {
@@ -241,16 +265,26 @@ io_pgtable_tlb_add_page(struct io_pgtable *iop,
iop->cfg.tlb->tlb_add_page(gather, iova, granule, iop->cookie);
}
+/**
+ * enum io_pgtable_caps - IO page table backend capabilities.
+ */
+enum io_pgtable_caps {
+ /** @IO_PGTABLE_CAP_CUSTOM_ALLOCATOR: Backend accepts custom page table allocators. */
+ IO_PGTABLE_CAP_CUSTOM_ALLOCATOR = BIT(0),
+};
+
/**
* struct io_pgtable_init_fns - Alloc/free a set of page tables for a
* particular format.
*
* @alloc: Allocate a set of page tables described by cfg.
* @free: Free the page tables associated with iop.
+ * @caps: Combination of @io_pgtable_caps flags encoding the backend capabilities.
*/
struct io_pgtable_init_fns {
struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
void (*free)(struct io_pgtable *iop);
+ u32 caps;
};
extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 2/2] iommu: Extend LPAE page table format to support custom allocators
2023-11-24 14:24 [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 1/2] " Boris Brezillon
@ 2023-11-24 14:24 ` Boris Brezillon
2023-11-27 10:10 ` [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Joerg Roedel
2 siblings, 0 replies; 5+ messages in thread
From: Boris Brezillon @ 2023-11-24 14:24 UTC (permalink / raw)
To: Joerg Roedel, iommu, Will Deacon, Robin Murphy, linux-arm-kernel
Cc: Rob Clark, Gaurav Kohli, Steven Price, Jason Gunthorpe, kernel,
Boris Brezillon
We need that in order to implement the VM_BIND ioctl in the GPU driver
targeting new Mali GPUs.
VM_BIND is about executing MMU map/unmap requests asynchronously,
possibly after waiting for external dependencies encoded as dma_fences.
We intend to use the drm_sched framework to automate the dependency
tracking and VM job dequeuing logic, but this comes with its own set
of constraints, one of them being the fact we are not allowed to
allocate memory in the drm_gpu_scheduler_ops::run_job() to avoid this
sort of deadlocks:
- VM_BIND map job needs to allocate a page table to map some memory
to the VM. No memory available, so kswapd is kicked
- GPU driver shrinker backend ends up waiting on the fence attached to
the VM map job or any other job fence depending on this VM operation.
With custom allocators, we will be able to pre-reserve enough pages to
guarantee the map/unmap operations we queued will take place without
going through the system allocator. But we can also optimize
allocation/reservation by not free-ing pages immediately, so any
upcoming page table allocation requests can be serviced by some free
page table pool kept at the driver level.
I might also be valuable for other aspects of GPU and similar
use-cases, like fine-grained memory accounting and resource limiting.
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
---
v3:
- Don't pass __GFP_ZERO to the custom ->alloc() hook. Returning zeroed
mem is partof the agreement between the io-pgtable and its user
- Add Robin R-b
v2:
- Add Steven R-b
- Expand on possible use-cases for custom allocators
---
drivers/iommu/io-pgtable-arm.c | 55 ++++++++++++++++++++++++----------
1 file changed, 39 insertions(+), 16 deletions(-)
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 72dcdd468cf3..f7828a7aad41 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -188,20 +188,28 @@ static dma_addr_t __arm_lpae_dma_addr(void *pages)
}
static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
- struct io_pgtable_cfg *cfg)
+ struct io_pgtable_cfg *cfg,
+ void *cookie)
{
struct device *dev = cfg->iommu_dev;
int order = get_order(size);
- struct page *p;
dma_addr_t dma;
void *pages;
VM_BUG_ON((gfp & __GFP_HIGHMEM));
- p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
- if (!p)
+
+ if (cfg->alloc) {
+ pages = cfg->alloc(cookie, size, gfp);
+ } else {
+ struct page *p;
+
+ p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
+ pages = p ? page_address(p) : NULL;
+ }
+
+ if (!pages)
return NULL;
- pages = page_address(p);
if (!cfg->coherent_walk) {
dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma))
@@ -220,18 +228,28 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
out_unmap:
dev_err(dev, "Cannot accommodate DMA translation for IOMMU page tables\n");
dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
+
out_free:
- __free_pages(p, order);
+ if (cfg->free)
+ cfg->free(cookie, pages, size);
+ else
+ free_pages((unsigned long)pages, order);
+
return NULL;
}
static void __arm_lpae_free_pages(void *pages, size_t size,
- struct io_pgtable_cfg *cfg)
+ struct io_pgtable_cfg *cfg,
+ void *cookie)
{
if (!cfg->coherent_walk)
dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
size, DMA_TO_DEVICE);
- free_pages((unsigned long)pages, get_order(size));
+
+ if (cfg->free)
+ cfg->free(cookie, pages, size);
+ else
+ free_pages((unsigned long)pages, get_order(size));
}
static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep, int num_entries,
@@ -373,13 +391,13 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
/* Grab a pointer to the next level */
pte = READ_ONCE(*ptep);
if (!pte) {
- cptep = __arm_lpae_alloc_pages(tblsz, gfp, cfg);
+ cptep = __arm_lpae_alloc_pages(tblsz, gfp, cfg, data->iop.cookie);
if (!cptep)
return -ENOMEM;
pte = arm_lpae_install_table(cptep, ptep, 0, data);
if (pte)
- __arm_lpae_free_pages(cptep, tblsz, cfg);
+ __arm_lpae_free_pages(cptep, tblsz, cfg, data->iop.cookie);
} else if (!cfg->coherent_walk && !(pte & ARM_LPAE_PTE_SW_SYNC)) {
__arm_lpae_sync_pte(ptep, 1, cfg);
}
@@ -524,7 +542,7 @@ static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
__arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
}
- __arm_lpae_free_pages(start, table_size, &data->iop.cfg);
+ __arm_lpae_free_pages(start, table_size, &data->iop.cfg, data->iop.cookie);
}
static void arm_lpae_free_pgtable(struct io_pgtable *iop)
@@ -552,7 +570,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS))
return 0;
- tablep = __arm_lpae_alloc_pages(tablesz, GFP_ATOMIC, cfg);
+ tablep = __arm_lpae_alloc_pages(tablesz, GFP_ATOMIC, cfg, data->iop.cookie);
if (!tablep)
return 0; /* Bytes unmapped */
@@ -575,7 +593,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
pte = arm_lpae_install_table(tablep, ptep, blk_pte, data);
if (pte != blk_pte) {
- __arm_lpae_free_pages(tablep, tablesz, cfg);
+ __arm_lpae_free_pages(tablep, tablesz, cfg, data->iop.cookie);
/*
* We may race against someone unmapping another part of this
* block, but anything else is invalid. We can't misinterpret
@@ -882,7 +900,7 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
/* Looking good; allocate a pgd */
data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data),
- GFP_KERNEL, cfg);
+ GFP_KERNEL, cfg, cookie);
if (!data->pgd)
goto out_free_data;
@@ -984,7 +1002,7 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
/* Allocate pgd pages */
data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data),
- GFP_KERNEL, cfg);
+ GFP_KERNEL, cfg, cookie);
if (!data->pgd)
goto out_free_data;
@@ -1059,7 +1077,7 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
<< ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_DEV));
data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data), GFP_KERNEL,
- cfg);
+ cfg, cookie);
if (!data->pgd)
goto out_free_data;
@@ -1080,26 +1098,31 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
}
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
+ .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR,
.alloc = arm_64_lpae_alloc_pgtable_s1,
.free = arm_lpae_free_pgtable,
};
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns = {
+ .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR,
.alloc = arm_64_lpae_alloc_pgtable_s2,
.free = arm_lpae_free_pgtable,
};
struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns = {
+ .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR,
.alloc = arm_32_lpae_alloc_pgtable_s1,
.free = arm_lpae_free_pgtable,
};
struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns = {
+ .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR,
.alloc = arm_32_lpae_alloc_pgtable_s2,
.free = arm_lpae_free_pgtable,
};
struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
+ .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR,
.alloc = arm_mali_lpae_alloc_pgtable,
.free = arm_lpae_free_pgtable,
};
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers
2023-11-24 14:24 [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 1/2] " Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 2/2] iommu: Extend LPAE page table format to support custom allocators Boris Brezillon
@ 2023-11-27 10:10 ` Joerg Roedel
2023-11-27 13:35 ` Gaurav Kohli
2 siblings, 1 reply; 5+ messages in thread
From: Joerg Roedel @ 2023-11-27 10:10 UTC (permalink / raw)
To: Boris Brezillon
Cc: iommu, Will Deacon, Robin Murphy, linux-arm-kernel, Rob Clark,
Gaurav Kohli, Steven Price, Jason Gunthorpe, kernel
On Fri, Nov 24, 2023 at 03:24:32PM +0100, Boris Brezillon wrote:
> Boris Brezillon (2):
> iommu: Allow passing custom allocators to pgtable drivers
> iommu: Extend LPAE page table format to support custom allocators
>
> drivers/iommu/io-pgtable-arm.c | 55 ++++++++++++++++++++++++----------
> drivers/iommu/io-pgtable.c | 23 ++++++++++++++
> include/linux/io-pgtable.h | 34 +++++++++++++++++++++
> 3 files changed, 96 insertions(+), 16 deletions(-)
Applied, thanks.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers
2023-11-27 10:10 ` [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Joerg Roedel
@ 2023-11-27 13:35 ` Gaurav Kohli
0 siblings, 0 replies; 5+ messages in thread
From: Gaurav Kohli @ 2023-11-27 13:35 UTC (permalink / raw)
To: Joerg Roedel, Boris Brezillon
Cc: iommu, Will Deacon, Robin Murphy, linux-arm-kernel, Rob Clark,
Steven Price, Jason Gunthorpe, kernel
On 11/27/2023 3:40 PM, Joerg Roedel wrote:
> On Fri, Nov 24, 2023 at 03:24:32PM +0100, Boris Brezillon wrote:
>> Boris Brezillon (2):
>> iommu: Allow passing custom allocators to pgtable drivers
>> iommu: Extend LPAE page table format to support custom allocators
>>
>> drivers/iommu/io-pgtable-arm.c | 55 ++++++++++++++++++++++++----------
>> drivers/iommu/io-pgtable.c | 23 ++++++++++++++
>> include/linux/io-pgtable.h | 34 +++++++++++++++++++++
>> 3 files changed, 96 insertions(+), 16 deletions(-)
>
> Applied, thanks.
Tested patch v3 also and reviewed also, both looks good , please feel
free to add in case of merging:
Reviewed-by: Gaurav Kohli <quic_gkohli@quicinc.com>
Tested-by: Gaurav Kohli <quic_gkohli@quicinc.com>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-11-27 13:37 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-24 14:24 [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 1/2] " Boris Brezillon
2023-11-24 14:24 ` [PATCH v3 2/2] iommu: Extend LPAE page table format to support custom allocators Boris Brezillon
2023-11-27 10:10 ` [PATCH v3 0/2] iommu: Allow passing custom allocators to pgtable drivers Joerg Roedel
2023-11-27 13:35 ` Gaurav Kohli
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).