Skip to content

Commit 40b93af

Browse files
Alexey Makhalovk-hagio
Alexey Makhalov
authored andcommitted
calc_kaslr_offset: 5-level paging support
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(). [ kh: added malloc for p4d page ] Signed-off-by: Alexey Makhalov <amakhalov@vmware.com> Acked-by: Lianbo Jiang <lijiang@redhat.com> Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
1 parent 7ccdda4 commit 40b93af

File tree

5 files changed

+34
-18
lines changed

5 files changed

+34
-18
lines changed

defs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6626,7 +6626,7 @@ struct sadump_data;
66266626
struct sadump_data *get_sadump_data(void);
66276627
int sadump_calc_kaslr_offset(ulong *);
66286628
int sadump_get_nr_cpus(void);
6629-
int sadump_get_cr3_idtr(int, ulong *, ulong *);
6629+
int sadump_get_cr3_cr4_idtr(int, ulong *, ulong *, ulong *);
66306630

66316631
/*
66326632
* qemu.c
@@ -6680,7 +6680,7 @@ int vmware_vmss_memory_dump(FILE *);
66806680
void dump_registers_for_vmss_dump(void);
66816681
int vmware_vmss_valid_regs(struct bt_info *);
66826682
int vmware_vmss_get_nr_cpus(void);
6683-
int vmware_vmss_get_cr3_idtr(int, ulong *, ulong *);
6683+
int vmware_vmss_get_cr3_cr4_idtr(int, ulong *, ulong *, ulong *);
66846684
int vmware_vmss_phys_base(ulong *phys_base);
66856685
int vmware_vmss_set_phys_base(ulong);
66866686

kaslr_helper.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ qemu_get_nr_cpus(void)
251251
}
252252

253253
static int
254-
qemu_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
254+
qemu_get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
255255
{
256256
QEMUCPUState *cpustat;
257257

@@ -266,6 +266,7 @@ qemu_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
266266
return FALSE;
267267

268268
*cr3 = cpustat->cr[3];
269+
*cr4 = cpustat->cr[4];
269270
*idtr = cpustat->idt.base;
270271

271272
return TRUE;
@@ -344,14 +345,14 @@ get_nr_cpus(void)
344345
}
345346

346347
static int
347-
get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
348+
get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
348349
{
349350
if (SADUMP_DUMPFILE())
350-
return sadump_get_cr3_idtr(cpu, cr3, idtr);
351+
return sadump_get_cr3_cr4_idtr(cpu, cr3, cr4, idtr);
351352
else if (QEMU_MEM_DUMP_NO_VMCOREINFO())
352-
return qemu_get_cr3_idtr(cpu, cr3, idtr);
353+
return qemu_get_cr3_cr4_idtr(cpu, cr3, cr4, idtr);
353354
else if (VMSS_DUMPFILE())
354-
return vmware_vmss_get_cr3_idtr(cpu, cr3, idtr);
355+
return vmware_vmss_get_cr3_cr4_idtr(cpu, cr3, cr4, idtr);
355356

356357
return FALSE;
357358
}
@@ -483,10 +484,11 @@ calc_kaslr_offset_from_idt(uint64_t idtr, uint64_t pgd, ulong *kaslr_offset, ulo
483484
#define PTI_USER_PGTABLE_BIT PAGE_SHIFT
484485
#define PTI_USER_PGTABLE_MASK (1 << PTI_USER_PGTABLE_BIT)
485486
#define CR3_PCID_MASK 0xFFFull
487+
#define CR4_LA57 (1 << 12)
486488
int
487489
calc_kaslr_offset(ulong *ko, ulong *pb)
488490
{
489-
uint64_t cr3 = 0, idtr = 0, pgd = 0;
491+
uint64_t cr3 = 0, cr4 = 0, idtr = 0, pgd = 0;
490492
ulong kaslr_offset, phys_base;
491493
ulong kaslr_offset_kdump, phys_base_kdump;
492494
int cpu, nr_cpus;
@@ -497,7 +499,7 @@ calc_kaslr_offset(ulong *ko, ulong *pb)
497499
nr_cpus = get_nr_cpus();
498500

499501
for (cpu = 0; cpu < nr_cpus; cpu++) {
500-
if (!get_cr3_idtr(cpu, &cr3, &idtr))
502+
if (!get_cr3_cr4_idtr(cpu, &cr3, &cr4, &idtr))
501503
continue;
502504

503505
if (!cr3)
@@ -514,13 +516,23 @@ calc_kaslr_offset(ulong *ko, ulong *pb)
514516
* calc_kaslr_offset() is called before machdep_init(PRE_GDB), so some
515517
* variables are not initialized yet. Set up them here to call kvtop().
516518
*
517-
* TODO: XEN and 5-level is not supported
519+
* TODO: XEN is not supported
518520
*/
519521
vt->kernel_pgd[0] = pgd;
520522
machdep->last_pgd_read = vt->kernel_pgd[0];
521-
machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
522-
machdep->machspec->pgdir_shift = PGDIR_SHIFT;
523-
machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD;
523+
if (cr4 & CR4_LA57) {
524+
machdep->flags |= VM_5LEVEL;
525+
machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_5LEVEL;
526+
machdep->machspec->pgdir_shift = PGDIR_SHIFT_5LEVEL;
527+
machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD_5LEVEL;
528+
if ((machdep->machspec->p4d = (char *)malloc(PAGESIZE())) == NULL)
529+
error(FATAL, "cannot malloc p4d space.");
530+
machdep->machspec->last_p4d_read = 0;
531+
} else {
532+
machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
533+
machdep->machspec->pgdir_shift = PGDIR_SHIFT;
534+
machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD;
535+
}
524536
if (!readmem(pgd, PHYSADDR, machdep->pgd, PAGESIZE(),
525537
"pgd", RETURN_ON_ERROR))
526538
continue;

