History

Merge tag 'x86-urgent-2026-03-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar: - Fix SEV guest boot failures in certain circumstances, due to very early code relying on a BSS-zeroed variable that isn't actually zeroed yet an may contain non-zero bootup values Move the variable into the .data section go gain even earlier zeroing - Expose & allow the IBPB-on-Entry feature on SNP guests, which was not properly exposed to guests due to initial implementational caution - Fix O= build failure when CONFIG_EFI_SBAT_FILE is using relative file paths - Fix the various SNC (Sub-NUMA Clustering) topology enumeration bugs/artifacts (sched-domain build errors mostly). SNC enumeration data got more complicated with Granite Rapids X (GNR) and Clearwater Forest X (CWF), which exposed these bugs and made their effects more serious - Also use the now sane(r) SNC code to fix resctrl SNC detection bugs - Work around a historic libgcc unwinder bug in the vdso32 sigreturn code (again), which regressed during an overly aggressive recent cleanup of DWARF annotations * tag 'x86-urgent-2026-03-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/entry/vdso32: Work around libgcc unwinder bug x86/resctrl: Fix SNC detection x86/topo: Fix SNC topology mess x86/topo: Replace x86_has_numa_in_package x86/topo: Add topology_num_nodes_per_package() x86/numa: Store extra copy of numa_nodes_parsed x86/boot: Handle relative CONFIG_EFI_SBAT_FILE file paths x86/sev: Allow IBPB-on-Entry feature for SNP guests x86/boot/sev: Move SEV decompressor variables into the .data section

Linus Torvalds committed 8 months ago

Commit c23719a2 parents 6ff1020 b5ef09a14 files · +228 −95Browse files

Unified · Split

14 files
  1. arch/x86/boot/compressed/Makefile +1 −0
  2. arch/x86/boot/compressed/sev.c +5 −4
  3. arch/x86/boot/startup/sev-shared.c +1 −1
  4. arch/x86/coco/sev/core.c +1 −0
  5. arch/x86/entry/vdso/vdso32/sigreturn.S +30 −0
  6. arch/x86/include/asm/msr-index.h +4 −1
  7. arch/x86/include/asm/numa.h +6 −0
  8. arch/x86/include/asm/topology.h +6 −0
  9. arch/x86/kernel/cpu/common.c +3 −0
  10. arch/x86/kernel/cpu/resctrl/monitor.c +5 −31
  11. arch/x86/kernel/cpu/topology.c +11 −2
  12. arch/x86/kernel/smpboot.c +145 −56
  13. arch/x86/mm/numa.c +8 −0
  14. arch/x86/mm/srat.c +2 −0
