[Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values
Atsushi Kumagai
ats-kumagai at wm.jp.nec.com
Thu Dec 8 23:35:55 PST 2016
Hello Pratyush,
>---
> arch/x86_64.c | 42 ++++++++----------------------------------
> makedumpfile.h | 4 ++--
> 2 files changed, 10 insertions(+), 36 deletions(-)
>
>diff --git a/arch/x86_64.c b/arch/x86_64.c
>index eba725e41aac..9afa38fd141a 100644
>--- a/arch/x86_64.c
>+++ b/arch/x86_64.c
>@@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
> {
> unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
> unsigned long pte_paddr, pte;
>+ unsigned long phys_base;
>+
>+ if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>+ phys_base = info->phys_base;
>+ else
>+ phys_base = 0;
>
> if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
> ERRMSG("Can't get the symbol of init_level4_pgt.\n");
>@@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
> /*
> * Get PGD.
> */
>- page_dir = SYMBOL(init_level4_pgt);
>+ page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
I found that this change breaks the backward compatibility for
kernel 2.6.21 or older since phys_base was introduced in kernel 2.6.22
by the commit below:
commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <vgoyal at in.ibm.com>
Date: Wed May 2 19:27:07 2007 +0200
[PATCH] x86-64: Relocatable Kernel Support
There is no problem if phys_base is always 0 in older kernel, but
get_phys_base_x86_64() calculates "phys_base = 0x100000" from my vmcore:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
NOTE 0x0000000000000190 0x0000000000000000 0x0000000000000000
0x0000000000000590 0x0000000000000590 0
LOAD 0x0000000000000720 0xffffffff80000000 0x0000000000100000 // CONFIG_PHYSICAL_START = 0x100000
0x00000000008b2000 0x00000000008b2000 RWE 0
LOAD 0x00000000008b2720 0xffff810000000000 0x0000000000000000
0x00000000000a0000 0x00000000000a0000 RWE 0
LOAD 0x0000000000952720 0xffff810000100000 0x0000000000100000
0x0000000000f00000 0x0000000000f00000 RWE 0
LOAD 0x0000000001852720 0xffff810005000000 0x0000000005000000
0x00000000caf70000 0x00000000caf70000 RWE 0
LOAD 0x00000000cc7c2720 0xffff810100000000 0x0000000100000000
0x0000000070000000 0x0000000070000000 RWE 0
Of course we shouldn't use that invalid phys_base:
crash> sym init_level4_pgt
ffffffff80101000 (T) init_level4_pgt
crash> vtop ffffffff80101000
VIRTUAL PHYSICAL
ffffffff80101000 101000 // just "VIRTUAL - __START_KERNEL_map"
PML4 DIRECTORY: ffffffff80101000
PAGE DIRECTORY: 103027
PUD: 103ff0 => 105027
PMD: 105000 => 1e3
PAGE: 0 (2MB)
PTE PHYSICAL FLAGS
1e3 0 (PRESENT|RW|ACCESSED|DIRTY|PSE|GLOBAL)
PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffff810005004838 101000 0 0 1 400
crash>
At first I thought about setting 0 to phys_base if the kernel is
older than 2.6.22, but unfortunately we can't get the kernel version
before getting correct phys_base since VtoP is necessary to read
system_utsname.
(and 2.6.21 doesn't have VMCOREINFO, OSRELEASE can't be used too.)
Do you have any ideas for this issue ?
Thanks,
Atsushi Kumagai
> page_dir += pml4_index(vaddr) * sizeof(unsigned long);
>- if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
>+ if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
> ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
> return NOT_PADDR;
> }
>@@ -285,38 +291,6 @@ vtop4_x86_64(unsigned long vaddr)
> return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
> }
>
>-unsigned long long
>-vaddr_to_paddr_x86_64(unsigned long vaddr)
>-{
>- unsigned long phys_base;
>- unsigned long long paddr;
>-
>- /*
>- * Check the relocatable kernel.
>- */
>- if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>- phys_base = info->phys_base;
>- else
>- phys_base = 0;
>-
>- if (is_vmalloc_addr_x86_64(vaddr)) {
>- if ((paddr = vtop4_x86_64(vaddr)) == NOT_PADDR) {
>- ERRMSG("Can't convert a virtual address(%lx) to " \
>- "physical address.\n", vaddr);
>- return NOT_PADDR;
>- }
>- } else if (vaddr >= __START_KERNEL_map) {
>- paddr = vaddr - __START_KERNEL_map + phys_base;
>-
>- } else {
>- if (is_xen_memory())
>- paddr = vaddr - PAGE_OFFSET_XEN_DOM0;
>- else
>- paddr = vaddr - PAGE_OFFSET;
>- }
>- return paddr;
>-}
>-
> /*
> * for Xen extraction
> */
>diff --git a/makedumpfile.h b/makedumpfile.h
>index a5955ff750e5..13559651feb6 100644
>--- a/makedumpfile.h
>+++ b/makedumpfile.h
>@@ -863,12 +863,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
> int get_phys_base_x86_64(void);
> int get_machdep_info_x86_64(void);
> int get_versiondep_info_x86_64(void);
>-unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
>+unsigned long long vtop4_x86_64(unsigned long vaddr);
> #define find_vmemmap() find_vmemmap_x86_64()
> #define get_phys_base() get_phys_base_x86_64()
> #define get_machdep_info() get_machdep_info_x86_64()
> #define get_versiondep_info() get_versiondep_info_x86_64()
>-#define vaddr_to_paddr(X) vaddr_to_paddr_x86_64(X)
>+#define vaddr_to_paddr(X) vtop4_x86_64(X)
> #define is_phys_addr(X) (!is_vmalloc_addr_x86_64(X))
> #endif /* x86_64 */
>
>--
>2.7.4
>
>
>_______________________________________________
>kexec mailing list
>kexec at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/kexec
More information about the kexec
mailing list