]> git.openfabrics.org - ~emulex/infiniband.git/commitdiff
s390/mem_detect: limit memory detection loop to "mem=" parameter
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Tue, 30 Apr 2013 08:34:04 +0000 (10:34 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 2 May 2013 13:50:26 +0000 (15:50 +0200)
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>
arch/s390/include/asm/setup.h
arch/s390/kernel/crash_dump.c
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/mm/mem_detect.c
drivers/s390/char/zcore.c

index 270fcd0fbf1aa3ca95efcf98658da13c94696954..2765e40d8739ef36045b4c922f63dd3333f6c13f 100644 (file)
@@ -46,7 +46,7 @@ extern struct mem_chunk memory_chunk[];
 extern int memory_end_set;
 extern unsigned long memory_end;
 
-void detect_memory_layout(struct mem_chunk chunk[]);
+void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize);
 void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
                     unsigned long size, int type);
 
index fb8d8781a0118574c236dd4ade4548ac4c25f5b2..30b7f63aa4e83217af59e2bc02c66e597d6456c0 100644 (file)
@@ -88,7 +88,7 @@ static struct mem_chunk *get_memory_layout(void)
        struct mem_chunk *chunk_array;
 
        chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
-       detect_memory_layout(chunk_array);
+       detect_memory_layout(chunk_array, 0);
        create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK);
        return chunk_array;
 }
index bda011e2f8ae99f5c1dc28bc49564c81028fd107..dc8770d7173c83aec5b3475d748eee99d99e60b7 100644 (file)
@@ -482,7 +482,6 @@ void __init startup_init(void)
        detect_machine_facilities();
        setup_topology();
        sclp_facilities_detect();
-       detect_memory_layout(memory_chunk);
 #ifdef CONFIG_DYNAMIC_FTRACE
        S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
 #endif
index 555f1895972eb1588a2f6b3d3d09bfa2d6e450ea..cdd9ec0a6fc0df6ee63fd9421a589eef3a776fe1 100644 (file)
@@ -1066,7 +1066,7 @@ void __init setup_arch(char **cmdline_p)
                memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
 
        parse_early_param();
-
+       detect_memory_layout(memory_chunk, memory_end);
        os_info_init();
        setup_ipl();
        reserve_oldmem();
index 854c08448de122485f336c8a3af3e1dabb1bd60a..ec00576bf8d5f3fce6174818a3aff1fd64fa682c 100644 (file)
@@ -12,7 +12,7 @@
 
 #define ADDR2G (1ULL << 31)
 
-static void find_memory_chunks(struct mem_chunk chunk[])
+static void find_memory_chunks(struct mem_chunk chunk[], unsigned long maxsize)
 {
        unsigned long long memsize, rnmax, rzm;
        unsigned long addr = 0, size;
@@ -27,6 +27,8 @@ static void find_memory_chunks(struct mem_chunk chunk[])
                rzm = min(ADDR2G, rzm);
                memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
        }
+       if (maxsize)
+               memsize = memsize ? min((unsigned long)memsize, maxsize) : maxsize;
        do {
                size = 0;
                type = tprot(addr);
@@ -36,6 +38,8 @@ static void find_memory_chunks(struct mem_chunk chunk[])
                                break;
                } while (type == tprot(addr + size));
                if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
+                       if (memsize && (addr + size > memsize))
+                               size = memsize - addr;
                        chunk[i].addr = addr;
                        chunk[i].size = size;
                        chunk[i].type = type;
@@ -45,7 +49,20 @@ static void find_memory_chunks(struct mem_chunk chunk[])
        } while (addr < memsize && i < MEMORY_CHUNKS);
 }
 
-void detect_memory_layout(struct mem_chunk chunk[])
+/**
+ * detect_memory_layout - fill mem_chunk array with memory layout data
+ * @chunk: mem_chunk array to be filled
+ * @maxsize: maximum address where memory detection should stop
+ *
+ * Fills the passed in memory chunk array with the memory layout of the
+ * machine. The array must have a size of at least MEMORY_CHUNKS and will
+ * be fully initialized afterwards.
+ * If the maxsize paramater has a value > 0 memory detection will stop at
+ * that address. It is guaranteed that all chunks have an ending address
+ * that is smaller than maxsize.
+ * If maxsize is 0 all memory will be detected.
+ */
+void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize)
 {
        unsigned long flags, flags_dat, cr0;
 
@@ -69,7 +86,7 @@ void detect_memory_layout(struct mem_chunk chunk[])
        }
        __ctl_store(cr0, 0, 0);
        __ctl_clear_bit(0, 28);
-       find_memory_chunks(chunk);
+       find_memory_chunks(chunk, maxsize);
        __ctl_load(cr0, 0, 0);
 out:
        __arch_local_irq_ssm(flags_dat);
index d415ba7f26a6807b74cce10fac13d08501a33496..9e5e14686e75b6ff37bfbe9faa555470c8263ab7 100644 (file)
@@ -426,7 +426,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp)
                              GFP_KERNEL);
        if (!chunk_array)
                return -ENOMEM;
-       detect_memory_layout(chunk_array);
+       detect_memory_layout(chunk_array, 0);
        buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
        if (!buf) {
                kfree(chunk_array);
@@ -610,7 +610,7 @@ static int __init get_mem_info(unsigned long *mem, unsigned long *end)
                              GFP_KERNEL);
        if (!chunk_array)
                return -ENOMEM;
-       detect_memory_layout(chunk_array);
+       detect_memory_layout(chunk_array, 0);
        for (i = 0; i < MEMORY_CHUNKS; i++) {
                if (chunk_array[i].size == 0)
                        break;