diff mbox series

[v2,1/5] x86/topology: Export helper to get CPU number from APIC ID

Message ID 20240624212008.663832-2-yazen.ghannam@amd.com (mailing list archive)
State New
Headers show
Series Rework mce_setup() | expand

Commit Message

Yazen Ghannam June 24, 2024, 9:20 p.m. UTC
The need to look up a CPU number from an APIC ID is done in at least one
other place outside of APIC/topology code: apei_smca_report_x86_error().

With the recent topology rework, there is now a helper function to do
just this task.

Export the helper so other code can use it. Also, update the name to
match other exported topology_* helpers.

Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
---
Link:
https://lkml.kernel.org/r/20240618172447.GA1387@yaz-khff2.amd.com

v1->v2:
* New in v2.

 arch/x86/include/asm/topology.h |  6 ++++++
 arch/x86/kernel/cpu/topology.c  | 15 ++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

Comments

Thomas Gleixner June 25, 2024, 6:50 a.m. UTC | #1
On Mon, Jun 24 2024 at 16:20, Yazen Ghannam wrote:

> The need to look up a CPU number from an APIC ID is done in at least one
> other place outside of APIC/topology code:
> apei_smca_report_x86_error().

The need .... is done?

>  #ifdef CONFIG_X86_LOCAL_APIC
>  int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level);
> +int topology_get_cpunr(u32 apic_id);
>  #else
>  static inline int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level)
>  {
>  	return 0;
>  }
> +
> +static inline int topology_get_cpunr(u32 apic_id)
> +{
> +	return -ENODEV;

Why ENODEV and not 0?

> +}
>  #endif

Thanks,

        tglx
Yazen Ghannam June 26, 2024, 1:42 a.m. UTC | #2
On Tue, Jun 25, 2024 at 08:50:13AM +0200, Thomas Gleixner wrote:
> On Mon, Jun 24 2024 at 16:20, Yazen Ghannam wrote:
> 
> > The need to look up a CPU number from an APIC ID is done in at least one
> > other place outside of APIC/topology code:
> > apei_smca_report_x86_error().
> 
> The need .... is done?

Hmm, yeah the wording isn't clear. I'll rephrase it.

