Skip to contentSkip to conversation

x86_64: Fix page_offset for randomized base enabled

PATCH In review Pratyush Anand 4 participants 16 messages Oct 31, 2016 – Dec 13, 2016

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v2 cover x86_64: Fix page_offset for randomized base enabled

Patch 1/4 fixes page_offset calculation, so that it is correctly calculated on KASLR enabled kernel as well.
Patch 2/4 simplifies VA to PA translation. New code has been benchmarked against old code on a 4T system.
Patch 3/4 and 4/4 is removal of (now) unnecessary code.

I think, we should find a way to kill find_vememmap() as well, so that VMEMMAP_START can be removed. I have very limited idea about x86, so unable to do that as of now.

Changes since V1:
* A bug in patch 1/4 fixed
* Patch log of 2/4 improved to include more number of trials

Pratyush Anand (4):
x86_64: Calculate page_offset from pt_load
x86_64: translate all VA to PA using page table values
x86_64: kill is_vmalloc_addr_x86_64()
x86_64: kill some unused initialization

 arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
 makedumpfile.h |  9 +++----
 2 files changed, 32 insertions(+), 61 deletions(-)
Signature · 7 lines
2.7.4


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#1 lore raw

PATCH v2 1/4 x86_64: Calculate page_offset from pt_load

page_offset can always be calculated as 'virtual - physical' for a direct mapping area on x86. Therefore, remove the version dependent calculation and use this method.

---
 arch/x86_64.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)
arch/x86_64.c +20 -4
index ddf7be6bc57b..eba725e41aac 100644
@@ -44,6 +44,24 @@ get_xen_p2m_mfn(void)
 	return NOT_FOUND_LONG_VALUE;
 }
 
