[PATCH] dma-contiguous: fix truncation of numa_cma / cma_pernuma sizes >= 2G

Alexander Graf <[email protected]>
Newsgroups dev.linux.lists.iommu,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
numa_cma=0:4G reserves nothing at all. dma_numa_cma_reserve() copies the
requested size into a local int before handing it to
cma_declare_contiguous_nid(), so 0x100000000 truncates to zero and the
loop skips the node silently. Both parameters are documented in
kernel-parameters.txt as nn[MG], so that is the syntax the documentation
invites.

Which bits survive decides what a request turns into: 4G, 8G and 16G
reserve nothing, 2G, 3G and 6G sign-extend into a size the allocator
rejects with a warning, and 5G quietly reserves 1G.

It reaches further than those parameters. On a CMA_SIZE_PERNUMA kernel
with no per-node parameter, dma_numa_cma_reserve() takes the per-node
size from the default area, so a plain cma=4G on a multi-node machine
feeds that size through the same local and loses every per-node area.

numa_cma_size[] and pernuma_size_bytes are both phys_addr_t, so use it
for the local too, and give early_numa_cma() separate variables for the
node id and the size while in there.

Fixes: d5cae2261b86 ("dma-contiguous: simplify numa cma area handling")
Cc: [email protected]
Assisted-by: Kiro:claude-opus-5
Signed-off-by: Alexander Graf <[email protected]>
---
 kernel/dma/contiguous.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index f754079a287d..66093460584e 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -140,21 +140,22 @@ static bool numa_cma_configured __initdata;
 static int __init early_numa_cma(char *p)
 {
 	int nid, count = 0;
-	unsigned long tmp;
+	unsigned long node;
+	phys_addr_t size;
 	char *s = p;
 
 	while (*s) {
-		if (sscanf(s, "%lu%n", &tmp, &count) != 1)
+		if (sscanf(s, "%lu%n", &node, &count) != 1)
 			break;
 
 		if (s[count] == ':') {
-			if (tmp >= MAX_NUMNODES)
+			if (node >= MAX_NUMNODES)
 				break;
-			nid = array_index_nospec(tmp, MAX_NUMNODES);
+			nid = array_index_nospec(node, MAX_NUMNODES);
 
 			s += count + 1;
-			tmp = memparse(s, &s);
-			numa_cma_size[nid] = tmp;
+			size = memparse(s, &s);
+			numa_cma_size[nid] = size;
 
 			if (*s == ',')
 				s++;
@@ -207,9 +208,10 @@ static void __init dma_numa_cma_reserve(void)
 		pernuma_size_bytes = cma_get_size(dma_contiguous_default_area);
 
 	for_each_node(nid) {
-		int size, ret;
+		phys_addr_t size;
 		char name[CMA_MAX_NAME];
 		struct cma **cma;
+		int ret;
 
 		if (!node_online(nid)) {
 			if (pernuma_size_bytes || numa_cma_size[nid])

base-commit: 26260251022fbc2f248a3d747a9b2b961b18d2d8
-- 
2.47.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.