Ensure that resume path on amd64 only accesses page tables for normal
operation after processor is configured to allow all required features. In particular, NX must be enabled in EFER, otherwise load of page table element with nx bit set causes reserved bit page fault. Since malloc uses direct mapping for small allocations, in particular for the suspension pcbs, and DMAP is nx after r316767, this commit tripped fault on resume path. Restore complete state of EFER while wakeup code is still executing with custom page table, before calling resumectx, instead of trying to guess which features might be needed before resumectx restored EFER on its own. Bisected and tested by: trasz Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
This commit is contained in:
parent
f701bdc59e
commit
bd101a6648
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=318318
@ -156,11 +156,12 @@ wakeup_32:
|
||||
/*
|
||||
* Enable EFER.LME so that we get long mode when all the prereqs are
|
||||
* in place. In this case, it turns on when CR0_PG is finally enabled.
|
||||
* Pick up a few other EFER bits that we'll use need we're here.
|
||||
* Also it picks up a few other EFER bits that we'll use need we're
|
||||
* here, like SYSCALL and NX enable.
|
||||
*/
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
orl $EFER_LME | EFER_SCE, %eax
|
||||
movl wakeup_efer - wakeup_start(%ebx), %eax
|
||||
movl wakeup_efer + 4 - wakeup_start(%ebx), %edx
|
||||
wrmsr
|
||||
|
||||
/*
|
||||
@ -276,6 +277,8 @@ wakeup_pcb:
|
||||
.quad 0
|
||||
wakeup_ret:
|
||||
.quad 0
|
||||
wakeup_efer:
|
||||
.quad 0
|
||||
wakeup_gdt:
|
||||
.word 0
|
||||
.quad 0
|
||||
|
@ -396,7 +396,7 @@ ENTRY(resumectx)
|
||||
movl 4 + PCB_KGSBASE(%rdi),%edx
|
||||
wrmsr
|
||||
|
||||
/* Restore EFER. */
|
||||
/* Restore EFER one more time. */
|
||||
movl $MSR_EFER,%ecx
|
||||
movl PCB_EFER(%rdi),%eax
|
||||
wrmsr
|
||||
|
@ -223,7 +223,9 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
|
||||
WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
|
||||
WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
|
||||
|
||||
#ifndef __amd64__
|
||||
#ifdef __amd64__
|
||||
WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER));
|
||||
#else
|
||||
WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4);
|
||||
#endif
|
||||
WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
|
||||
|
Loading…
Reference in New Issue
Block a user