#include <IOKit/IOHibernatePrivate.h>
#include <vm/vm_page.h>
#include <i386/i386_lowmem.h>
+#include <san/kasan.h>
extern ppnum_t max_ppnum;
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)
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))
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;
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);
}