]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm64/cpuinfo: only show one cpu's info in c_show()
authorYe Bin <yebin10@huawei.com>
Mon, 21 Apr 2025 06:29:47 +0000 (14:29 +0800)
committerWill Deacon <will@kernel.org>
Fri, 9 May 2025 14:30:20 +0000 (15:30 +0100)
Currently, when ARM64 displays CPU information, every call to c_show()
assembles all CPU information. However, as the number of CPUs increases,
this can lead to insufficient buffer space due to excessive assembly in
a single call, causing repeated expansion and multiple calls to c_show().

To prevent this invalid c_show() call, only one CPU's information is
assembled each time c_show() is called.

Signed-off-by: Ye Bin <yebin10@huawei.com>
Link: https://lore.kernel.org/r/20250421062947.4072855-1-yebin@huaweicloud.com
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/kernel/cpuinfo.c

index 285d7d53834205b4eb966de3776a34bef326b930..750864d0165bd3481a5db3eff235d79e65f4282f 100644 (file)
@@ -209,80 +209,79 @@ static const char *const compat_hwcap2_str[] = {
 
 static int c_show(struct seq_file *m, void *v)
 {
-       int i, j;
+       int j;
+       int cpu = m->index;
        bool compat = personality(current->personality) == PER_LINUX32;
+       struct cpuinfo_arm64 *cpuinfo = v;
+       u32 midr = cpuinfo->reg_midr;
 
-       for_each_online_cpu(i) {
-               struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
-               u32 midr = cpuinfo->reg_midr;
-
-               /*
-                * glibc reads /proc/cpuinfo to determine the number of
-                * online processors, looking for lines beginning with
-                * "processor".  Give glibc what it expects.
-                */
-               seq_printf(m, "processor\t: %d\n", i);
-               if (compat)
-                       seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
-                                  MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
+       /*
+        * glibc reads /proc/cpuinfo to determine the number of
+        * online processors, looking for lines beginning with
+        * "processor".  Give glibc what it expects.
+        */
+       seq_printf(m, "processor\t: %d\n", cpu);
+       if (compat)
+               seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+                          MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
 
-               seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
-                          loops_per_jiffy / (500000UL/HZ),
-                          loops_per_jiffy / (5000UL/HZ) % 100);
+       seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+                  loops_per_jiffy / (500000UL/HZ),
+                  loops_per_jiffy / (5000UL/HZ) % 100);
 
-               /*
-                * Dump out the common processor features in a single line.
-                * Userspace should read the hwcaps with getauxval(AT_HWCAP)
-                * rather than attempting to parse this, but there's a body of
-                * software which does already (at least for 32-bit).
-                */
-               seq_puts(m, "Features\t:");
-               if (compat) {
+       /*
+        * Dump out the common processor features in a single line.
+        * Userspace should read the hwcaps with getauxval(AT_HWCAP)
+        * rather than attempting to parse this, but there's a body of
+        * software which does already (at least for 32-bit).
+        */
+       seq_puts(m, "Features\t:");
+       if (compat) {
 #ifdef CONFIG_COMPAT
-                       for (j = 0; j < ARRAY_SIZE(compat_hwcap_str); j++) {
-                               if (compat_elf_hwcap & (1 << j)) {
-                                       /*
-                                        * Warn once if any feature should not
-                                        * have been present on arm64 platform.
-                                        */
-                                       if (WARN_ON_ONCE(!compat_hwcap_str[j]))
-                                               continue;
-
-                                       seq_printf(m, " %s", compat_hwcap_str[j]);
-                               }
+               for (j = 0; j < ARRAY_SIZE(compat_hwcap_str); j++) {
+                       if (compat_elf_hwcap & (1 << j)) {
+                               /*
+                                * Warn once if any feature should not
+                                * have been present on arm64 platform.
+                                */
+                               if (WARN_ON_ONCE(!compat_hwcap_str[j]))
+                                       continue;
+
+                               seq_printf(m, " %s", compat_hwcap_str[j]);
                        }
+               }
 
-                       for (j = 0; j < ARRAY_SIZE(compat_hwcap2_str); j++)
-                               if (compat_elf_hwcap2 & (1 << j))
-                                       seq_printf(m, " %s", compat_hwcap2_str[j]);
+               for (j = 0; j < ARRAY_SIZE(compat_hwcap2_str); j++)
+                       if (compat_elf_hwcap2 & (1 << j))
+                               seq_printf(m, " %s", compat_hwcap2_str[j]);
 #endif /* CONFIG_COMPAT */
-               } else {
-                       for (j = 0; j < ARRAY_SIZE(hwcap_str); j++)
-                               if (cpu_have_feature(j))
-                                       seq_printf(m, " %s", hwcap_str[j]);
-               }
-               seq_puts(m, "\n");
-
-               seq_printf(m, "CPU implementer\t: 0x%02x\n",
-                          MIDR_IMPLEMENTOR(midr));
-               seq_printf(m, "CPU architecture: 8\n");
-               seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
-               seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
-               seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
+       } else {
+               for (j = 0; j < ARRAY_SIZE(hwcap_str); j++)
+                       if (cpu_have_feature(j))
+                               seq_printf(m, " %s", hwcap_str[j]);
        }
+       seq_puts(m, "\n");
+
+       seq_printf(m, "CPU implementer\t: 0x%02x\n",
+                  MIDR_IMPLEMENTOR(midr));
+       seq_puts(m, "CPU architecture: 8\n");
+       seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
+       seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
+       seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
 
        return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-       return *pos < 1 ? (void *)1 : NULL;
+       *pos = cpumask_next(*pos - 1, cpu_online_mask);
+       return *pos < nr_cpu_ids ? &per_cpu(cpu_data, *pos) : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
        ++*pos;
-       return NULL;
+       return c_start(m, pos);
 }
 
 static void c_stop(struct seq_file *m, void *v)