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;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to