aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2017-09-19 06:52:22 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-09-20 07:47:54 -0400
commit1b25fda0533462c9cee3a22e8a7bea68fa670af2 (patch)
tree1a4832e32bc9cb33e9a8e807a47b3045c7f1e3ca
parentba385c0594e723d41790ecfb12c610e6f90c7785 (diff)
s390/topology: alternative topology for topology-less machines
If running on machines that do not provide topology information we currently generate a "fake" topology which defines the maximum distance between each cpu: each cpu will be put into an own drawer. Historically this used to be the best option for (virtual) machines in overcommited hypervisors. For some workloads however it is better to generate a different topology where all cpus are siblings within a package (all cpus are core siblings). This shows performance improvements of up to 10%, depending on the workload. In order to keep the current behaviour, but also allow to switch to the different core sibling topology use the existing "topology=" kernel parameter: Specifying "topology=on" on machines without topology information will generate the core siblings (fake) topology information, instead of the default topology information where all cpus have the maximum distance. On machines which provide topology information specifying "topology=on" does not have any effect. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/kernel/early.c12
-rw-r--r--arch/s390/kernel/topology.c72
2 files changed, 61 insertions, 23 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index ca8cd80e8feb..60181caf8e8a 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -404,18 +404,6 @@ static inline void save_vector_registers(void)
404#endif 404#endif
405} 405}
406 406
407static int __init topology_setup(char *str)
408{
409 bool enabled;
410 int rc;
411
412 rc = kstrtobool(str, &enabled);
413 if (!rc && !enabled)
414 S390_lowcore.machine_flags &= ~MACHINE_FLAG_TOPOLOGY;
415 return rc;
416}
417early_param("topology", topology_setup);
418
419static int __init disable_vector_extension(char *str) 407static int __init disable_vector_extension(char *str)
420{ 408{
421 S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; 409 S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index bb47c92476f0..a0ce9c83f589 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -29,12 +29,20 @@
29#define PTF_VERTICAL (1UL) 29#define PTF_VERTICAL (1UL)
30#define PTF_CHECK (2UL) 30#define PTF_CHECK (2UL)
31 31
32enum {
33 TOPOLOGY_MODE_HW,
34 TOPOLOGY_MODE_SINGLE,
35 TOPOLOGY_MODE_PACKAGE,
36 TOPOLOGY_MODE_UNINITIALIZED
37};
38
32struct mask_info { 39struct mask_info {
33 struct mask_info *next; 40 struct mask_info *next;
34 unsigned char id; 41 unsigned char id;
35 cpumask_t mask; 42 cpumask_t mask;
36}; 43};
37 44
45static int topology_mode = TOPOLOGY_MODE_UNINITIALIZED;
38static void set_topology_timer(void); 46static void set_topology_timer(void);
39static void topology_work_fn(struct work_struct *work); 47static void topology_work_fn(struct work_struct *work);
40static struct sysinfo_15_1_x *tl_info; 48static struct sysinfo_15_1_x *tl_info;
@@ -59,11 +67,26 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
59 cpumask_t mask; 67 cpumask_t mask;
60 68
61 cpumask_copy(&mask, cpumask_of(cpu)); 69 cpumask_copy(&mask, cpumask_of(cpu));
62 if (!MACHINE_HAS_TOPOLOGY) 70 switch (topology_mode) {
63 return mask; 71 case TOPOLOGY_MODE_HW:
64 for (; info; info = info->next) { 72 while (info) {
65 if (cpumask_test_cpu(cpu, &info->mask)) 73 if (cpumask_test_cpu(cpu, &info->mask)) {
66 return info->mask; 74 mask = info->mask;
75 break;
76 }
77 info = info->next;
78 }
79 if (cpumask_empty(&mask))
80 cpumask_copy(&mask, cpumask_of(cpu));
81 break;
82 case TOPOLOGY_MODE_PACKAGE:
83 cpumask_copy(&mask, cpu_present_mask);
84 break;
85 default:
86 /* fallthrough */
87 case TOPOLOGY_MODE_SINGLE:
88 cpumask_copy(&mask, cpumask_of(cpu));
89 break;
67 } 90 }
68 return mask; 91 return mask;
69} 92}
@@ -74,7 +97,7 @@ static cpumask_t cpu_thread_map(unsigned int cpu)
74 int i; 97 int i;
75 98
76 cpumask_copy(&mask, cpumask_of(cpu)); 99 cpumask_copy(&mask, cpumask_of(cpu));
77 if (!MACHINE_HAS_TOPOLOGY) 100 if (topology_mode != TOPOLOGY_MODE_HW)
78 return mask; 101 return mask;
79 cpu -= cpu % (smp_cpu_mtid + 1); 102 cpu -= cpu % (smp_cpu_mtid + 1);
80 for (i = 0; i <= smp_cpu_mtid; i++) 103 for (i = 0; i <= smp_cpu_mtid; i++)
@@ -223,7 +246,7 @@ int topology_set_cpu_management(int fc)
223static void update_cpu_masks(void) 246static void update_cpu_masks(void)
224{ 247{
225 struct cpu_topology_s390 *topo; 248 struct cpu_topology_s390 *topo;
226 int cpu; 249 int cpu, id;
227 250
228 for_each_possible_cpu(cpu) { 251 for_each_possible_cpu(cpu) {
229 topo = &cpu_topology[cpu]; 252 topo = &cpu_topology[cpu];
@@ -231,12 +254,13 @@ static void update_cpu_masks(void)
231 topo->core_mask = cpu_group_map(&socket_info, cpu); 254 topo->core_mask = cpu_group_map(&socket_info, cpu);
232 topo->book_mask = cpu_group_map(&book_info, cpu); 255 topo->book_mask = cpu_group_map(&book_info, cpu);
233 topo->drawer_mask = cpu_group_map(&drawer_info, cpu); 256 topo->drawer_mask = cpu_group_map(&drawer_info, cpu);
234 if (!MACHINE_HAS_TOPOLOGY) { 257 if (topology_mode != TOPOLOGY_MODE_HW) {
258 id = topology_mode == TOPOLOGY_MODE_PACKAGE ? 0 : cpu;
235 topo->thread_id = cpu; 259 topo->thread_id = cpu;
236 topo->core_id = cpu; 260 topo->core_id = cpu;
237 topo->socket_id = cpu; 261 topo->socket_id = id;
238 topo->book_id = cpu; 262 topo->book_id = id;
239 topo->drawer_id = cpu; 263 topo->drawer_id = id;
240 if (cpu_present(cpu)) 264 if (cpu_present(cpu))
241 cpumask_set_cpu(cpu, &cpus_with_topology); 265 cpumask_set_cpu(cpu, &cpus_with_topology);
242 } 266 }
@@ -459,6 +483,12 @@ void __init topology_init_early(void)
459 struct sysinfo_15_1_x *info; 483 struct sysinfo_15_1_x *info;
460 484
461 set_sched_topology(s390_topology); 485 set_sched_topology(s390_topology);
486 if (topology_mode == TOPOLOGY_MODE_UNINITIALIZED) {
487 if (MACHINE_HAS_TOPOLOGY)
488 topology_mode = TOPOLOGY_MODE_HW;
489 else
490 topology_mode = TOPOLOGY_MODE_SINGLE;
491 }
462 if (!MACHINE_HAS_TOPOLOGY) 492 if (!MACHINE_HAS_TOPOLOGY)
463 goto out; 493 goto out;
464 tl_info = memblock_virt_alloc(PAGE_SIZE, PAGE_SIZE); 494 tl_info = memblock_virt_alloc(PAGE_SIZE, PAGE_SIZE);
@@ -474,6 +504,26 @@ out:
474 __arch_update_cpu_topology(); 504 __arch_update_cpu_topology();
475} 505}
476 506
507static inline int topology_get_mode(int enabled)
508{
509 if (!enabled)
510 return TOPOLOGY_MODE_SINGLE;
511 return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE;
512}
513
514static int __init topology_setup(char *str)
515{
516 bool enabled;
517 int rc;
518
519 rc = kstrtobool(str, &enabled);
520 if (rc)
521 return rc;
522 topology_mode = topology_get_mode(enabled);
523 return 0;
524}
525early_param("topology", topology_setup);
526
477static int __init topology_init(void) 527static int __init topology_init(void)
478{ 528{
479 if (MACHINE_HAS_TOPOLOGY) 529 if (MACHINE_HAS_TOPOLOGY)