[Crash-utility] [PATCH v4 2/3] calc_kaslr_offset: 5-level paging support

Alexey Makhalov amakhalov at vmware.com
Thu Nov 5 09:42:22 UTC 2020


Use LA57 bit in CR4 to check whether 5-level paging enabled.
Initialize machdep to 5-level paging operation mode used by
x86_64_kvtop.
Replaced *_get_cr3_idtr() set of functions by
*_get_cr3_cr4_idtr().

Signed-off-by: Alexey Makhalov <amakhalov at vmware.com>
---
 defs.h         |  4 ++--
 kaslr_helper.c | 31 ++++++++++++++++++++-----------
 sadump.c       |  3 ++-
 vmware_vmss.c  |  3 ++-
 4 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/defs.h b/defs.h
index d024756..9594950 100644
--- a/defs.h
+++ b/defs.h
@@ -6626,7 +6626,7 @@ struct sadump_data;
 struct sadump_data *get_sadump_data(void);
 int sadump_calc_kaslr_offset(ulong *);
 int sadump_get_nr_cpus(void);
-int sadump_get_cr3_idtr(int, ulong *, ulong *);
+int sadump_get_cr3_cr4_idtr(int, ulong *, ulong *, ulong *);
 
 /*
  * qemu.c
@@ -6680,7 +6680,7 @@ int vmware_vmss_memory_dump(FILE *);
 void dump_registers_for_vmss_dump(void);
 int vmware_vmss_valid_regs(struct bt_info *);
 int vmware_vmss_get_nr_cpus(void);
-int vmware_vmss_get_cr3_idtr(int, ulong *, ulong *);
+int vmware_vmss_get_cr3_cr4_idtr(int, ulong *, ulong *, ulong *);
 int vmware_vmss_phys_base(ulong *phys_base);
 int vmware_vmss_set_phys_base(ulong);
 
diff --git a/kaslr_helper.c b/kaslr_helper.c
index a0b537e..f9ed56b 100644
--- a/kaslr_helper.c
+++ b/kaslr_helper.c
@@ -251,7 +251,7 @@ qemu_get_nr_cpus(void)
 }
 
 static int
-qemu_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
+qemu_get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
 {
 	QEMUCPUState *cpustat;
 
@@ -266,6 +266,7 @@ qemu_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
 		return FALSE;
 
 	*cr3 = cpustat->cr[3];
+	*cr4 = cpustat->cr[4];
 	*idtr = cpustat->idt.base;
 
 	return TRUE;
@@ -344,14 +345,14 @@ get_nr_cpus(void)
 }
 
 static int
-get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
+get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
 {
 	if (SADUMP_DUMPFILE())
-		return sadump_get_cr3_idtr(cpu, cr3, idtr);
+		return sadump_get_cr3_cr4_idtr(cpu, cr3, cr4, idtr);
 	else if (QEMU_MEM_DUMP_NO_VMCOREINFO())
-		return qemu_get_cr3_idtr(cpu, cr3, idtr);
+		return qemu_get_cr3_cr4_idtr(cpu, cr3, cr4, idtr);
 	else if (VMSS_DUMPFILE())
-		return vmware_vmss_get_cr3_idtr(cpu, cr3, idtr);
+		return vmware_vmss_get_cr3_cr4_idtr(cpu, cr3, cr4, idtr);
 
 	return FALSE;
 }
@@ -483,10 +484,11 @@ calc_kaslr_offset_from_idt(uint64_t idtr, uint64_t pgd, ulong *kaslr_offset, ulo
 #define PTI_USER_PGTABLE_BIT	PAGE_SHIFT
 #define PTI_USER_PGTABLE_MASK	(1 << PTI_USER_PGTABLE_BIT)
 #define CR3_PCID_MASK		0xFFFull
+#define CR4_LA57		(1 << 12)
 int
 calc_kaslr_offset(ulong *ko, ulong *pb)
 {
-	uint64_t cr3 = 0, idtr = 0, pgd = 0;
+	uint64_t cr3 = 0, cr4 = 0, idtr = 0, pgd = 0;
 	ulong kaslr_offset, phys_base;
 	ulong kaslr_offset_kdump, phys_base_kdump;
 	int cpu, nr_cpus;
@@ -497,7 +499,7 @@ calc_kaslr_offset(ulong *ko, ulong *pb)
 	nr_cpus = get_nr_cpus();
 
 	for (cpu = 0; cpu < nr_cpus; cpu++) {
-		if (!get_cr3_idtr(cpu, &cr3, &idtr))
+		if (!get_cr3_cr4_idtr(cpu, &cr3, &cr4, &idtr))
 			continue;
 
 		if (!cr3)
@@ -514,13 +516,20 @@ calc_kaslr_offset(ulong *ko, ulong *pb)
 		 * calc_kaslr_offset() is called before machdep_init(PRE_GDB), so some
 		 * variables are not initialized yet. Set up them here to call kvtop().
 		 *
-		 * TODO: XEN and 5-level is not supported
+		 * TODO: XEN is not supported
 		 */
 		vt->kernel_pgd[0] = pgd;
 		machdep->last_pgd_read = vt->kernel_pgd[0];
-		machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
-		machdep->machspec->pgdir_shift = PGDIR_SHIFT;
-		machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD;
+		if (cr4 & CR4_LA57) {
+			machdep->flags |= VM_5LEVEL;
+			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;
+		} else {
+			machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
+			machdep->machspec->pgdir_shift = PGDIR_SHIFT;
+			machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD;
+		}
 		if (!readmem(pgd, PHYSADDR, machdep->pgd, PAGESIZE(),
 					"pgd", RETURN_ON_ERROR))
 			continue;
diff --git a/sadump.c b/sadump.c
index 08893c4..d75c66b 100644
--- a/sadump.c
+++ b/sadump.c
@@ -1679,7 +1679,7 @@ sadump_get_nr_cpus(void)
 }
 
 int
-sadump_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
+sadump_get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
 {
 	struct sadump_smram_cpu_state scs;
 
@@ -1688,6 +1688,7 @@ sadump_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
 		return FALSE;
 
 	*cr3 = scs.Cr3;
+	*cr4 = scs.Cr4;
 	*idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
 
 	return TRUE;
diff --git a/vmware_vmss.c b/vmware_vmss.c
index 952ac48..52d58e8 100644
--- a/vmware_vmss.c
+++ b/vmware_vmss.c
@@ -879,12 +879,13 @@ vmware_vmss_get_nr_cpus(void)
 }
 
 int
-vmware_vmss_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
+vmware_vmss_get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
 {
 	if (cpu >= vmss.num_vcpus || vmss.vcpu_regs[cpu] != REGS_PRESENT_ALL)
 		return FALSE;
 
 	*cr3 = vmss.regs64[cpu]->cr[3];
+	*cr4 = vmss.regs64[cpu]->cr[4];
 	*idtr = vmss.regs64[cpu]->idtr;
 
 	return TRUE;
-- 
2.11.0




More information about the Crash-utility mailing list