Date: Thu, 7 Feb 2019 02:09:34 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r343851 - in head/sys: i386/acpica x86/acpica Message-ID: <201902070209.x1729YSX068323@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Thu Feb 7 02:09:34 2019 New Revision: 343851 URL: https://svnweb.freebsd.org/changeset/base/343851 Log: Fix resume on i386 PAE. It was broken before PAE/no-PAE merge, but since now PAE is the default, resume is apparently becomes for all machines. The corrected issues: - the trampoline page is not mapped executable, so machine faults when paging is on; - MSR.EFER and %cr4 both should be loaded before paging is enabled, otherwise paging structures are invalid (cr4.PAE and EFER.NX). - MSR.EFER and %cr4 should be only loaded if present. I attempt to handle this by not touching the registers if the value is zero. There are some more bits still not quite correct, e.g. unconditional access to %cr4 in resumectx. Reported and debugging help by: bde Sponsored by: The FreeBSD Foundation MFC after: 1 week Modified: head/sys/i386/acpica/acpi_wakecode.S head/sys/x86/acpica/acpi_wakeup.c Modified: head/sys/i386/acpica/acpi_wakecode.S ============================================================================== --- head/sys/i386/acpica/acpi_wakecode.S Thu Feb 7 02:00:23 2019 (r343850) +++ head/sys/i386/acpica/acpi_wakecode.S Thu Feb 7 02:09:34 2019 (r343851) @@ -143,16 +143,26 @@ wakeup_32: mov $bootdata32 - bootgdt, %eax mov %ax, %ds - /* Get PCB and return address. */ - movl wakeup_pcb - wakeup_start(%ebx), %ecx - movl wakeup_ret - wakeup_start(%ebx), %edx - - /* Restore CR4 and CR3. */ - movl wakeup_cr4 - wakeup_start(%ebx), %eax + /* Restore EFER, CR4 and CR3. */ + movl wakeup_efer - wakeup_start(%ebx), %eax + movl wakeup_efer - wakeup_start + 4(%ebx), %edx + cmpl $0, %eax + jne 1f + cmpl $0, %edx + je 2f +1: movl $MSR_EFER, %ecx + wrmsr +2: movl wakeup_cr4 - wakeup_start(%ebx), %eax + cmpl $0, %eax + je 3f mov %eax, %cr4 - movl wakeup_cr3 - wakeup_start(%ebx), %eax +3: movl wakeup_cr3 - wakeup_start(%ebx), %eax mov %eax, %cr3 + /* Get PCB and return address. */ + movl wakeup_ret - wakeup_start(%ebx), %edx + movl wakeup_pcb - wakeup_start(%ebx), %ecx + /* Enable paging. */ mov %cr0, %eax orl $CR0_PG, %eax @@ -187,6 +197,9 @@ bootgdtdesc: .long bootgdt - wakeup_start /* Offset plus %ds << 4 */ ALIGN_DATA +wakeup_efer: + .long 0 + .long 0 wakeup_cr4: .long 0 wakeup_cr3: Modified: head/sys/x86/acpica/acpi_wakeup.c ============================================================================== --- head/sys/x86/acpica/acpi_wakeup.c Thu Feb 7 02:00:23 2019 (r343850) +++ head/sys/x86/acpica/acpi_wakeup.c Thu Feb 7 02:09:34 2019 (r343851) @@ -260,6 +260,8 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER) & ~(EFER_LMA)); #else + if ((amd_feature & AMDID_NX) != 0) + WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER)); WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4); #endif WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb); @@ -375,8 +377,12 @@ acpi_alloc_wakeup_handler(void *wakepages[ACPI_WAKEPAG * page-aligned. */ for (i = 0; i < ACPI_WAKEPAGES; i++) { - wakepages[i] = contigmalloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT, - 0x500, 0xa0000, PAGE_SIZE, 0ul); + wakepages[i] = contigmalloc(PAGE_SIZE, M_DEVBUF, + M_NOWAIT +#ifdef __i386__ + | M_EXEC +#endif + , 0x500, 0xa0000, PAGE_SIZE, 0ul); if (wakepages[i] == NULL) { printf("%s: can't alloc wake memory\n", __func__); goto freepages;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902070209.x1729YSX068323>