----- Original Message -----
Hello Dave and Mahesh,
We also tried to solve the problem and came up with an alternative
solution.
The function s390x_max_physmem_bits() solves the following equation:
array_len == NR_MEM_SECTIONS / SECTIONS_PER_ROOT
2^(MAX_PYSMEM_BITS - SECTION_SIZE_BITS)
---------------------------------------
== PAGE_SIZE
-------------------------
sizeof(struct mem_section)
This leads to the following:
MAX_PYSMEM_BITS == SECTION_SIZE_BITS + log2(array_len) +
log2(PAGE_SIZE)
- log2(sizeof(struct mem_section));
I tested the patch with 42 and 46 bits and for both it seems to work.
I will leave now for vacation and will return January the 9th 2012.
I leave it to you which solution to take.
No -- I leave to you guys to decide. I appreciate the simplicity of
your solution, but Mahesh's patch is easier to understand.
So please decide before you go home -- I was hoping to get a release
out today!
Merry Christmas!
Michael
PS: I think this patch also fixes a bug in verify_ptn()...
BTOP vs. PTOB :-)
Hey, you're right!
Dave
---
kernel.c | 2 +-
memory.c | 2 +-
s390x.c | 17 ++++++++++++++++-
3 files changed, 18 insertions(+), 3 deletions(-)
--- a/kernel.c
+++ b/kernel.c
@@ -275,7 +275,7 @@ kernel_init()
MEMBER_OFFSET_INIT(prio_array_nr_active, "prio_array",
"nr_active");
STRUCT_SIZE_INIT(runqueue, rqstruct);
STRUCT_SIZE_INIT(prio_array, "prio_array");
-
+ STRUCT_SIZE_INIT(mem_section, "mem_section");
MEMBER_OFFSET_INIT(rq_cfs, "rq", "cfs");
/*
--- a/memory.c
+++ b/memory.c
@@ -13601,7 +13601,7 @@ verify_pfn(ulong pfn)
for (i = machdep->max_physmem_bits; i < machdep->bits; i++)
mask |= ((physaddr_t)1 << i);
- if (mask & BTOP(pfn))
+ if (mask & PTOB(pfn))
return FALSE;
return TRUE;
--- a/s390x.c
+++ b/s390x.c
@@ -17,6 +17,7 @@
*/
#ifdef S390X
#include <elf.h>
+#include <math.h>
#include "defs.h"
#include "netdump.h"
@@ -283,6 +284,19 @@ static void s390x_process_elf_notes(void
}
/*
+ * The older s390x kernels use _MAX_PHYSMEM_BITS as 42 and the
+ * newer kernels use 46 bits. This function calculates the bits
+ * via a generic function.
+ */
+static int s390x_max_physmem_bits(void)
+{
+ unsigned long array_len = get_array_length("mem_section", NULL, 0);
+
+ return _SECTION_SIZE_BITS + log2(array_len) + 12 /* log2(PAGE_SIZE)
*/
+ - log2(SIZE(mem_section));
+}
+
+/*
* Do all necessary machine-specific setup here. This is called
several
* times during initialization.
*/
@@ -350,13 +364,14 @@ s390x_init(int when)
if (!machdep->hz)
machdep->hz = HZ;
machdep->section_size_bits = _SECTION_SIZE_BITS;
- machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
+ machdep->max_physmem_bits = s390x_max_physmem_bits();
s390x_offsets_init();
break;
case POST_INIT:
break;
}
+ fprintf(stderr, "XXX %d\n", machdep->max_physmem_bits);
}
/*