+static int
+get_page_offset_x86_64(void)
+{
+	int i;
+	unsigned long long phys_start;
+	unsigned long long virt_start;
+
+	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
+		if (virt_start < __START_KERNEL_map) {
+			info->page_offset = virt_start - phys_start;
+			return TRUE;
+		}
+	}
+
+	ERRMSG("Can't get any pt_load to calculate page offset.\n");
+	return FALSE;
+}
+
 int
 get_phys_base_x86_64(void)
 {
@@ -159,10 +177,8 @@ get_versiondep_info_x86_64(void)
 	else
 		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
 
-	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
-		info->page_offset = __PAGE_OFFSET_ORIG;
-	else
-		info->page_offset = __PAGE_OFFSET_2_6_27;
+	if (!get_page_offset_x86_64())
+		return FALSE;
 
 	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
 		info->vmalloc_start = VMALLOC_START_ORIG;
Signature · 7 lines
2.7.4


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#2 lore raw

PATCH v2 2/4 x86_64: translate all VA to PA using page table values

In reply to Pratyush Anand

Currently we translate some of the VA areas using linear mapping while some other(which can not be linearly mapped) using page table.

However, we will have entry of a page in the page table irrespective of its virtual region. So, we can always look into page table for any VA to PA translation. This approach will solve lot of complexity in makedumpfile. It will in turn remove dependency over variables like VMALLOC_START, MODULES_VADDR etc whose definition keeps changing in newer kernel version.

Moreover, I do not see any side effect of this approach in terms of execution timing. I tested with IBM x3950 X6 machine having 4136359 MB of memory with -d 1 option. In fact, over a 19+ trials, new code shows slightly better result (2592 S) than upstream code (2652 S). These are the results of makedumpfile execution time:

$ cat console.log | grep "makedumpfile execution time with upstream code
is"
makedumpfile execution time with upstream code is 2750.243266765
makedumpfile execution time with upstream code is 2772.954322748
makedumpfile execution time with upstream code is 2778.147847869
makedumpfile execution time with upstream code is 2668.136180424
makedumpfile execution time with upstream code is 2543.101660682
makedumpfile execution time with upstream code is 2757.314292073
makedumpfile execution time with upstream code is 2478.658846427
makedumpfile execution time with upstream code is 2745.728099825
makedumpfile execution time with upstream code is 2577.807602709
makedumpfile execution time with upstream code is 2548.787385748
makedumpfile execution time with upstream code is 2757.644602365
makedumpfile execution time with upstream code is 2562.336482019
makedumpfile execution time with upstream code is 2559.935682252
makedumpfile execution time with upstream code is 2546.670738446
makedumpfile execution time with upstream code is 2744.063245015
makedumpfile execution time with upstream code is 2744.243866098
makedumpfile execution time with upstream code is 2549.050846459
makedumpfile execution time with upstream code is 2759.081822434
makedumpfile execution time with upstream code is 2549.571317987
$ cat console.log | grep "makedumpfile execution time with upstream code
is" | cut -d ' ' -f 8 | awk -F : '{sum+=$1} END {print "AVG=",sum/NR}'
AVG= 2652.29
$ cat console.log | grep "makedumpfile execution time with new code is"
makedumpfile execution time with new code is 2534.312841588
makedumpfile execution time with new code is 2549.943691468
makedumpfile execution time with new code is 2562.056355355
makedumpfile execution time with new code is 2744.429671429
makedumpfile execution time with new code is 2536.959188162
makedumpfile execution time with new code is 2543.148060626
makedumpfile execution time with new code is 2548.634229064
makedumpfile execution time with new code is 2554.985669453
makedumpfile execution time with new code is 2756.479546003
makedumpfile execution time with new code is 2736.303174442
makedumpfile execution time with new code is 2564.855527093
makedumpfile execution time with new code is 2479.417937688
makedumpfile execution time with new code is 2555.431578921
makedumpfile execution time with new code is 2741.293207275
makedumpfile execution time with new code is 2745.547802440
makedumpfile execution time with new code is 2555.950078489
makedumpfile execution time with new code is 2558.421768940
makedumpfile execution time with new code is 2534.342072864
makedumpfile execution time with new code is 2542.824611652
makedumpfile execution time with new code is 2557.413054122
makedumpfile execution time with new code is 2553.609188082
makedumpfile execution time with new code is 2766.161683444
makedumpfile execution time with new code is 2571.997408197
makedumpfile execution time with new code is 2541.121903364
makedumpfile execution time with new code is 2472.805795262
$ cat console.log | grep "makedumpfile execution time with new code is" |
cut -d ' ' -f 8 | awk -F : '{sum+=$1} END {print "AVG=",sum/NR}'
AVG= 2592.34
---
 arch/x86_64.c  | 42 ++++++++----------------------------------
 makedumpfile.h |  4 ++--
 2 files changed, 10 insertions(+), 36 deletions(-)
arch/x86_64.c +8 -34
index eba725e41aac..9afa38fd141a 100644
@@ -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;
 	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
  */
makedumpfile.h +2 -2
index a5955ff750e5..13559651feb6 100644
@@ -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 */
 
Signature · 7 lines
2.7.4


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#3 lore raw

RE: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Hello Pratyush,

Quoted 23 lines

---
arch/x86_64.c | 42 ++++++++---------------------------------- makedumpfile.h | 4 ++--

2 files changed, 10 insertions(+), 36 deletions(-)
arch/x86_64.c +6 -0
index eba725e41aac..9afa38fd141a 100644
@@ -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");

arch/x86_64.c vtop4_x86_64(unsigned long vaddr) · line 221

Quoted 5 lines
arch/x86_64.c +1 -1
@@ -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 <[email protected]>
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

Quoted 68 lines
arch/x86_64.c +1 -33
 	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
 */
makedumpfile.h +2 -3
index a5955ff750e5..13559651feb6 100644
@@ -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

Quoted 4 lines

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#4 lore raw

Re: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 80 lines · Atsushi Kumagai

Hello Pratyush,

Quoted 23 lines

---
arch/x86_64.c | 42 ++++++++---------------------------------- makedumpfile.h | 4 ++--

2 files changed, 10 insertions(+), 36 deletions(-)
arch/x86_64.c +6 -0
index eba725e41aac..9afa38fd141a 100644
@@ -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");

arch/x86_64.c vtop4_x86_64(unsigned long vaddr) · line 221

Quoted 5 lines
arch/x86_64.c +1 -1
@@ -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 <[email protected]>
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>

Quoted 5 lines

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.)

