]>
Commit | Line | Data |
---|---|---|
3a60a9f5 A |
1 | /* |
2 | * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
3a60a9f5 | 5 | * |
8f6c56a5 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
3a60a9f5 A |
27 | */ |
28 | ||
29 | #include <kern/machine.h> | |
30 | #include <kern/misc_protos.h> | |
31 | #include <kern/thread.h> | |
32 | #include <kern/processor.h> | |
33 | #include <kern/kalloc.h> | |
34 | #include <mach/machine.h> | |
35 | #include <mach/processor_info.h> | |
36 | #include <mach/mach_types.h> | |
37 | #include <i386/pmap.h> | |
38 | #include <kern/cpu_data.h> | |
39 | #include <IOKit/IOPlatformExpert.h> | |
8f6c56a5 | 40 | #define KERNEL |
3a60a9f5 A |
41 | |
42 | #include <IOKit/IOHibernatePrivate.h> | |
43 | #include <vm/vm_page.h> | |
8ad349bb | 44 | |
5d5c5d0d | 45 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
8ad349bb | 46 | |
8f6c56a5 A |
47 | /* This assumes that |
48 | * - we never will want to read or write memory below the start of kernel text | |
49 | * - kernel text and data isn't included in pmap memory regions | |
50 | */ | |
51 | ||
52 | extern void *sectTEXTB; | |
53 | extern char *first_avail; | |
54 | ||
3a60a9f5 A |
55 | hibernate_page_list_t * |
56 | hibernate_page_list_allocate(void) | |
57 | { | |
8f6c56a5 | 58 | vm_offset_t base; |
3a60a9f5 | 59 | vm_size_t size; |
8f6c56a5 | 60 | uint32_t bank; |
3a60a9f5 A |
61 | uint32_t pages, page_count; |
62 | hibernate_page_list_t * list; | |
63 | hibernate_bitmap_t * bitmap; | |
8f6c56a5 A |
64 | pmap_memory_region_t * regions; |
65 | pmap_memory_region_t * rp; | |
66 | uint32_t num_regions, num_alloc_regions; | |
3a60a9f5 | 67 | |
8f6c56a5 | 68 | page_count = 0; |
c0fea474 | 69 | |
8f6c56a5 A |
70 | /* Make a list of the maximum number of regions needed */ |
71 | num_alloc_regions = 1 + pmap_memory_region_count; | |
c0fea474 | 72 | |
8f6c56a5 A |
73 | /* Allocate our own list of memory regions so we can sort them in order. */ |
74 | regions = (pmap_memory_region_t *)kalloc(sizeof(pmap_memory_region_t) * num_alloc_regions); | |
75 | if (!regions) | |
76 | return (0); | |
77 | ||
78 | /* Fill in the actual regions we will be returning. */ | |
79 | rp = regions; | |
8ad349bb | 80 | |
8f6c56a5 A |
81 | /* XXX should check for non-volatile memory region below kernel space. */ |
82 | /* Kernel region is first. */ | |
83 | base = (vm_offset_t)(sectTEXTB) & 0x3FFFFFFF; | |
84 | rp->base = atop_32(base); | |
85 | rp->end = atop_32((vm_offset_t)first_avail) - 1; | |
86 | rp->alloc = 0; | |
87 | num_regions = 1; | |
5d5c5d0d | 88 | |
8f6c56a5 A |
89 | /* Remaining memory regions. Consolidate adjacent regions. */ |
90 | for (bank = 0; bank < (uint32_t) pmap_memory_region_count; bank++) | |
91 | { | |
92 | if ((rp->end + 1) == pmap_memory_regions[bank].base) { | |
93 | rp->end = pmap_memory_regions[bank].end; | |
94 | } else { | |
95 | ++rp; | |
96 | ++num_regions; | |
97 | rp->base = pmap_memory_regions[bank].base; | |
98 | rp->end = pmap_memory_regions[bank].end; | |
99 | rp->alloc = 0; | |
100 | } | |
101 | } | |
5d5c5d0d | 102 | |
8f6c56a5 | 103 | /* Size the hibernation bitmap */ |
3a60a9f5 A |
104 | size = sizeof(hibernate_page_list_t); |
105 | page_count = 0; | |
8f6c56a5 A |
106 | for (bank = 0, rp = regions; bank < num_regions; bank++, rp++) { |
107 | pages = rp->end + 1 - rp->base; | |
3a60a9f5 A |
108 | page_count += pages; |
109 | size += sizeof(hibernate_bitmap_t) + ((pages + 31) >> 5) * sizeof(uint32_t); | |
110 | } | |
111 | ||
112 | list = (hibernate_page_list_t *)kalloc(size); | |
113 | if (!list) | |
114 | return (list); | |
115 | ||
116 | list->list_size = size; | |
117 | list->page_count = page_count; | |
8f6c56a5 | 118 | list->bank_count = num_regions; |
3a60a9f5 | 119 | |
8f6c56a5 A |
120 | /* Convert to hibernation bitmap. */ |
121 | /* This assumes that ranges are in order and do not overlap. */ | |
3a60a9f5 | 122 | bitmap = &list->bank_bitmap[0]; |
8f6c56a5 A |
123 | for (bank = 0, rp = regions; bank < num_regions; bank++, rp++) { |
124 | bitmap->first_page = rp->base; | |
125 | bitmap->last_page = rp->end; | |
3a60a9f5 A |
126 | bitmap->bitmapwords = (bitmap->last_page + 1 |
127 | - bitmap->first_page + 31) >> 5; | |
8f6c56a5 A |
128 | kprintf("HIB: Bank %d: 0x%x end 0x%x\n", bank, |
129 | ptoa_32(bitmap->first_page), | |
130 | ptoa_32(bitmap->last_page)); | |
3a60a9f5 A |
131 | bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords]; |
132 | } | |
133 | ||
8f6c56a5 | 134 | kfree((void *)regions, sizeof(pmap_memory_region_t) * num_alloc_regions); |
3a60a9f5 A |
135 | return (list); |
136 | } | |
137 | ||
5d5c5d0d | 138 | void |
8f6c56a5 A |
139 | hibernate_page_list_setall_machine(hibernate_page_list_t * page_list, |
140 | hibernate_page_list_t * page_list_wired, | |
141 | uint32_t * pagesOut) | |
5d5c5d0d | 142 | { |
8f6c56a5 A |
143 | KernelBootArgs_t * bootArgs = (KernelBootArgs_t *)PE_state.bootArgs; |
144 | MemoryRange * mptr; | |
145 | uint32_t bank; | |
146 | uint32_t page, count; | |
147 | ||
148 | for (bank = 0, mptr = bootArgs->memoryMap; bank < bootArgs->memoryMapCount; bank++, mptr++) { | |
149 | ||
150 | if (kMemoryRangeNVS != mptr->type) continue; | |
151 | kprintf("Base NVS region 0x%x + 0x%x\n", (vm_offset_t)mptr->base, (vm_size_t)mptr->length); | |
152 | /* Round to page size. Hopefully this does not overlap any reserved areas. */ | |
153 | page = atop_32(trunc_page((vm_offset_t)mptr->base)); | |
154 | count = atop_32(round_page((vm_offset_t)mptr->base + (vm_size_t)mptr->length)) - page; | |
155 | kprintf("Rounded NVS region 0x%x size 0x%x\n", page, count); | |
156 | ||
157 | hibernate_set_page_state(page_list, page_list_wired, page, count, 1); | |
158 | pagesOut -= count; | |
3a60a9f5 A |
159 | } |
160 | } | |
161 | ||
162 | kern_return_t | |
163 | hibernate_processor_setup(IOHibernateImageHeader * header) | |
164 | { | |
8f6c56a5 | 165 | current_cpu_datap()->cpu_hibernate = 1; |
3a60a9f5 A |
166 | header->processorFlags = 0; |
167 | return (KERN_SUCCESS); | |
168 | } | |
169 | ||
170 | void | |
171 | hibernate_vm_lock(void) | |
172 | { | |
8f6c56a5 | 173 | if (FALSE /* getPerProc()->hibernate */) |
3a60a9f5 A |
174 | { |
175 | vm_page_lock_queues(); | |
176 | mutex_lock(&vm_page_queue_free_lock); | |
177 | } | |
178 | } | |
179 | ||
180 | void | |
181 | hibernate_vm_unlock(void) | |
182 | { | |
8f6c56a5 | 183 | if (FALSE /* getPerProc()->hibernate */) |
3a60a9f5 A |
184 | { |
185 | mutex_unlock(&vm_page_queue_free_lock); | |
186 | vm_page_unlock_queues(); | |
187 | } | |
188 | } |