amd64: Handle 5-level paging on wakeup.
We can switch into long mode directly with LA57 enabled. Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D25273
This commit is contained in:
parent
f770d93b45
commit
94cc06b8c6
@ -148,10 +148,18 @@ wakeup_32:
|
||||
mov $bootdata32 - bootgdt, %eax
|
||||
mov %ax, %ds
|
||||
|
||||
/* Turn on the PAE bit for when paging is enabled */
|
||||
/*
|
||||
* Turn on the PAE bit and optionally the LA57 bit for when paging
|
||||
* is later enabled.
|
||||
*/
|
||||
mov %cr4, %eax
|
||||
orl $CR4_PAE, %eax
|
||||
mov %eax, %cr4
|
||||
leal wakeup_pagetables - wakeup_start(%ebx), %ecx
|
||||
movl (%ecx), %ecx
|
||||
testl $0x1, %ecx
|
||||
je 1f
|
||||
orl $CR4_LA57, %eax
|
||||
1: mov %eax, %cr4
|
||||
|
||||
/*
|
||||
* Enable EFER.LME so that we get long mode when all the prereqs are
|
||||
@ -174,6 +182,7 @@ wakeup_32:
|
||||
*/
|
||||
leal wakeup_pagetables - wakeup_start(%ebx), %eax
|
||||
movl (%eax), %eax
|
||||
andl $~0x1, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
/*
|
||||
|
@ -382,8 +382,11 @@ END(savectx)
|
||||
* Resuming processor state from pcb.
|
||||
*/
|
||||
ENTRY(resumectx)
|
||||
/* Switch to KPML4phys. */
|
||||
/* Switch to KPML5/4phys. */
|
||||
movq KPML4phys,%rax
|
||||
movq KPML5phys,%rcx
|
||||
cmpl $0, la57
|
||||
cmovne %rcx, %rax
|
||||
movq %rax,%cr3
|
||||
|
||||
/* Force kernel segment registers. */
|
||||
|
@ -99,7 +99,7 @@ static void acpi_wakeup_cpus(struct acpi_softc *);
|
||||
#endif
|
||||
|
||||
#ifdef __amd64__
|
||||
#define ACPI_WAKEPAGES 4
|
||||
#define ACPI_WAKEPAGES 5
|
||||
#else
|
||||
#define ACPI_WAKEPAGES 1
|
||||
#endif
|
||||
@ -414,8 +414,8 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
|
||||
static void *wakeaddr;
|
||||
void *wakepages[ACPI_WAKEPAGES];
|
||||
#ifdef __amd64__
|
||||
uint64_t *pt4, *pt3, *pt2;
|
||||
vm_paddr_t pt4pa, pt3pa, pt2pa;
|
||||
uint64_t *pt5, *pt4, *pt3, *pt2;
|
||||
vm_paddr_t pt5pa, pt4pa, pt3pa, pt2pa;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
@ -430,6 +430,10 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
|
||||
sc->acpi_wakephys = vtophys(wakeaddr);
|
||||
|
||||
#ifdef __amd64__
|
||||
if (la57) {
|
||||
pt5 = wakepages[4];
|
||||
pt5pa = vtophys(pt5);
|
||||
}
|
||||
pt4 = wakepages[1];
|
||||
pt3 = wakepages[2];
|
||||
pt2 = wakepages[3];
|
||||
@ -448,7 +452,8 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
|
||||
#ifdef __amd64__
|
||||
WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
|
||||
sc->acpi_wakephys + wakeup_64);
|
||||
WAKECODE_FIXUP(wakeup_pagetables, uint32_t, pt4pa);
|
||||
WAKECODE_FIXUP(wakeup_pagetables, uint32_t, la57 ? (pt5pa | 0x1) :
|
||||
pt4pa);
|
||||
#endif
|
||||
|
||||
/* Save pointers to some global data. */
|
||||
@ -457,7 +462,12 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
|
||||
WAKECODE_FIXUP(wakeup_cr3, register_t, pmap_get_kcr3());
|
||||
#else /* __amd64__ */
|
||||
/* Create the initial 1GB replicated page tables */
|
||||
for (i = 0; i < 512; i++) {
|
||||
for (i = 0; i < NPTEPG; i++) {
|
||||
if (la57) {
|
||||
pt5[i] = (uint64_t)pt4pa;
|
||||
pt5[i] |= PG_V | PG_RW | PG_U;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each slot of the level 4 pages points
|
||||
* to the same level 3 page
|
||||
@ -473,7 +483,7 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
|
||||
pt3[i] |= PG_V | PG_RW | PG_U;
|
||||
|
||||
/* The level 2 page slots are mapped with 2MB pages for 1GB. */
|
||||
pt2[i] = i * (2 * 1024 * 1024);
|
||||
pt2[i] = i * NBPDR;
|
||||
pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
|
||||
}
|
||||
#endif /* !__amd64__ */
|
||||
|
Loading…
Reference in New Issue
Block a user