From: Suren Baghdasaryan <surenb@google.com>
To: akpm@linux-foundation.org
Cc: willy@infradead.org, david@redhat.com, vbabka@suse.cz,
lorenzo.stoakes@oracle.com, liam.howlett@oracle.com,
alexandru.elisei@arm.com, peterx@redhat.com, hannes@cmpxchg.org,
mhocko@kernel.org, m.szyprowski@samsung.com,
iamjoonsoo.kim@lge.com, mina86@mina86.com, axboe@kernel.dk,
viro@zeniv.linux.org.uk, brauner@kernel.org, hch@infradead.org,
jack@suse.cz, hbathini@linux.ibm.com, sourabhjain@linux.ibm.com,
ritesh.list@gmail.com, aneesh.kumar@kernel.org,
bhelgaas@google.com, sj@kernel.org, fvdl@google.com,
ziy@nvidia.com, yuzhao@google.com, minchan@kernel.org,
surenb@google.com, linux-mm@kvack.org,
linuxppc-dev@lists.ozlabs.org, linux-block@vger.kernel.org,
linux-fsdevel@vger.kernel.org, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, Minchan Kim <minchan@google.com>
Subject: [RFC 3/3] mm: integrate GCMA with CMA using dt-bindings
Date: Thu, 20 Mar 2025 10:39:31 -0700 [thread overview]
Message-ID: <20250320173931.1583800-4-surenb@google.com> (raw)
In-Reply-To: <20250320173931.1583800-1-surenb@google.com>
This patch introduces a new "guarantee" property for shared-dma-pool.
With this property, admin can create specific memory pool as
GCMA-based CMA if they care about allocation success rate and latency.
The downside of GCMA is that it can host only clean file-backed pages
since it's using cleancache as its secondary user.
Signed-off-by: Minchan Kim <minchan@google.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
---
arch/powerpc/kernel/fadump.c | 2 +-
include/linux/cma.h | 2 +-
kernel/dma/contiguous.c | 11 ++++++++++-
mm/cma.c | 33 ++++++++++++++++++++++++++-------
mm/cma.h | 1 +
mm/cma_sysfs.c | 10 ++++++++++
6 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 4b371c738213..4eb7be0cdcdb 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -111,7 +111,7 @@ void __init fadump_cma_init(void)
return;
}
- rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
+ rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma, false);
if (rc) {
pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc);
/*
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 62d9c1cf6326..3207db979e94 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -46,7 +46,7 @@ extern int __init cma_declare_contiguous_multi(phys_addr_t size,
extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
unsigned int order_per_bit,
const char *name,
- struct cma **res_cma);
+ struct cma **res_cma, bool gcma);
extern struct page *cma_alloc(struct cma *cma, unsigned long count, unsigned int align,
bool no_warn);
extern bool cma_pages_valid(struct cma *cma, const struct page *pages, unsigned long count);
diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index 055da410ac71..a68b3123438c 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -459,6 +459,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
unsigned long node = rmem->fdt_node;
bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
struct cma *cma;
+ bool gcma;
int err;
if (size_cmdline != -1 && default_cma) {
@@ -476,7 +477,15 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
return -EINVAL;
}
- err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma);
+ gcma = !!of_get_flat_dt_prop(node, "guarantee", NULL);
+#ifndef CONFIG_GCMA
+ if (gcma) {
+ pr_err("Reserved memory: unable to setup GCMA region, GCMA is not enabled\n");
+ return -EINVAL;
+ }
+#endif
+ err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name,
+ &cma, gcma);
if (err) {
pr_err("Reserved memory: unable to setup CMA region\n");
return err;
diff --git a/mm/cma.c b/mm/cma.c
index b06d5fe73399..f12cef849e58 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -26,6 +26,7 @@
#include <linux/cma.h>
#include <linux/highmem.h>
#include <linux/io.h>
+#include <linux/gcma.h>
#include <linux/kmemleak.h>
#include <trace/events/cma.h>
@@ -165,11 +166,18 @@ static void __init cma_activate_area(struct cma *cma)
count = cmr->early_pfn - cmr->base_pfn;
bitmap_count = cma_bitmap_pages_to_bits(cma, count);
bitmap_set(cmr->bitmap, 0, bitmap_count);
+ } else {
+ count = 0;
}
- for (pfn = cmr->early_pfn; pfn < cmr->base_pfn + cmr->count;
- pfn += pageblock_nr_pages)
- init_cma_reserved_pageblock(pfn_to_page(pfn));
+ if (cma->gcma) {
+ gcma_register_area(cma->name, cmr->early_pfn,
+ cma->count - count);
+ } else {
+ for (pfn = cmr->early_pfn; pfn < cmr->base_pfn + cmr->count;
+ pfn += pageblock_nr_pages)
+ init_cma_reserved_pageblock(pfn_to_page(pfn));
+ }
}
spin_lock_init(&cma->lock);
@@ -270,7 +278,7 @@ static void __init cma_drop_area(struct cma *cma)
int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
unsigned int order_per_bit,
const char *name,
- struct cma **res_cma)
+ struct cma **res_cma, bool gcma)
{
struct cma *cma;
int ret;
@@ -301,6 +309,7 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
cma->ranges[0].count = cma->count;
cma->nranges = 1;
cma->nid = NUMA_NO_NODE;
+ cma->gcma = gcma;
*res_cma = cma;
@@ -721,7 +730,8 @@ static int __init __cma_declare_contiguous_nid(phys_addr_t base,
base = addr;
}
- ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma);
+ ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma,
+ false);
if (ret)
memblock_phys_free(base, size);
@@ -815,7 +825,13 @@ static int cma_range_alloc(struct cma *cma, struct cma_memrange *cmr,
pfn = cmr->base_pfn + (bitmap_no << cma->order_per_bit);
mutex_lock(&cma->alloc_mutex);
- ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, gfp);
+ if (cma->gcma) {
+ gcma_alloc_range(pfn, count);
+ ret = 0;
+ } else {
+ ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA,
+ gfp);
+ }
mutex_unlock(&cma->alloc_mutex);
if (ret == 0) {
page = pfn_to_page(pfn);
@@ -992,7 +1008,10 @@ bool cma_release(struct cma *cma, const struct page *pages,
if (r == cma->nranges)
return false;
- free_contig_range(pfn, count);
+ if (cma->gcma)
+ gcma_free_range(pfn, count);
+ else
+ free_contig_range(pfn, count);
cma_clear_bitmap(cma, cmr, pfn, count);
cma_sysfs_account_release_pages(cma, count);
trace_cma_release(cma->name, pfn, pages, count);
diff --git a/mm/cma.h b/mm/cma.h
index 41a3ab0ec3de..c2a5576d7987 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -47,6 +47,7 @@ struct cma {
char name[CMA_MAX_NAME];
int nranges;
struct cma_memrange ranges[CMA_MAX_RANGES];
+ bool gcma;
#ifdef CONFIG_CMA_SYSFS
/* the number of CMA page successful allocations */
atomic64_t nr_pages_succeeded;
diff --git a/mm/cma_sysfs.c b/mm/cma_sysfs.c
index 97acd3e5a6a5..4ecc36270a4d 100644
--- a/mm/cma_sysfs.c
+++ b/mm/cma_sysfs.c
@@ -80,6 +80,15 @@ static ssize_t available_pages_show(struct kobject *kobj,
}
CMA_ATTR_RO(available_pages);
+static ssize_t gcma_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct cma *cma = cma_from_kobj(kobj);
+
+ return sysfs_emit(buf, "%d\n", cma->gcma);
+}
+CMA_ATTR_RO(gcma);
+
static void cma_kobj_release(struct kobject *kobj)
{
struct cma *cma = cma_from_kobj(kobj);
@@ -95,6 +104,7 @@ static struct attribute *cma_attrs[] = {
&release_pages_success_attr.attr,
&total_pages_attr.attr,
&available_pages_attr.attr,
+ &gcma_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(cma);
--
2.49.0.rc1.451.g8f38331e32-goog
next prev parent reply other threads:[~2025-03-20 17:39 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-20 17:39 [RFC 0/3] Guaranteed CMA Suren Baghdasaryan
2025-03-20 17:39 ` [RFC 1/3] mm: implement cleancache Suren Baghdasaryan
2025-03-21 5:13 ` Christoph Hellwig
2025-03-21 16:03 ` Suren Baghdasaryan
2025-03-20 17:39 ` [RFC 2/3] mm: introduce GCMA Suren Baghdasaryan
2025-03-21 5:14 ` Christoph Hellwig
2025-03-21 16:13 ` Suren Baghdasaryan
2025-03-20 17:39 ` Suren Baghdasaryan [this message]
2025-03-21 6:12 ` [RFC 3/3] mm: integrate GCMA with CMA using dt-bindings kernel test robot
2025-03-21 6:12 ` kernel test robot
2025-03-21 14:05 ` Conor Dooley
2025-03-21 16:14 ` Suren Baghdasaryan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250320173931.1583800-4-surenb@google.com \
--to=surenb@google.com \
--cc=akpm@linux-foundation.org \
--cc=alexandru.elisei@arm.com \
--cc=aneesh.kumar@kernel.org \
--cc=axboe@kernel.dk \
--cc=bhelgaas@google.com \
--cc=brauner@kernel.org \
--cc=david@redhat.com \
--cc=fvdl@google.com \
--cc=hannes@cmpxchg.org \
--cc=hbathini@linux.ibm.com \
--cc=hch@infradead.org \
--cc=iamjoonsoo.kim@lge.com \
--cc=iommu@lists.linux.dev \
--cc=jack@suse.cz \
--cc=liam.howlett@oracle.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=m.szyprowski@samsung.com \
--cc=mhocko@kernel.org \
--cc=mina86@mina86.com \
--cc=minchan@google.com \
--cc=minchan@kernel.org \
--cc=peterx@redhat.com \
--cc=ritesh.list@gmail.com \
--cc=sj@kernel.org \
--cc=sourabhjain@linux.ibm.com \
--cc=vbabka@suse.cz \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--cc=yuzhao@google.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.