]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/hibernate_restore.s
087efcb0549850236cd1f5616af3419030c9c181
[apple/xnu.git] / osfmk / i386 / hibernate_restore.s
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30
31 #include <i386/asm.h>
32 #include <i386/proc_reg.h>
33
34 #include <i386/postcode.h>
35 #include <assym.s>
36
37 /*
38 This code is linked into the kernel but part of the "__HIB" section, which means
39 its used by code running in the special context of restoring the kernel text and data
40 from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
41 it calls or references (ie. hibernate_restore_phys_page())
42 needs to be careful to only touch memory also in the "__HIB" section.
43 */
44
45 /*
46 * GAS won't handle an intersegment jump with a relocatable offset.
47 */
48 #define LJMP(segment,address) \
49 .byte 0xea ;\
50 .long address ;\
51 .word segment
52
53 #define KVTOPHYS (-KERNELBASE)
54 #define KVTOLINEAR LINEAR_KERNELBASE
55
56 #define PA(addr) ((addr)+KVTOPHYS)
57 #define VA(addr) ((addr)-KVTOPHYS)
58
59 /* Location of temporary page tables */
60 #define HPTD 0x80000
61
62 #define KERNEL_MAP_SIZE ( 4 * 1024 * 1024)
63
64 /*
65 * fillkpt
66 * eax = page frame address
67 * ebx = index into page table
68 * ecx = how many pages to map
69 * base = base address of page dir/table
70 * prot = protection bits
71 */
72 #define fillkpt(base, prot) \
73 shll $2,%ebx ; \
74 addl base,%ebx ; \
75 orl $(PTE_V), %eax ; \
76 orl prot,%eax ; \
77 1: movl %eax,(%ebx) ; \
78 addl $(PAGE_SIZE),%eax ; /* increment physical address */ \
79 addl $4,%ebx ; /* next pte */ \
80 loop 1b
81
82 /*
83 * fillpse
84 * eax = physical page address
85 * ebx = index into page table
86 * ecx = how many pages to map
87 * base = base address of page dir/table
88 * prot = protection bits
89 */
90 #define fillpse(base, prot) \
91 shll $2,%ebx ; \
92 addl base,%ebx ; \
93 orl $(PTE_V|PTE_PS), %eax ; \
94 orl prot,%eax ; \
95 1: movl %eax,(%ebx) ; \
96 addl $(1 << PDESHIFT),%eax ; /* increment physical address 4Mb */ \
97 addl $4,%ebx ; /* next entry */ \
98 loop 1b
99
100 /*
101 * fillkptphys(base, prot)
102 * eax = physical address
103 * ecx = how many pages to map
104 * base = base of page table
105 * prot = protection bits
106 */
107 #define fillkptphys(base, prot) \
108 movl %eax, %ebx ; \
109 shrl $(PAGE_SHIFT), %ebx ; \
110 fillkpt(base, prot)
111
112 /*
113 * Hibernation code restarts here. Steal some pages from 0x10000
114 * to 0x90000 for pages tables and directories etc to temporarily
115 * map the hibernation code (put at 0x100000 (phys) by the booter
116 * and linked to 0xC0100000 by the linker) to 0xC0100000 so it can
117 * execute. It's self-contained and won't make any references outside
118 * of itself.
119 *
120 * On the way down it has to save IdlePTD (and if PAE also IdlePDPT)
121 * and after it runs it has to restore those and load IdlePTD (or
122 * IdlePDPT if PAE) into %cr3 to re-establish the original mappings
123 */
124
125 .align ALIGN
126 .globl EXT(hibernate_machine_entrypoint)
127 LEXT(hibernate_machine_entrypoint)
128 cli
129
130 mov %eax, %edi
131
132 POSTCODE(0x1)
133
134 /* Map physical memory from zero to 0xC0000000 */
135 xorl %eax, %eax
136 xorl %ebx, %ebx
137 movl $(KPTDI), %ecx
138 fillpse( $(HPTD), $(PTE_W) )
139
140 /* Map 0 again at 0xC0000000 */
141 xorl %eax, %eax
142 movl $(KPTDI), %ebx
143 movl $(KERNEL_MAP_SIZE >> PDESHIFT), %ecx
144 fillpse( $(HPTD), $(PTE_W) )
145
146 movl $(HPTD), %eax
147 movl %eax, %cr3
148
149 POSTCODE(0x3)
150
151 movl %cr4,%eax
152 orl $(CR4_PSE),%eax
153 movl %eax,%cr4 /* enable page size extensions */
154 movl %cr0, %eax
155 orl $(CR0_PG|CR0_WP|CR0_PE), %eax
156 movl %eax, %cr0 /* ready paging */
157
158 POSTCODE(0x4)
159
160 lgdt PA(EXT(gdtptr)) /* load GDT */
161 lidt PA(EXT(idtptr)) /* load IDT */
162
163 POSTCODE(0x5)
164
165 LJMP (KERNEL_CS,EXT(hstart)) /* paging on and go to correct vaddr */
166
167 /* Hib restart code now running with correct addresses */
168 LEXT(hstart)
169 POSTCODE(0x6)
170
171 mov $(KERNEL_DS),%ax /* set kernel data segment */
172 mov %ax,%ds
173 mov %ax,%es
174 mov %ax,%ss
175
176 mov $0,%ax /* fs must be zeroed; */
177 mov %ax,%fs /* some bootstrappers don`t do this */
178 mov %ax,%gs
179
180 lea EXT(gIOHibernateRestoreStackEnd),%esp /* switch to the bootup stack */
181
182 POSTCODE(0x7)
183
184 xorl %eax, %eax /* Video memory - N/A */
185 pushl %eax
186 mov %edi, %eax /* Pointer to hibernate header */
187 pushl %eax
188 call EXT(hibernate_kernel_entrypoint)
189 /* NOTREACHED */
190 hlt
191
192
193
194 /*
195 void
196 hibernate_restore_phys_page(uint64_t src, uint64_t dst, uint32_t len, uint32_t procFlags);
197 */
198
199 .align 5
200 .globl EXT(hibernate_restore_phys_page)
201
202 /* XXX doesn't handle 64-bit addresses yet */
203 /* XXX can only deal with exactly one page */
204 LEXT(hibernate_restore_phys_page)
205 pushl %edi
206 pushl %esi
207
208 movl 8+ 4(%esp),%esi /* source virtual address */
209 addl $0, %esi
210 jz 2f /* If source == 0, nothing to do */
211
212
213 movl 8+ 12(%esp),%edi /* destination physical address */
214 cmpl $(LINEAR_KERNELBASE), %edi
215 jl 1f /* no need to map, below 0xC0000000 */
216
217 movl %edi, %eax /* destination physical address */
218 /* Map physical address to virt. address 0xffc00000 (4GB - 4MB) */
219 andl $0xFFC00000, %eax
220 orl $(PTE_V | PTE_PS | PTE_W), %eax
221 movl %eax, (HPTD + (0x3FF * 4))
222 orl $0xFFC00000, %edi
223 invlpg (%edi)
224
225 1:
226 movl 8+ 20(%esp),%edx /* number of bytes */
227 cld
228 /* move longs*/
229 movl %edx,%ecx
230 sarl $2,%ecx
231 rep
232 movsl
233 /* move bytes*/
234 movl %edx,%ecx
235 andl $3,%ecx
236 rep
237 movsb
238 2:
239 popl %esi
240 popl %edi
241 ret