[PATCH] makedumpfile: ARM: get correct mem_map offset

Atsushi Kumagai kumagai-atsushi at mxc.nes.nec.co.jp
Thu May 15 01:21:16 PDT 2014


>>> When converting paddr to pfn, makedumpfile firstly minuses the
>>> offset of physical memory, and then do the right shift. But the
>>> kernel only does the right shift.

(This is a trivial comment)
makedumpfile do the right shift first, this description isn't right.

  #define paddr_to_pfn(X) \
          (((unsigned long long)(X) >> PAGESHIFT()) - ARCH_PFN_OFFSET)

>> Did you mean the patch below is wrong?
>>
>>   commit 1e93ee75f9d47c219e833210eb31e4a747cc3a8d
>>   Author: Mika Westerberg <ext-mika.1.westerberg at nokia.com>
>>   Date:   Tue Jun 22 09:59:10 2010 +0300
>>
>>       use ARCH_PFN_OFFSET for pfn_to_paddr/paddr_to_pfn translations
>>
>> Your description sounds we should fix the way to convert paddr to pfn,
>> but there is no such fix in your patch.
>
>
>Yes, my first version does just as what you say. But the patch is huge.
>I thing this patch is much better.
>
>Though commit 1e93ee75f9d47c219e833210eb31e4a747cc3a8d brings some problems
>. But we can easy fix them.
>
>
>Make my platform for example: ARCH_PFN_OFFSET=0x80000 sparse memory model.
>mem 1G ; SECTION_SIZE_BITS 26
>
> (a) for the kernel
>
>    section number |phy start |  start pfn   | end pfn  |  valid  | mem_section  	|
>	0	   |0	      |   0          |  3fff    |   0	  |   [0]	|
> 	1	   |4000000   |   4000       |  7fff    |   0	  |   [1]	|
>	2	   |8000000   |   8000       |  bfff    |   0	  |   [2]	|
>
>    [cut ...]
>
>       32 	   |80000000  |  80000	     | 83fff	|   1	  |  [32]	|
>       33 	   |84000000  |  84000	     | 87fff	|   1	  |  [33]	|
>
>    [cut ...]
>
>       47 	   |bfc00000  |  bfc000	     | bffff	|   1	  |  [47]	|
>
>
>  (b) for makedumpfile
>
>
>       0	   |80000000  |    0         |  3fff    |   0	  |   [0]	|
>       1 	   |84000000  |  4000        |  7fff    |   0	  |   [1]	|
>
>    [cut ...]
>
>       15 	   |bfc00000  |  3c000       | 3ffff	|   1	  |  [15]	|
>
>
>So makedumpfile removes the offset of section number and pfn. The relationship between
>pfn and section number remains as before. So this will not introduce problem.
>
>But the section nember and mem_section array do not match each other.
>
>For paddr 80000000
>	kernel        : pfn 8000: mem_section: 32
>	makedumpfile  : pfn 0   : mem_section: 0
>
>And we do not remove the offset of array mem_section. So makedumofile can not
>get the right page struct. When fix this offset, everything is ok.

Thanks for your explanation, I understand the sparse_mem case.

>But If we revert 1e93ee75f9d:
>
>  (a) codes likes "for(pfn = 0" ,"for_each_cycle(0" and "for (section_nr = 0"  should be changed;
>  (b) Due to "set_bit_on_1st_bitmap(pfn, cycle)", we will waste some bits.
>  (c) crash utility should also be changed.
>
>BTW, when ARCH_PFN_OFFSET=0, section nember and mem_section matches each other..
>So no problem was intrduced
>
>>
>>> For the cases of ARCH_PFN_OFFSET=0 or non sparse memormy model,
>>> this introduces no problem.
>>>
>>> But for my arma9 platform with ARCH_PFN_OFFSET=0x80000 and sparse
>>> memory model. Makedumfile can not get the mem_map correctly. It it
>>> due to there is still offset for mem_map array.
>>
>> Why the other memory models are OK? There is no offset even if ARCH_PFN_OFFSET!=0?
>> I need more explanation to understand this issue.
>
>(1) For flatmem, the mem_map is continuous, And the start address of mem_map comes from
>the kernel symbol.
>
>For paddr 80000000
>	kernel        : pfn 8000: mem_map[0]
>	makedumpfile  : pfn 0   : mem_map[0]
>
>This will not introduce problem.