We can use this fact may be. So, when has_vmcoreinfo() is false we can consider it as old kernel and can set phys_start as 0.

Bao, any opnion?

~Pratyush

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw

Re: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 7 lines · Pratyush Anand
Quoted 7 lines

arch/x86_64.c vtop4_x86_64(unsigned long vaddr) · line 221

Quoted 2 lines
arch/x86_64.c +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

Quoted 43 lines
Quoted 37 lines

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>

Quoted 5 lines

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.)

Quoted 7 lines

We can use this fact may be. So, when has_vmcoreinfo() is false we can consider it as old kernel and can set phys_start as 0.

Bao, any opnion?

~Pratyush

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#6 lore raw

Re: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 17 lines · Baoquan He
Quoted 7 lines · Pratyush Anand
Quoted 7 lines

arch/x86_64.c vtop4_x86_64(unsigned long vaddr) · line 221

Quoted 2 lines
arch/x86_64.c +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

Quoted 7 lines

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

I meant making a judgement:

if (page_offset == 0xffff810000000000 && info->kernel_version > KERNEL_VERSION(2, 6, 21))

	info->phys_base = 0;	
Quoted 44 lines
Quoted 44 lines
Quoted 43 lines

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.)

Quoted 7 lines
Quoted 7 lines

We can use this fact may be. So, when has_vmcoreinfo() is false we can consider it as old kernel and can set phys_start as 0.

Bao, any opnion?

~Pratyush

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#7 lore raw

Re: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 23 lines · Baoquan He
Quoted 22 lines · Baoquan He
Quoted 7 lines · Pratyush Anand
Quoted 7 lines

arch/x86_64.c vtop4_x86_64(unsigned long vaddr) · line 221

Quoted 2 lines
arch/x86_64.c +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

Quoted 5 lines
Quoted 2 lines

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

I meant making a judgement:

Sorry, should be:
if (page_offset == 0xffff810000000000 && !info->kernel_version > KERNEL_VERSION(2, 6, 21))

	info->phys_base = 0;	
Quoted 44 lines
Quoted 44 lines
Quoted 44 lines
Quoted 43 lines

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.)

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

We can use this fact may be. So, when has_vmcoreinfo() is false we can consider it as old kernel and can set phys_start as 0.

Bao, any opnion?

~Pratyush

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#8 lore raw

Re: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 27 lines · On Saturday 10 December 2016 07:03 AM, [email protected] wrote:
Quoted 26 lines · Baoquan He
Quoted 24 lines · Baoquan He
Quoted 7 lines · Pratyush Anand
Quoted 7 lines

arch/x86_64.c vtop4_x86_64(unsigned long vaddr) · line 221

Quoted 2 lines
arch/x86_64.c +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

Quoted 7 lines
Quoted 2 lines

I meant making a judgement:

Sorry, should be:
if (page_offset == 0xffff810000000000 && !info->kernel_version > KERNEL_VERSION(2, 6, 21))

	info->phys_base = 0;	

But you can not read kernel_version because those version does not have VMCOREINFO. So, has_vmcoreinfo() still need to be used.

~Pratyush

Quoted 44 lines
Quoted 44 lines
Quoted 44 lines
Quoted 44 lines
Quoted 43 lines

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.)

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

We can use this fact may be. So, when has_vmcoreinfo() is false we can consider it as old kernel and can set phys_start as 0.

Bao, any opnion?

~Pratyush

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#9 lore raw

