#include <kern/machine.h>
#include <kern/misc_protos.h>
#include <kern/thread.h>
#include <kern/processor.h>
#include <kern/kalloc.h>
#include <mach/machine.h>
#include <mach/processor_info.h>
#include <mach/mach_types.h>
#include <i386/pmap.h>
#include <kern/cpu_data.h>
#include <IOKit/IOPlatformExpert.h>
#define KERNEL
#include <IOKit/IOHibernatePrivate.h>
#include <vm/vm_page.h>
extern void *sectTEXTB;
extern char *first_avail;
hibernate_page_list_t *
hibernate_page_list_allocate(void)
{
vm_offset_t base;
vm_size_t size;
uint32_t bank;
uint32_t pages, page_count;
hibernate_page_list_t * list;
hibernate_bitmap_t * bitmap;
pmap_memory_region_t * regions;
pmap_memory_region_t * rp;
uint32_t num_regions, num_alloc_regions;
page_count = 0;
num_alloc_regions = 1 + pmap_memory_region_count;
regions = (pmap_memory_region_t *)kalloc(sizeof(pmap_memory_region_t) * num_alloc_regions);
if (!regions)
return (0);
rp = regions;
base = (vm_offset_t)(sectTEXTB) & 0x3FFFFFFF;
rp->base = atop_32(base);
rp->end = atop_32((vm_offset_t)first_avail) - 1;
rp->alloc = 0;
num_regions = 1;
for (bank = 0; bank < (uint32_t) pmap_memory_region_count; bank++)
{
if ((rp->end + 1) == pmap_memory_regions[bank].base) {
rp->end = pmap_memory_regions[bank].end;
} else {
++rp;
++num_regions;
rp->base = pmap_memory_regions[bank].base;
rp->end = pmap_memory_regions[bank].end;
rp->alloc = 0;
}
}
size = sizeof(hibernate_page_list_t);
page_count = 0;
for (bank = 0, rp = regions; bank < num_regions; bank++, rp++) {
pages = rp->end + 1 - rp->base;
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 = size;
list->page_count = page_count;
list->bank_count = num_regions;
bitmap = &list->bank_bitmap[0];
for (bank = 0, rp = regions; bank < num_regions; bank++, rp++) {
bitmap->first_page = rp->base;
bitmap->last_page = rp->end;
bitmap->bitmapwords = (bitmap->last_page + 1
- bitmap->first_page + 31) >> 5;
kprintf("HIB: Bank %d: 0x%x end 0x%x\n", bank,
ptoa_32(bitmap->first_page),
ptoa_32(bitmap->last_page));
bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
}
kfree((void *)regions, sizeof(pmap_memory_region_t) * num_alloc_regions);
return (list);
}
void
hibernate_page_list_setall_machine(hibernate_page_list_t * page_list,
hibernate_page_list_t * page_list_wired,
uint32_t * pagesOut)
{
KernelBootArgs_t * bootArgs = (KernelBootArgs_t *)PE_state.bootArgs;
MemoryRange * mptr;
uint32_t bank;
uint32_t page, count;
for (bank = 0, mptr = bootArgs->memoryMap; bank < bootArgs->memoryMapCount; bank++, mptr++) {
if (kMemoryRangeNVS != mptr->type) continue;
kprintf("Base NVS region 0x%x + 0x%x\n", (vm_offset_t)mptr->base, (vm_size_t)mptr->length);
page = atop_32(trunc_page((vm_offset_t)mptr->base));
count = atop_32(round_page((vm_offset_t)mptr->base + (vm_size_t)mptr->length)) - page;
kprintf("Rounded NVS region 0x%x size 0x%x\n", page, count);
hibernate_set_page_state(page_list, page_list_wired, page, count, 1);
pagesOut -= count;
}
}
kern_return_t
hibernate_processor_setup(IOHibernateImageHeader * header)
{
current_cpu_datap()->cpu_hibernate = 1;
header->processorFlags = 0;
return (KERN_SUCCESS);
}
void
hibernate_vm_lock(void)
{
if (FALSE )
{
vm_page_lock_queues();
mutex_lock(&vm_page_queue_free_lock);
}
}
void
hibernate_vm_unlock(void)
{
if (FALSE )
{
mutex_unlock(&vm_page_queue_free_lock);
vm_page_unlock_queues();
}
}