aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2016-05-25 04:25:50 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-06-13 09:58:27 -0400
commitadac0f1e8c08548d82a48c9913ebc9787f946440 (patch)
tree290e69f3e727a33b0e3a8ed8f012141f4a469b88
parenta62247e1f5c13b926f535bb64ecbd7f9fdef7b21 (diff)
s390/topology: add drawer scheduling domain level
The z13 machine added a fourth level to the cpu topology information. The new top level is called drawer. A drawer contains two books, which used to be the top level. Adding this additional scheduling domain did show performance improvements for some workloads of up to 8%, while there don't seem to be any workloads impacted in a negative way. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/include/asm/topology.h4
-rw-r--r--arch/s390/kernel/topology.c33
-rw-r--r--arch/s390/numa/mode_emu.c25
4 files changed, 55 insertions, 11 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 3529a285dda8..ac963903d54f 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -478,6 +478,9 @@ config SCHED_MC
478config SCHED_BOOK 478config SCHED_BOOK
479 def_bool n 479 def_bool n
480 480
481config SCHED_DRAWER
482 def_bool n
483
481config SCHED_TOPOLOGY 484config SCHED_TOPOLOGY
482 def_bool y 485 def_bool y
483 prompt "Topology scheduler support" 486 prompt "Topology scheduler support"
@@ -485,6 +488,7 @@ config SCHED_TOPOLOGY
485 select SCHED_SMT 488 select SCHED_SMT
486 select SCHED_MC 489 select SCHED_MC
487 select SCHED_BOOK 490 select SCHED_BOOK
491 select SCHED_DRAWER
488 help 492 help
489 Topology scheduler support improves the CPU scheduler's decision 493 Topology scheduler support improves the CPU scheduler's decision
490 making when dealing with machines that have multi-threading, 494 making when dealing with machines that have multi-threading,
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index 6b53962e807e..f15f5571ca2b 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -14,10 +14,12 @@ struct cpu_topology_s390 {
14 unsigned short core_id; 14 unsigned short core_id;
15 unsigned short socket_id; 15 unsigned short socket_id;
16 unsigned short book_id; 16 unsigned short book_id;
17 unsigned short drawer_id;
17 unsigned short node_id; 18 unsigned short node_id;
18 cpumask_t thread_mask; 19 cpumask_t thread_mask;
19 cpumask_t core_mask; 20 cpumask_t core_mask;
20 cpumask_t book_mask; 21 cpumask_t book_mask;
22 cpumask_t drawer_mask;
21}; 23};
22 24
23DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology); 25DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);
@@ -30,6 +32,8 @@ DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);
30#define topology_core_cpumask(cpu) (&per_cpu(cpu_topology, cpu).core_mask) 32#define topology_core_cpumask(cpu) (&per_cpu(cpu_topology, cpu).core_mask)
31#define topology_book_id(cpu) (per_cpu(cpu_topology, cpu).book_id) 33#define topology_book_id(cpu) (per_cpu(cpu_topology, cpu).book_id)
32#define topology_book_cpumask(cpu) (&per_cpu(cpu_topology, cpu).book_mask) 34#define topology_book_cpumask(cpu) (&per_cpu(cpu_topology, cpu).book_mask)
35#define topology_drawer_id(cpu) (per_cpu(cpu_topology, cpu).drawer_id)
36#define topology_drawer_cpumask(cpu) (&per_cpu(cpu_topology, cpu).drawer_mask)
33 37
34#define mc_capable() 1 38#define mc_capable() 1
35 39
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 64298a867589..44745e751c3a 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -46,6 +46,7 @@ static DECLARE_WORK(topology_work, topology_work_fn);
46 */ 46 */
47static struct mask_info socket_info; 47static struct mask_info socket_info;
48static struct mask_info book_info; 48static struct mask_info book_info;
49static struct mask_info drawer_info;
49 50
50DEFINE_PER_CPU(struct cpu_topology_s390, cpu_topology); 51DEFINE_PER_CPU(struct cpu_topology_s390, cpu_topology);
51EXPORT_PER_CPU_SYMBOL_GPL(cpu_topology); 52EXPORT_PER_CPU_SYMBOL_GPL(cpu_topology);
@@ -80,6 +81,7 @@ static cpumask_t cpu_thread_map(unsigned int cpu)
80} 81}
81 82
82static struct mask_info *add_cpus_to_mask(struct topology_core *tl_core, 83static struct mask_info *add_cpus_to_mask(struct topology_core *tl_core,
84 struct mask_info *drawer,
83 struct mask_info *book, 85 struct mask_info *book,
84 struct mask_info *socket, 86 struct mask_info *socket,
85 int one_socket_per_cpu) 87 int one_socket_per_cpu)
@@ -97,9 +99,11 @@ static struct mask_info *add_cpus_to_mask(struct topology_core *tl_core,
97 continue; 99 continue;
98 for (i = 0; i <= smp_cpu_mtid; i++) { 100 for (i = 0; i <= smp_cpu_mtid; i++) {
99 topo = &per_cpu(cpu_topology, lcpu + i); 101 topo = &per_cpu(cpu_topology, lcpu + i);
102 topo->drawer_id = drawer->id;
100 topo->book_id = book->id; 103 topo->book_id = book->id;
101 topo->core_id = rcore; 104 topo->core_id = rcore;
102 topo->thread_id = lcpu + i; 105 topo->thread_id = lcpu + i;
106 cpumask_set_cpu(lcpu + i, &drawer->mask);
103 cpumask_set_cpu(lcpu + i, &book->mask); 107 cpumask_set_cpu(lcpu + i, &book->mask);
104 cpumask_set_cpu(lcpu + i, &socket->mask); 108 cpumask_set_cpu(lcpu + i, &socket->mask);
105 if (one_socket_per_cpu) 109 if (one_socket_per_cpu)
@@ -128,6 +132,11 @@ static void clear_masks(void)
128 cpumask_clear(&info->mask); 132 cpumask_clear(&info->mask);
129 info = info->next; 133 info = info->next;
130 } 134 }
135 info = &drawer_info;
136 while (info) {
137 cpumask_clear(&info->mask);
138 info = info->next;
139 }
131} 140}
132 141
133static union topology_entry *next_tle(union topology_entry *tle) 142static union topology_entry *next_tle(union topology_entry *tle)
@@ -141,12 +150,17 @@ static void __tl_to_masks_generic(struct sysinfo_15_1_x *info)
141{ 150{
142 struct mask_info *socket = &socket_info; 151 struct mask_info *socket = &socket_info;
143 struct mask_info *book = &book_info; 152 struct mask_info *book = &book_info;
153 struct mask_info *drawer = &drawer_info;
144 union topology_entry *tle, *end; 154 union topology_entry *tle, *end;
145 155
146 tle = info->tle; 156 tle = info->tle;
147 end = (union topology_entry *)((unsigned long)info + info->length); 157 end = (union topology_entry *)((unsigned long)info + info->length);
148 while (tle < end) { 158 while (tle < end) {
149 switch (tle->nl) { 159 switch (tle->nl) {
160 case 3:
161 drawer = drawer->next;
162 drawer->id = tle->container.id;
163 break;
150 case 2: 164 case 2:
151 book = book->next; 165 book = book->next;
152 book->id = tle->container.id; 166 book->id = tle->container.id;
@@ -156,7 +170,7 @@ static void __tl_to_masks_generic(struct sysinfo_15_1_x *info)
156 socket->id = tle->container.id; 170 socket->id = tle->container.id;
157 break; 171 break;
158 case 0: 172 case 0:
159 add_cpus_to_mask(&tle->cpu, book, socket, 0); 173 add_cpus_to_mask(&tle->cpu, drawer, book, socket, 0);
160 break; 174 break;
161 default: 175 default:
162 clear_masks(); 176 clear_masks();
@@ -170,6 +184,7 @@ static void __tl_to_masks_z10(struct sysinfo_15_1_x *info)
170{ 184{
171 struct mask_info *socket = &socket_info; 185 struct mask_info *socket = &socket_info;
172 struct mask_info *book = &book_info; 186 struct mask_info *book = &book_info;
187 struct mask_info *drawer = &drawer_info;
173 union topology_entry *tle, *end; 188 union topology_entry *tle, *end;
174 189
175 tle = info->tle; 190 tle = info->tle;
@@ -181,7 +196,7 @@ static void __tl_to_masks_z10(struct sysinfo_15_1_x *info)
181 book->id = tle->container.id; 196 book->id = tle->container.id;
182 break; 197 break;
183 case 0: 198 case 0:
184 socket = add_cpus_to_mask(&tle->cpu, book, socket, 1); 199 socket = add_cpus_to_mask(&tle->cpu, drawer, book, socket, 1);
185 break; 200 break;
186 default: 201 default:
187 clear_masks(); 202 clear_masks();
@@ -257,11 +272,13 @@ static void update_cpu_masks(void)
257 topo->thread_mask = cpu_thread_map(cpu); 272 topo->thread_mask = cpu_thread_map(cpu);
258 topo->core_mask = cpu_group_map(&socket_info, cpu); 273 topo->core_mask = cpu_group_map(&socket_info, cpu);
259 topo->book_mask = cpu_group_map(&book_info, cpu); 274 topo->book_mask = cpu_group_map(&book_info, cpu);
275 topo->drawer_mask = cpu_group_map(&drawer_info, cpu);
260 if (!MACHINE_HAS_TOPOLOGY) { 276 if (!MACHINE_HAS_TOPOLOGY) {
261 topo->thread_id = cpu; 277 topo->thread_id = cpu;
262 topo->core_id = cpu; 278 topo->core_id = cpu;
263 topo->socket_id = cpu; 279 topo->socket_id = cpu;
264 topo->book_id = cpu; 280 topo->book_id = cpu;
281 topo->drawer_id = cpu;
265 } 282 }
266 } 283 }
267 numa_update_cpu_topology(); 284 numa_update_cpu_topology();
@@ -269,10 +286,7 @@ static void update_cpu_masks(void)
269 286
270void store_topology(struct sysinfo_15_1_x *info) 287void store_topology(struct sysinfo_15_1_x *info)
271{ 288{
272 if (topology_max_mnest >= 3) 289 stsi(info, 15, 1, min(topology_max_mnest, 4));
273 stsi(info, 15, 1, 3);
274 else
275 stsi(info, 15, 1, 2);
276} 290}
277 291
278int arch_update_cpu_topology(void) 292int arch_update_cpu_topology(void)
@@ -442,6 +456,11 @@ static const struct cpumask *cpu_book_mask(int cpu)
442 return &per_cpu(cpu_topology, cpu).book_mask; 456 return &per_cpu(cpu_topology, cpu).book_mask;
443} 457}
444 458
459static const struct cpumask *cpu_drawer_mask(int cpu)
460{
461 return &per_cpu(cpu_topology, cpu).drawer_mask;
462}
463
445static int __init early_parse_topology(char *p) 464static int __init early_parse_topology(char *p)
446{ 465{
447 return kstrtobool(p, &topology_enabled); 466 return kstrtobool(p, &topology_enabled);
@@ -452,6 +471,7 @@ static struct sched_domain_topology_level s390_topology[] = {
452 { cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, 471 { cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
453 { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, 472 { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
454 { cpu_book_mask, SD_INIT_NAME(BOOK) }, 473 { cpu_book_mask, SD_INIT_NAME(BOOK) },
474 { cpu_drawer_mask, SD_INIT_NAME(DRAWER) },
455 { cpu_cpu_mask, SD_INIT_NAME(DIE) }, 475 { cpu_cpu_mask, SD_INIT_NAME(DIE) },
456 { NULL, }, 476 { NULL, },
457}; 477};
@@ -487,6 +507,7 @@ static int __init s390_topology_init(void)
487 printk(KERN_CONT " / %d\n", info->mnest); 507 printk(KERN_CONT " / %d\n", info->mnest);
488 alloc_masks(info, &socket_info, 1); 508 alloc_masks(info, &socket_info, 1);
489 alloc_masks(info, &book_info, 2); 509 alloc_masks(info, &book_info, 2);
510 alloc_masks(info, &drawer_info, 3);
490 set_sched_topology(s390_topology); 511 set_sched_topology(s390_topology);
491 return 0; 512 return 0;
492} 513}
diff --git a/arch/s390/numa/mode_emu.c b/arch/s390/numa/mode_emu.c
index 828d0695d0d4..fbc394e16b2c 100644
--- a/arch/s390/numa/mode_emu.c
+++ b/arch/s390/numa/mode_emu.c
@@ -34,7 +34,8 @@
34#define DIST_CORE 1 34#define DIST_CORE 1
35#define DIST_MC 2 35#define DIST_MC 2
36#define DIST_BOOK 3 36#define DIST_BOOK 3
37#define DIST_MAX 4 37#define DIST_DRAWER 4
38#define DIST_MAX 5
38 39
39/* Node distance reported to common code */ 40/* Node distance reported to common code */
40#define EMU_NODE_DIST 10 41#define EMU_NODE_DIST 10
@@ -43,7 +44,7 @@
43#define NODE_ID_FREE -1 44#define NODE_ID_FREE -1
44 45
45/* Different levels of toptree */ 46/* Different levels of toptree */
46enum toptree_level {CORE, MC, BOOK, NODE, TOPOLOGY}; 47enum toptree_level {CORE, MC, BOOK, DRAWER, NODE, TOPOLOGY};
47 48
48/* The two toptree IDs */ 49/* The two toptree IDs */
49enum {TOPTREE_ID_PHYS, TOPTREE_ID_NUMA}; 50enum {TOPTREE_ID_PHYS, TOPTREE_ID_NUMA};
@@ -114,6 +115,14 @@ static int cores_free(struct toptree *tree)
114 */ 115 */
115static struct toptree *core_node(struct toptree *core) 116static struct toptree *core_node(struct toptree *core)
116{ 117{
118 return core->parent->parent->parent->parent;
119}
120
121/*
122 * Return drawer of core
123 */
124static struct toptree *core_drawer(struct toptree *core)
125{
117 return core->parent->parent->parent; 126 return core->parent->parent->parent;
118} 127}
119 128
@@ -138,6 +147,8 @@ static struct toptree *core_mc(struct toptree *core)
138 */ 147 */
139static int dist_core_to_core(struct toptree *core1, struct toptree *core2) 148static int dist_core_to_core(struct toptree *core1, struct toptree *core2)
140{ 149{
150 if (core_drawer(core1)->id != core_drawer(core2)->id)
151 return DIST_DRAWER;
141 if (core_book(core1)->id != core_book(core2)->id) 152 if (core_book(core1)->id != core_book(core2)->id)
142 return DIST_BOOK; 153 return DIST_BOOK;
143 if (core_mc(core1)->id != core_mc(core2)->id) 154 if (core_mc(core1)->id != core_mc(core2)->id)
@@ -262,6 +273,8 @@ static void toptree_to_numa_first(struct toptree *numa, struct toptree *phys)
262 struct toptree *core; 273 struct toptree *core;
263 274
264 /* Always try to move perfectly fitting structures first */ 275 /* Always try to move perfectly fitting structures first */
276 move_level_to_numa(numa, phys, DRAWER, true);
277 move_level_to_numa(numa, phys, DRAWER, false);
265 move_level_to_numa(numa, phys, BOOK, true); 278 move_level_to_numa(numa, phys, BOOK, true);
266 move_level_to_numa(numa, phys, BOOK, false); 279 move_level_to_numa(numa, phys, BOOK, false);
267 move_level_to_numa(numa, phys, MC, true); 280 move_level_to_numa(numa, phys, MC, true);
@@ -335,7 +348,7 @@ static struct toptree *toptree_to_numa(struct toptree *phys)
335 */ 348 */
336static struct toptree *toptree_from_topology(void) 349static struct toptree *toptree_from_topology(void)
337{ 350{
338 struct toptree *phys, *node, *book, *mc, *core; 351 struct toptree *phys, *node, *drawer, *book, *mc, *core;
339 struct cpu_topology_s390 *top; 352 struct cpu_topology_s390 *top;
340 int cpu; 353 int cpu;
341 354
@@ -344,10 +357,11 @@ static struct toptree *toptree_from_topology(void)
344 for_each_online_cpu(cpu) { 357 for_each_online_cpu(cpu) {
345 top = &per_cpu(cpu_topology, cpu); 358 top = &per_cpu(cpu_topology, cpu);
346 node = toptree_get_child(phys, 0); 359 node = toptree_get_child(phys, 0);
347 book = toptree_get_child(node, top->book_id); 360 drawer = toptree_get_child(node, top->drawer_id);
361 book = toptree_get_child(drawer, top->book_id);
348 mc = toptree_get_child(book, top->socket_id); 362 mc = toptree_get_child(book, top->socket_id);
349 core = toptree_get_child(mc, top->core_id); 363 core = toptree_get_child(mc, top->core_id);
350 if (!book || !mc || !core) 364 if (!drawer || !book || !mc || !core)
351 panic("NUMA emulation could not allocate memory"); 365 panic("NUMA emulation could not allocate memory");
352 cpumask_set_cpu(cpu, &core->mask); 366 cpumask_set_cpu(cpu, &core->mask);
353 toptree_update_mask(mc); 367 toptree_update_mask(mc);
@@ -368,6 +382,7 @@ static void topology_add_core(struct toptree *core)
368 cpumask_copy(&top->thread_mask, &core->mask); 382 cpumask_copy(&top->thread_mask, &core->mask);
369 cpumask_copy(&top->core_mask, &core_mc(core)->mask); 383 cpumask_copy(&top->core_mask, &core_mc(core)->mask);
370 cpumask_copy(&top->book_mask, &core_book(core)->mask); 384 cpumask_copy(&top->book_mask, &core_book(core)->mask);
385 cpumask_copy(&top->drawer_mask, &core_drawer(core)->mask);
371 cpumask_set_cpu(cpu, &node_to_cpumask_map[core_node(core)->id]); 386 cpumask_set_cpu(cpu, &node_to_cpumask_map[core_node(core)->id]);
372 top->node_id = core_node(core)->id; 387 top->node_id = core_node(core)->id;
373 } 388 }