RE: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 31 lines · On Saturday 10 December 2016 07:03 AM, [email protected] wrote:
Quoted 30 lines · Baoquan He
Quoted 28 lines · Baoquan He
Quoted 17 lines · Pratyush Anand
Quoted 7 lines
Quoted 7 lines

Review

Quoted 2 lines
(quoted diff) +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

Quoted 7 lines

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

I meant making a judgement:

Quoted 8 lines
Quoted 4 lines

Sorry, should be:
if (page_offset == 0xffff810000000000 && !info->kernel_version > KERNEL_VERSION(2, 6, 21))

	info->phys_base = 0;

But you can not read kernel_version because those version does not have VMCOREINFO. So, has_vmcoreinfo() still need to be used.

Thanks for your comments, using has_vmcoreinfo() sounds like a good approach, but not perfect way. VMCOREINFO has been introduced since 2.6.24, 2.6.22 and 2.6.23 don't have VMCOREINFO but have phys_base.

Conversely, 2.6.22 and 2.6.23 require vmlinux, so we can confirm the existence of phys_base with that. My idea is:

arch/x86_64.c +8 -0
index 010ea10..893cd51 100644
@@ -67,6 +67,14 @@ get_phys_base_x86_64(void)
                return TRUE;
        }
 
+       /* linux-2.6.21 or older don't have phys_base, should be set to 0. */
+       if (!has_vmcoreinfo()) {
+               SYMBOL_INIT(phys_base, "phys_base");
+               if (SYMBOL(phys_base) == NOT_FOUND_SYMBOL) {
+                       return TRUE;
+               }
+       }
+
        for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
                if (virt_start >= __START_KERNEL_map) {
 

This fix may resolve my issue, but now I have another question that "Is the logic of get_phys_base_x86_64() correct in any kernel configuration ?" I mean I'm worried about the possibility that another offset gets mixed with the result of get_phys_base_x86_64() like my 2.6.21 case.
After phys_base was introduced, does it always equal to the offset which can be calculated from PT_LOAD headers ?

Thanks,
Atsushi Kumagai

Quoted 51 lines

~Pratyush

Quoted 48 lines
Quoted 48 lines
Quoted 48 lines
Quoted 48 lines
Quoted 38 lines

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>

Quoted 5 lines

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.)

We can use this fact may be. So, when has_vmcoreinfo() is false we can consider it as old kernel and can set phys_start as 0.

Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Bao, any opnion?

~Pratyush

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#10 lore raw

Re: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 67 lines · Atsushi Kumagai
Quoted 31 lines · On Saturday 10 December 2016 07:03 AM, [email protected] wrote:
Quoted 30 lines · Baoquan He
Quoted 28 lines · Baoquan He
Quoted 17 lines · Pratyush Anand
Quoted 7 lines
Quoted 7 lines

Review

Quoted 2 lines
(quoted diff) +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

Quoted 7 lines

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

I meant making a judgement:

Quoted 8 lines
Quoted 4 lines

Sorry, should be:
if (page_offset == 0xffff810000000000 && !info->kernel_version > KERNEL_VERSION(2, 6, 21))

	info->phys_base = 0;

But you can not read kernel_version because those version does not have VMCOREINFO. So, has_vmcoreinfo() still need to be used.

Thanks for your comments, using has_vmcoreinfo() sounds like a good approach, but not perfect way. VMCOREINFO has been introduced since 2.6.24, 2.6.22 and 2.6.23 don't have VMCOREINFO but have phys_base.

Conversely, 2.6.22 and 2.6.23 require vmlinux, so we can confirm the existence of phys_base with that. My idea is:

arch/x86_64.c +8 -0
index 010ea10..893cd51 100644
@@ -67,6 +67,14 @@ get_phys_base_x86_64(void)
                return TRUE;
        }
 
