forked from luck/tmp_suning_uos_patched
x86, sched: Treat Intel SNC topology as default, COD as exception
commit 2c88d45edbb89029c1190bb3b136d2602f057c98 upstream.
Commit 1340ccfa9a
("x86,sched: Allow topologies where NUMA nodes
share an LLC") added a vendor and model specific check to never
call topology_sane() for Intel Skylake Server systems where NUMA
nodes share an LLC.
Intel Ice Lake and Sapphire Rapids CPUs also enumerate an LLC that is
shared by multiple NUMA nodes. The LLC on these CPUs is shared for
off-package data access but private to the NUMA node for on-package
access. Rather than managing a list of allowable SNC topologies, make
this SNC topology the default, and treat Intel's Cluster-On-Die (COD)
topology as the exception.
In SNC mode, Sky Lake, Ice Lake, and Sapphire Rapids servers do not
emit this warning:
sched: CPU #3's llc-sibling CPU #0 is not on the same node! [node: 1 != 0]. Ignoring dependency.
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20210310190233.31752-1-alison.schofield@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4c0ddc8712
commit
a4c421b12c
|
@ -452,47 +452,12 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Define snc_cpu[] for SNC (Sub-NUMA Cluster) CPUs.
|
||||
*
|
||||
* These are Intel CPUs that enumerate an LLC that is shared by
|
||||
* multiple NUMA nodes. The LLC on these systems is shared for
|
||||
* off-package data access but private to the NUMA node (half
|
||||
* of the package) for on-package access.
|
||||
*
|
||||
* CPUID (the source of the information about the LLC) can only
|
||||
* enumerate the cache as being shared *or* unshared, but not
|
||||
* this particular configuration. The CPU in this case enumerates
|
||||
* the cache to be shared across the entire package (spanning both
|
||||
* NUMA nodes).
|
||||
*/
|
||||
|
||||
static const struct x86_cpu_id snc_cpu[] = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
|
||||
static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
|
||||
{
|
||||
int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
|
||||
|
||||
/* Do not match if we do not have a valid APICID for cpu: */
|
||||
if (per_cpu(cpu_llc_id, cpu1) == BAD_APICID)
|
||||
return false;
|
||||
|
||||
/* Do not match if LLC id does not match: */
|
||||
if (per_cpu(cpu_llc_id, cpu1) != per_cpu(cpu_llc_id, cpu2))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Allow the SNC topology without warning. Return of false
|
||||
* means 'c' does not share the LLC of 'o'. This will be
|
||||
* reflected to userspace.
|
||||
*/
|
||||
if (!topology_same_node(c, o) && x86_match_cpu(snc_cpu))
|
||||
return false;
|
||||
|
||||
return topology_sane(c, o, "llc");
|
||||
if (c->phys_proc_id == o->phys_proc_id &&
|
||||
c->cpu_die_id == o->cpu_die_id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -507,12 +472,50 @@ static bool match_pkg(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
|
||||
/*
|
||||
* Define intel_cod_cpu[] for Intel COD (Cluster-on-Die) CPUs.
|
||||
*
|
||||
* Any Intel CPU that has multiple nodes per package and does not
|
||||
* match intel_cod_cpu[] has the SNC (Sub-NUMA Cluster) topology.
|
||||
*
|
||||
* When in SNC mode, these CPUs enumerate an LLC that is shared
|
||||
* by multiple NUMA nodes. The LLC is shared for off-package data
|
||||
* access but private to the NUMA node (half of the package) for
|
||||
* on-package access. CPUID (the source of the information about
|
||||
* the LLC) can only enumerate the cache as shared or unshared,
|
||||
* but not this particular configuration.
|
||||
*/
|
||||
|
||||
static const struct x86_cpu_id intel_cod_cpu[] = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, 0), /* COD */
|
||||
X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, 0), /* COD */
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ANY, 1), /* SNC */
|
||||
{}
|
||||
};
|
||||
|
||||
static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
|
||||
{
|
||||
if ((c->phys_proc_id == o->phys_proc_id) &&
|
||||
(c->cpu_die_id == o->cpu_die_id))
|
||||
return true;
|
||||
return false;
|
||||
const struct x86_cpu_id *id = x86_match_cpu(intel_cod_cpu);
|
||||
int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
|
||||
bool intel_snc = id && id->driver_data;
|
||||
|
||||
/* Do not match if we do not have a valid APICID for cpu: */
|
||||
if (per_cpu(cpu_llc_id, cpu1) == BAD_APICID)
|
||||
return false;
|
||||
|
||||
/* Do not match if LLC id does not match: */
|
||||
if (per_cpu(cpu_llc_id, cpu1) != per_cpu(cpu_llc_id, cpu2))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Allow the SNC topology without warning. Return of false
|
||||
* means 'c' does not share the LLC of 'o'. This will be
|
||||
* reflected to userspace.
|
||||
*/
|
||||
if (match_pkg(c, o) && !topology_same_node(c, o) && intel_snc)
|
||||
return false;
|
||||
|
||||
return topology_sane(c, o, "llc");
|
||||
}
|
||||
|
||||
|
||||
|
@ -586,14 +589,23 @@ void set_cpu_sibling_map(int cpu)
|
|||
for_each_cpu(i, cpu_sibling_setup_mask) {
|
||||
o = &cpu_data(i);
|
||||
|
||||
if (match_pkg(c, o) && !topology_same_node(c, o))
|
||||
x86_has_numa_in_package = true;
|
||||
|
||||
if ((i == cpu) || (has_smt && match_smt(c, o)))
|
||||
link_mask(topology_sibling_cpumask, cpu, i);
|
||||
|
||||
if ((i == cpu) || (has_mp && match_llc(c, o)))
|
||||
link_mask(cpu_llc_shared_mask, cpu, i);
|
||||
|
||||
if ((i == cpu) || (has_mp && match_die(c, o)))
|
||||
link_mask(topology_die_cpumask, cpu, i);
|
||||
}
|
||||
|
||||
threads = cpumask_weight(topology_sibling_cpumask(cpu));
|
||||
if (threads > __max_smt_threads)
|
||||
__max_smt_threads = threads;
|
||||
|
||||
/*
|
||||
* This needs a separate iteration over the cpus because we rely on all
|
||||
* topology_sibling_cpumask links to be set-up.
|
||||
|
@ -607,8 +619,7 @@ void set_cpu_sibling_map(int cpu)
|
|||
/*
|
||||
* Does this new cpu bringup a new core?
|
||||
*/
|
||||
if (cpumask_weight(
|
||||
topology_sibling_cpumask(cpu)) == 1) {
|
||||
if (threads == 1) {
|
||||
/*
|
||||
* for each core in package, increment
|
||||
* the booted_cores for this new cpu
|
||||
|
@ -625,16 +636,7 @@ void set_cpu_sibling_map(int cpu)
|
|||
} else if (i != cpu && !c->booted_cores)
|
||||
c->booted_cores = cpu_data(i).booted_cores;
|
||||
}
|
||||
if (match_pkg(c, o) && !topology_same_node(c, o))
|
||||
x86_has_numa_in_package = true;
|
||||
|
||||
if ((i == cpu) || (has_mp && match_die(c, o)))
|
||||
link_mask(topology_die_cpumask, cpu, i);
|
||||
}
|
||||
|
||||
threads = cpumask_weight(topology_sibling_cpumask(cpu));
|
||||
if (threads > __max_smt_threads)
|
||||
__max_smt_threads = threads;
|
||||
}
|
||||
|
||||
/* maps the cpu to the sched domain representing multi-core */
|
||||
|
|
Loading…
Reference in New Issue
Block a user