aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-09-04 08:26:03 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 09:45:08 -0400
commitfade4dc49101e3b68fb375fd2b00d0ef1f31a36f (patch)
tree302bd25e0575ce0b0ad33e34378577ad506bb786 /arch
parent34cda99260247873df53ae00885fb0f426b149a5 (diff)
s390/sysinfo,topology: fix cpu topology maximum nesting detection
The maximum nesting of the cpu topology is evaluated when /proc/sysinfo is the first time read. This happens without a lock and a concurrent reader on a different cpu can see and use an invalid intermediate value. Besides the fact that this race is quite unlikely the worst thing that could happen is that /proc/sysinfo would contain bogus information about the machine's cpu topology. Nevertheless this should be fixed. So move the detection code to the early machine detection code and since now the value is early available use it in the topology code as well. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/sysinfo.h2
-rw-r--r--arch/s390/kernel/early.c27
-rw-r--r--arch/s390/kernel/sysinfo.c12
-rw-r--r--arch/s390/kernel/topology.c10
4 files changed, 31 insertions, 20 deletions
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h
index 12e5256adca3..04e6e9774708 100644
--- a/arch/s390/include/asm/sysinfo.h
+++ b/arch/s390/include/asm/sysinfo.h
@@ -118,6 +118,8 @@ struct sysinfo_3_2_2 {
118 char reserved_544[3552]; 118 char reserved_544[3552];
119}; 119};
120 120
121extern int topology_max_mnest;
122
121#define TOPOLOGY_CPU_BITS 64 123#define TOPOLOGY_CPU_BITS 64
122#define TOPOLOGY_NR_MAG 6 124#define TOPOLOGY_NR_MAG 6
123 125
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 1345ba452c83..f4bcdc01bfc8 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -215,26 +215,44 @@ static noinline __init void init_kernel_storage_key(void)
215 PAGE_DEFAULT_KEY, 0); 215 PAGE_DEFAULT_KEY, 0);
216} 216}
217 217
218static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); 218static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE);
219 219
220static noinline __init void detect_machine_type(void) 220static noinline __init void detect_machine_type(void)
221{ 221{
222 struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page;
223
222 /* Check current-configuration-level */ 224 /* Check current-configuration-level */
223 if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) { 225 if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) {
224 S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; 226 S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR;
225 return; 227 return;
226 } 228 }
227 /* Get virtual-machine cpu information. */ 229 /* Get virtual-machine cpu information. */
228 if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count) 230 if (stsi(vmms, 3, 2, 2) == -ENOSYS || !vmms->count)
229 return; 231 return;
230 232
231 /* Running under KVM? If not we assume z/VM */ 233 /* Running under KVM? If not we assume z/VM */
232 if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3)) 234 if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
233 S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; 235 S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
234 else 236 else
235 S390_lowcore.machine_flags |= MACHINE_FLAG_VM; 237 S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
236} 238}
237 239
240static __init void setup_topology(void)
241{
242#ifdef CONFIG_64BIT
243 int max_mnest;
244
245 if (!test_facility(11))
246 return;
247 S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY;
248 for (max_mnest = 6; max_mnest > 1; max_mnest--) {
249 if (stsi(&sysinfo_page, 15, 1, max_mnest) != -ENOSYS)
250 break;
251 }
252 topology_max_mnest = max_mnest;
253#endif
254}
255
238static void early_pgm_check_handler(void) 256static void early_pgm_check_handler(void)
239{ 257{
240 unsigned long addr; 258 unsigned long addr;
@@ -364,8 +382,6 @@ static __init void detect_machine_facilities(void)
364 S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; 382 S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
365 if (test_facility(8)) 383 if (test_facility(8))
366 S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; 384 S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;
367 if (test_facility(11))
368 S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY;
369 if (test_facility(27)) 385 if (test_facility(27))
370 S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; 386 S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
371 if (test_facility(40)) 387 if (test_facility(40))
@@ -467,6 +483,7 @@ void __init startup_init(void)
467 detect_diag44(); 483 detect_diag44();
468 detect_machine_facilities(); 484 detect_machine_facilities();
469 setup_hpage(); 485 setup_hpage();
486 setup_topology();
470 sclp_facilities_detect(); 487 sclp_facilities_detect();
471 detect_memory_layout(memory_chunk); 488 detect_memory_layout(memory_chunk);
472#ifdef CONFIG_DYNAMIC_FTRACE 489#ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c
index 2249b0cf80ef..2af4ee67fe52 100644
--- a/arch/s390/kernel/sysinfo.c
+++ b/arch/s390/kernel/sysinfo.c
@@ -22,6 +22,8 @@
22#include <math-emu/soft-fp.h> 22#include <math-emu/soft-fp.h>
23#include <math-emu/single.h> 23#include <math-emu/single.h>
24 24
25int topology_max_mnest;
26
25static inline int stsi_0(void) 27static inline int stsi_0(void)
26{ 28{
27 int rc = stsi(NULL, 0, 0, 0); 29 int rc = stsi(NULL, 0, 0, 0);
@@ -95,15 +97,7 @@ static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info)
95 seq_putc(m, '\n'); 97 seq_putc(m, '\n');
96 if (!MACHINE_HAS_TOPOLOGY) 98 if (!MACHINE_HAS_TOPOLOGY)
97 return; 99 return;
98 if (max_mnest) { 100 stsi(info, 15, 1, topology_max_mnest);
99 stsi(info, 15, 1, max_mnest);
100 } else {
101 for (max_mnest = 6; max_mnest > 1; max_mnest--) {
102 rc = stsi(info, 15, 1, max_mnest);
103 if (rc != -ENOSYS)
104 break;
105 }
106 }
107 seq_printf(m, "CPU Topology HW: "); 101 seq_printf(m, "CPU Topology HW: ");
108 for (i = 0; i < TOPOLOGY_NR_MAG; i++) 102 for (i = 0; i < TOPOLOGY_NR_MAG; i++)
109 seq_printf(m, " %d", info->mag[i]); 103 seq_printf(m, " %d", info->mag[i]);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index fc957f2eef7c..80ca4ba759f6 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -251,12 +251,10 @@ static void update_cpu_core_map(void)
251 251
252void store_topology(struct sysinfo_15_1_x *info) 252void store_topology(struct sysinfo_15_1_x *info)
253{ 253{
254 int rc; 254 if (topology_max_mnest >= 3)
255 255 stsi(info, 15, 1, 3);
256 rc = stsi(info, 15, 1, 3); 256 else
257 if (rc != -ENOSYS) 257 stsi(info, 15, 1, 2);
258 return;
259 stsi(info, 15, 1, 2);
260} 258}
261 259
262int arch_update_cpu_topology(void) 260int arch_update_cpu_topology(void)