aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2013-04-30 04:34:04 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-05-02 09:50:26 -0400
commitdf1bd59c5cc247d1d02588ff0a4e86a0cc5f9733 (patch)
tree619ab3b2ef639ebbcd102961c8710b852cd9adfc
parent67b5c3eeb4814bceb9a7e17fecb14ef59d511812 (diff)
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>
-rw-r--r--arch/s390/include/asm/setup.h2
-rw-r--r--arch/s390/kernel/crash_dump.c2
-rw-r--r--arch/s390/kernel/early.c1
-rw-r--r--arch/s390/kernel/setup.c2
-rw-r--r--arch/s390/mm/mem_detect.c23
-rw-r--r--drivers/s390/char/zcore.c4
6 files changed, 25 insertions, 9 deletions
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 270fcd0fbf1a..2765e40d8739 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -46,7 +46,7 @@ extern struct mem_chunk memory_chunk[];
46extern int memory_end_set; 46extern int memory_end_set;
47extern unsigned long memory_end; 47extern unsigned long memory_end;
48 48
49void detect_memory_layout(struct mem_chunk chunk[]); 49void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize);
50void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr, 50void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
51 unsigned long size, int type); 51 unsigned long size, int type);
52 52
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index fb8d8781a011..30b7f63aa4e8 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -88,7 +88,7 @@ static struct mem_chunk *get_memory_layout(void)
88 struct mem_chunk *chunk_array; 88 struct mem_chunk *chunk_array;
89 89
90 chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk)); 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 create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK); 92 create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK);
93 return chunk_array; 93 return chunk_array;
94} 94}
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index bda011e2f8ae..dc8770d7173c 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -482,7 +482,6 @@ void __init startup_init(void)
482 detect_machine_facilities(); 482 detect_machine_facilities();
483 setup_topology(); 483 setup_topology();
484 sclp_facilities_detect(); 484 sclp_facilities_detect();
485 detect_memory_layout(memory_chunk);
486#ifdef CONFIG_DYNAMIC_FTRACE 485#ifdef CONFIG_DYNAMIC_FTRACE
487 S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; 486 S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
488#endif 487#endif
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 555f1895972e..cdd9ec0a6fc0 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -1066,7 +1066,7 @@ void __init setup_arch(char **cmdline_p)
1066 memcpy(&uaccess, &uaccess_std, sizeof(uaccess)); 1066 memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
1067 1067
1068 parse_early_param(); 1068 parse_early_param();
1069 1069 detect_memory_layout(memory_chunk, memory_end);
1070 os_info_init(); 1070 os_info_init();
1071 setup_ipl(); 1071 setup_ipl();
1072 reserve_oldmem(); 1072 reserve_oldmem();
diff --git a/arch/s390/mm/mem_detect.c b/arch/s390/mm/mem_detect.c
index 854c08448de1..ec00576bf8d5 100644
--- a/arch/s390/mm/mem_detect.c
+++ b/arch/s390/mm/mem_detect.c
@@ -12,7 +12,7 @@
12 12
13#define ADDR2G (1ULL << 31) 13#define ADDR2G (1ULL << 31)
14 14
15static void find_memory_chunks(struct mem_chunk chunk[]) 15static void find_memory_chunks(struct mem_chunk chunk[], unsigned long maxsize)
16{ 16{
17 unsigned long long memsize, rnmax, rzm; 17 unsigned long long memsize, rnmax, rzm;
18 unsigned long addr = 0, size; 18 unsigned long addr = 0, size;
@@ -27,6 +27,8 @@ static void find_memory_chunks(struct mem_chunk chunk[])
27 rzm = min(ADDR2G, rzm); 27 rzm = min(ADDR2G, rzm);
28 memsize = memsize ? min(ADDR2G, memsize) : ADDR2G; 28 memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
29 } 29 }
30 if (maxsize)
31 memsize = memsize ? min((unsigned long)memsize, maxsize) : maxsize;
30 do { 32 do {
31 size = 0; 33 size = 0;
32 type = tprot(addr); 34 type = tprot(addr);
@@ -36,6 +38,8 @@ static void find_memory_chunks(struct mem_chunk chunk[])
36 break; 38 break;
37 } while (type == tprot(addr + size)); 39 } while (type == tprot(addr + size));
38 if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) { 40 if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
41 if (memsize && (addr + size > memsize))
42 size = memsize - addr;
39 chunk[i].addr = addr; 43 chunk[i].addr = addr;
40 chunk[i].size = size; 44 chunk[i].size = size;
41 chunk[i].type = type; 45 chunk[i].type = type;
@@ -45,7 +49,20 @@ static void find_memory_chunks(struct mem_chunk chunk[])
45 } while (addr < memsize && i < MEMORY_CHUNKS); 49 } while (addr < memsize && i < MEMORY_CHUNKS);
46} 50}
47 51
48void 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 */
65void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize)
49{ 66{
50 unsigned long flags, flags_dat, cr0; 67 unsigned long flags, flags_dat, cr0;
51 68
@@ -69,7 +86,7 @@ void detect_memory_layout(struct mem_chunk chunk[])
69 } 86 }
70 __ctl_store(cr0, 0, 0); 87 __ctl_store(cr0, 0, 0);
71 __ctl_clear_bit(0, 28); 88 __ctl_clear_bit(0, 28);
72 find_memory_chunks(chunk); 89 find_memory_chunks(chunk, maxsize);
73 __ctl_load(cr0, 0, 0); 90 __ctl_load(cr0, 0, 0);
74out: 91out:
75 __arch_local_irq_ssm(flags_dat); 92 __arch_local_irq_ssm(flags_dat);
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index d415ba7f26a6..9e5e14686e75 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -426,7 +426,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp)
426 GFP_KERNEL); 426 GFP_KERNEL);
427 if (!chunk_array) 427 if (!chunk_array)
428 return -ENOMEM; 428 return -ENOMEM;
429 detect_memory_layout(chunk_array); 429 detect_memory_layout(chunk_array, 0);
430 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL); 430 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
431 if (!buf) { 431 if (!buf) {
432 kfree(chunk_array); 432 kfree(chunk_array);
@@ -610,7 +610,7 @@ static int __init get_mem_info(unsigned long *mem, unsigned long *end)
610 GFP_KERNEL); 610 GFP_KERNEL);
611 if (!chunk_array) 611 if (!chunk_array)
612 return -ENOMEM; 612 return -ENOMEM;
613 detect_memory_layout(chunk_array); 613 detect_memory_layout(chunk_array, 0);
614 for (i = 0; i < MEMORY_CHUNKS; i++) { 614 for (i = 0; i < MEMORY_CHUNKS; i++) {
615 if (chunk_array[i].size == 0) 615 if (chunk_array[i].size == 0)
616 break; 616 break;