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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility