Commit 94c16366 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

s390/memory hotplug: prevent offline of active memory increments

In case a machine supports memory hotplug all active memory increments
present at IPL time have been initialized with a "usecount" of 1.
This is wrong if the memory increment size is larger than the memory
section size of the memory hotplug code. If that is the case the
usecount must be initialized with the number of memory sections that
fit into one memory increment.
Otherwise it is possible to put a memory increment into standby state
even if there are still active sections.
Afterwards addressing exceptions might happen which cause the kernel
to panic.
However even worse, if a memory increment was put into standby state
and afterwards into active state again, it's contents would have been
zeroed, leading to memory corruption.

This was only an issue for machines that support standby memory and
have at least 256GB memory.

This is broken since commit fdb1bb15 "[S390] sclp/memory hotplug: fix
initial usecount of increments".
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Cc: stable@vger.kernel.org # 2.6.39+
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 581618f2
...@@ -561,6 +561,8 @@ static void __init sclp_add_standby_memory(void) ...@@ -561,6 +561,8 @@ static void __init sclp_add_standby_memory(void)
add_memory_merged(0); add_memory_merged(0);
} }
#define MEM_SCT_SIZE (1UL << SECTION_SIZE_BITS)
static void __init insert_increment(u16 rn, int standby, int assigned) static void __init insert_increment(u16 rn, int standby, int assigned)
{ {
struct memory_increment *incr, *new_incr; struct memory_increment *incr, *new_incr;
...@@ -573,7 +575,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned) ...@@ -573,7 +575,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned)
new_incr->rn = rn; new_incr->rn = rn;
new_incr->standby = standby; new_incr->standby = standby;
if (!standby) if (!standby)
new_incr->usecount = 1; new_incr->usecount = rzm > MEM_SCT_SIZE ? rzm/MEM_SCT_SIZE : 1;
last_rn = 0; last_rn = 0;
prev = &sclp_mem_list; prev = &sclp_mem_list;
list_for_each_entry(incr, &sclp_mem_list, list) { list_for_each_entry(incr, &sclp_mem_list, list) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment