On 2011-12-21 12:12:54 Wed, Dave Anderson wrote:
----- Original Message -----
>
> And complicating matters even further, your patch presumes that the
> kernel has configured CONFIG_SPARSEMEM_EXTREME in conjunction with
> CONFIG_SPARSEMEM. Would it be possible for an s390x to be configured
> with just CONFIG_SPARSEMEM alone? If so, your patch breaks down.
>
> Or is there another way you can determine which MAX_PHYSMEM_BITS value
> is in use?
>
> Dave
>
Using your scheme, this is the best I can come up with (untested):
--- s390x.c 10 Nov 2011 14:37:15 -0000 1.57
+++ s390x.c 21 Dec 2011 17:07:20 -0000
@@ -282,6 +282,43 @@
}
}
+static int
+set_s390x_max_physmem_bits(void)
+{
+ int array_len, dimension;
+
+ if (!kernel_symbol_exists("mem_section"))
+ return TRUE;
+
+ if (!(array_len = get_array_length("mem_section", &dimension, 0))
+ return FALSE;
+
Agree, Makes sense.
+ /*
+ * If not CONFIG_SPARSEMEM_EXTREME, presume the older 42.
+ */
+ if (dimension) {
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_OLD;
+ return TRUE;
+ }
Even with max_physmem_bits = 46, it may be possible that newer kernel can be
built with CONFIG_SPARSEMEM and !CONFIG_SPARSEMEM_EXTREME. In which case
dimension can still hold +ve value and we may end up seletecting wrong
value for physmem_bits.
+
+ /*
+ * The older s390x kernels uses _MAX_PHYSMEM_BITS as 42 and the
+ * newer kernels uses 46 bits.
+ */
+ STRUCT_SIZE_INIT(mem_section, "mem_section");
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_OLD;
+ if ((array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT_EXTREME()))
+ || (array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT())))
+ return TRUE;
+
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_NEW;
+ if ((array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT_EXTREME()))
+ || (array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT())))
+ return TRUE;
+
+ return FALSE;
+}
+
The above code does compare array_len for both the conditions
CONFIG_SPARSEMEM_EXTREME and !CONFIG_SPARSEMEM_EXTREME for old/new
max_physmem_bits. However, with use of dimension value the above
logic can be more simpler like this:
diff --git a/s390x.c b/s390x.c
index 22e29a9..5b6a38e 100755
--- a/s390x.c
+++ b/s390x.c
@@ -282,6 +282,53 @@ static void s390x_process_elf_notes(void *note_ptr, unsigned long
size_note)
}
}
+static int
+set_s390x_max_physmem_bits(void)
+{
+ int array_len, dimension;
+
+ if (!kernel_symbol_exists("mem_section"))
+ return TRUE;
+
+ if (!(array_len = get_array_length("mem_section", &dimension, 0)))
+ return FALSE;
+
+ /*
+ * The older s390x kernels uses _MAX_PHYSMEM_BITS as 42 and the
+ * newer kernels uses 46 bits.
+ */
+
+ STRUCT_SIZE_INIT(mem_section, "mem_section");
+
+ /*
+ * !CONFIG_SPARSEMEM_EXTREME
+ */
+ if (dimension) {
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_OLD;
+ if (array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT()))
+ return TRUE;
+
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_NEW;
+ if (array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT()))
+ return TRUE;
+
+ return FALSE;
+ }
+
+ /*
+ * CONFIG_SPARSEMEM_EXTREME
+ */
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_OLD;
+ if (array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT_EXTREME()))
+ return TRUE;
+
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_NEW;
+ if (array_len == (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT_EXTREME()))
+ return TRUE;
+
+ return FALSE;
+}
+
/*
* Do all necessary machine-specific setup here. This is called several
* times during initialization.
What do you think?
Thanks,
-Mahesh.
--
Mahesh J Salgaonkar