LoongArch: Support mem=<size> kernel parameter
authorMing Wang <wangming01@loongson.cn>
Sun, 3 Aug 2025 14:49:47 +0000 (22:49 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Sun, 3 Aug 2025 14:49:47 +0000 (22:49 +0800)
The LoongArch mem= parameter parser was previously limited to the
mem=<size>@<start> format. This was inconvenient for the common use
case of simply capping the total system memory, as it forced users to
manually specify a start address. It was also inconsistent with the
behavior on other architectures.

This patch enhances the parser in early_parse_mem() to also support the
more user-friendly mem=<size> format. The implementation now checks for
the presence of the '@' symbol to determine the user's intent:

- If mem=<size> is provided (no '@'), the kernel now calls
  memblock_enforce_memory_limit(). This trims memory from the top down
  to the specified size.
- If mem=<size>@<start> is provided, the original behavior is retained
  for backward compatibility. This allows for defining specific memory
  banks.

This change introduces an important usage rule reflected in the code's
comments: the mem=<size> format should only be specified once on the
kernel command line. It acts as a single, global cap on total memory. In
contrast, the mem=<size>@<start> format can be specified multiple times
to define several distinct memory regions.

Signed-off-by: Ming Wang <wangming01@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/kernel/setup.c

index b99fbb388fe03ca09fb81b2f7ec97476eaa5d7d9..b0be564823689f55efb528a7683997c3236ba1b7 100644 (file)
@@ -191,6 +191,16 @@ static int __init early_parse_mem(char *p)
                return -EINVAL;
        }
 
+       start = 0;
+       size = memparse(p, &p);
+       if (*p == '@')  /* Every mem=... should contain '@' */
+               start = memparse(p + 1, &p);
+       else {          /* Only one mem=... is allowed if no '@' */
+               usermem = 1;
+               memblock_enforce_memory_limit(size);
+               return 0;
+       }
+
        /*
         * If a user specifies memory size, we
         * blow away any automatically generated
@@ -201,14 +211,6 @@ static int __init early_parse_mem(char *p)
                memblock_remove(memblock_start_of_DRAM(),
                        memblock_end_of_DRAM() - memblock_start_of_DRAM());
        }
-       start = 0;
-       size = memparse(p, &p);
-       if (*p == '@')
-               start = memparse(p + 1, &p);
-       else {
-               pr_err("Invalid format!\n");
-               return -EINVAL;
-       }
 
        if (!IS_ENABLED(CONFIG_NUMA))
                memblock_add(start, size);