/*
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ * @APPLE_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
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * 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.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
*
- * 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
+ * This 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,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
*
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ * @APPLE_LICENSE_HEADER_END@
*/
#include <stdint.h>
#include <mach/mach_types.h>
#include <mach/vm_param.h>
#include <IOKit/IOHibernatePrivate.h>
-#include <IOKit/IOLib.h>
#include <pexpert/boot.h>
#include <crypto/aes.h>
static hibernate_cryptwakevars_t _cryptWakeVars;
hibernate_cryptwakevars_t * gIOHibernateCryptWakeVars = &_cryptWakeVars;
-vm_offset_t gIOHibernateWakeMap; // ppnum
-vm_size_t gIOHibernateWakeMapSize;
-
#if __i386__
extern void acpi_wake_prot_entry(void);
#endif
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define BASE 65521L /* largest prime smaller than 65536 */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static hibernate_bitmap_t *
-hibernate_page_bitmap(hibernate_page_list_t * list, uint32_t page)
+#if __ppc__
+static __inline__ unsigned int cntlzw(unsigned int num)
{
- uint32_t bank;
- hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
-
- for (bank = 0; bank < list->bank_count; bank++)
- {
- if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
- break;
- bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
- }
- if (bank == list->bank_count)
- bitmap = 0;
-
- return (bitmap);
+ unsigned int result;
+ __asm__ volatile("cntlzw %0, %1" : "=r" (result) : "r" (num));
+ return result;
+}
+#elif __i386__
+static __inline__ unsigned int cntlzw(unsigned int num)
+{
+ unsigned int result;
+ __asm__ volatile( "bsrl %1, %0\n\t"
+ "cmovel %2, %0"
+ : "=r" (result)
+ : "rm" (num), "r" (63));
+ return 31 ^ result;
}
+#else
+#error arch
+#endif
-hibernate_bitmap_t *
-hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * pPage)
+void
+hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page)
{
- uint32_t bank, page = *pPage;
+ uint32_t bank;
hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
for (bank = 0; bank < list->bank_count; bank++)
{
- if (page <= bitmap->first_page)
+ if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
{
- *pPage = bitmap->first_page;
+ page -= bitmap->first_page;
+ if (set)
+ bitmap->bitmap[page >> 5] |= (0x80000000 >> (page & 31));
+ //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
+ else
+ bitmap->bitmap[page >> 5] &= ~(0x80000000 >> (page & 31));
+ //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
break;
}
- if (page <= bitmap->last_page)
- break;
bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
}
- if (bank == list->bank_count)
- bitmap = 0;
-
- return (bitmap);
-}
-
-void
-hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page)
-{
- hibernate_bitmap_t * bitmap;
-
- bitmap = hibernate_page_bitmap(list, page);
- if (bitmap)
- {
- page -= bitmap->first_page;
- if (set)
- bitmap->bitmap[page >> 5] |= (0x80000000 >> (page & 31));
- //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
- else
- bitmap->bitmap[page >> 5] &= ~(0x80000000 >> (page & 31));
- //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
- }
}
boolean_t
hibernate_page_bittst(hibernate_page_list_t * list, uint32_t page)
{
boolean_t result = TRUE;
- hibernate_bitmap_t * bitmap;
+ uint32_t bank;
+ hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
- bitmap = hibernate_page_bitmap(list, page);
- if (bitmap)
+ for (bank = 0; bank < list->bank_count; bank++)
{
- page -= bitmap->first_page;
- result = (0 != (bitmap->bitmap[page >> 5] & (0x80000000 >> (page & 31))));
+ if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
+ {
+ page -= bitmap->first_page;
+ result = (0 != (bitmap->bitmap[page >> 5] & (0x80000000 >> (page & 31))));
+ break;
+ }
+ bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
}
return (result);
}
-// count bits clear or set (set == TRUE) starting at page.
+// count bits clear or set (set == TRUE) starting at index page.
uint32_t
-hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page)
+hibernate_page_list_count(hibernate_page_list_t * list, uint32_t set, uint32_t page)
{
- uint32_t index, bit, bits;
- uint32_t count;
-
- count = 0;
+ uint32_t bank, count;
+ hibernate_bitmap_t * bitmap;
- index = (page - bitmap->first_page) >> 5;
- bit = (page - bitmap->first_page) & 31;
+ bitmap = &list->bank_bitmap[0];
+ count = 0;
- bits = bitmap->bitmap[index];
- if (set)
- bits = ~bits;
- bits = (bits << bit);
- if (bits)
- count += __builtin_clz(bits);
- else
+ for (bank = 0; bank < list->bank_count; bank++)
{
- count += 32 - bit;
- while (++index < bitmap->bitmapwords)
+ // bits between banks are "set"
+ if (set && (page < bitmap->first_page))
{
- bits = bitmap->bitmap[index];
- if (set)
- bits = ~bits;
- if (bits)
+ count += bitmap->first_page - page;
+ page = bitmap->first_page;
+ }
+ if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
+ {
+ uint32_t index, bit, bits;
+
+ index = (page - bitmap->first_page) >> 5;
+ bit = (page - bitmap->first_page) & 31;
+
+ while (TRUE)
{
- count += __builtin_clz(bits);
- break;
+ bits = bitmap->bitmap[index];
+ if (set)
+ bits = ~bits;
+ bits = (bits << bit);
+ count += cntlzw(bits);
+ if (bits)
+ break;
+ count -= bit;
+
+ while (++index < bitmap->bitmapwords)
+ {
+ bits = bitmap->bitmap[index];
+ if (set)
+ bits = ~bits;
+ count += cntlzw(bits);
+ if (bits)
+ break;
+ }
+ if (bits)
+ break;
+ if (!set)
+ break;
+ // bits between banks are "set"
+ bank++;
+ if (bank >= list->bank_count)
+ break;
+ count -= (bitmap->last_page + 1);
+ bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
+ count += bitmap->first_page;
+ index = 0;
+ bit = 0;
}
- count += 32;
+ break;
}
+ bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
}
return (count);
}
-static vm_offset_t
-hibernate_page_list_grab(hibernate_page_list_t * list, uint32_t * pNextFree)
+
+static uint32_t
+hibernate_page_list_grab(hibernate_page_list_t * map, uint32_t * _nextFree)
{
- uint32_t nextFree = *pNextFree;
- uint32_t nextFreeInBank;
- hibernate_bitmap_t * bitmap;
+ uint32_t nextFree = *_nextFree;
- nextFreeInBank = nextFree + 1;
- while ((bitmap = hibernate_page_bitmap_pin(list, &nextFreeInBank)))
- {
- nextFreeInBank += hibernate_page_bitmap_count(bitmap, FALSE, nextFreeInBank);
- if (nextFreeInBank <= bitmap->last_page)
- {
- *pNextFree = nextFreeInBank;
- break;
- }
- }
+ if (!nextFree)
+ nextFree = hibernate_page_list_count(map, 0, 0);
- if (!bitmap)
- IOPanic(__FUNCTION__);
+ *_nextFree = nextFree + 1 + hibernate_page_list_count(map, 0, nextFree + 1);
return (nextFree);
}
uint32_t sum;
dst = ptoa_64(ppnum);
+#if __ppc__
if (ppnum < 0x00100000)
buffer = (uint32_t *) (uint32_t) dst;
+#elif __i386__
+ if (ppnum < atop_32(0xC0000000)) {
+ buffer = (uint32_t *) (uint32_t) dst;
+ }
+#endif
if (compressedSize != PAGE_SIZE)
{
}
}
-#define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
-
long
hibernate_kernel_entrypoint(IOHibernateImageHeader * header,
- void * p2, void * p3, void * p4)
+ void * p2, void * p3, __unused void * p4)
{
typedef void (*ResetProc)(void);
uint32_t idx;
uint32_t lastMapPage;
uint32_t lastPageIndexPage;
- C_ASSERT(sizeof(IOHibernateImageHeader) == 512);
bcopy_internal(header,
gIOHibernateCurrentHeader,
sizeof(IOHibernateImageHeader));
- if (!p2)
- {
- count = header->graphicsInfoOffset;
- if (count)
- p2 = (void *)(((uintptr_t) header) - count);
- }
if (p2)
bcopy_internal(p2,
gIOHibernateGraphicsInfo,
else
gIOHibernateGraphicsInfo->physicalAddress = gIOHibernateGraphicsInfo->depth = 0;
- if (!p3)
- {
- count = header->cryptVarsOffset;
- if (count)
- p3 = (void *)(((uintptr_t) header) - count);
- }
if (p3)
bcopy_internal(p3,
gIOHibernateCryptWakeVars,
}
nextFree = 0;
- hibernate_page_list_grab(map, &nextFree);
buffer = (uint32_t *) ptoa_32(hibernate_page_list_grab(map, &nextFree));
- if (header->memoryMapSize && (count = header->memoryMapOffset))
- {
- p4 = (void *)(((uintptr_t) header) - count);
- gIOHibernateWakeMap = hibernate_page_list_grab(map, &nextFree);
- gIOHibernateWakeMapSize = header->memoryMapSize;
- bcopy_internal(p4, (void *) ptoa_32(gIOHibernateWakeMap), gIOHibernateWakeMapSize);
- }
- else
- gIOHibernateWakeMapSize = 0;
-
sum = gIOHibernateCurrentHeader->actualRestore1Sum;
gIOHibernateCurrentHeader->diag[0] = (uint32_t) header;
gIOHibernateCurrentHeader->diag[1] = sum;
compressedSize = kIOHibernateTagLength & tag;
}
-// SINT(ppnum);
-
conflicts = (((ppnum >= atop_32(map)) && (ppnum <= lastMapPage))
|| ((ppnum >= atop_32(src)) && (ppnum <= lastImagePage)));
#elif __i386__
ResetProc proc;
proc = (ResetProc) acpi_wake_prot_entry;
- // flush caches
- __asm__("wbinvd");
+
proc();
#endif