arch/x86/boot/compressed/Makefile+1−0
@@ -113,6 +113,7 @@ vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o · 112 unmodified lines
113113
114114 ifdef CONFIG_EFI_SBAT
115115 $(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE)
116+AFLAGS_sbat.o += -I $(srctree)
116117 endif
117118
118119 $(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
arch/x86/boot/compressed/sev.c+5−4
@@ -28,17 +28,17 @@ · 27 unmodified lines
2828 #include "sev.h"
2929
3030 static struct ghcb boot_ghcb_page __aligned(PAGE_SIZE);
31−struct ghcb *boot_ghcb;
31+struct ghcb *boot_ghcb __section(".data");
3232
3333 #undef __init
3434 #define __init
3535
3636 #define __BOOT_COMPRESSED
3737
38−u8 snp_vmpl;
39−u16 ghcb_version;
38+u8 snp_vmpl __section(".data");
39+u16 ghcb_version __section(".data");
4040
41−u64 boot_svsm_caa_pa;
41+u64 boot_svsm_caa_pa __section(".data");
4242
4343 /* Include code for early handlers */
4444 #include "../../boot/startup/sev-shared.c"
@@ -188,6 +188,7 @@ bool sev_es_check_ghcb_fault(unsigned long address) · 143 unmodified lines
188188 MSR_AMD64_SNP_RESERVED_BIT13 | \
189189 MSR_AMD64_SNP_RESERVED_BIT15 | \
190190 MSR_AMD64_SNP_SECURE_AVIC | \
191+ MSR_AMD64_SNP_RESERVED_BITS19_22 | \
191192 MSR_AMD64_SNP_RESERVED_MASK)
192193
193194 #ifdef CONFIG_AMD_SECURE_AVIC
arch/x86/boot/startup/sev-shared.c+1−1
@@ -31,7 +31,7 @@ static u32 cpuid_std_range_max __ro_after_init; · 30 unmodified lines
3131 static u32 cpuid_hyp_range_max __ro_after_init;
3232 static u32 cpuid_ext_range_max __ro_after_init;
3333
34−bool sev_snp_needs_sfw;
34+bool sev_snp_needs_sfw __section(".data");
3535
3636 void __noreturn
3737 sev_es_terminate(unsigned int set, unsigned int reason)
arch/x86/coco/sev/core.c+1−0
@@ -89,6 +89,7 @@ static const char * const sev_status_feat_names[] = { · 88 unmodified lines
8989 [MSR_AMD64_SNP_VMSA_REG_PROT_BIT] = "VMSARegProt",
9090 [MSR_AMD64_SNP_SMT_PROT_BIT] = "SMTProt",
9191 [MSR_AMD64_SNP_SECURE_AVIC_BIT] = "SecureAVIC",
92+ [MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT] = "IBPBOnEntry",
9293 };
9394
9495 /*
arch/x86/entry/vdso/vdso32/sigreturn.S+30−0
@@ -35,9 +35,38 @@ · 34 unmodified lines
3535 #endif
3636 .endm
3737
38+/*
39+ * WARNING:
40+ *
41+ * A bug in the libgcc unwinder as of at least gcc 15.2 (2026) means that
42+ * the unwinder fails to recognize the signal frame flag.
43+ *
44+ * There is a hacky legacy fallback path in libgcc which ends up
45+ * getting invoked instead. It happens to work as long as BOTH of the
46+ * following conditions are true:
47+ *
48+ * 1. There is at least one byte before the each of the sigreturn
49+ * functions which falls outside any function. This is enforced by
50+ * an explicit nop instruction before the ALIGN.
51+ * 2. The code sequences between the entry point up to and including
52+ * the int $0x80 below need to match EXACTLY. Do not change them
53+ * in any way. The exact byte sequences are:
54+ *
55+ * __kernel_sigreturn:
56+ * 0: 58 pop %eax
57+ * 1: b8 77 00 00 00 mov $0x77,%eax
58+ * 6: cd 80 int $0x80
59+ *
60+ * __kernel_rt_sigreturn:
61+ * 0: b8 ad 00 00 00 mov $0xad,%eax
62+ * 5: cd 80 int $0x80
63+ *
64+ * For details, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124050
65+ */
3866 .text
3967 .globl __kernel_sigreturn
4068 .type __kernel_sigreturn,@function
69+ nop /* libgcc hack: see comment above */
4170 ALIGN
4271 __kernel_sigreturn:
4372 STARTPROC_SIGNAL_FRAME IA32_SIGFRAME_sigcontext
@@ -52,6 +81,7 @@ SYM_INNER_LABEL(vdso32_sigreturn_landing_pad, SYM_L_GLOBAL) · 8 unmodified lines
5281
5382 .globl __kernel_rt_sigreturn
5483 .type __kernel_rt_sigreturn,@function
84+ nop /* libgcc hack: see comment above */
5585 ALIGN
5686 __kernel_rt_sigreturn:
5787 STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext
arch/x86/include/asm/msr-index.h+4−1
@@ -740,7 +740,10 @@ · 739 unmodified lines
740740 #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
741741 #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18
742742 #define MSR_AMD64_SNP_SECURE_AVIC BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT)
743−#define MSR_AMD64_SNP_RESV_BIT 19
743+#define MSR_AMD64_SNP_RESERVED_BITS19_22 GENMASK_ULL(22, 19)
744+#define MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT 23
745+#define MSR_AMD64_SNP_IBPB_ON_ENTRY BIT_ULL(MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT)
746+#define MSR_AMD64_SNP_RESV_BIT 24
744747 #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
745748 #define MSR_AMD64_SAVIC_CONTROL 0xc0010138
746749 #define MSR_AMD64_SAVIC_EN_BIT 0
arch/x86/include/asm/numa.h+6−0
@@ -22,6 +22,7 @@ extern int numa_off; · 21 unmodified lines
2222 */
2323 extern s16 __apicid_to_node[MAX_LOCAL_APIC];
2424 extern nodemask_t numa_nodes_parsed __initdata;
25+extern nodemask_t numa_phys_nodes_parsed __initdata;
2526
2627 static inline void set_apicid_to_node(int apicid, s16 node)
2728 {
@@ -48,6 +49,7 @@ extern void __init init_cpu_to_node(void); · 20 unmodified lines
4849 extern void numa_add_cpu(unsigned int cpu);
4950 extern void numa_remove_cpu(unsigned int cpu);
5051 extern void init_gi_nodes(void);
52+extern int num_phys_nodes(void);
5153 #else /* CONFIG_NUMA */
5254 static inline void numa_set_node(int cpu, int node) { }
5355 static inline void numa_clear_node(int cpu) { }
@@ -55,6 +57,10 @@ static inline void init_cpu_to_node(void) { } · 1 unmodified line
5557 static inline void numa_add_cpu(unsigned int cpu) { }
5658 static inline void numa_remove_cpu(unsigned int cpu) { }
5759 static inline void init_gi_nodes(void) { }
60+static inline int num_phys_nodes(void)
61+{
62+ return 1;
63+}
5864 #endif /* CONFIG_NUMA */
5965
6066 #ifdef CONFIG_DEBUG_PER_CPU_MAPS
arch/x86/include/asm/topology.h+6−0
@@ -155,6 +155,7 @@ extern unsigned int __max_logical_packages; · 154 unmodified lines
155155 extern unsigned int __max_threads_per_core;
156156 extern unsigned int __num_threads_per_package;
157157 extern unsigned int __num_cores_per_package;
158+extern unsigned int __num_nodes_per_package;
158159
159160 const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c);
160161 enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c);
@@ -179,6 +180,11 @@ static inline unsigned int topology_num_threads_per_package(void) · 18 unmodified lines
179180 return __num_threads_per_package;
180181 }
181182
183+static inline unsigned int topology_num_nodes_per_package(void)
184+{
185+ return __num_nodes_per_package;
186+}
187+
182188 #ifdef CONFIG_X86_LOCAL_APIC
183189 int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level);
184190 #else
arch/x86/kernel/cpu/common.c+3−0
@@ -95,6 +95,9 @@ EXPORT_SYMBOL(__max_dies_per_package); · 94 unmodified lines
9595 unsigned int __max_logical_packages __ro_after_init = 1;
9696 EXPORT_SYMBOL(__max_logical_packages);
9797
98+unsigned int __num_nodes_per_package __ro_after_init = 1;
99+EXPORT_SYMBOL(__num_nodes_per_package);
100+
98101 unsigned int __num_cores_per_package __ro_after_init = 1;
99102 EXPORT_SYMBOL(__num_cores_per_package);
100103
arch/x86/kernel/cpu/resctrl/monitor.c+5−31
@@ -364,7 +364,7 @@ void arch_mon_domain_online(struct rdt_resource *r, struct rdt_l3_mon_domain *d) · 363 unmodified lines
364364 msr_clear_bit(MSR_RMID_SNC_CONFIG, 0);
365365 }
366366
367−/* CPU models that support MSR_RMID_SNC_CONFIG */
367+/* CPU models that support SNC and MSR_RMID_SNC_CONFIG */
368368 static const struct x86_cpu_id snc_cpu_ids[] __initconst = {
369369 X86_MATCH_VFM(INTEL_ICELAKE_X, 0),
370370 X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, 0),
@@ -375,40 +375,14 @@ static const struct x86_cpu_id snc_cpu_ids[] __initconst = { · 4 unmodified lines
375375 {}
376376 };
377377
378−/*
379− * There isn't a simple hardware bit that indicates whether a CPU is running
380− * in Sub-NUMA Cluster (SNC) mode. Infer the state by comparing the
381− * number of CPUs sharing the L3 cache with CPU0 to the number of CPUs in
382− * the same NUMA node as CPU0.
383− * It is not possible to accurately determine SNC state if the system is
384− * booted with a maxcpus=N parameter. That distorts the ratio of SNC nodes
385− * to L3 caches. It will be OK if system is booted with hyperthreading
386− * disabled (since this doesn't affect the ratio).
387− */
388378 static __init int snc_get_config(void)
389379 {
390− struct cacheinfo *ci = get_cpu_cacheinfo_level(0, RESCTRL_L3_CACHE);
391− const cpumask_t *node0_cpumask;
392− int cpus_per_node, cpus_per_l3;
393− int ret;
394−
395− if (!x86_match_cpu(snc_cpu_ids) || !ci)
396− return 1;
380+ int ret = topology_num_nodes_per_package();
397381
398− cpus_read_lock();
399− if (num_online_cpus() != num_present_cpus())
400− pr_warn("Some CPUs offline, SNC detection may be incorrect\n");
401− cpus_read_unlock();
402−
403− node0_cpumask = cpumask_of_node(cpu_to_node(0));
404−
405− cpus_per_node = cpumask_weight(node0_cpumask);
406− cpus_per_l3 = cpumask_weight(&ci->shared_cpu_map);
407−
408− if (!cpus_per_node || !cpus_per_l3)
382+ if (ret > 1 && !x86_match_cpu(snc_cpu_ids)) {
383+ pr_warn("CoD enabled system? Resctrl not supported\n");
409384 return 1;
410−
411− ret = cpus_per_l3 / cpus_per_node;
385+ }
412386
413387 /* sanity check: Only valid results are 1, 2, 3, 4, 6 */
414388 switch (ret) {
arch/x86/kernel/cpu/topology.c+11−2
@@ -31,6 +31,7 @@ · 30 unmodified lines
3131 #include <asm/mpspec.h>
3232 #include <asm/msr.h>
3333 #include <asm/smp.h>
34+#include <asm/numa.h>
3435
3536 #include "cpu.h"
3637
@@ -492,11 +493,19 @@ void __init topology_init_possible_cpus(void) · 455 unmodified lines
492493 set_nr_cpu_ids(allowed);
493494
494495 cnta = domain_weight(TOPO_PKG_DOMAIN);
495− cntb = domain_weight(TOPO_DIE_DOMAIN);
496496 __max_logical_packages = cnta;
497+
498+ pr_info("Max. logical packages: %3u\n", __max_logical_packages);
499+
500+ cntb = num_phys_nodes();
501+ __num_nodes_per_package = DIV_ROUND_UP(cntb, cnta);
502+
503+ pr_info("Max. logical nodes: %3u\n", cntb);
504+ pr_info("Num. nodes per package:%3u\n", __num_nodes_per_package);
505+
506+ cntb = domain_weight(TOPO_DIE_DOMAIN);
497507 __max_dies_per_package = 1U << (get_count_order(cntb) - get_count_order(cnta));
498508
499− pr_info("Max. logical packages: %3u\n", cnta);
500509 pr_info("Max. logical dies: %3u\n", cntb);
501510 pr_info("Max. dies per package: %3u\n", __max_dies_per_package);
502511
arch/x86/kernel/smpboot.c+145−56
@@ -468,13 +468,6 @@ static int x86_cluster_flags(void) · 467 unmodified lines
468468 }
469469 #endif
470470
471−/*
472− * Set if a package/die has multiple NUMA nodes inside.
473− * AMD Magny-Cours, Intel Cluster-on-Die, and Intel
474− * Sub-NUMA Clustering have this.
475− */
476−static bool x86_has_numa_in_package;
477−
478471 static struct sched_domain_topology_level x86_topology[] = {
479472 SDTL_INIT(tl_smt_mask, cpu_smt_flags, SMT),
480473 #ifdef CONFIG_SCHED_CLUSTER
@@ -496,7 +489,7 @@ static void __init build_sched_topology(void) · 15 unmodified lines
496489 * PKG domain since the NUMA domains will auto-magically create the
497490 * right spanning domains based on the SLIT.
498491 */
499− if (x86_has_numa_in_package) {
492+ if (topology_num_nodes_per_package() > 1) {
500493 unsigned int pkgdom = ARRAY_SIZE(x86_topology) - 2;
501494
502495 memset(&x86_topology[pkgdom], 0, sizeof(x86_topology[pkgdom]));
@@ -513,33 +506,149 @@ static void __init build_sched_topology(void) · 10 unmodified lines
513506 }
514507
515508 #ifdef CONFIG_NUMA
516−static int sched_avg_remote_distance;
517−static int avg_remote_numa_distance(void)
509+/*
510+ * Test if the on-trace cluster at (N,N) is symmetric.
511+ * Uses upper triangle iteration to avoid obvious duplicates.
512+ */
513+static bool slit_cluster_symmetric(int N)
518514 {
519− int i, j;
520− int distance, nr_remote, total_distance;
521−
522− if (sched_avg_remote_distance > 0)
523− return sched_avg_remote_distance;
524−
525− nr_remote = 0;
526− total_distance = 0;
527− for_each_node_state(i, N_CPU) {
528− for_each_node_state(j, N_CPU) {
529− distance = node_distance(i, j);
530−
531− if (distance >= REMOTE_DISTANCE) {
532− nr_remote++;
533− total_distance += distance;
534− }
515+ int u = topology_num_nodes_per_package();
516+
517+ for (int k = 0; k < u; k++) {
518+ for (int l = k; l < u; l++) {
519+ if (node_distance(N + k, N + l) !=
520+ node_distance(N + l, N + k))
521+ return false;
535522 }
536523 }
537− if (nr_remote)
538− sched_avg_remote_distance = total_distance / nr_remote;
539− else
540− sched_avg_remote_distance = REMOTE_DISTANCE;
541524
542− return sched_avg_remote_distance;
525+ return true;
526+}
527+
528+/*
529+ * Return the package-id of the cluster, or ~0 if indeterminate.
530+ * Each node in the on-trace cluster should have the same package-id.
531+ */
532+static u32 slit_cluster_package(int N)
533+{
534+ int u = topology_num_nodes_per_package();
535+ u32 pkg_id = ~0;
536+
537+ for (int n = 0; n < u; n++) {
538+ const struct cpumask *cpus = cpumask_of_node(N + n);
539+ int cpu;
540+
541+ for_each_cpu(cpu, cpus) {
542+ u32 id = topology_logical_package_id(cpu);
543+
544+ if (pkg_id == ~0)
545+ pkg_id = id;
546+ if (pkg_id != id)
547+ return ~0;
548+ }
549+ }
550+
551+ return pkg_id;
552+}
553+
554+/*
555+ * Validate the SLIT table is of the form expected for SNC, specifically:
556+ *
557+ * - each on-trace cluster should be symmetric,
558+ * - each on-trace cluster should have a unique package-id.
559+ *
560+ * If you NUMA_EMU on top of SNC, you get to keep the pieces.
561+ */
562+static bool slit_validate(void)
563+{
564+ int u = topology_num_nodes_per_package();
565+ u32 pkg_id, prev_pkg_id = ~0;
566+
567+ for (int pkg = 0; pkg < topology_max_packages(); pkg++) {
568+ int n = pkg * u;
569+
570+ /*
571+ * Ensure the on-trace cluster is symmetric and each cluster
572+ * has a different package id.
573+ */
574+ if (!slit_cluster_symmetric(n))
575+ return false;
576+ pkg_id = slit_cluster_package(n);
577+ if (pkg_id == ~0)
578+ return false;
579+ if (pkg && pkg_id == prev_pkg_id)
580+ return false;
581+
582+ prev_pkg_id = pkg_id;
583+ }
584+
585+ return true;
586+}
587+
588+/*
589+ * Compute a sanitized SLIT table for SNC; notably SNC-3 can end up with
590+ * asymmetric off-trace clusters, reflecting physical assymmetries. However
591+ * this leads to 'unfortunate' sched_domain configurations.
592+ *
593+ * For example dual socket GNR with SNC-3:
594+ *
595+ * node distances:
596+ * node 0 1 2 3 4 5
597+ * 0: 10 15 17 21 28 26
598+ * 1: 15 10 15 23 26 23
599+ * 2: 17 15 10 26 23 21
600+ * 3: 21 28 26 10 15 17
601+ * 4: 23 26 23 15 10 15
602+ * 5: 26 23 21 17 15 10
603+ *
604+ * Fix things up by averaging out the off-trace clusters; resulting in:
605+ *
606+ * node 0 1 2 3 4 5
607+ * 0: 10 15 17 24 24 24
608+ * 1: 15 10 15 24 24 24
609+ * 2: 17 15 10 24 24 24
610+ * 3: 24 24 24 10 15 17
611+ * 4: 24 24 24 15 10 15
612+ * 5: 24 24 24 17 15 10
613+ */
614+static int slit_cluster_distance(int i, int j)
615+{
616+ static int slit_valid = -1;
617+ int u = topology_num_nodes_per_package();
618+ long d = 0;
619+ int x, y;
620+
621+ if (slit_valid < 0) {
622+ slit_valid = slit_validate();
623+ if (!slit_valid)
624+ pr_err(FW_BUG "SLIT table doesn't have the expected form for SNC -- fixup disabled!\n");
625+ else
626+ pr_info("Fixing up SNC SLIT table.\n");
627+ }
628+
629+ /*
630+ * Is this a unit cluster on the trace?
631+ */
632+ if ((i / u) == (j / u) || !slit_valid)
633+ return node_distance(i, j);
634+
635+ /*
636+ * Off-trace cluster.
637+ *
638+ * Notably average out the symmetric pair of off-trace clusters to
639+ * ensure the resulting SLIT table is symmetric.
640+ */
641+ x = i - (i % u);
642+ y = j - (j % u);
643+
644+ for (i = x; i < x + u; i++) {
645+ for (j = y; j < y + u; j++) {
646+ d += node_distance(i, j);
647+ d += node_distance(j, i);
648+ }
649+ }
650+
651+ return d / (2*u*u);
543652 }
544653
545654 int arch_sched_node_distance(int from, int to)
@@ -549,34 +658,14 @@ int arch_sched_node_distance(int from, int to) · 3 unmodified lines
549658 switch (boot_cpu_data.x86_vfm) {
550659 case INTEL_GRANITERAPIDS_X:
551660 case INTEL_ATOM_DARKMONT_X:
552−
553− if (!x86_has_numa_in_package || topology_max_packages() == 1 ||
554− d < REMOTE_DISTANCE)
661+ if (topology_max_packages() == 1 ||
662+ topology_num_nodes_per_package() < 3)
555663 return d;
556664
557665 /*
558− * With SNC enabled, there could be too many levels of remote
559− * NUMA node distances, creating NUMA domain levels
560− * including local nodes and partial remote nodes.
561− *
562− * Trim finer distance tuning for NUMA nodes in remote package
563− * for the purpose of building sched domains. Group NUMA nodes
564− * in the remote package in the same sched group.
565− * Simplify NUMA domains and avoid extra NUMA levels including
566− * different remote NUMA nodes and local nodes.
567− *
568− * GNR and CWF don't expect systems with more than 2 packages
569− * and more than 2 hops between packages. Single average remote
570− * distance won't be appropriate if there are more than 2
571− * packages as average distance to different remote packages
572− * could be different.
666+ * Handle SNC-3 asymmetries.
573667 */
574− WARN_ONCE(topology_max_packages() > 2,
575− "sched: Expect only up to 2 packages for GNR or CWF, "
576− "but saw %d packages when building sched domains.",
577− topology_max_packages());
578−
579− d = avg_remote_numa_distance();
668+ return slit_cluster_distance(from, to);
580669 }
581670 return d;
582671 }
@@ -606,7 +695,7 @@ void set_cpu_sibling_map(int cpu) · 23 unmodified lines
606695 o = &cpu_data(i);
607696
608697 if (match_pkg(c, o) && !topology_same_node(c, o))
609− x86_has_numa_in_package = true;
698+ WARN_ON_ONCE(topology_num_nodes_per_package() == 1);
610699
611700 if ((i == cpu) || (has_smt && match_smt(c, o)))
612701 link_mask(topology_sibling_cpumask, cpu, i);
arch/x86/mm/numa.c+8−0
@@ -48,6 +48,8 @@ s16 __apicid_to_node[MAX_LOCAL_APIC] = { · 47 unmodified lines
4848 [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
4949 };
5050
51+nodemask_t numa_phys_nodes_parsed __initdata;
52+
5153 int numa_cpu_node(int cpu)
5254 {
5355 u32 apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
@@ -57,6 +59,11 @@ int numa_cpu_node(int cpu) · 3 unmodified lines
5759 return NUMA_NO_NODE;
5860 }
5961
62+int __init num_phys_nodes(void)
63+{
64+ return bitmap_weight(numa_phys_nodes_parsed.bits, MAX_NUMNODES);
65+}
66+
6067 cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
6168 EXPORT_SYMBOL(node_to_cpumask_map);
6269
@@ -210,6 +217,7 @@ static int __init dummy_numa_init(void) · 147 unmodified lines
210217 0LLU, PFN_PHYS(max_pfn) - 1);
211218
212219 node_set(0, numa_nodes_parsed);
220+ node_set(0, numa_phys_nodes_parsed);
213221 numa_add_memblk(0, 0, PFN_PHYS(max_pfn));
214222
215223 return 0;
arch/x86/mm/srat.c+2−0
@@ -57,6 +57,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) · 56 unmodified lines
5757 }
5858 set_apicid_to_node(apic_id, node);
5959 node_set(node, numa_nodes_parsed);
60+ node_set(node, numa_phys_nodes_parsed);
6061 pr_debug("SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", pxm, apic_id, node);
6162 }
6263
@@ -97,6 +98,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) · 34 unmodified lines
9798
9899 set_apicid_to_node(apic_id, node);
99100 node_set(node, numa_nodes_parsed);
101+ node_set(node, numa_phys_nodes_parsed);
100102 pr_debug("SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", pxm, apic_id, node);
101103 }
102104