Commit df1bd59c5cc247d1d02588ff0a4e86a0cc5f9733

Authored by Heiko Carstens
Committed by Martin Schwidefsky
1 parent 67b5c3eeb4

s390/mem_detect: limit memory detection loop to "mem=" parameter

The current memory detection loop will detect all present memory of
a machine. This is true even if the user specified the "mem=" parameter
on the kernel command line.
This can be a problem since the memory detection may cause a fully
populated host page table for the guest, even for those parts of the
memory that the guest will never use afterwards.

So fix this and only detect memory up to a user supplied "mem=" limit
if specified.

Reported-by: Michael Johanssen <johanssn@de.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

Showing 6 changed files with 25 additions and 9 deletions Side-by-side Diff

arch/s390/include/asm/setup.h
... ... @@ -46,7 +46,7 @@
46 46 extern int memory_end_set;
47 47 extern unsigned long memory_end;
48 48  
49   -void detect_memory_layout(struct mem_chunk chunk[]);
  49 +void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize);
50 50 void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
51 51 unsigned long size, int type);
52 52  
arch/s390/kernel/crash_dump.c
... ... @@ -88,7 +88,7 @@
88 88 struct mem_chunk *chunk_array;
89 89  
90 90 chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
91   - detect_memory_layout(chunk_array);
  91 + detect_memory_layout(chunk_array, 0);
92 92 create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK);
93 93 return chunk_array;
94 94 }
arch/s390/kernel/early.c
... ... @@ -482,7 +482,6 @@
482 482 detect_machine_facilities();
483 483 setup_topology();
484 484 sclp_facilities_detect();
485   - detect_memory_layout(memory_chunk);
486 485 #ifdef CONFIG_DYNAMIC_FTRACE
487 486 S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
488 487 #endif
arch/s390/kernel/setup.c
... ... @@ -1066,7 +1066,7 @@
1066 1066 memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
1067 1067  
1068 1068 parse_early_param();
1069   -
  1069 + detect_memory_layout(memory_chunk, memory_end);
1070 1070 os_info_init();
1071 1071 setup_ipl();
1072 1072 reserve_oldmem();
arch/s390/mm/mem_detect.c
... ... @@ -12,7 +12,7 @@
12 12  
13 13 #define ADDR2G (1ULL << 31)
14 14  
15   -static void find_memory_chunks(struct mem_chunk chunk[])
  15 +static void find_memory_chunks(struct mem_chunk chunk[], unsigned long maxsize)
16 16 {
17 17 unsigned long long memsize, rnmax, rzm;
18 18 unsigned long addr = 0, size;
... ... @@ -27,6 +27,8 @@
27 27 rzm = min(ADDR2G, rzm);
28 28 memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
29 29 }
  30 + if (maxsize)
  31 + memsize = memsize ? min((unsigned long)memsize, maxsize) : maxsize;
30 32 do {
31 33 size = 0;
32 34 type = tprot(addr);
... ... @@ -36,6 +38,8 @@
36 38 break;
37 39 } while (type == tprot(addr + size));
38 40 if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
  41 + if (memsize && (addr + size > memsize))
  42 + size = memsize - addr;
39 43 chunk[i].addr = addr;
40 44 chunk[i].size = size;
41 45 chunk[i].type = type;
... ... @@ -45,7 +49,20 @@
45 49 } while (addr < memsize && i < MEMORY_CHUNKS);
46 50 }
47 51  
48   -void detect_memory_layout(struct mem_chunk chunk[])
  52 +/**
  53 + * detect_memory_layout - fill mem_chunk array with memory layout data
  54 + * @chunk: mem_chunk array to be filled
  55 + * @maxsize: maximum address where memory detection should stop
  56 + *
  57 + * Fills the passed in memory chunk array with the memory layout of the
  58 + * machine. The array must have a size of at least MEMORY_CHUNKS and will
  59 + * be fully initialized afterwards.
  60 + * If the maxsize paramater has a value > 0 memory detection will stop at
  61 + * that address. It is guaranteed that all chunks have an ending address
  62 + * that is smaller than maxsize.
  63 + * If maxsize is 0 all memory will be detected.
  64 + */
  65 +void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize)
49 66 {
50 67 unsigned long flags, flags_dat, cr0;
51 68  
... ... @@ -69,7 +86,7 @@
69 86 }
70 87 __ctl_store(cr0, 0, 0);
71 88 __ctl_clear_bit(0, 28);
72   - find_memory_chunks(chunk);
  89 + find_memory_chunks(chunk, maxsize);
73 90 __ctl_load(cr0, 0, 0);
74 91 out:
75 92 __arch_local_irq_ssm(flags_dat);
drivers/s390/char/zcore.c
... ... @@ -426,7 +426,7 @@
426 426 GFP_KERNEL);
427 427 if (!chunk_array)
428 428 return -ENOMEM;
429   - detect_memory_layout(chunk_array);
  429 + detect_memory_layout(chunk_array, 0);
430 430 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
431 431 if (!buf) {
432 432 kfree(chunk_array);
... ... @@ -610,7 +610,7 @@
610 610 GFP_KERNEL);
611 611 if (!chunk_array)
612 612 return -ENOMEM;
613   - detect_memory_layout(chunk_array);
  613 + detect_memory_layout(chunk_array, 0);
614 614 for (i = 0; i < MEMORY_CHUNKS; i++) {
615 615 if (chunk_array[i].size == 0)
616 616 break;