diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-04-30 07:38:45 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-04-30 07:38:47 -0400 |
commit | 2e5061e40af88070984e3769eafb5a06022375fd (patch) | |
tree | 2964cc88a68f826fc8e025d145f692e1e78740e0 | |
parent | 8fc63658681f32e6e29f6d1138de933d7272e0ec (diff) |
[S390] Convert machine feature detection code to C.
From: Heiko Carstens <heiko.carstens@de.ibm.com>
From: Carsten Otte <cotte@de.ibm.com>
This lets us use defines for the magic bits in machine flags instead
of using plain numbers all over the place.
In addition on newer machines features/facilities are indicated by the
result of the stfl instruction. So we use these bits instead of trying
to execute new instructions and check wether we get an exception or
not.
Also the mvpg instruction is always available when in zArch mode,
whereas the idte instruction is only available in zArch mode. This
results in some minor optimizations.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/kernel/early.c | 109 | ||||
-rw-r--r-- | arch/s390/kernel/head31.S | 61 | ||||
-rw-r--r-- | arch/s390/kernel/head64.S | 62 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 2 | ||||
-rw-r--r-- | include/asm-s390/setup.h | 33 | ||||
-rw-r--r-- | include/asm-s390/smp.h | 6 | ||||
-rw-r--r-- | include/asm-s390/system.h | 8 |
7 files changed, 140 insertions, 141 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 68ec4083bf73..bd188f6bd0e2 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -139,15 +139,15 @@ static noinline __init void detect_machine_type(void) | |||
139 | 139 | ||
140 | /* Running under z/VM ? */ | 140 | /* Running under z/VM ? */ |
141 | if (cpuinfo->cpu_id.version == 0xff) | 141 | if (cpuinfo->cpu_id.version == 0xff) |
142 | machine_flags |= 1; | 142 | machine_flags |= MACHINE_FLAG_VM; |
143 | 143 | ||
144 | /* Running on a P/390 ? */ | 144 | /* Running on a P/390 ? */ |
145 | if (cpuinfo->cpu_id.machine == 0x7490) | 145 | if (cpuinfo->cpu_id.machine == 0x7490) |
146 | machine_flags |= 4; | 146 | machine_flags |= MACHINE_FLAG_P390; |
147 | 147 | ||
148 | /* Running under KVM ? */ | 148 | /* Running under KVM ? */ |
149 | if (cpuinfo->cpu_id.version == 0xfe) | 149 | if (cpuinfo->cpu_id.version == 0xfe) |
150 | machine_flags |= 64; | 150 | machine_flags |= MACHINE_FLAG_KVM; |
151 | } | 151 | } |
152 | 152 | ||
153 | #ifdef CONFIG_64BIT | 153 | #ifdef CONFIG_64BIT |
@@ -268,6 +268,103 @@ static noinline __init void setup_lowcore_early(void) | |||
268 | s390_base_pgm_handler_fn = early_pgm_check_handler; | 268 | s390_base_pgm_handler_fn = early_pgm_check_handler; |
269 | } | 269 | } |
270 | 270 | ||
271 | static __init void detect_mvpg(void) | ||
272 | { | ||
273 | #ifndef CONFIG_64BIT | ||
274 | int rc; | ||
275 | |||
276 | asm volatile( | ||
277 | " la 0,0\n" | ||
278 | " mvpg %2,%2\n" | ||
279 | "0: la %0,0\n" | ||
280 | "1:\n" | ||
281 | EX_TABLE(0b,1b) | ||
282 | : "=d" (rc) : "0" (-EOPNOTSUPP), "a" (0) : "memory", "cc", "0"); | ||
283 | if (!rc) | ||
284 | machine_flags |= MACHINE_FLAG_MVPG; | ||
285 | #endif | ||
286 | } | ||
287 | |||
288 | static __init void detect_ieee(void) | ||
289 | { | ||
290 | #ifndef CONFIG_64BIT | ||
291 | int rc, tmp; | ||
292 | |||
293 | asm volatile( | ||
294 | " efpc %1,0\n" | ||
295 | "0: la %0,0\n" | ||
296 | "1:\n" | ||
297 | EX_TABLE(0b,1b) | ||
298 | : "=d" (rc), "=d" (tmp): "0" (-EOPNOTSUPP) : "cc"); | ||
299 | if (!rc) | ||
300 | machine_flags |= MACHINE_FLAG_IEEE; | ||
301 | #endif | ||
302 | } | ||
303 | |||
304 | static __init void detect_csp(void) | ||
305 | { | ||
306 | #ifndef CONFIG_64BIT | ||
307 | int rc; | ||
308 | |||
309 | asm volatile( | ||
310 | " la 0,0\n" | ||
311 | " la 1,0\n" | ||
312 | " la 2,4\n" | ||
313 | " csp 0,2\n" | ||
314 | "0: la %0,0\n" | ||
315 | "1:\n" | ||
316 | EX_TABLE(0b,1b) | ||
317 | : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc", "0", "1", "2"); | ||
318 | if (!rc) | ||
319 | machine_flags |= MACHINE_FLAG_CSP; | ||
320 | #endif | ||
321 | } | ||
322 | |||
323 | static __init void detect_diag9c(void) | ||
324 | { | ||
325 | unsigned int cpu_address; | ||
326 | int rc; | ||
327 | |||
328 | cpu_address = stap(); | ||
329 | asm volatile( | ||
330 | " diag %2,0,0x9c\n" | ||
331 | "0: la %0,0\n" | ||
332 | "1:\n" | ||
333 | EX_TABLE(0b,1b) | ||
334 | : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc"); | ||
335 | if (!rc) | ||
336 | machine_flags |= MACHINE_FLAG_DIAG9C; | ||
337 | } | ||
338 | |||
339 | static __init void detect_diag44(void) | ||
340 | { | ||
341 | #ifdef CONFIG_64BIT | ||
342 | int rc; | ||
343 | |||
344 | asm volatile( | ||
345 | " diag 0,0,0x44\n" | ||
346 | "0: la %0,0\n" | ||
347 | "1:\n" | ||
348 | EX_TABLE(0b,1b) | ||
349 | : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc"); | ||
350 | if (!rc) | ||
351 | machine_flags |= MACHINE_FLAG_DIAG44; | ||
352 | #endif | ||
353 | } | ||
354 | |||
355 | static __init void detect_machine_facilities(void) | ||
356 | { | ||
357 | #ifdef CONFIG_64BIT | ||
358 | unsigned int facilities; | ||
359 | |||
360 | facilities = stfl(); | ||
361 | if (facilities & (1 << 28)) | ||
362 | machine_flags |= MACHINE_FLAG_IDTE; | ||
363 | if (facilities & (1 << 4)) | ||
364 | machine_flags |= MACHINE_FLAG_MVCOS; | ||
365 | #endif | ||
366 | } | ||
367 | |||
271 | /* | 368 | /* |
272 | * Save ipl parameters, clear bss memory, initialize storage keys | 369 | * Save ipl parameters, clear bss memory, initialize storage keys |
273 | * and create a kernel NSS at startup if the SAVESYS= parm is defined | 370 | * and create a kernel NSS at startup if the SAVESYS= parm is defined |
@@ -285,6 +382,12 @@ void __init startup_init(void) | |||
285 | create_kernel_nss(); | 382 | create_kernel_nss(); |
286 | sort_main_extable(); | 383 | sort_main_extable(); |
287 | setup_lowcore_early(); | 384 | setup_lowcore_early(); |
385 | detect_mvpg(); | ||
386 | detect_ieee(); | ||
387 | detect_csp(); | ||
388 | detect_diag9c(); | ||
389 | detect_diag44(); | ||
390 | detect_machine_facilities(); | ||
288 | sclp_read_info_early(); | 391 | sclp_read_info_early(); |
289 | sclp_facilities_detect(); | 392 | sclp_facilities_detect(); |
290 | memsize = sclp_memory_detect(); | 393 | memsize = sclp_memory_detect(); |
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index dc364c1419af..a816e2de32b9 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S | |||
@@ -57,61 +57,6 @@ startup_continue: | |||
57 | # | 57 | # |
58 | l %r14,.Lstartup_init-.LPG1(%r13) | 58 | l %r14,.Lstartup_init-.LPG1(%r13) |
59 | basr %r14,%r14 | 59 | basr %r14,%r14 |
60 | |||
61 | l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags | ||
62 | # | ||
63 | # find out if we have an IEEE fpu | ||
64 | # | ||
65 | mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) | ||
66 | efpc %r0,0 # test IEEE extract fpc instruction | ||
67 | oi 3(%r12),2 # set IEEE fpu flag | ||
68 | .Lchkfpu: | ||
69 | |||
70 | # | ||
71 | # find out if we have the CSP instruction | ||
72 | # | ||
73 | mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13) | ||
74 | la %r0,0 | ||
75 | lr %r1,%r0 | ||
76 | la %r2,4 | ||
77 | csp %r0,%r2 # Test CSP instruction | ||
78 | oi 3(%r12),8 # set CSP flag | ||
79 | .Lchkcsp: | ||
80 | |||
81 | # | ||
82 | # find out if we have the MVPG instruction | ||
83 | # | ||
84 | mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13) | ||
85 | sr %r0,%r0 | ||
86 | la %r1,0 | ||
87 | la %r2,0 | ||
88 | mvpg %r1,%r2 # Test CSP instruction | ||
89 | oi 3(%r12),16 # set MVPG flag | ||
90 | .Lchkmvpg: | ||
91 | |||
92 | # | ||
93 | # find out if we have the IDTE instruction | ||
94 | # | ||
95 | mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) | ||
96 | .long 0xb2b10000 # store facility list | ||
97 | tm 0xc8,0x08 # check bit for clearing-by-ASCE | ||
98 | bno .Lchkidte-.LPG1(%r13) | ||
99 | lhi %r1,2094 | ||
100 | lhi %r2,0 | ||
101 | .long 0xb98e2001 | ||
102 | oi 3(%r12),0x80 # set IDTE flag | ||
103 | .Lchkidte: | ||
104 | |||
105 | # | ||
106 | # find out if the diag 0x9c is available | ||
107 | # | ||
108 | mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13) | ||
109 | stap __LC_CPUID+4 # store cpu address | ||
110 | lh %r1,__LC_CPUID+4 | ||
111 | diag %r1,0,0x9c # test diag 0x9c | ||
112 | oi 2(%r12),1 # set diag9c flag | ||
113 | .Lchkdiag9c: | ||
114 | |||
115 | lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, | 60 | lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, |
116 | # virtual and never return ... | 61 | # virtual and never return ... |
117 | .align 8 | 62 | .align 8 |
@@ -132,13 +77,7 @@ startup_continue: | |||
132 | .long 0 # cr13: home space segment table | 77 | .long 0 # cr13: home space segment table |
133 | .long 0xc0000000 # cr14: machine check handling off | 78 | .long 0xc0000000 # cr14: machine check handling off |
134 | .long 0 # cr15: linkage stack operations | 79 | .long 0 # cr15: linkage stack operations |
135 | .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu | ||
136 | .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp | ||
137 | .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg | ||
138 | .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte | ||
139 | .Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c | ||
140 | .Lmchunk:.long memory_chunk | 80 | .Lmchunk:.long memory_chunk |
141 | .Lmflags:.long machine_flags | ||
142 | .Lbss_bgn: .long __bss_start | 81 | .Lbss_bgn: .long __bss_start |
143 | .Lbss_end: .long _end | 82 | .Lbss_end: .long _end |
144 | .Lparmaddr: .long PARMAREA | 83 | .Lparmaddr: .long PARMAREA |
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 79dccd206a6e..9c2c6f7d37e7 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S | |||
@@ -125,68 +125,6 @@ startup_continue: | |||
125 | # and create a kernel NSS if the SAVESYS= parm is defined | 125 | # and create a kernel NSS if the SAVESYS= parm is defined |
126 | # | 126 | # |
127 | brasl %r14,startup_init | 127 | brasl %r14,startup_init |
128 | # set program check new psw mask | ||
129 | mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) | ||
130 | larl %r12,machine_flags | ||
131 | # | ||
132 | # find out if we have the MVPG instruction | ||
133 | # | ||
134 | la %r1,0f-.LPG1(%r13) # set program check address | ||
135 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
136 | sgr %r0,%r0 | ||
137 | lghi %r1,0 | ||
138 | lghi %r2,0 | ||
139 | mvpg %r1,%r2 # test MVPG instruction | ||
140 | oi 7(%r12),16 # set MVPG flag | ||
141 | 0: | ||
142 | |||
143 | # | ||
144 | # find out if the diag 0x44 works in 64 bit mode | ||
145 | # | ||
146 | la %r1,0f-.LPG1(%r13) # set program check address | ||
147 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
148 | diag 0,0,0x44 # test diag 0x44 | ||
149 | oi 7(%r12),32 # set diag44 flag | ||
150 | 0: | ||
151 | |||
152 | # | ||
153 | # find out if we have the IDTE instruction | ||
154 | # | ||
155 | la %r1,0f-.LPG1(%r13) # set program check address | ||
156 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
157 | .long 0xb2b10000 # store facility list | ||
158 | tm 0xc8,0x08 # check bit for clearing-by-ASCE | ||
159 | bno 0f-.LPG1(%r13) | ||
160 | lhi %r1,2048 | ||
161 | lhi %r2,0 | ||
162 | .long 0xb98e2001 | ||
163 | oi 7(%r12),0x80 # set IDTE flag | ||
164 | 0: | ||
165 | |||
166 | # | ||
167 | # find out if the diag 0x9c is available | ||
168 | # | ||
169 | la %r1,0f-.LPG1(%r13) # set program check address | ||
170 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
171 | stap __LC_CPUID+4 # store cpu address | ||
172 | lh %r1,__LC_CPUID+4 | ||
173 | diag %r1,0,0x9c # test diag 0x9c | ||
174 | oi 6(%r12),1 # set diag9c flag | ||
175 | 0: | ||
176 | |||
177 | # | ||
178 | # find out if we have the MVCOS instruction | ||
179 | # | ||
180 | la %r1,0f-.LPG1(%r13) # set program check address | ||
181 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
182 | .short 0xc800 # mvcos 0(%r0),0(%r0),%r0 | ||
183 | .short 0x0000 | ||
184 | .short 0x0000 | ||
185 | 0: tm 0x8f,0x13 # special-operation exception? | ||
186 | bno 1f-.LPG1(%r13) # if yes, MVCOS is present | ||
187 | oi 6(%r12),2 # set MVCOS flag | ||
188 | 1: | ||
189 | |||
190 | lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, | 128 | lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, |
191 | # virtual and never return ... | 129 | # virtual and never return ... |
192 | .align 16 | 130 | .align 16 |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 024180e25e85..694c6546ce64 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(uaccess); | |||
73 | unsigned int console_mode = 0; | 73 | unsigned int console_mode = 0; |
74 | unsigned int console_devno = -1; | 74 | unsigned int console_devno = -1; |
75 | unsigned int console_irq = -1; | 75 | unsigned int console_irq = -1; |
76 | unsigned long machine_flags = 0; | 76 | unsigned long machine_flags; |
77 | unsigned long elf_hwcap = 0; | 77 | unsigned long elf_hwcap = 0; |
78 | char elf_platform[ELF_PLATFORM_SIZE]; | 78 | char elf_platform[ELF_PLATFORM_SIZE]; |
79 | 79 | ||
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h index aaf4b518b940..3a9e458fd8c3 100644 --- a/include/asm-s390/setup.h +++ b/include/asm-s390/setup.h | |||
@@ -59,23 +59,36 @@ extern unsigned int s390_noexec; | |||
59 | */ | 59 | */ |
60 | extern unsigned long machine_flags; | 60 | extern unsigned long machine_flags; |
61 | 61 | ||
62 | #define MACHINE_IS_VM (machine_flags & 1) | 62 | #define MACHINE_FLAG_VM (1UL << 0) |
63 | #define MACHINE_IS_P390 (machine_flags & 4) | 63 | #define MACHINE_FLAG_IEEE (1UL << 1) |
64 | #define MACHINE_HAS_MVPG (machine_flags & 16) | 64 | #define MACHINE_FLAG_P390 (1UL << 2) |
65 | #define MACHINE_IS_KVM (machine_flags & 64) | 65 | #define MACHINE_FLAG_CSP (1UL << 3) |
66 | #define MACHINE_HAS_IDTE (machine_flags & 128) | 66 | #define MACHINE_FLAG_MVPG (1UL << 4) |
67 | #define MACHINE_HAS_DIAG9C (machine_flags & 256) | 67 | #define MACHINE_FLAG_DIAG44 (1UL << 5) |
68 | #define MACHINE_FLAG_IDTE (1UL << 6) | ||
69 | #define MACHINE_FLAG_DIAG9C (1UL << 7) | ||
70 | #define MACHINE_FLAG_MVCOS (1UL << 8) | ||
71 | #define MACHINE_FLAG_KVM (1UL << 9) | ||
72 | |||
73 | #define MACHINE_IS_VM (machine_flags & MACHINE_FLAG_VM) | ||
74 | #define MACHINE_IS_KVM (machine_flags & MACHINE_FLAG_KVM) | ||
75 | #define MACHINE_IS_P390 (machine_flags & MACHINE_FLAG_P390) | ||
76 | #define MACHINE_HAS_DIAG9C (machine_flags & MACHINE_FLAG_DIAG9C) | ||
68 | 77 | ||
69 | #ifndef __s390x__ | 78 | #ifndef __s390x__ |
70 | #define MACHINE_HAS_IEEE (machine_flags & 2) | 79 | #define MACHINE_HAS_IEEE (machine_flags & MACHINE_FLAG_IEEE) |
71 | #define MACHINE_HAS_CSP (machine_flags & 8) | 80 | #define MACHINE_HAS_CSP (machine_flags & MACHINE_FLAG_CSP) |
81 | #define MACHINE_HAS_IDTE (0) | ||
72 | #define MACHINE_HAS_DIAG44 (1) | 82 | #define MACHINE_HAS_DIAG44 (1) |
83 | #define MACHINE_HAS_MVPG (machine_flags & MACHINE_FLAG_MVPG) | ||
73 | #define MACHINE_HAS_MVCOS (0) | 84 | #define MACHINE_HAS_MVCOS (0) |
74 | #else /* __s390x__ */ | 85 | #else /* __s390x__ */ |
75 | #define MACHINE_HAS_IEEE (1) | 86 | #define MACHINE_HAS_IEEE (1) |
76 | #define MACHINE_HAS_CSP (1) | 87 | #define MACHINE_HAS_CSP (1) |
77 | #define MACHINE_HAS_DIAG44 (machine_flags & 32) | 88 | #define MACHINE_HAS_IDTE (machine_flags & MACHINE_FLAG_IDTE) |
78 | #define MACHINE_HAS_MVCOS (machine_flags & 512) | 89 | #define MACHINE_HAS_DIAG44 (machine_flags & MACHINE_FLAG_DIAG44) |
90 | #define MACHINE_HAS_MVPG (1) | ||
91 | #define MACHINE_HAS_MVCOS (machine_flags & MACHINE_FLAG_MVCOS) | ||
79 | #endif /* __s390x__ */ | 92 | #endif /* __s390x__ */ |
80 | 93 | ||
81 | #define MACHINE_HAS_SCLP (!MACHINE_IS_P390) | 94 | #define MACHINE_HAS_SCLP (!MACHINE_IS_P390) |
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h index 8376b195a1b6..ae89cf2478fc 100644 --- a/include/asm-s390/smp.h +++ b/include/asm-s390/smp.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
20 | #include <asm/sigp.h> | 20 | #include <asm/sigp.h> |
21 | #include <asm/ptrace.h> | 21 | #include <asm/ptrace.h> |
22 | #include <asm/system.h> | ||
22 | 23 | ||
23 | /* | 24 | /* |
24 | s390 specific smp.c headers | 25 | s390 specific smp.c headers |
@@ -53,10 +54,7 @@ extern void machine_power_off_smp(void); | |||
53 | 54 | ||
54 | static inline __u16 hard_smp_processor_id(void) | 55 | static inline __u16 hard_smp_processor_id(void) |
55 | { | 56 | { |
56 | __u16 cpu_address; | 57 | return stap(); |
57 | |||
58 | asm volatile("stap %0" : "=m" (cpu_address)); | ||
59 | return cpu_address; | ||
60 | } | 58 | } |
61 | 59 | ||
62 | /* | 60 | /* |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index 79bdbf4b33a7..c819ae25a842 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -432,6 +432,14 @@ static inline unsigned int stfl(void) | |||
432 | return S390_lowcore.stfl_fac_list; | 432 | return S390_lowcore.stfl_fac_list; |
433 | } | 433 | } |
434 | 434 | ||
435 | static inline unsigned short stap(void) | ||
436 | { | ||
437 | unsigned short cpu_address; | ||
438 | |||
439 | asm volatile("stap %0" : "=m" (cpu_address)); | ||
440 | return cpu_address; | ||
441 | } | ||
442 | |||
435 | extern void (*_machine_restart)(char *command); | 443 | extern void (*_machine_restart)(char *command); |
436 | extern void (*_machine_halt)(void); | 444 | extern void (*_machine_halt)(void); |
437 | extern void (*_machine_power_off)(void); | 445 | extern void (*_machine_power_off)(void); |