sadump.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1679,7 +1679,7 @@ sadump_get_nr_cpus(void)
16791679
}
16801680

16811681
int
1682-
sadump_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
1682+
sadump_get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
16831683
{
16841684
struct sadump_smram_cpu_state scs;
16851685

@@ -1688,6 +1688,7 @@ sadump_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
16881688
return FALSE;
16891689

16901690
*cr3 = scs.Cr3;
1691+
*cr4 = scs.Cr4;
16911692
*idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
16921693

16931694
return TRUE;

vmware_vmss.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,12 +879,13 @@ vmware_vmss_get_nr_cpus(void)
879879
}
880880

881881
int
882-
vmware_vmss_get_cr3_idtr(int cpu, ulong *cr3, ulong *idtr)
882+
vmware_vmss_get_cr3_cr4_idtr(int cpu, ulong *cr3, ulong *cr4, ulong *idtr)
883883
{
884884
if (cpu >= vmss.num_vcpus || vmss.vcpu_regs[cpu] != REGS_PRESENT_ALL)
885885
return FALSE;
886886

887887
*cr3 = vmss.regs64[cpu]->cr[3];
888+
*cr4 = vmss.regs64[cpu]->cr[4];
888889
*idtr = vmss.regs64[cpu]->idtr;
889890

890891
return TRUE;

x86_64.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,11 @@ x86_64_init(int when)
356356
machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_5LEVEL;
357357
machdep->machspec->pgdir_shift = PGDIR_SHIFT_5LEVEL;
358358
machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD_5LEVEL;
359-
if ((machdep->machspec->p4d = (char *)malloc(PAGESIZE())) == NULL)
360-
error(FATAL, "cannot malloc p4d space.");
361-
machdep->machspec->last_p4d_read = 0;
359+
if (!machdep->machspec->p4d) {
360+
if ((machdep->machspec->p4d = (char *)malloc(PAGESIZE())) == NULL)
361+
error(FATAL, "cannot malloc p4d space.");
362+
machdep->machspec->last_p4d_read = 0;
363+
}
362364
machdep->uvtop = x86_64_uvtop_level4; /* 5-level is optional per-task */
363365
machdep->kvbase = (ulong)PAGE_OFFSET;
364366
machdep->identity_map_base = (ulong)PAGE_OFFSET;

0 commit comments

Comments
 (0)