[v3,2/2] powerpc: Enable CPU_FTR_ASYM_SMT for interleaved big-cores

Message ID 03b97f95b42a9044a4280c318a92ac5e53e79828.1530867876.git.ego@linux.vnet.ibm.com
State New
Headers show
Series
  • powerpc: Detection and scheduler optimization for POWER9 bigcore
Related show

Commit Message

Gautham R. Shenoy July 6, 2018, 9:05 a.m.
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>

A pair of IBM POWER9 SMT4 cores can be fused together to form a big-core
with 8 SMT threads. This can be discovered via the "ibm,thread-groups"
CPU property in the device tree which will indicate which group of
threads that share the L1 cache, translation cache and instruction data
flow. If there are multiple such group of threads, then the core is a
big-core.

Furthermore, if the thread-ids of the threads of the big-core can be
obtained by interleaving the thread-ids of the thread-groups
(component small core), then such a big-core is called an interleaved
big-core.

Eg: Threads in the pair of component SMT4 cores of an interleaved
big-core are numbered {0,2,4,6} and {1,3,5,7} respectively.

The SMT4 cores forming a big-core are more or less independent
units. Thus when multiple tasks are scheduled to run on the fused
core, we get the best performance when the tasks are spread across the
pair of SMT4 cores.

This patch enables CPU_FTR_ASYM_SMT bit in the cpu-features on
detecting the presence of interleaved big-cores at boot up. This will
will bias the load-balancing of tasks on smaller numbered threads,
which will automatically result in spreading the tasks uniformly
across the associated pair of SMT4 cores.

Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/setup-common.c | 67 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

Comments

kbuild test robot July 11, 2018, 8:32 a.m. | #1
Hi Gautham,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[also build test ERROR on v4.18-rc4 next-20180710]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gautham-R-Shenoy/powerpc-Detect-the-presence-of-big-cores-via-ibm-thread-groups/20180706-174756
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-g5_defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   In file included from include/linux/static_key.h:1:0,
                    from include/linux/context_tracking_state.h:6,
                    from include/linux/vtime.h:5,
                    from include/linux/hardirq.h:8,
                    from include/linux/interrupt.h:11,
                    from include/linux/serial_core.h:25,
                    from include/linux/serial_8250.h:14,
                    from arch/powerpc/kernel/setup-common.c:33:
   arch/powerpc/kernel/setup-common.c: In function 'smp_setup_cpu_maps':
>> arch/powerpc/kernel/setup-common.c:777:25: error: 'cpu_feature_keys' undeclared (first use in this function); did you mean 'setup_feature_keys'?
      static_branch_enable(&cpu_feature_keys[key]);
                            ^
   include/linux/jump_label.h:434:55: note: in definition of macro 'static_branch_enable'
    #define static_branch_enable(x)   static_key_enable(&(x)->key)
                                                          ^
   arch/powerpc/kernel/setup-common.c:777:25: note: each undeclared identifier is reported only once for each function it appears in
      static_branch_enable(&cpu_feature_keys[key]);
                            ^
   include/linux/jump_label.h:434:55: note: in definition of macro 'static_branch_enable'
    #define static_branch_enable(x)   static_key_enable(&(x)->key)
                                                          ^

vim +777 arch/powerpc/kernel/setup-common.c

   772	
   773		if (has_interleaved_big_cores) {
   774			int key = __builtin_ctzl(CPU_FTR_ASYM_SMT);
   775	
   776			cur_cpu_spec->cpu_features |= CPU_FTR_ASYM_SMT;
 > 777			static_branch_enable(&cpu_feature_keys[key]);
   778			pr_info("Detected interleaved big-cores\n");
   779		}
   780	
   781		/* Initialize CPU <=> thread mapping/
   782		 *
   783		 * WARNING: We assume that the number of threads is the same for
   784		 * every CPU in the system. If that is not the case, then some code
   785		 * here will have to be reworked
   786		 */
   787		cpu_init_thread_core_maps(nthreads);
   788	
   789		/* Now that possible cpus are set, set nr_cpu_ids for later use */
   790		setup_nr_cpu_ids();
   791	
   792		free_unused_pacas();
   793	}
   794	#endif /* CONFIG_SMP */
   795	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Gautham R. Shenoy July 16, 2018, 5:25 a.m. | #2
