aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/early.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 03:59:21 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:02:17 -0400
commit23d1742179170b69e61ac9166248ffd64857e55a (patch)
tree5afb9b76b666f1543a6e8c42d760dfe0454e62e7 /arch/s390/kernel/early.c
parentef60cd13ecee0ccf2439d63013cbfc798aea2bb9 (diff)
[S390] Move memory detection code to own file.
Move memory detection code to own file and also simplify it. Also add an interface which can be called at any time to get the current memory layout. This interface is needed by our kernel internal system dumper. Cc: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Cc: Michael Holzheu <holzheu@de.ibm.com> Cc: Frank Munzert <munzert@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/early.c')
-rw-r--r--arch/s390/kernel/early.c109
1 files changed, 1 insertions, 108 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e22473993dc9..4c0ec7b46e37 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -192,100 +192,6 @@ static noinline __init void detect_machine_type(void)
192 machine_flags |= MACHINE_FLAG_KVM; 192 machine_flags |= MACHINE_FLAG_KVM;
193} 193}
194 194
195#ifdef CONFIG_64BIT
196static noinline __init int memory_fast_detect(void)
197{
198 unsigned long val0 = 0;
199 unsigned long val1 = 0xc;
200 int ret = -ENOSYS;
201
202 if (ipl_flags & IPL_NSS_VALID)
203 return -ENOSYS;
204
205 asm volatile(
206 " diag %1,%2,0x260\n"
207 "0: lhi %0,0\n"
208 "1:\n"
209 EX_TABLE(0b,1b)
210 : "+d" (ret), "+d" (val0), "+d" (val1) : : "cc");
211
212 if (ret || val0 != val1)
213 return -ENOSYS;
214
215 memory_chunk[0].size = val0 + 1;
216 return 0;
217}
218#else
219static inline int memory_fast_detect(void)
220{
221 return -ENOSYS;
222}
223#endif
224
225static inline __init unsigned long __tprot(unsigned long addr)
226{
227 int cc = -1;
228
229 asm volatile(
230 " tprot 0(%1),0\n"
231 "0: ipm %0\n"
232 " srl %0,28\n"
233 "1:\n"
234 EX_TABLE(0b,1b)
235 : "+d" (cc) : "a" (addr) : "cc");
236 return (unsigned long)cc;
237}
238
239/* Checking memory in 128KB increments. */
240#define CHUNK_INCR (1UL << 17)
241#define ADDR2G (1UL << 31)
242
243static noinline __init void find_memory_chunks(unsigned long memsize)
244{
245 unsigned long addr = 0, old_addr = 0;
246 unsigned long old_cc = CHUNK_READ_WRITE;
247 unsigned long cc;
248 int chunk = 0;
249
250 while (chunk < MEMORY_CHUNKS) {
251 cc = __tprot(addr);
252 while (cc == old_cc) {
253 addr += CHUNK_INCR;
254 if (memsize && addr >= memsize)
255 break;
256#ifndef CONFIG_64BIT
257 if (addr == ADDR2G)
258 break;
259#endif
260 cc = __tprot(addr);
261 }
262
263 if (old_addr != addr &&
264 (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) {
265 memory_chunk[chunk].addr = old_addr;
266 memory_chunk[chunk].size = addr - old_addr;
267 memory_chunk[chunk].type = old_cc;
268 chunk++;
269 }
270
271 old_addr = addr;
272 old_cc = cc;
273
274#ifndef CONFIG_64BIT
275 if (addr == ADDR2G)
276 break;
277#endif
278 /*
279 * Finish memory detection at the first hole
280 * if storage size is unknown.
281 */
282 if (cc == -1UL && !memsize)
283 break;
284 if (memsize && addr >= memsize)
285 break;
286 }
287}
288
289static __init void early_pgm_check_handler(void) 195static __init void early_pgm_check_handler(void)
290{ 196{
291 unsigned long addr; 197 unsigned long addr;
@@ -465,8 +371,6 @@ static void __init setup_boot_command_line(void)
465 */ 371 */
466void __init startup_init(void) 372void __init startup_init(void)
467{ 373{
468 unsigned long long memsize;
469
470 ipl_save_parameters(); 374 ipl_save_parameters();
471 rescue_initrd(); 375 rescue_initrd();
472 clear_bss_section(); 376 clear_bss_section();
@@ -486,18 +390,7 @@ void __init startup_init(void)
486 detect_diag44(); 390 detect_diag44();
487 detect_machine_facilities(); 391 detect_machine_facilities();
488 setup_hpage(); 392 setup_hpage();
489 sclp_read_info_early();
490 sclp_facilities_detect(); 393 sclp_facilities_detect();
491 memsize = sclp_memory_detect(); 394 detect_memory_layout(memory_chunk);
492#ifndef CONFIG_64BIT
493 /*
494 * Can't deal with more than 2G in 31 bit addressing mode, so
495 * limit the value in order to avoid strange side effects.
496 */
497 if (memsize > ADDR2G)
498 memsize = ADDR2G;
499#endif
500 if (memory_fast_detect() < 0)
501 find_memory_chunks((unsigned long) memsize);
502 lockdep_on(); 395 lockdep_on();
503} 396}