+       /* linux-2.6.21 or older don't have phys_base, should be set to 0. */
+       if (!has_vmcoreinfo()) {
+               SYMBOL_INIT(phys_base, "phys_base");
+               if (SYMBOL(phys_base) == NOT_FOUND_SYMBOL) {
+                       return TRUE;
+               }
+       }
+
        for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
                if (virt_start >= __START_KERNEL_map) {
 
Quoted 6 lines

This fix may resolve my issue, but now I have another question that "Is the logic of get_phys_base_x86_64() correct in any kernel configuration ?" I mean I'm worried about the possibility that another offset gets mixed with the result of get_phys_base_x86_64() like my 2.6.21 case.
After phys_base was introduced, does it always equal to the offset which can be calculated from PT_LOAD headers ?

Don't worry. phys_base was introduced just after 2.6.21.

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408

Author: Vivek Goyal <[email protected]>
Date:   Wed May 2 19:27:07 2007 +0200

[PATCH] x86-64: Relocatable Kernel Support

[bhe@x1 linux]$ git describe 1ab60e0f72f71ec54831e525a3e1154f1c092408 v2.6.21-1836-g1ab60e0

Thanks
Baoquan

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#11 lore raw

RE: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page table values

Quoted 77 lines · Atsushi Kumagai
Quoted 67 lines
Quoted 31 lines · On Saturday 10 December 2016 07:03 AM, [email protected] wrote:
Quoted 30 lines · Baoquan He
Quoted 28 lines · Baoquan He
Quoted 17 lines · Pratyush Anand
Quoted 7 lines
Quoted 7 lines

Review

Quoted 2 lines
(quoted diff) +1 -1
-	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:

Quoted 8 lines
Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408
Author: Vivek Goyal <[email protected]>
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:

Quoted 7 lines

This is really awkward. Checked code, found PAGE_OFFSET is 0xffff810000000000 before 2.6.26, then changed to 0xffff880000000000 after that. Can we check the page_offset calculated from pt_load segments, meanwhile check if has VMCOREINFO and osrelease after 2.6.21.

With both of above condition, we could set phys_vase to 0. Not sure if this can solve the existing problem.

I meant making a judgement:

Quoted 8 lines
Quoted 4 lines

Sorry, should be:
if (page_offset == 0xffff810000000000 && !info->kernel_version > KERNEL_VERSION(2, 6, 21))

	info->phys_base = 0;

But you can not read kernel_version because those version does not have VMCOREINFO. So, has_vmcoreinfo() still need to be used.

Thanks for your comments, using has_vmcoreinfo() sounds like a good approach, but not perfect way. VMCOREINFO has been introduced since 2.6.24, 2.6.22 and 2.6.23 don't have VMCOREINFO but have phys_base.

Conversely, 2.6.22 and 2.6.23 require vmlinux, so we can confirm the existence of phys_base with that. My idea is:

arch/x86_64.c +8 -0
index 010ea10..893cd51 100644
@@ -67,6 +67,14 @@ get_phys_base_x86_64(void)
                return TRUE;
        }
 
