[Patch v2 1/2] smp: Add helper function to mark possible bad package number

From: Feng Tang
Date: Tue Jun 13 2023 - 01:36:40 EST


For some architecture like x86, it calculates processor package number
in the process of bringing up all CPUs. The 'nr_cpus=' and 'maxcpus='
cmdline parameter setup may reduce the number of CPUs which actually
get brought up, and make the package number inaccurate (less than the
real number).

Add a general helper function arch_mark_bad_package_count() to enable
affected architectures to mark the possible unreliable package
estimation. Also implement the support in x86 to leverage it.

Suggested-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
Signed-off-by: Feng Tang <feng.tang@xxxxxxxxx>
---
arch/x86/kernel/smpboot.c | 9 +++++++++
include/linux/smp.h | 13 +++++++++++++
kernel/smp.c | 10 +++++++++-
3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 352f0ce1ece4..b78770b0c43d 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1274,6 +1274,15 @@ void arch_disable_smp_support(void)
disable_ioapic_support();
}

+void arch_mark_bad_package_count(char *reason)
+{
+ if (package_count_unreliable)
+ return;
+
+ package_count_unreliable = true;
+ pr_warn("Processor package count may be unreliable due to: %s\n", reason);
+}
+
/*
* Fall back to non SMP mode after errors.
*
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 91ea4a67f8ca..25bfdc73cc78 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -188,6 +188,13 @@ static inline int get_boot_cpu_id(void)
return __boot_cpu_id;
}

+extern bool package_count_unreliable;
+
+static inline bool is_package_count_reliable(void)
+{
+ return !package_count_unreliable;
+}
+
#else /* !SMP */

static inline void smp_send_stop(void) { }
@@ -230,6 +237,10 @@ static inline int get_boot_cpu_id(void)
return 0;
}

+static inline bool is_package_count_reliable(void)
+{
+ return true;
+}
#endif /* !SMP */

/**
@@ -283,6 +294,8 @@ extern void arch_disable_smp_support(void);
extern void arch_thaw_secondary_cpus_begin(void);
extern void arch_thaw_secondary_cpus_end(void);

+extern void arch_mark_bad_package_count(char *reason);
+
void smp_setup_processor_id(void);

int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par,
diff --git a/kernel/smp.c b/kernel/smp.c
index ab3e5dad6cfe..494288bedd9b 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -904,13 +904,20 @@ static int __init nosmp(char *str)

early_param("nosmp", nosmp);

+bool package_count_unreliable;
+
+void __weak arch_mark_bad_package_count(char *reason) { }
+
/* this is hard limit */
static int __init nrcpus(char *str)
{
int nr_cpus;

- if (get_option(&str, &nr_cpus) && nr_cpus > 0 && nr_cpus < nr_cpu_ids)
+ if (get_option(&str, &nr_cpus) && nr_cpus > 0 &&
+ nr_cpus < nr_cpu_ids) {
set_nr_cpu_ids(nr_cpus);
+ arch_mark_bad_package_count("'nr_cpus' setup");
+ }

return 0;
}
@@ -923,6 +930,7 @@ static int __init maxcpus(char *str)
if (setup_max_cpus == 0)
arch_disable_smp_support();

+ arch_mark_bad_package_count("'maxcpus' setup");
return 0;
}

--
2.34.1