]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/hibernate_i386.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / osfmk / i386 / hibernate_i386.c
CommitLineData
3a60a9f5
A
1/*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
3a60a9f5 11 *
37839358
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
3a60a9f5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
37839358
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
3a60a9f5
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <kern/machine.h>
24#include <kern/misc_protos.h>
25#include <kern/thread.h>
26#include <kern/processor.h>
27#include <kern/kalloc.h>
28#include <mach/machine.h>
29#include <mach/processor_info.h>
30#include <mach/mach_types.h>
31#include <i386/pmap.h>
32#include <kern/cpu_data.h>
33#include <IOKit/IOPlatformExpert.h>
c0fea474
A
34
35#include <pexpert/i386/efi.h>
3a60a9f5
A
36
37#include <IOKit/IOHibernatePrivate.h>
38#include <vm/vm_page.h>
c0fea474 39#include "i386_lowmem.h"
3a60a9f5 40
c0fea474 41#define MAX_BANKS 32
3a60a9f5 42
c0fea474 43/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3a60a9f5
A
44
45hibernate_page_list_t *
46hibernate_page_list_allocate(void)
47{
c0fea474 48 ppnum_t base, num;
3a60a9f5 49 vm_size_t size;
c0fea474 50 uint32_t bank, num_banks;
3a60a9f5
A
51 uint32_t pages, page_count;
52 hibernate_page_list_t * list;
53 hibernate_bitmap_t * bitmap;
3a60a9f5 54
c0fea474
A
55 EfiMemoryRange * mptr;
56 uint32_t mcount, msize, i;
57 hibernate_bitmap_t dram_ranges[MAX_BANKS];
58 boot_args * args = (boot_args *) PE_state.bootArgs;
3a60a9f5 59
c0fea474
A
60 mptr = args->MemoryMap;
61 if (args->MemoryMapDescriptorSize == 0)
62 panic("Invalid memory map descriptor size");
63 msize = args->MemoryMapDescriptorSize;
64 mcount = args->MemoryMapSize / msize;
3a60a9f5 65
c0fea474
A
66 num_banks = 0;
67 for (i = 0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize))
3a60a9f5 68 {
c0fea474
A
69 base = (ppnum_t) (mptr->PhysicalStart >> I386_PGSHIFT);
70 num = (ppnum_t) mptr->NumberOfPages;
71 if (!num)
72 continue;
73
74 switch (mptr->Type)
75 {
76 // any kind of dram
77 case kEfiLoaderCode:
78 case kEfiLoaderData:
79 case kEfiBootServicesCode:
80 case kEfiBootServicesData:
81 case kEfiConventionalMemory:
82 case kEfiACPIReclaimMemory:
83 case kEfiACPIMemoryNVS:
84 case kEfiPalCode:
85
86 if (!num_banks || (base != (1 + dram_ranges[num_banks - 1].last_page)))
87 {
88 num_banks++;
89 if (num_banks >= MAX_BANKS)
90 break;
91 dram_ranges[num_banks - 1].first_page = base;
92 }
93 dram_ranges[num_banks - 1].last_page = base + num - 1;
94 break;
95
96 // runtime services will be restarted, so no save
97 case kEfiRuntimeServicesCode:
98 case kEfiRuntimeServicesData:
99 // non dram
100 case kEfiReservedMemoryType:
101 case kEfiUnusableMemory:
102 case kEfiMemoryMappedIO:
103 case kEfiMemoryMappedIOPortSpace:
104 default:
105 break;
106 }
3a60a9f5
A
107 }
108
c0fea474
A
109 if (num_banks >= MAX_BANKS)
110 return (NULL);
111
112 // size the hibernation bitmap
113
3a60a9f5
A
114 size = sizeof(hibernate_page_list_t);
115 page_count = 0;
c0fea474
A
116 for (bank = 0; bank < num_banks; bank++) {
117 pages = dram_ranges[bank].last_page + 1 - dram_ranges[bank].first_page;
3a60a9f5
A
118 page_count += pages;
119 size += sizeof(hibernate_bitmap_t) + ((pages + 31) >> 5) * sizeof(uint32_t);
120 }
121
122 list = (hibernate_page_list_t *)kalloc(size);
123 if (!list)
124 return (list);
125
126 list->list_size = size;
127 list->page_count = page_count;
c0fea474
A
128 list->bank_count = num_banks;
129
130 // convert to hibernation bitmap.
3a60a9f5 131
3a60a9f5 132 bitmap = &list->bank_bitmap[0];
c0fea474
A
133 for (bank = 0; bank < num_banks; bank++)
134 {
135 bitmap->first_page = dram_ranges[bank].first_page;
136 bitmap->last_page = dram_ranges[bank].last_page;
3a60a9f5
A
137 bitmap->bitmapwords = (bitmap->last_page + 1
138 - bitmap->first_page + 31) >> 5;
c0fea474
A
139 kprintf("hib bank[%d]: 0x%x000 end 0x%xfff\n", bank,
140 bitmap->first_page,
141 bitmap->last_page);
3a60a9f5
A
142 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
143 }
144
3a60a9f5
A
145 return (list);
146}
147
c0fea474
A
148// mark pages not to be saved, but available for scratch usage during restore
149
150void
151hibernate_page_list_setall_machine( __unused hibernate_page_list_t * page_list,
152 __unused hibernate_page_list_t * page_list_wired,
153 __unused uint32_t * pagesOut)
154{
155}
156
157// mark pages not to be saved and not for scratch usage during restore
3a60a9f5 158void
c0fea474
A
159hibernate_page_list_set_volatile( hibernate_page_list_t * page_list,
160 hibernate_page_list_t * page_list_wired,
161 uint32_t * pagesOut)
3a60a9f5 162{
c0fea474
A
163 boot_args * args = (boot_args *) PE_state.bootArgs;
164
165 hibernate_set_page_state(page_list, page_list_wired,
166 I386_HIB_PAGETABLE, I386_HIB_PAGETABLE_COUNT,
167 kIOHibernatePageStateFree);
168 *pagesOut -= I386_HIB_PAGETABLE_COUNT;
169
170 if (args->efiRuntimeServicesPageStart)
171 {
172 hibernate_set_page_state(page_list, page_list_wired,
173 args->efiRuntimeServicesPageStart, args->efiRuntimeServicesPageCount,
174 kIOHibernatePageStateFree);
175 *pagesOut -= args->efiRuntimeServicesPageCount;
3a60a9f5
A
176 }
177}
178
179kern_return_t
180hibernate_processor_setup(IOHibernateImageHeader * header)
181{
c0fea474
A
182 boot_args * args = (boot_args *) PE_state.bootArgs;
183
184 cpu_datap(0)->cpu_hibernate = 1;
3a60a9f5 185 header->processorFlags = 0;
c0fea474
A
186
187 header->runtimePages = args->efiRuntimeServicesPageStart;
188 header->runtimePageCount = args->efiRuntimeServicesPageCount;
189
3a60a9f5
A
190 return (KERN_SUCCESS);
191}
192
193void
194hibernate_vm_lock(void)
195{
c0fea474 196 if (current_cpu_datap()->cpu_hibernate)
3a60a9f5
A
197 {
198 vm_page_lock_queues();
199 mutex_lock(&vm_page_queue_free_lock);
200 }
201}
202
203void
204hibernate_vm_unlock(void)
205{
c0fea474 206 if (current_cpu_datap()->cpu_hibernate)
3a60a9f5
A
207 {
208 mutex_unlock(&vm_page_queue_free_lock);
209 vm_page_unlock_queues();
210 }
211}