+       /* linux-2.6.21 or older don't have phys_base, should be set to 0. */
+       if (!has_vmcoreinfo()) {
+               SYMBOL_INIT(phys_base, "phys_base");
+               if (SYMBOL(phys_base) == NOT_FOUND_SYMBOL) {
+                       return TRUE;
+               }
+       }
+
        for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
                if (virt_start >= __START_KERNEL_map) {
 
Quoted 6 lines

This fix may resolve my issue, but now I have another question that "Is the logic of get_phys_base_x86_64() correct in any kernel configuration ?" I mean I'm worried about the possibility that another offset gets mixed with the result of get_phys_base_x86_64() like my 2.6.21 case.
After phys_base was introduced, does it always equal to the offset which can be calculated from PT_LOAD headers ?

Don't worry. phys_base was introduced just after 2.6.21.

Quoted 8 lines

commit 1ab60e0f72f71ec54831e525a3e1154f1c092408

Author: Vivek Goyal <[email protected]>
Date:   Wed May 2 19:27:07 2007 +0200

[PATCH] x86-64: Relocatable Kernel Support

[bhe@x1 linux]$ git describe 1ab60e0f72f71ec54831e525a3e1154f1c092408 v2.6.21-1836-g1ab60e0

All right, thanks.
I'll release v1.6.1 soon if there is nothing wrong with the retest.

Regards,
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#12 lore raw

PATCH v2 3/4 x86_64: kill is_vmalloc_addr_x86_64()

In reply to Pratyush Anand

From kernel documentation:
ffffffff80000000 - ffffffff9fffffff (=512 MB) kernel text mapping, from phys 0 ffffffffa0000000 - ffffffffff5fffff (=1526 MB) module mapping space

So, it is only the module area which is lying above __START_KERNEL_map. However, kexec-tools only creates PT_LOAD segments for kernel text region and crash memory region. So, we can safely remove the check for !is_vmalloc_addr_x86_64() from get_phys_base_x86_64().

Since, this was the last usage of is_vmalloc_addr_x86_64(), so kill it as well.

---
 arch/x86_64.c  | 14 +-------------
 makedumpfile.h |  3 +--
 2 files changed, 2 insertions(+), 15 deletions(-)
arch/x86_64.c +1 -13
index 9afa38fd141a..9e2940ca75d9 100644
@@ -21,17 +21,6 @@
 extern struct vmap_pfns *gvmem_pfns;
 extern int nr_gvmem_pfns;
 
-int
-is_vmalloc_addr_x86_64(ulong vaddr)
-{
-	/*
-	 *  vmalloc, virtual memmap, and module space as VMALLOC space.
-	 */
-	return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END)
-	    || (vaddr >= VMEMMAP_START && vaddr <= VMEMMAP_END)
-	    || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END));
-}
-
 static unsigned long
 get_xen_p2m_mfn(void)
 {
@@ -75,8 +64,7 @@ get_phys_base_x86_64(void)
 	info->phys_base = 0; /* default/traditional */
 
 	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
-		if ((virt_start >= __START_KERNEL_map) &&
-		    !(is_vmalloc_addr_x86_64(virt_start))) {
+		if (virt_start >= __START_KERNEL_map) {
 
 			info->phys_base = phys_start -
 			    (virt_start & ~(__START_KERNEL_map));
makedumpfile.h +1 -2
index 13559651feb6..8a96da1f61bd 100644
@@ -859,7 +859,6 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
 #endif /* x86 */
 
 #ifdef __x86_64__
-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);
@@ -869,7 +868,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr);
 #define get_machdep_info()	get_machdep_info_x86_64()
 #define get_versiondep_info()	get_versiondep_info_x86_64()
 #define vaddr_to_paddr(X)	vtop4_x86_64(X)
-#define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
+#define is_phys_addr(X)		stub_true_ul(X)
 #endif /* x86_64 */
 
 #ifdef __powerpc64__ /* powerpc64 */
Signature · 7 lines
2.7.4


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#13 lore raw

PATCH v2 4/4 x86_64: kill some unused initialization

In reply to Pratyush Anand

VMALLOC_START, VMALLOC_END, MODULES_VADDR and MODULES_END are mo more needed for x86_64 now. So, kill their initialization.

---
 arch/x86_64.c  | 4 ----
 makedumpfile.h | 2 --
 2 files changed, 6 deletions(-)
arch/x86_64.c +0 -4
index 9e2940ca75d9..3ef33ae4ef2d 100644
@@ -169,13 +169,9 @@ get_versiondep_info_x86_64(void)
 		return FALSE;
 
 	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
-		info->vmalloc_start = VMALLOC_START_ORIG;
-		info->vmalloc_end   = VMALLOC_END_ORIG;
 		info->vmemmap_start = VMEMMAP_START_ORIG;
 		info->vmemmap_end   = VMEMMAP_END_ORIG;
 	} else {
-		info->vmalloc_start = VMALLOC_START_2_6_31;
-		info->vmalloc_end   = VMALLOC_END_2_6_31;
 		info->vmemmap_start = VMEMMAP_START_2_6_31;
 		info->vmemmap_end   = VMEMMAP_END_2_6_31;
 	}
