]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/hibernate_i386.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / osfmk / i386 / hibernate_i386.c
index a16994234bc29b218e59819711a21f64f9b6bdb1..21322b7518eadc8582bcd70b5a67d14d460ec0f1 100644 (file)
@@ -43,6 +43,7 @@
 #include <IOKit/IOHibernatePrivate.h>
 #include <vm/vm_page.h>
 #include <i386/i386_lowmem.h>
+#include <san/kasan.h>
 
 extern ppnum_t max_ppnum;
 
@@ -65,6 +66,7 @@ hibernate_page_list_allocate(boolean_t log)
     hibernate_bitmap_t     dram_ranges[MAX_BANKS];
     boot_args *                    args = (boot_args *) PE_state.bootArgs;
     uint32_t               non_os_pagecount;
+    ppnum_t                pnmax = max_ppnum;
 
     mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
     if (args->MemoryMapDescriptorSize == 0)
@@ -72,6 +74,13 @@ hibernate_page_list_allocate(boolean_t log)
     msize = args->MemoryMapDescriptorSize;
     mcount = args->MemoryMapSize / msize;
 
+#if KASAN
+    /* adjust max page number to include stolen memory */
+    if (atop(shadow_ptop) > pnmax) {
+       pnmax = (ppnum_t)atop(shadow_ptop);
+    }
+#endif
+
     num_banks = 0;
     non_os_pagecount = 0;
     for (i = 0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize))
@@ -79,10 +88,20 @@ hibernate_page_list_allocate(boolean_t log)
        base = (ppnum_t) (mptr->PhysicalStart >> I386_PGSHIFT);
        num = (ppnum_t) mptr->NumberOfPages;
 
-       if (base > max_ppnum)
+#if KASAN
+       if (i == shadow_stolen_idx) {
+           /*
+            * Add all stolen pages to the bitmap. Later we will prune the unused
+            * pages.
+            */
+           num += shadow_pages_total;
+       }
+#endif
+
+       if (base > pnmax)
                continue;
-       if ((base + num - 1) > max_ppnum)
-               num = max_ppnum - base + 1;
+       if ((base + num - 1) > pnmax)
+               num = pnmax - base + 1;
        if (!num)
                continue;
 
@@ -225,14 +244,40 @@ hibernate_processor_setup(IOHibernateImageHeader * header)
     return (KERN_SUCCESS);
 }
 
+static boolean_t hibernate_vm_locks_safe;
+
 void
 hibernate_vm_lock(void)
 {
-    if (current_cpu_datap()->cpu_hibernate) hibernate_vm_lock_queues();
+    if (current_cpu_datap()->cpu_hibernate) {
+       hibernate_vm_lock_queues();
+       hibernate_vm_locks_safe = TRUE;
+    }
 }
 
 void
 hibernate_vm_unlock(void)
 {
+    assert(FALSE == ml_get_interrupts_enabled());
     if (current_cpu_datap()->cpu_hibernate)  hibernate_vm_unlock_queues();
+    ml_set_is_quiescing(TRUE);
+}
+
+// ACPI calls hibernate_vm_lock(), interrupt disable, hibernate_vm_unlock() on sleep,
+// hibernate_vm_lock_end() and interrupt enable on wake.
+// VM locks are safely single threaded between hibernate_vm_lock() and hibernate_vm_lock_end().
+
+void
+hibernate_vm_lock_end(void)
+{
+    assert(FALSE == ml_get_interrupts_enabled());
+    hibernate_vm_locks_safe = FALSE;
+    ml_set_is_quiescing(FALSE);
+}
+
+boolean_t
+hibernate_vm_locks_are_safe(void)
+{
+    assert(FALSE == ml_get_interrupts_enabled());
+    return (hibernate_vm_locks_safe);
 }