mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3 v2] x86/smpboot: Cleanup logical package ID
@ 2017-09-14 20:26 Prarit Bhargava
  2017-09-14 20:26 ` [PATCH 1/3 v2] perf/x86/intel/uncore: Cache logical pkg id in uncore driver Prarit Bhargava
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Prarit Bhargava @ 2017-09-14 20:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: kan.liang, x86, andi, peterz, Prarit Bhargava

Cleanup the logical package ID code by storing the logical package ID in
the cpuinfo_x86 struct and calculating the maximum logical package ID
after all the CPUs have been enumerated.

[v2]: Decrease logical_packages when the last thread in a socket is
removed.

Signed-off-by: Prarit Bhargava <prarit@redhat.com>

Andi Kleen (2):
  perf/x86/intel/uncore: Cache logical pkg id in uncore driver
  x86/topology: Avoid wasting 128k for package id array

Prarit Bhargava (1):
  x86/smpboot: Fix __max_logical_packages estimate

 arch/x86/events/intel/uncore.c       |   1 +
 arch/x86/events/intel/uncore.h       |   1 +
 arch/x86/events/intel/uncore_snbep.c |   2 +-
 arch/x86/include/asm/processor.h     |   6 +-
 arch/x86/kernel/smpboot.c            | 113 +++++++++++------------------------
 5 files changed, 42 insertions(+), 81 deletions(-)

-- 
1.8.5.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3 v2] perf/x86/intel/uncore: Cache logical pkg id in uncore driver
  2017-09-14 20:26 [PATCH 0/3 v2] x86/smpboot: Cleanup logical package ID Prarit Bhargava
@ 2017-09-14 20:26 ` Prarit Bhargava
  2017-09-14 20:26 ` [PATCH 2/3 v2] x86/topology: Avoid wasting 128k for package id array Prarit Bhargava
  2017-09-14 20:27 ` [PATCH 3/3 v2] x86/smpboot: Fix __max_logical_packages estimate Prarit Bhargava
  2 siblings, 0 replies; 4+ messages in thread
From: Prarit Bhargava @ 2017-09-14 20:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: kan.liang, x86, andi, peterz, Andi Kleen

From: Andi Kleen <ak@linux.intel.com>

The SNB-EP uncore driver is the only user of topology_phys_to_logical_pkg
in a performance critical path. Change it query the logical pkg ID
only once at initialization time and then cache it in box structure.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 arch/x86/events/intel/uncore.c       | 1 +
 arch/x86/events/intel/uncore.h       | 1 +
 arch/x86/events/intel/uncore_snbep.c | 2 +-
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 1c5390f1cf09..d13ac98e922b 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -939,6 +939,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
 
 	atomic_inc(&box->refcnt);
 	box->pci_phys_id = phys_id;