makedumpfile.h +0 -2
index 8a96da1f61bd..338c651388f0 100644
@@ -575,8 +575,6 @@ int get_va_bits_arm64(void);
 #define __START_KERNEL_map	(0xffffffff80000000)
 #define KERNEL_IMAGE_SIZE_ORIG		(0x0000000008000000) /* 2.6.25, or former */
 #define KERNEL_IMAGE_SIZE_2_6_26	(0x0000000020000000) /* 2.6.26, or later  */
-#define MODULES_VADDR          (__START_KERNEL_map + NUMBER(KERNEL_IMAGE_SIZE))
-#define MODULES_END		(0xfffffffffff00000)
 #define KVBASE			PAGE_OFFSET
 #define _SECTION_SIZE_BITS	(27)
 #define _MAX_PHYSMEM_BITS_ORIG		(40)
Signature · 7 lines
2.7.4


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#14 lore raw
In reply to Pratyush Anand

Pratyush, the patches works for me, thanks~

Quoted 9 lines · Pratyush Anand

Patch 1/4 fixes page_offset calculation, so that it is correctly calculated on KASLR enabled kernel as well.
Patch 2/4 simplifies VA to PA translation. New code has been benchmarked against old code on a 4T system.
Patch 3/4 and 4/4 is removal of (now) unnecessary code.

I think, we should find a way to kill find_vememmap() as well, so that VMEMMAP_START can be removed. I have very limited idea about x86, so unable to do that as of now.

It was introduced in below commit, ccing Cliff Wickman, see if he has thoughts.

commit 46176a97f329904c10d4efe5582594d55a04339c

Author: Cliff Wickman <[email protected]>
Date:   Mon Oct 26 23:20:18 2015 +0900
Quoted 11 lines

Changes since V1:
* A bug in patch 1/4 fixed
* Patch log of 2/4 improved to include more number of trials

Pratyush Anand (4):
x86_64: Calculate page_offset from pt_load
x86_64: translate all VA to PA using page table values
x86_64: kill is_vmalloc_addr_x86_64()
x86_64: kill some unused initialization

Quoted 12 lines
 arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
 makedumpfile.h |  9 +++----
 2 files changed, 32 insertions(+), 61 deletions(-)
Signature · 7 lines
2.7.4


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#15 lore raw
In reply to Pratyush Anand

Hello Pratyush,

Quoted 6 lines

Patch 1/4 fixes page_offset calculation, so that it is correctly calculated on KASLR enabled kernel as well.
Patch 2/4 simplifies VA to PA translation. New code has been benchmarked against old code on a 4T system.
Patch 3/4 and 4/4 is removal of (now) unnecessary code.

Quoted 7 lines

I think, we should find a way to kill find_vememmap() as well, so that VMEMMAP_START can be removed. I have very limited idea about x86, so unable to do that as of now.

Changes since V1:
* A bug in patch 1/4 fixed
* Patch log of 2/4 improved to include more number of trials

The most of concern was the performance degradation, but there is no degradation in the additional benchmark. So I decide to merge this patch set into v1.6.1, thanks for your work.

Regards,
Atsushi Kumagai

Quoted 10 lines

Pratyush Anand (4):
x86_64: Calculate page_offset from pt_load
x86_64: translate all VA to PA using page table values
x86_64: kill is_vmalloc_addr_x86_64()
x86_64: kill some unused initialization

arch/x86_64.c | 84 ++++++++++++++++++++-------------------------------------- makedumpfile.h | 9 +++----

2 files changed, 32 insertions(+), 61 deletions(-)
Quoted 8 lines

--
2.7.4

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec