Disable PAE when switching to the hibernate resume pagetables. This involves
authorkettenis <kettenis@openbsd.org>
Sun, 26 Apr 2015 11:09:32 +0000 (11:09 +0000)
committerkettenis <kettenis@openbsd.org>
Sun, 26 Apr 2015 11:09:32 +0000 (11:09 +0000)
a slightly conmplicated dance where we stash the PAE PDPTEs into the
hibernate resume pagetables and use those before turning off PAE.
Makes (un)hibernate work with the new PAE pmap.

ok mlarkin@

sys/arch/i386/i386/acpi_wakecode.S
sys/arch/i386/i386/hibernate_machdep.c

index 952dc78..5cd7170 100644 (file)
@@ -359,9 +359,25 @@ NENTRY(hibernate_activate_resume_pt_machdep)
        andl    $(~CR4_PGE), %eax
        movl    %eax, %cr4
 
+       /* 
+        * Switch to the hibernate resume pagetable if we're running
+        * in non-PAE mode.  If we're running in PAE mode, this will
+        * switch to the PTPDEs we stashed into the hibernate resume
+        * pagetable, but continue to use the normal pagetables until we
+        * disable PAE below.
+        */
+       movl    $HIBERNATE_PD_PAGE, %eax
+       orl     $0xfe0, %eax
+       movl    %eax, %cr3
+
+       /* Disable PAE */
+       movl    %cr4, %eax
+       andl    $(~CR4_PAE), %eax
+       movl    %eax, %cr4
+
        wbinvd
        movl    $HIBERNATE_PD_PAGE, %eax
-       movl    %eax,   %cr3
+       movl    %eax, %cr3
        jmp     1f
 
 1:     nop
index 6b2eeb5..c76850d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hibernate_machdep.c,v 1.45 2015/04/12 18:37:53 mlarkin Exp $  */
+/*     $OpenBSD: hibernate_machdep.c,v 1.46 2015/04/26 11:09:32 kettenis Exp $ */
 
 /*
  * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
@@ -244,6 +244,7 @@ hibernate_populate_resume_pt(union hibernate_info *hib_info,
        paddr_t pa;
        vaddr_t kern_start_4m_va, kern_end_4m_va, page;
        vaddr_t piglet_start_va, piglet_end_va;
+       struct pmap *kpm = pmap_kernel();
 
        /* Identity map PD, PT, and stack pages */
        pmap_kenter_pa(HIBERNATE_PT_PAGE, HIBERNATE_PT_PAGE, PROT_MASK);
@@ -307,6 +308,17 @@ hibernate_populate_resume_pt(union hibernate_info *hib_info,
                hibernate_enter_resume_mapping(page, pa, 1);
        }
 
+       /*
+        * Fill last 8 slots of the new PD with the PAE PDPTEs of the
+        * kernel pmap, such that we can easily switch back into
+        * non-PAE mode.  If we're running in non-PAE mode, this will
+        * just fill the slots with zeroes.
+        */
+       ((uint64_t *)HIBERNATE_PD_PAGE)[508] = kpm->pm_pdidx[0];
+       ((uint64_t *)HIBERNATE_PD_PAGE)[509] = kpm->pm_pdidx[1];
+       ((uint64_t *)HIBERNATE_PD_PAGE)[510] = kpm->pm_pdidx[2];
+       ((uint64_t *)HIBERNATE_PD_PAGE)[511] = kpm->pm_pdidx[3];
+
        /* Unmap MMU pages (stack remains mapped) */
        pmap_kremove(HIBERNATE_PT_PAGE, PAGE_SIZE);
        pmap_kremove(HIBERNATE_PD_PAGE, PAGE_SIZE);