I understand that alloc_node_mem_map() allocates mem_map for flatmem and it
considers ARCH_PFN_OFFSET like:

        if (pgdat == NODE_DATA(0)) {
                mem_map = NODE_DATA(0)->node_mem_map;
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
                if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
                        mem_map -= (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
        }

So there is no problem in this model since the top of mem_map corresponds to
ARCH_PFN_OFFSET, right?

>(2) For discontigmem, it manages the mem_map with node_memblk. commit
>1e93ee75f9d47c21 also does no harm.

alloc_node_mem_map() allocates mem_map also for discontigmem, but I can't find
any codes to consider ARCH_PFN_OFFSET for this model.
So I suspect the mismatch between the pfn for makedumpfile and the actual content
of mem_map can exist. Could you explain why this case is OK in more detail?


Thanks
Atsushi Kumagai

>What do you think?
>
>Thanks,
>Liu Hua
>
>>
>>
>> Thanks
>> Atsushi Kumagai
>>
>>>
>>> This patch introduces the offset of the mem_map.
>>>
>>> But I have no environment to test this patch for other paltfrom.
>>> So I am not sure this patch works on other platforms.
>>>
>>> Signed-off-by: Liu Hua <sdu.liu at huawei.com>
>>> ---
>>> makedumpfile.c | 6 ++++--
>>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/makedumpfile.c b/makedumpfile.c
>>> index 94515f6..6cf6e24 100644
>>> --- a/makedumpfile.c
>>> +++ b/makedumpfile.c
>>> @@ -2807,6 +2807,7 @@ int
>>> get_mm_sparsemem(void)
>>> {
>>> 	unsigned int section_nr, mem_section_size, num_section;
>>> +	unsigned int section_start;
>>> 	mdf_pfn_t pfn_start, pfn_end;
>>> 	unsigned long section, mem_map;
>>> 	unsigned long *mem_sec = NULL;
>>> @@ -2817,6 +2818,7 @@ get_mm_sparsemem(void)
>>> 	 * Get the address of the symbol "mem_section".
>>> 	 */
>>> 	num_section = divideup(info->max_mapnr, PAGES_PER_SECTION());
>>> +	section_start = ARCH_PFN_OFFSET / PAGES_PER_SECTION();
>>> 	if (is_sparsemem_extreme()) {
>>> 		info->sections_per_root = _SECTIONS_PER_ROOT_EXTREME();
>>> 		mem_section_size = sizeof(void *) * NR_SECTION_ROOTS();
>>> @@ -2842,7 +2844,7 @@ get_mm_sparsemem(void)
>>> 		goto out;
>>> 	}
>>> 	for (section_nr = 0; section_nr < num_section; section_nr++) {
>>> -		section = nr_to_section(section_nr, mem_sec);
>>> +		section = nr_to_section(section_nr + section_start, mem_sec);
>>> 		if (section == NOT_KV_ADDR) {
>>> 			mem_map = NOT_MEMMAP_ADDR;
>>> 		} else {
>>> @@ -2851,7 +2853,7 @@ get_mm_sparsemem(void)
>>> 				mem_map = NOT_MEMMAP_ADDR;
>>> 			} else {
>>> 				mem_map = sparse_decode_mem_map(mem_map,
>>> -								section_nr);
>>> +								section_nr + section_start);
>>> 				if (!is_kvaddr(mem_map))
>>> 					mem_map = NOT_MEMMAP_ADDR;
>>> 			}
>>> --
>>> 1.9.0
>>
>>
>


More information about the kexec mailing list