> 
> >  #ifdef CONFIG_X86_LOCAL_APIC
> >  int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level);
> > +int topology_get_cpunr(u32 apic_id);
> >  #else
> >  static inline int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level)
> >  {
> >  	return 0;
> >  }
> > +
> > +static inline int topology_get_cpunr(u32 apic_id)
> > +{
> > +	return -ENODEV;
> 
> Why ENODEV and not 0?
>

Since '0' is a valid CPU number, my first thought was that we should
return an error code if we can't explicitly find the correct CPU number.

But would/could we have SMP support without X86_LOCAL_APIC? If not, then
we'd only have CPU 0 in any case. Is this why the function above returns
0?

I can make the change to return 0 here also. But...

The MCE code depends on X86_LOCAL_APIC, and it is the only external
user. So should I drop the config check and export?

Thanks,
Yazen
Borislav Petkov June 28, 2024, 8:37 a.m. UTC | #3
On Tue, Jun 25, 2024 at 09:42:12PM -0400, Yazen Ghannam wrote:
> But would/could we have SMP support without X86_LOCAL_APIC?

Look at how X86_LOCAL_APIC is defined in Kconfig.
Yazen Ghannam June 28, 2024, 2:15 p.m. UTC | #4
On Fri, Jun 28, 2024 at 10:37:22AM +0200, Borislav Petkov wrote:
> On Tue, Jun 25, 2024 at 09:42:12PM -0400, Yazen Ghannam wrote:
> > But would/could we have SMP support without X86_LOCAL_APIC?
> 
> Look at how X86_LOCAL_APIC is defined in Kconfig.
>

Thanks for the tip. It looks to me that SMP and X86_LOCAL_APIC are
generally independent.

Thanks,
Yazen
Borislav Petkov June 28, 2024, 2:45 p.m. UTC | #5
On Fri, Jun 28, 2024 at 10:15:42AM -0400, Yazen Ghannam wrote:
> Thanks for the tip. It looks to me that SMP and X86_LOCAL_APIC are
> generally independent.

They are?

config X86_LOCAL_APIC
        def_bool y
        depends on X86_64 || SMP
	^^^^^^^		     ^^^
Yazen Ghannam July 1, 2024, 5:51 p.m. UTC | #6
On Fri, Jun 28, 2024 at 04:45:35PM +0200, Borislav Petkov wrote:
> On Fri, Jun 28, 2024 at 10:15:42AM -0400, Yazen Ghannam wrote:
> > Thanks for the tip. It looks to me that SMP and X86_LOCAL_APIC are
> > generally independent.
> 
> They are?
> 
> config X86_LOCAL_APIC
>         def_bool y
>         depends on X86_64 || SMP
> 	^^^^^^^		     ^^^
>

Right, SMP does not depend on X86_LOCAL_APIC. Otherwise, there would be
a circular dependency here.

X86_LOCAL_APIC depends on the logical OR of a bunch of options. So it
depends on "any one" of the options to be enabled. But it doesn't need
all of them.

config UP_LATE_INIT
        def_bool y
        depends on !SMP && X86_LOCAL_APIC
	           ^^^^^^^^^^^^

This shows that X86_LOCAL_APIC doesn't have a hard dependency on SMP.
Otherwise, this option would never work.

Thanks,
Yazen
Borislav Petkov July 1, 2024, 7:07 p.m. UTC | #7
On Mon, Jul 01, 2024 at 01:51:42PM -0400, Yazen Ghannam wrote:
> X86_LOCAL_APIC depends on the logical OR of a bunch of options. So it
> depends on "any one" of the options to be enabled. But it doesn't need
> all of them.

Yes, I can see that.

How does any of that info answer your initial question?

IOW, if you don't have LAPIC support in the kernel, what CPU number should we
return for any APIC ID serving as input, and why?
Yazen Ghannam July 12, 2024, 2:28 p.m. UTC | #8
On Mon, Jul 01, 2024 at 09:07:04PM +0200, Borislav Petkov wrote:
> On Mon, Jul 01, 2024 at 01:51:42PM -0400, Yazen Ghannam wrote:
> > X86_LOCAL_APIC depends on the logical OR of a bunch of options. So it
> > depends on "any one" of the options to be enabled. But it doesn't need
> > all of them.
> 
> Yes, I can see that.
> 
> How does any of that info answer your initial question?
> 
> IOW, if you don't have LAPIC support in the kernel, what CPU number should we
> return for any APIC ID serving as input, and why?
>

I still think it should return an error code, because theoretically
LAPIC can be disabled and SMP can be enabled.

But I spent some time trying to see if this would work in practice, and
it looks like you can't disable X86_LOCAL_APIC without hitting a bunch
of build errors on x86_64. It seems like a lot of common APIC and SMP
code implicitly depends on X86_LOCAL_APIC. This was true even for a tiny
config. However, this worked for an i386 build (with SMP=n).

I think the most practical option is to keep the local search routine in
mce/apei. I don't think all the additional complexity is worth it for a
simple for-loop.

Regarding the X86_LOCAL_APIC=n build issues, should these be
investigated?

Thanks,
Yazen
diff mbox series

Patch

diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index abe3a8f22cbd..d8c3c3c818bc 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -171,11 +171,17 @@  static inline unsigned int topology_num_threads_per_package(void)
 
 #ifdef CONFIG_X86_LOCAL_APIC
 int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level);
+int topology_get_cpunr(u32 apic_id);
 #else
 static inline int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level)
 {
 	return 0;
 }
+
+static inline int topology_get_cpunr(u32 apic_id)
+{
+	return -ENODEV;
+}
 #endif
 
 #ifdef CONFIG_SMP
diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
index 621a151ccf7d..fc74578ee3bd 100644
--- a/arch/x86/kernel/cpu/topology.c
+++ b/arch/x86/kernel/cpu/topology.c
@@ -95,7 +95,15 @@  static inline u32 topo_apicid(u32 apicid, enum x86_topology_domains dom)
 	return apicid & (UINT_MAX << x86_topo_system.dom_shifts[dom - 1]);
 }
 
-static int topo_lookup_cpuid(u32 apic_id)
+/**
+ * topology_get_cpunr - Retrieve the CPU number for the given APIC ID
+ * @apic_id:		The APIC ID for which to lookup the CPU number
+ *
+ * Returns:
+ *  - >= 0:	The CPU number for the given APIC ID
+ *  - -ENODEV:	@apic_id does not match any known CPU
+ */
+int topology_get_cpunr(u32 apic_id)
 {
 	int i;
 
@@ -106,10 +114,11 @@  static int topo_lookup_cpuid(u32 apic_id)
 	}
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(topology_get_cpunr);
 
 static __init int topo_get_cpunr(u32 apic_id)
 {
-	int cpu = topo_lookup_cpuid(apic_id);
+	int cpu = topology_get_cpunr(apic_id);
 
 	if (cpu >= 0)
 		return cpu;
@@ -388,7 +397,7 @@  int topology_hotplug_apic(u32 apic_id, u32 acpi_id)
 	if (!test_bit(apic_id, apic_maps[TOPO_SMT_DOMAIN].map))
 		return -ENODEV;
 
-	cpu = topo_lookup_cpuid(apic_id);
+	cpu = topology_get_cpunr(apic_id);
 	if (cpu < 0)
 		return -ENOSPC;