/*
- * Copyright (c) 2004-2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2016 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,
* 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@
*/
-
/*
Sleep:
#include <IOKit/IONVRAM.h>
#include "IOHibernateInternal.h"
#include <vm/WKdm_new.h>
+#include <vm/vm_protos.h>
#include "IOKitKernelInternal.h"
#include <pexpert/device_tree.h>
#include <machine/pal_routines.h>
#include <machine/pal_hibernate.h>
#include <i386/tsc.h>
+#include <i386/cpuid.h>
extern "C" addr64_t kvtophys(vm_offset_t va);
extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define DISABLE_TRIM 0
-#define TRIM_DELAY 5000
+#define TRIM_DELAY 25000
-extern boolean_t root_is_CF_drive;
extern unsigned int save_kdebug_enable;
extern uint32_t gIOHibernateState;
uint32_t gIOHibernateMode;
static uint32_t gIOHibernateFreeRatio = 0; // free page target (percent)
uint32_t gIOHibernateFreeTime = 0*1000; // max time to spend freeing pages (ms)
static uint64_t gIOHibernateCompression = 0x80; // default compression 50%
+boolean_t gIOHibernateStandbyDisabled;
static IODTNVRAM * gIOOptionsEntry;
static IORegistryEntry * gIOChosenEntry;
OSObject * obj;
OSString * str;
OSNumber * num;
- bool dsSSD, vmflush;
+ bool dsSSD, vmflush, swapPinned;
IOHibernateVars * vars;
uint64_t setFileSize = 0;
gFSState = kFSOpening;
IOLockUnlock(gFSLock);
+ swapPinned = false;
do
{
vars->srcBuffer = IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn,
- 2 * page_size + WKdm_SCRATCH_BUF_SIZE, page_size);
+ 2 * page_size + WKdm_SCRATCH_BUF_SIZE_INTERNAL, page_size);
vars->handoffBuffer = IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn,
ptoa_64(gIOHibernateHandoffPageCount), page_size);
gIOHibernateCurrentHeader->debugFlags = gIOHibernateDebugFlags;
gIOHibernateCurrentHeader->signature = kIOHibernateHeaderInvalidSignature;
- vmflush = ((kOSBooleanTrue == IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey)) && root_is_CF_drive == FALSE);
+ vmflush = ((kOSBooleanTrue == IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey)));
err = hibernate_alloc_page_lists(&vars->page_list,
&vars->page_list_wired,
&vars->page_list_pal);
- if (KERN_SUCCESS != err)
- break;
+ if (KERN_SUCCESS != err) break;
+
+ err = hibernate_pin_swap(TRUE);
+ if (KERN_SUCCESS != err) break;
+ swapPinned = true;
if (vars->fileMinSize || (kIOHibernateModeFileResize & gIOHibernateMode))
{
clock_get_uptime(&endTime);
SUB_ABSOLUTETIME(&endTime, &startTime);
absolutetime_to_nanoseconds(endTime, &nsec);
- HIBLOG("hibernate_setup(%d) took %qd ms\n", err, nsec / 1000000ULL);
+
+ boolean_t haveSwapPin, hibFileSSD;
+ haveSwapPin = vm_swap_files_pinned();
+
+ hibFileSSD = (kIOPolledFileSSD & vars->fileVars->flags);
+
+ HIBLOG("hibernate_setup(%d) took %qd ms, swapPin(%d) ssd(%d)\n",
+ err, nsec / 1000000ULL,
+ haveSwapPin, hibFileSSD);
if (KERN_SUCCESS != err) break;
+ gIOHibernateStandbyDisabled = ((!haveSwapPin || !hibFileSSD));
+
dsSSD = ((0 != (kIOPolledFileSSD & vars->fileVars->flags))
&& (kOSBooleanTrue == IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey)));
}
while (false);
+ if (swapPinned) hibernate_pin_swap(FALSE);
+
IOLockLock(gFSLock);
if ((kIOReturnSuccess == err) && (kFSOpening != gFSState))
{
int rc;
IOPolledFileExtent * fileExtents;
- fileExtents = (typeof(fileExtents)) vars->fileExtents->getBytesNoCopy(),
+ fileExtents = (typeof(fileExtents)) vars->fileExtents->getBytesNoCopy();
memset(&hdr, 0, sizeof(IOHibernateImageHeader));
count = vars->fileExtents->getLength();
return err;
}
+extern "C" boolean_t root_is_CF_drive;
+
void
IOOpenDebugDataFile(const char *fname, uint64_t size)
{
gDebugImageLock = IOLockAlloc();
}
+ if (root_is_CF_drive) return;
+
// Try to get a lock, but don't block for getting lock
if (!IOLockTryLock(gDebugImageLock)) {
HIBLOG("IOOpenDebugDataFile: Failed to get lock\n");
return;
}
+void
+IOCloseDebugDataFile()
+{
+ IOSetBootImageNVRAM(0);
+
+ if (gDebugImageLock) {
+ IOLockLock(gDebugImageLock);
+ if (gDebugImageFileVars != 0) {
+ kprintf("IOHibernateSystemPostWake: Closing debugdata file\n");
+ IOPolledFileClose(&gDebugImageFileVars, 0, 0, 0, 0, 0);
+ }
+ IOLockUnlock(gDebugImageLock);
+ }
+
+
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
DECLARE_IOHIBERNATEPROGRESSALPHA
IOHibernateSystemPostWake(void)
{
gIOHibernateCurrentHeader->signature = kIOHibernateHeaderInvalidSignature;
+ IOLockLock(gFSLock);
if (kFSOpened == gFSState)
{
// invalidate & close the image file
}
gFSState = kFSIdle;
- IOSetBootImageNVRAM(0);
-
- if (gDebugImageLock) {
- IOLockLock(gDebugImageLock);
- if (gDebugImageFileVars != 0) {
- kprintf("IOHibernateSystemPostWake: Closing debugdata file\n");
- IOPolledFileClose(&gDebugImageFileVars, 0, 0, 0, 0, 0);
- }
- IOLockUnlock(gDebugImageLock);
- }
+ IOLockUnlock(gFSLock);
+ // IOCloseDebugDataFile() calls IOSetBootImageNVRAM() unconditionally
+ IOCloseDebugDataFile( );
return (kIOReturnSuccess);
}
&gIOHibernateMode, 0, "");
SYSCTL_STRUCT(_kern, OID_AUTO, hibernatestatistics,
CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
- gIOHibernateStats, hibernate_statistics_t, "");
+ &_hibernateStats, hibernate_statistics_t, "");
SYSCTL_UINT(_kern, OID_AUTO, hibernategraphicsready,
CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_ANYBODY,
- &gIOHibernateStats->graphicsReadyTime, 0, "");
+ &_hibernateStats.graphicsReadyTime, 0, "");
SYSCTL_UINT(_kern, OID_AUTO, hibernatewakenotification,
CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_ANYBODY,
- &gIOHibernateStats->wakeNotificationTime, 0, "");
+ &_hibernateStats.wakeNotificationTime, 0, "");
SYSCTL_UINT(_kern, OID_AUTO, hibernatelockscreenready,
CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_ANYBODY,
- &gIOHibernateStats->lockScreenReadyTime, 0, "");
+ &_hibernateStats.lockScreenReadyTime, 0, "");
SYSCTL_UINT(_kern, OID_AUTO, hibernatehidready,
CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_ANYBODY,
- &gIOHibernateStats->hidReadyTime, 0, "");
+ &_hibernateStats.hidReadyTime, 0, "");
void
gFSLock = IOLockAlloc();
}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-static void
-hibernate_setup_for_wake(void)
-{
-}
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static IOReturn
IOHibernateVars * vars = &gIOHibernateVars;
IOPolledFileExtent * fileExtents;
- assert_static(sizeof(IOHibernateImageHeader) == 512);
+ _static_assert_1_arg(sizeof(IOHibernateImageHeader) == 512);
uint32_t pageCount, pagesDone;
IOReturn err;
svPageCount = 0;
zvPageCount = 0;
- if (!vars->fileVars || !vars->fileVars->pollers)
- return (false /* sleep */ );
+ if (!vars->fileVars
+ || !vars->fileVars->pollers
+ || !(kIOHibernateModeOn & gIOHibernateMode)) return (kIOHibernatePostWriteSleep);
if (kIOHibernateModeSleep & gIOHibernateMode)
kdebug_enable = save_kdebug_enable;
}
#endif /* CRYPTO */
- hibernate_setup_for_wake();
-
hibernate_page_list_setall(vars->page_list,
vars->page_list_wired,
vars->page_list_pal,
kUnwiredEncrypt = kEncrypt
};
+ bool cpuAES = (0 != (CPUID_FEATURE_AES & cpuid_features()));
+#define _pmap_is_noencrypt(x) (cpuAES ? false : pmap_is_noencrypt((x)))
+
for (pageType = kWiredEncrypt; pageType >= kUnwiredEncrypt; pageType--)
{
if (kUnwiredEncrypt == pageType)
&ppnum);
// kprintf("[%d](%x : %x)\n", pageType, ppnum, count);
iterDone = !count;
-
+
if (count && (kWired & pageType) && needEncrypt)
{
uint32_t checkIndex;
for (checkIndex = 0;
(checkIndex < count)
- && (((kEncrypt & pageType) == 0) == pmap_is_noencrypt(ppnum + checkIndex));
+ && (((kEncrypt & pageType) == 0) == _pmap_is_noencrypt(ppnum + checkIndex));
checkIndex++)
{}
if (!checkIndex)
#define t40ms(x) (tmrCvt((((uint64_t)(x)) << 8), tscFCvtt2n) / 1000000)
#define tStat(x, y) gIOHibernateStats->x = t40ms(gIOHibernateCurrentHeader->y);
tStat(booterStart, booterStart);
- gIOHibernateStats->smcStart = gIOHibernateCurrentHeader->smcStart,
+ gIOHibernateStats->smcStart = gIOHibernateCurrentHeader->smcStart;
tStat(booterDuration0, booterTime0);
tStat(booterDuration1, booterTime1);
tStat(booterDuration2, booterTime2);
break;
case kIOHibernateHandoffTypeGraphicsInfo:
- bcopy(data, gIOHibernateGraphicsInfo, sizeof(*gIOHibernateGraphicsInfo));
+ if (handoff->bytecount == sizeof(*gIOHibernateGraphicsInfo))
+ {
+ bcopy(data, gIOHibernateGraphicsInfo, sizeof(*gIOHibernateGraphicsInfo));
+ }
break;
case kIOHibernateHandoffTypeCryptVars:
if (cryptvars && !foundCryptData)
panic("hibernate handoff");
- HIBPRINT("video %x %d %d %d status %x\n",
+ HIBPRINT("video 0x%llx %d %d %d status %x\n",
gIOHibernateGraphicsInfo->physicalAddress, gIOHibernateGraphicsInfo->depth,
gIOHibernateGraphicsInfo->width, gIOHibernateGraphicsInfo->height, gIOHibernateGraphicsInfo->gfxStatus);