aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2013-04-30 10:34:04 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-05-02 15:50:26 +0200
commitdf1bd59c5cc247d1d02588ff0a4e86a0cc5f9733 (patch)
tree619ab3b2ef639ebbcd102961c8710b852cd9adfc /arch/s390/mm
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>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/mem_detect.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/arch/s390/mm/mem_detect.c b/arch/s390/mm/mem_detect.c
index 854c08448de..ec00576bf8d 100644
--- a/arch/s390/mm/mem_detect.c
+++ b/arch/s390/mm/mem_detect.c
@@ -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);