+	box->logical_pkg_id = topology_phys_to_logical_pkg(box->pci_phys_id);
 	box->pkgid = pkg;
 	box->pci_dev = pdev;
 	box->pmu = pmu;
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index df5989f27b1b..6214cd33a9fb 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -99,6 +99,7 @@ struct intel_uncore_extra_reg {
 
 struct intel_uncore_box {
 	int pci_phys_id;
+	int logical_pkg_id;
 	int pkgid;
 	int n_active;	/* number of active events */
 	int n_events;
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index db1fe377e6dd..11dec9f94cb0 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -1056,7 +1056,7 @@ static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_eve
 
 	if (reg1->idx != EXTRA_REG_NONE) {
 		int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
-		int pkg = topology_phys_to_logical_pkg(box->pci_phys_id);
+		int pkg = box->logical_pkg_id;
 		struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx];
 
 		if (filter_pdev) {
-- 
1.8.5.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/3 v2] x86/topology: Avoid wasting 128k for package id array
  2017-09-14 20:26 [PATCH 0/3 v2] x86/smpboot: Cleanup logical package ID Prarit Bhargava
  2017-09-14 20:26 ` [PATCH 1/3 v2] perf/x86/intel/uncore: Cache logical pkg id in uncore driver Prarit Bhargava
@ 2017-09-14 20:26 ` Prarit Bhargava
  2017-09-14 20:27 ` [PATCH 3/3 v2] x86/smpboot: Fix __max_logical_packages estimate Prarit Bhargava
  2 siblings, 0 replies; 4+ messages in thread
From: Prarit Bhargava @ 2017-09-14 20:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: kan.liang, x86, andi, peterz, Andi Kleen

From: Andi Kleen <ak@linux.intel.com>

I was looking at large early boot allocations and noticed that
since (1f12e32f x86/topology: Create logical package id)
every 64bit system allocates a 128k array to convert logical
package ids.

This happens because the array is sized for
MAX_LOCAL_APIC and that is always 32k on 64bit systems,
and it needs 4 bytes for each entry.

This is fairly wasteful, especially for the common case
of having only one socket, where we need 128K just to store
a single 4 byte value.

The max logical APIC value is not known at this point,
so it's hard to size it correctly.

The previous patch converted the only performance critical
user to cache the value, and all others are fairly
slow path, so we can just convert the O(1) array
lookup to a linear search in cpu_data()

This can also avoid the need for an extra bitmap structure
to know if the logical package ID is already allocated.
We can also save this information in cpu_data and look it
up during the search.

This patch removes the explicit arrays and replaces
the lookups with explicit searches.

Overall the new code is somewhat simpler, and needs a lot
less run time memory.

The naming of the variables in cpu_data is still not
great (_proc sometimes means package and sometimes means
logical processor), but I followed the existing (messy)
conventions when possible. At some point would be probably good
to clean this up too.

Tested on a 2S system, but it would be good
to test on more obscure systems which may have problems
with package IDs. I'm copying Prarit who had problematic systems
before.

[v2]: Decrease logical_packages when the last thread in a socket is
removed.
---
 arch/x86/include/asm/processor.h |  6 +++-
 arch/x86/kernel/smpboot.c        | 62 +++++++++++++++++-----------------------
 2 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 3fa26a61eabc..d369d2a82d8f 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -124,13 +124,17 @@ struct cpuinfo_x86 {
 	u16			booted_cores;
 	/* Physical processor id: */
 	u16			phys_proc_id;
-	/* Logical processor id: */
+	/* Logical processor (package) id: */
 	u16			logical_proc_id;
+	/* Physical package ID */
+	u16			phys_pkg_id;
 	/* Core id: */
 	u16			cpu_core_id;
 	/* Index into per_cpu list: */
 	u16			cpu_index;
 	u32			microcode;
+	/* Flags */
+	unsigned		logical_proc_set : 1;
 } __randomize_layout;
 
 struct cpuid_regs {
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 0854ff169274..a6e9bd971b91 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -100,9 +100,6 @@
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 /* Logical package management. We might want to allocate that dynamically */
-static int *physical_to_logical_pkg __read_mostly;
-static unsigned long *physical_package_map __read_mostly;;
-static unsigned int max_physical_pkg_id __read_mostly;
 unsigned int __max_logical_packages __read_mostly;
 EXPORT_SYMBOL(__max_logical_packages);
 static unsigned int logical_packages __read_mostly;
@@ -284,17 +281,11 @@ static void notrace start_secondary(void *unused)
  */
 int topology_update_package_map(unsigned int pkg, unsigned int cpu)
 {
-	unsigned int new;
+	int new;
 
-	/* Called from early boot ? */
-	if (!physical_package_map)
-		return 0;
-
-	if (pkg >= max_physical_pkg_id)
-		return -EINVAL;
-
-	/* Set the logical package id */
-	if (test_and_set_bit(pkg, physical_package_map))
+	/* Already available somewhere? */
+	new = topology_phys_to_logical_pkg(pkg);
+	if (new >= 0)
 		goto found;
 
 	if (logical_packages >= __max_logical_packages) {
@@ -304,14 +295,14 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
 	}
 
 	new = logical_packages++;
-	if (new != pkg) {
+	if (new != pkg)
 		pr_info("CPU %u Converting physical %u to logical package %u\n",
 			cpu, pkg, new);
-	}
-	physical_to_logical_pkg[pkg] = new;
 
 found:
-	cpu_data(cpu).logical_proc_id = physical_to_logical_pkg[pkg];
+	cpu_data(cpu).phys_pkg_id = pkg;
+	cpu_data(cpu).logical_proc_id = new;
+	cpu_data(cpu).logical_proc_set = 1;
 	return 0;
 }
 
@@ -322,16 +313,21 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
  */
 int topology_phys_to_logical_pkg(unsigned int phys_pkg)
 {
-	if (phys_pkg >= max_physical_pkg_id)
-		return -1;
-	return physical_to_logical_pkg[phys_pkg];
+	int cpu;
+
+	for_each_possible_cpu (cpu) {
+		if (cpu_data(cpu).phys_pkg_id == phys_pkg &&
+		    cpu_data(cpu).logical_proc_set) {
+			return cpu_data(cpu).logical_proc_id;
+		}
+	}
+	return -1;
 }
 EXPORT_SYMBOL(topology_phys_to_logical_pkg);
 
 static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu)
 {
 	unsigned int ncpus;
-	size_t size;
 
 	/*
 	 * Today neither Intel nor AMD support heterogenous systems. That
@@ -362,21 +358,10 @@ static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu)
 	}
 
 	__max_logical_packages = DIV_ROUND_UP(total_cpus, ncpus);
-	logical_packages = 0;
-
-	/*
-	 * Possibly larger than what we need as the number of apic ids per
-	 * package can be smaller than the actual used apic ids.
-	 */
-	max_physical_pkg_id = DIV_ROUND_UP(MAX_LOCAL_APIC, ncpus);
-	size = max_physical_pkg_id * sizeof(unsigned int);
-	physical_to_logical_pkg = kmalloc(size, GFP_KERNEL);
-	memset(physical_to_logical_pkg, 0xff, size);
-	size = BITS_TO_LONGS(max_physical_pkg_id) * sizeof(unsigned long);
-	physical_package_map = kzalloc(size, GFP_KERNEL);
-
 	pr_info("Max logical packages: %u\n", __max_logical_packages);
 
+	logical_packages = 0;
+
 	topology_update_package_map(c->phys_proc_id, cpu);
 }
 
@@ -1507,7 +1492,7 @@ static void recompute_smt_state(void)
 
 static void remove_siblinginfo(int cpu)
 {
-	int sibling;
+	int phys_pkg_id, sibling;
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	for_each_cpu(sibling, topology_core_cpumask(cpu)) {
@@ -1528,6 +1513,13 @@ static void remove_siblinginfo(int cpu)
 	cpumask_clear(topology_core_cpumask(cpu));
 	c->phys_proc_id = 0;
 	c->cpu_core_id = 0;
+
+	/* last core in socket going down? */
+	phys_pkg_id = c->phys_pkg_id;
+	c->phys_pkg_id = U16_MAX;
+	if (topology_phys_to_logical_pkg(phys_pkg_id) < 0)
+		logical_packages--;
+
 	cpumask_clear_cpu(cpu, cpu_sibling_setup_mask);
 	recompute_smt_state();
 }
-- 
1.8.5.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/3 v2] x86/smpboot: Fix __max_logical_packages estimate
  2017-09-14 20:26 [PATCH 0/3 v2] x86/smpboot: Cleanup logical package ID Prarit Bhargava
  2017-09-14 20:26 ` [PATCH 1/3 v2] perf/x86/intel/uncore: Cache logical pkg id in uncore driver Prarit Bhargava
  2017-09-14 20:26 ` [PATCH 2/3 v2] x86/topology: Avoid wasting 128k for package id array Prarit Bhargava
@ 2017-09-14 20:27 ` Prarit Bhargava
  2 siblings, 0 replies; 4+ messages in thread
From: Prarit Bhargava @ 2017-09-14 20:27 UTC (permalink / raw)
  To: linux-kernel; +Cc: kan.liang, x86, andi, peterz, Prarit Bhargava

A system booted with a small number of cores enabled per package
panics because the estimate of __max_logical_packages is too low.
This occurs when the total number of active cores across all packages
is less than the maximum core count for a single package.

ie) On a 4 package system with 20 cores/package where only 4 cores
are enabled on each package, the value of __max_logical_packages is
calculated as DIV_ROUND_UP(16 / 20) = 1 and not 4.

Calculate __max_logical_packages after the cpu enumeration has completed.
Use the boot cpu's data to extrapolate the number of packages.

Signed-off-by: Prarit Bhargava <prarit@redhat.com>
---
 arch/x86/kernel/smpboot.c | 57 +++++++++--------------------------------------
 1 file changed, 10 insertions(+), 47 deletions(-)

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index a6e9bd971b91..1b86ba57ab1a 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -288,12 +288,6 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
 	if (new >= 0)
 		goto found;
 
-	if (logical_packages >= __max_logical_packages) {
-		pr_warn("Package %u of CPU %u exceeds BIOS package data %u.\n",
-			logical_packages, cpu, __max_logical_packages);
-		return -ENOSPC;
-	}
-
 	new = logical_packages++;
 	if (new != pkg)
 		pr_info("CPU %u Converting physical %u to logical package %u\n",
@@ -325,46 +319,6 @@ int topology_phys_to_logical_pkg(unsigned int phys_pkg)
 }
 EXPORT_SYMBOL(topology_phys_to_logical_pkg);
 
-static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu)
-{
-	unsigned int ncpus;
-
-	/*
-	 * Today neither Intel nor AMD support heterogenous systems. That
-	 * might change in the future....
-	 *
-	 * While ideally we'd want '* smp_num_siblings' in the below @ncpus
-	 * computation, this won't actually work since some Intel BIOSes
-	 * report inconsistent HT data when they disable HT.
-	 *
-	 * In particular, they reduce the APIC-IDs to only include the cores,
-	 * but leave the CPUID topology to say there are (2) siblings.
-	 * This means we don't know how many threads there will be until
-	 * after the APIC enumeration.
-	 *
-	 * By not including this we'll sometimes over-estimate the number of
-	 * logical packages by the amount of !present siblings, but this is
-	 * still better than MAX_LOCAL_APIC.
-	 *
-	 * We use total_cpus not nr_cpu_ids because nr_cpu_ids can be limited
-	 * on the command line leading to a similar issue as the HT disable
-	 * problem because the hyperthreads are usually enumerated after the
-	 * primary cores.
-	 */
-	ncpus = boot_cpu_data.x86_max_cores;
-	if (!ncpus) {
-		pr_warn("x86_max_cores == zero !?!?");
-		ncpus = 1;
-	}
-
-	__max_logical_packages = DIV_ROUND_UP(total_cpus, ncpus);
-	pr_info("Max logical packages: %u\n", __max_logical_packages);
-
-	logical_packages = 0;
-
-	topology_update_package_map(c->phys_proc_id, cpu);
-}
-
 void __init smp_store_boot_cpu_info(void)
 {
 	int id = 0; /* CPU 0 */
@@ -372,7 +326,7 @@ void __init smp_store_boot_cpu_info(void)
 
 	*c = boot_cpu_data;
 	c->cpu_index = id;
-	smp_init_package_map(c, id);
+	topology_update_package_map(c->phys_proc_id, id);
 }
 
 /*
@@ -1372,7 +1326,16 @@ void __init native_smp_prepare_boot_cpu(void)
 
 void __init native_smp_cpus_done(unsigned int max_cpus)
 {
+	int ncpus;
+
 	pr_debug("Boot done\n");
+	/*
+	 * Today neither Intel nor AMD support heterogenous systems so
+	 * extrapolate the boot cpu's data to all packages.
+	 */
+	ncpus = cpu_data(0).booted_cores * smp_num_siblings;
+	__max_logical_packages = DIV_ROUND_UP(nr_cpu_ids, ncpus);
+	pr_info("Max logical packages: %u\n", __max_logical_packages);
 
 	if (x86_has_numa_in_package)
 		set_sched_topology(x86_numa_in_package_topology);
-- 
1.8.5.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-09-14 20:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-14 20:26 [PATCH 0/3 v2] x86/smpboot: Cleanup logical package ID Prarit Bhargava
2017-09-14 20:26 ` [PATCH 1/3 v2] perf/x86/intel/uncore: Cache logical pkg id in uncore driver Prarit Bhargava
2017-09-14 20:26 ` [PATCH 2/3 v2] x86/topology: Avoid wasting 128k for package id array Prarit Bhargava
2017-09-14 20:27 ` [PATCH 3/3 v2] x86/smpboot: Fix __max_logical_packages estimate Prarit Bhargava

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®