aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r--arch/s390/kernel/setup.c69
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];
95int __initdata memory_end_set; 95int __initdata memory_end_set;
96unsigned long __initdata memory_end; 96unsigned long __initdata memory_end;
97 97
98unsigned long VMALLOC_START;
99EXPORT_SYMBOL(VMALLOC_START);
100
101unsigned long VMALLOC_END;
102EXPORT_SYMBOL(VMALLOC_END);
103
104struct page *vmemmap;
105EXPORT_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. */
99struct _lowcore *lowcore_ptr[NR_CPUS]; 108struct _lowcore *lowcore_ptr[NR_CPUS];
100EXPORT_SYMBOL(lowcore_ptr); 109EXPORT_SYMBOL(lowcore_ptr);
@@ -278,6 +287,15 @@ static int __init early_parse_mem(char *p)
278} 287}
279early_param("mem", early_parse_mem); 288early_param("mem", early_parse_mem);
280 289
290static 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}
297early_param("vmalloc", parse_vmalloc);
298
281unsigned int user_mode = HOME_SPACE_MODE; 299unsigned int user_mode = HOME_SPACE_MODE;
282EXPORT_SYMBOL_GPL(user_mode); 300EXPORT_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
480static void __init setup_memory_end(void) 497static 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
537void *restart_stack __attribute__((__section__(".data"))); 575void *restart_stack __attribute__((__section__(".data")));
@@ -655,7 +693,6 @@ static int __init verify_crash_base(unsigned long crash_base,
655static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size, 693static 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