diff options
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r-- | arch/s390/kernel/setup.c | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f11d1b037c5..354de0763ef 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -95,6 +95,15 @@ struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS]; | |||
95 | int __initdata memory_end_set; | 95 | int __initdata memory_end_set; |
96 | unsigned long __initdata memory_end; | 96 | unsigned long __initdata memory_end; |
97 | 97 | ||
98 | unsigned long VMALLOC_START; | ||
99 | EXPORT_SYMBOL(VMALLOC_START); | ||
100 | |||
101 | unsigned long VMALLOC_END; | ||
102 | EXPORT_SYMBOL(VMALLOC_END); | ||
103 | |||
104 | struct page *vmemmap; | ||
105 | EXPORT_SYMBOL(vmemmap); | ||
106 | |||
98 | /* An array with a pointer to the lowcore of every CPU. */ | 107 | /* An array with a pointer to the lowcore of every CPU. */ |
99 | struct _lowcore *lowcore_ptr[NR_CPUS]; | 108 | struct _lowcore *lowcore_ptr[NR_CPUS]; |
100 | EXPORT_SYMBOL(lowcore_ptr); | 109 | EXPORT_SYMBOL(lowcore_ptr); |
@@ -278,6 +287,15 @@ static int __init early_parse_mem(char *p) | |||
278 | } | 287 | } |
279 | early_param("mem", early_parse_mem); | 288 | early_param("mem", early_parse_mem); |
280 | 289 | ||
290 | static int __init parse_vmalloc(char *arg) | ||
291 | { | ||
292 | if (!arg) | ||
293 | return -EINVAL; | ||
294 | VMALLOC_END = (memparse(arg, &arg) + PAGE_SIZE - 1) & PAGE_MASK; | ||
295 | return 0; | ||
296 | } | ||
297 | early_param("vmalloc", parse_vmalloc); | ||
298 | |||
281 | unsigned int user_mode = HOME_SPACE_MODE; | 299 | unsigned int user_mode = HOME_SPACE_MODE; |
282 | EXPORT_SYMBOL_GPL(user_mode); | 300 | EXPORT_SYMBOL_GPL(user_mode); |
283 | 301 | ||
@@ -383,7 +401,6 @@ setup_lowcore(void) | |||
383 | __ctl_set_bit(14, 29); | 401 | __ctl_set_bit(14, 29); |
384 | } | 402 | } |
385 | #else | 403 | #else |
386 | lc->cmf_hpp = -1ULL; | ||
387 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; | 404 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; |
388 | #endif | 405 | #endif |
389 | lc->sync_enter_timer = S390_lowcore.sync_enter_timer; | 406 | lc->sync_enter_timer = S390_lowcore.sync_enter_timer; |
@@ -479,8 +496,7 @@ EXPORT_SYMBOL_GPL(real_memory_size); | |||
479 | 496 | ||
480 | static void __init setup_memory_end(void) | 497 | static void __init setup_memory_end(void) |
481 | { | 498 | { |
482 | unsigned long memory_size; | 499 | unsigned long vmax, vmalloc_size, tmp; |
483 | unsigned long max_mem; | ||
484 | int i; | 500 | int i; |
485 | 501 | ||
486 | 502 | ||
@@ -490,12 +506,9 @@ static void __init setup_memory_end(void) | |||
490 | memory_end_set = 1; | 506 | memory_end_set = 1; |
491 | } | 507 | } |
492 | #endif | 508 | #endif |
493 | memory_size = 0; | 509 | real_memory_size = 0; |
494 | memory_end &= PAGE_MASK; | 510 | memory_end &= PAGE_MASK; |
495 | 511 | ||
496 | max_mem = memory_end ? min(VMEM_MAX_PHYS, memory_end) : VMEM_MAX_PHYS; | ||
497 | memory_end = min(max_mem, memory_end); | ||
498 | |||
499 | /* | 512 | /* |
500 | * Make sure all chunks are MAX_ORDER aligned so we don't need the | 513 | * Make sure all chunks are MAX_ORDER aligned so we don't need the |
501 | * extra checks that HOLES_IN_ZONE would require. | 514 | * extra checks that HOLES_IN_ZONE would require. |
@@ -515,23 +528,48 @@ static void __init setup_memory_end(void) | |||
515 | chunk->addr = start; | 528 | chunk->addr = start; |
516 | chunk->size = end - start; | 529 | chunk->size = end - start; |
517 | } | 530 | } |
531 | real_memory_size = max(real_memory_size, | ||
532 | chunk->addr + chunk->size); | ||
518 | } | 533 | } |
519 | 534 | ||
535 | /* Choose kernel address space layout: 2, 3, or 4 levels. */ | ||
536 | #ifdef CONFIG_64BIT | ||
537 | vmalloc_size = VMALLOC_END ?: 128UL << 30; | ||
538 | tmp = (memory_end ?: real_memory_size) / PAGE_SIZE; | ||
539 | tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size; | ||
540 | if (tmp <= (1UL << 42)) | ||
541 | vmax = 1UL << 42; /* 3-level kernel page table */ | ||
542 | else | ||
543 | vmax = 1UL << 53; /* 4-level kernel page table */ | ||
544 | #else | ||
545 | vmalloc_size = VMALLOC_END ?: 96UL << 20; | ||
546 | vmax = 1UL << 31; /* 2-level kernel page table */ | ||
547 | #endif | ||
548 | /* vmalloc area is at the end of the kernel address space. */ | ||
549 | VMALLOC_END = vmax; | ||
550 | VMALLOC_START = vmax - vmalloc_size; | ||
551 | |||
552 | /* Split remaining virtual space between 1:1 mapping & vmemmap array */ | ||
553 | tmp = VMALLOC_START / (PAGE_SIZE + sizeof(struct page)); | ||
554 | tmp = VMALLOC_START - tmp * sizeof(struct page); | ||
555 | tmp &= ~((vmax >> 11) - 1); /* align to page table level */ | ||
556 | tmp = min(tmp, 1UL << MAX_PHYSMEM_BITS); | ||
557 | vmemmap = (struct page *) tmp; | ||
558 | |||
559 | /* Take care that memory_end is set and <= vmemmap */ | ||
560 | memory_end = min(memory_end ?: real_memory_size, tmp); | ||
561 | |||
562 | /* Fixup memory chunk array to fit into 0..memory_end */ | ||
520 | for (i = 0; i < MEMORY_CHUNKS; i++) { | 563 | for (i = 0; i < MEMORY_CHUNKS; i++) { |
521 | struct mem_chunk *chunk = &memory_chunk[i]; | 564 | struct mem_chunk *chunk = &memory_chunk[i]; |
522 | 565 | ||
523 | real_memory_size = max(real_memory_size, | 566 | if (chunk->addr >= memory_end) { |
524 | chunk->addr + chunk->size); | ||
525 | if (chunk->addr >= max_mem) { | ||
526 | memset(chunk, 0, sizeof(*chunk)); | 567 | memset(chunk, 0, sizeof(*chunk)); |
527 | continue; | 568 | continue; |
528 | } | 569 | } |
529 | if (chunk->addr + chunk->size > max_mem) | 570 | if (chunk->addr + chunk->size > memory_end) |
530 | chunk->size = max_mem - chunk->addr; | 571 | chunk->size = memory_end - chunk->addr; |
531 | memory_size = max(memory_size, chunk->addr + chunk->size); | ||
532 | } | 572 | } |
533 | if (!memory_end) | ||
534 | memory_end = memory_size; | ||
535 | } | 573 | } |
536 | 574 | ||
537 | void *restart_stack __attribute__((__section__(".data"))); | 575 | void *restart_stack __attribute__((__section__(".data"))); |
@@ -655,7 +693,6 @@ static int __init verify_crash_base(unsigned long crash_base, | |||
655 | static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size, | 693 | static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size, |
656 | int type) | 694 | int type) |
657 | { | 695 | { |
658 | |||
659 | create_mem_hole(memory_chunk, addr, size, type); | 696 | create_mem_hole(memory_chunk, addr, size, type); |
660 | } | 697 | } |
661 | 698 | ||