[PATCH] crash: s390x: Auto-detect the correct MAX_PHYSMEM_BITS used in vmcore being analyzed

Dave Anderson anderson at redhat.com
Thu Dec 22 08:47:22 EST 2011



----- 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);
>  }
>  
>  /*
> 
> 



More information about the kexec mailing list