On Wed, Jul 11, 2018 at 04:32:30PM +0800, kbuild test robot wrote:
> Hi Gautham,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on powerpc/next]
> [also build test ERROR on v4.18-rc4 next-20180710]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Gautham-R-Shenoy/powerpc-Detect-the-presence-of-big-cores-via-ibm-thread-groups/20180706-174756
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
> config: powerpc-g5_defconfig (attached as .config)
> compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.2.0 make.cross ARCH=powerpc 
> 
> All errors (new ones prefixed by >>):
> 
>    In file included from include/linux/static_key.h:1:0,
>                     from include/linux/context_tracking_state.h:6,
>                     from include/linux/vtime.h:5,
>                     from include/linux/hardirq.h:8,
>                     from include/linux/interrupt.h:11,
>                     from include/linux/serial_core.h:25,
>                     from include/linux/serial_8250.h:14,
>                     from arch/powerpc/kernel/setup-common.c:33:
>    arch/powerpc/kernel/setup-common.c: In function 'smp_setup_cpu_maps':
> >> arch/powerpc/kernel/setup-common.c:777:25: error: 'cpu_feature_keys' undeclared (first use in this function); did you mean 'setup_feature_keys'?
>       static_branch_enable(&cpu_feature_keys[key]);

Ok, so this needs to be enabled only on CONFIG_PPC_PSERIES and
CONFIG_PPC_POWERNV. Will fix this.


--
Thanks and Regards
gautham.

Patch

diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 989edc1..c200fb8 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -581,6 +581,56 @@  int get_cpu_thread_group_start(int cpu, struct thread_groups *tg)
 	return -1;
 }
 
+/*
+ * check_interleaved_big_core - Checks if the thread group tg
+ * corresponds to a big-core whose threads are interleavings of the
+ * threads of the component small cores.
+ *
+ * @tg: A thread-group struct for the core.
+ *
+ * Returns true if the core is a interleaved big-core.
+ * Returns false otherwise.
+ */
+static inline bool check_interleaved_big_core(struct thread_groups *tg)
+{
+	int nr_groups;
+	int threads_per_group;
+	int cur_cpu, next_cpu, i, j;
+
+	nr_groups = tg->nr_groups;
+	threads_per_group = tg->threads_per_group;
+
+	if (tg->property != 1)
+		return false;
+
+	if (nr_groups < 2 || threads_per_group < 2)
+		return false;
+
+	/*
+	 * In case of an interleaved big-core, the thread-ids of the
+	 * big-core can be obtained by interleaving the the thread-ids
+	 * of the component small
+	 *
+	 * Eg: On a 8-thread big-core with two SMT4 small cores, the
+	 * threads of the two component small cores will be
+	 * {0, 2, 4, 6} and {1, 3, 5, 7}.
+	 */
+	for (i = 0; i < nr_groups; i++) {
+		int group_start = i * threads_per_group;
+
+		for (j = 0; j < threads_per_group - 1; j++) {
+			int cur_idx = group_start + j;
+
+			cur_cpu = tg->thread_list[cur_idx];
+			next_cpu = tg->thread_list[cur_idx + 1];
+			if (next_cpu != cur_cpu + nr_groups)
+				return false;
+		}
+	}
+
+	return true;
+}
+
 /**
  * setup_cpu_maps - initialize the following cpu maps:
  *                  cpu_possible_mask
@@ -604,6 +654,7 @@  void __init smp_setup_cpu_maps(void)
 	struct device_node *dn;
 	int cpu = 0;
 	int nthreads = 1;
+	bool has_interleaved_big_cores = true;
 
 	has_big_cores = true;
 	DBG("smp_setup_cpu_maps()\n");
@@ -657,6 +708,12 @@  void __init smp_setup_cpu_maps(void)
 
 		if (has_big_cores && !dt_has_big_core(dn, &tg)) {
 			has_big_cores = false;
+			has_interleaved_big_cores = false;
+		}
+
+		if (has_interleaved_big_cores) {
+			has_interleaved_big_cores =
+				check_interleaved_big_core(&tg);
 		}
 
 		if (cpu >= nr_cpu_ids) {
@@ -713,7 +770,15 @@  void __init smp_setup_cpu_maps(void)
 	vdso_data->processorCount = num_present_cpus();
 #endif /* CONFIG_PPC64 */
 
-        /* Initialize CPU <=> thread mapping/
+	if (has_interleaved_big_cores) {
+		int key = __builtin_ctzl(CPU_FTR_ASYM_SMT);
+
+		cur_cpu_spec->cpu_features |= CPU_FTR_ASYM_SMT;
+		static_branch_enable(&cpu_feature_keys[key]);
+		pr_info("Detected interleaved big-cores\n");
+	}
+
+	/* Initialize CPU <=> thread mapping/
 	 *
 	 * WARNING: We assume that the number of threads is the same for
 	 * every CPU in the system. If that is not the case, then some code