]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/hibernate_i386.c
xnu-4903.270.47.tar.gz
[apple/xnu.git] / osfmk / i386 / hibernate_i386.c
index 21322b7518eadc8582bcd70b5a67d14d460ec0f1..d88bb1897312998551dbac9b9ade126787a7444a 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 
 extern ppnum_t max_ppnum;
 
-#define MAX_BANKS      32
+#define MAX_BANKS       32
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 hibernate_page_list_t *
 hibernate_page_list_allocate(boolean_t log)
 {
-    ppnum_t                base, num;
-    vm_size_t               size;
-    uint32_t                bank, num_banks;
-    uint32_t               pages, page_count;
-    hibernate_page_list_t * list;
-    hibernate_bitmap_t *    bitmap;
-
-    EfiMemoryRange *       mptr;
-    uint32_t               mcount, msize, i;
-    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)
-       panic("Invalid memory map descriptor size");
-    msize = args->MemoryMapDescriptorSize;
-    mcount = args->MemoryMapSize / msize;
+       ppnum_t                 base, num;
+       vm_size_t               size;
+       uint32_t                bank, num_banks;
+       uint32_t                pages, page_count;
+       hibernate_page_list_t * list;
+       hibernate_bitmap_t *    bitmap;
+
+       EfiMemoryRange *        mptr;
+       uint32_t                mcount, msize, i;
+       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) {
+               panic("Invalid memory map descriptor size");
+       }
+       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);
-    }
+       /* 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;
+       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 KASAN
-       if (i == shadow_stolen_idx) {
-           /*
-            * Add all stolen pages to the bitmap. Later we will prune the unused
-            * pages.
-            */
-           num += shadow_pages_total;
-       }
+               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) > pnmax)
-               num = pnmax - base + 1;
-       if (!num)
-               continue;
-
-       switch (mptr->Type)
-       {
-           // any kind of dram
-           case kEfiACPIMemoryNVS:
-           case kEfiPalCode:
-               non_os_pagecount += num;
-
-           // OS used dram
-           case kEfiLoaderCode:
-           case kEfiLoaderData:
-           case kEfiBootServicesCode:
-           case kEfiBootServicesData:
-           case kEfiConventionalMemory:
-
-               for (bank = 0; bank < num_banks; bank++)
-               {
-                   if (dram_ranges[bank].first_page <= base)
+               if (base > pnmax) {
                        continue;
-                   if ((base + num) == dram_ranges[bank].first_page)
-                   {
-                       dram_ranges[bank].first_page = base;
-                       num = 0;
-                   }
-                   break;
                }
-               if (!num) break;
-               
-               if (bank && (base == (1 + dram_ranges[bank - 1].last_page)))
-                   bank--;
-               else
-               {
-                   num_banks++;
-                   if (num_banks >= MAX_BANKS) break;
-                   bcopy(&dram_ranges[bank], 
-                         &dram_ranges[bank + 1], 
-                         (num_banks - bank - 1) * sizeof(hibernate_bitmap_t));
-                   dram_ranges[bank].first_page = base;
+               if ((base + num - 1) > pnmax) {
+                       num = pnmax - base + 1;
+               }
+               if (!num) {
+                       continue;
                }
-               dram_ranges[bank].last_page = base + num - 1;
-               break;
-
-           // runtime services will be restarted, so no save
-           case kEfiRuntimeServicesCode:
-           case kEfiRuntimeServicesData:
-           // contents are volatile once the platform expert starts
-           case kEfiACPIReclaimMemory:
-           // non dram
-           case kEfiReservedMemoryType:
-           case kEfiUnusableMemory:
-           case kEfiMemoryMappedIO:
-           case kEfiMemoryMappedIOPortSpace:
-           default:
-               break;
+
+               switch (mptr->Type) {
+               // any kind of dram
+               case kEfiACPIMemoryNVS:
+               case kEfiPalCode:
+                       non_os_pagecount += num;
+
+               // OS used dram
+               case kEfiLoaderCode:
+               case kEfiLoaderData:
+               case kEfiBootServicesCode:
+               case kEfiBootServicesData:
+               case kEfiConventionalMemory:
+
+                       for (bank = 0; bank < num_banks; bank++) {
+                               if (dram_ranges[bank].first_page <= base) {
+                                       continue;
+                               }
+                               if ((base + num) == dram_ranges[bank].first_page) {
+                                       dram_ranges[bank].first_page = base;
+                                       num = 0;
+                               }
+                               break;
+                       }
+                       if (!num) {
+                               break;
+                       }
+
+                       if (bank && (base == (1 + dram_ranges[bank - 1].last_page))) {
+                               bank--;
+                       } else {
+                               num_banks++;
+                               if (num_banks >= MAX_BANKS) {
+                                       break;
+                               }
+                               bcopy(&dram_ranges[bank],
+                                   &dram_ranges[bank + 1],
+                                   (num_banks - bank - 1) * sizeof(hibernate_bitmap_t));
+                               dram_ranges[bank].first_page = base;
+                       }
+                       dram_ranges[bank].last_page = base + num - 1;
+                       break;
+
+               // runtime services will be restarted, so no save
+               case kEfiRuntimeServicesCode:
+               case kEfiRuntimeServicesData:
+               // contents are volatile once the platform expert starts
+               case kEfiACPIReclaimMemory:
+               // non dram
+               case kEfiReservedMemoryType:
+               case kEfiUnusableMemory:
+               case kEfiMemoryMappedIO:
+               case kEfiMemoryMappedIOPortSpace:
+               default:
+                       break;
+               }
+       }
+
+       if (num_banks >= MAX_BANKS) {
+               return NULL;
        }
-    }
-
-    if (num_banks >= MAX_BANKS)
-       return (NULL);
-
-    // size the hibernation bitmap
-
-    size = sizeof(hibernate_page_list_t);
-    page_count = 0;
-    for (bank = 0; bank < num_banks; bank++) {
-       pages = dram_ranges[bank].last_page + 1 - dram_ranges[bank].first_page;
-       page_count += pages;
-        size += sizeof(hibernate_bitmap_t) + ((pages + 31) >> 5) * sizeof(uint32_t);
-    }
-
-    list = (hibernate_page_list_t *)kalloc(size);
-    if (!list)
-       return (list);
-       
-    list->list_size  = (uint32_t)size;
-    list->page_count = page_count;
-    list->bank_count = num_banks;
-
-    // convert to hibernation bitmap.
-
-    bitmap = &list->bank_bitmap[0];
-    for (bank = 0; bank < num_banks; bank++)
-    {
-        bitmap->first_page = dram_ranges[bank].first_page;
-        bitmap->last_page  = dram_ranges[bank].last_page;
-        bitmap->bitmapwords = (bitmap->last_page + 1
-                               - bitmap->first_page + 31) >> 5;
-        if (log) kprintf("hib bank[%d]: 0x%x000 end 0x%xfff\n",
-                         bank, bitmap->first_page, bitmap->last_page);
-       bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
-    }
-    if (log) printf("efi pagecount %d\n", non_os_pagecount);
-
-    return (list);
+
+       // size the hibernation bitmap
+
+       size = sizeof(hibernate_page_list_t);
+       page_count = 0;
+       for (bank = 0; bank < num_banks; bank++) {
+               pages = dram_ranges[bank].last_page + 1 - dram_ranges[bank].first_page;
+               page_count += pages;
+               size += sizeof(hibernate_bitmap_t) + ((pages + 31) >> 5) * sizeof(uint32_t);
+       }
+
+       list = (hibernate_page_list_t *)kalloc(size);
+       if (!list) {
+               return list;
+       }
+
+       list->list_size  = (uint32_t)size;
+       list->page_count = page_count;
+       list->bank_count = num_banks;
+
+       // convert to hibernation bitmap.
+
+       bitmap = &list->bank_bitmap[0];
+       for (bank = 0; bank < num_banks; bank++) {
+               bitmap->first_page = dram_ranges[bank].first_page;
+               bitmap->last_page  = dram_ranges[bank].last_page;
+               bitmap->bitmapwords = (bitmap->last_page + 1
+                   - bitmap->first_page + 31) >> 5;
+               if (log) {
+                       kprintf("hib bank[%d]: 0x%x000 end 0x%xfff\n",
+                           bank, bitmap->first_page, bitmap->last_page);
+               }
+               bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
+       }
+       if (log) {
+               printf("efi pagecount %d\n", non_os_pagecount);
+       }
+
+       return list;
 }
 
 // mark pages not to be saved, but available for scratch usage during restore
 
 void
 hibernate_page_list_setall_machine( __unused hibernate_page_list_t * page_list,
-                                    __unused hibernate_page_list_t * page_list_wired,
-                                    __unused boolean_t preflight,
-                                    __unused uint32_t * pagesOut)
+    __unused hibernate_page_list_t * page_list_wired,
+    __unused boolean_t preflight,
+    __unused uint32_t * pagesOut)
 {
 }
 
 // mark pages not to be saved and not for scratch usage during restore
 void
 hibernate_page_list_set_volatile( hibernate_page_list_t * page_list,
-                                 hibernate_page_list_t * page_list_wired,
-                                 uint32_t * pagesOut)
+    hibernate_page_list_t * page_list_wired,
+    uint32_t * pagesOut)
 {
-    boot_args * args = (boot_args *) PE_state.bootArgs;
+       boot_args * args = (boot_args *) PE_state.bootArgs;
 
-    if (args->efiRuntimeServicesPageStart)
-    {
-       hibernate_set_page_state(page_list, page_list_wired, 
-                   args->efiRuntimeServicesPageStart, args->efiRuntimeServicesPageCount, 
+       if (args->efiRuntimeServicesPageStart) {
+               hibernate_set_page_state(page_list, page_list_wired,
+                   args->efiRuntimeServicesPageStart, args->efiRuntimeServicesPageCount,
                    kIOHibernatePageStateFree);
-       *pagesOut -= args->efiRuntimeServicesPageCount;
-    }
+               *pagesOut -= args->efiRuntimeServicesPageCount;
+       }
 }
 
-kern_return_t 
+kern_return_t
 hibernate_processor_setup(IOHibernateImageHeader * header)
 {
-    boot_args * args = (boot_args *) PE_state.bootArgs;
+       boot_args * args = (boot_args *) PE_state.bootArgs;
 
-    cpu_datap(0)->cpu_hibernate = 1;
-    header->processorFlags = 0;
+       cpu_datap(0)->cpu_hibernate = 1;
+       header->processorFlags = 0;
 
-    header->runtimePages     = args->efiRuntimeServicesPageStart;
-    header->runtimePageCount = args->efiRuntimeServicesPageCount;
-    header->runtimeVirtualPages = args->efiRuntimeServicesVirtualPageStart;
-    header->performanceDataStart = args->performanceDataStart;
-    header->performanceDataSize = args->performanceDataSize;
+       header->runtimePages     = args->efiRuntimeServicesPageStart;
+       header->runtimePageCount = args->efiRuntimeServicesPageCount;
+       header->runtimeVirtualPages = args->efiRuntimeServicesVirtualPageStart;
+       header->performanceDataStart = args->performanceDataStart;
+       header->performanceDataSize = args->performanceDataSize;
 
-    return (KERN_SUCCESS);
+       return KERN_SUCCESS;
 }
 
 static boolean_t hibernate_vm_locks_safe;
@@ -249,18 +257,20 @@ static boolean_t hibernate_vm_locks_safe;
 void
 hibernate_vm_lock(void)
 {
-    if (current_cpu_datap()->cpu_hibernate) {
-       hibernate_vm_lock_queues();
-       hibernate_vm_locks_safe = TRUE;
-    }
+       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);
+       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,
@@ -270,14 +280,14 @@ hibernate_vm_unlock(void)
 void
 hibernate_vm_lock_end(void)
 {
-    assert(FALSE == ml_get_interrupts_enabled());
-    hibernate_vm_locks_safe = FALSE;
-    ml_set_is_quiescing(FALSE);
+       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);
+       assert(FALSE == ml_get_interrupts_enabled());
+       return hibernate_vm_locks_safe;
 }