[Crash-utility] [PATCH] x86_64: Make the conversion between 4level and 5level paging automatically

Dou Liyang douly.fnst at cn.fujitsu.com
Tue Jul 10 02:42:30 UTC 2018


Dear Dave,

At 07/09/2018 10:20 PM, Dave Anderson wrote:
[...]
> Since the "__pgtable_l5_enabled" symbol is a static data symbol located
> in the __START_KERNEL_map region, x86_64_VTOP() only needs the kernel's
> "phys_base" value in order to translate the symbol value into a
> physical address:
> 
>    ulong x86_64_VTOP(ulong vaddr)
>    {
>            if (vaddr >= __START_KERNEL_map)
>                    return ((vaddr) - (ulong)__START_KERNEL_map + machdep->machspec->phys_base);
>            else
>                    return ((vaddr) - PAGE_OFFSET);
>    }
> 
> So if the contents of "__pgtable_l5_enabled" is all that is needed,
> I think you can do something like:
> 
> 	case POST_RELOC:
> +		if (!(machdep->flags & VM_5LEVEL) &&
> +		    kernel_symbol_exists("__pgtable_l5_enabled")) {
> +			int l5_enabled;
> +                       readmem(symbol_value("__pgtable_l5_enabled"), KVADDR,
> +                                &l5_enabled, sizeof(int), "__pgtable_l5_enabled",
> +				FAULT_ON_ERROR);
> +
> +			if (l5_enabled) {
> +				... execute the relevant section from PRE_GDB ...
> +			}
> 
> which would be this section from PRE_GDB:
> 
>                  case VM_5LEVEL:
>                          machdep->machspec->userspace_top = USERSPACE_TOP_5LEVEL;
>                          machdep->machspec->page_offset = PAGE_OFFSET_5LEVEL;
>                          machdep->machspec->vmalloc_start_addr = VMALLOC_START_ADDR_5LEVEL;
>                          machdep->machspec->vmalloc_end = VMALLOC_END_5LEVEL;
>                          machdep->machspec->modules_vaddr = MODULES_VADDR_5LEVEL;
>                          machdep->machspec->modules_end = MODULES_END_5LEVEL;
>                          machdep->machspec->vmemmap_vaddr = VMEMMAP_VADDR_5LEVEL;
>                          machdep->machspec->vmemmap_end = VMEMMAP_END_5LEVEL;
>                          if (symbol_exists("vmemmap_populate"))
>                                  machdep->flags |= VMEMMAP;
>                          machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_5LEVEL;
>                          machdep->machspec->pgdir_shift = PGDIR_SHIFT_5LEVEL;
>                          machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD_5LEVEL;
>                          if ((machdep->machspec->p4d = (char *)malloc(PAGESIZE())) == NULL)
>                                  error(FATAL, "cannot malloc p4d space.");
>                          machdep->machspec->last_p4d_read = 0;
>                          machdep->uvtop = x86_64_uvtop_level4;  /* 5-level is optional per-task */
>                  }
>                  machdep->kvbase = (ulong)PAGE_OFFSET;
>                  machdep->identity_map_base = (ulong)PAGE_OFFSET;
> 
> The only things that I can think of that might be a problem is the
> readmem() of "__pgtable_l5_enabled" will need to get by this part
> of x86_64_kvtop() in order to use x86_64_VTOP():
> 
>                 if (!IS_VMALLOC_ADDR(kvaddr)) {
>                          *paddr = x86_64_VTOP(kvaddr);
>                          if (!verbose)
>                                  return TRUE;
>                 }
> 
> where IS_VMALLOC_ADDR() would still be using the 4-level addresses.
> But that could be worked around some way.

AFAIC, It doesn't matter, here, due to the vt->vmalloc_start is 0 at
this time, we always use the x86_64_VTOP().

         	if (!vt->vmalloc_start) {
                 	*paddr = x86_64_VTOP(kvaddr);
                 	return TRUE;
         	}

         	if (!IS_VMALLOC_ADDR(kvaddr)) {
                 	*paddr = x86_64_VTOP(kvaddr);
                 	if (!verbose)
                         	return TRUE;
         	}

> 
> Can you give that a test?
> 

Yes, I have tested this both in KDump and virsh dump cases. It can work
well. I will send v2 patch for you.

Thanks,
	dou.






More information about the Crash-utility mailing list