]>
Commit | Line | Data |
---|---|---|
5d5c5d0d A |
1 | /* |
2 | * Copyright (c) 2006 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 <string.h> | |
32 | ||
33 | #include <mach/machine/vm_types.h> | |
34 | ||
35 | #include <mach/boolean.h> | |
36 | #include <kern/thread.h> | |
37 | #include <kern/zalloc.h> | |
38 | ||
39 | #include <kern/lock.h> | |
40 | #include <kern/kalloc.h> | |
41 | #include <kern/spl.h> | |
42 | ||
43 | #include <vm/pmap.h> | |
44 | #include <vm/vm_map.h> | |
45 | #include <vm/vm_kern.h> | |
46 | #include <mach/vm_param.h> | |
47 | #include <mach/vm_prot.h> | |
48 | #include <vm/vm_object.h> | |
49 | #include <vm/vm_page.h> | |
50 | ||
51 | #include <mach/machine/vm_param.h> | |
52 | #include <machine/thread.h> | |
53 | ||
54 | #include <kern/misc_protos.h> /* prototyping */ | |
55 | #include <i386/misc_protos.h> | |
56 | ||
57 | #include <i386/cpuid.h> | |
58 | #include <i386/cpu_data.h> | |
59 | #include <i386/mp.h> | |
60 | #include <i386/cpu_number.h> | |
61 | #include <i386/machine_cpu.h> | |
62 | #include <i386/mp_slave_boot.h> | |
63 | #include <i386/seg.h> | |
64 | ||
65 | #include <vm/vm_protos.h> | |
66 | ||
67 | #include <sys/kdebug.h> | |
68 | ||
69 | #include <i386/postcode.h> | |
70 | ||
71 | void | |
72 | cpu_IA32e_enable(cpu_data_t *cdp) | |
73 | { | |
74 | uint32_t cr0 = get_cr0(); | |
75 | uint64_t efer = rdmsr64(MSR_IA32_EFER); | |
76 | ||
77 | assert(!ml_get_interrupts_enabled()); | |
78 | ||
79 | postcode(CPU_IA32_ENABLE_ENTRY); | |
80 | ||
81 | /* Turn paging off - works because we're identity mapped */ | |
82 | set_cr0(cr0 & ~CR0_PG); | |
83 | ||
84 | /* pop in new top level phys pg addr */ | |
85 | set_cr3((vm_offset_t) kernel64_cr3); | |
86 | ||
87 | wrmsr64(MSR_IA32_EFER, efer | MSR_IA32_EFER_LME); /* set mode */ | |
88 | ||
89 | /* Turn paging on */ | |
90 | set_cr0(cr0 | CR0_PG); | |
91 | ||
92 | /* this call is required to re-activate paging */ | |
93 | kprintf("cpu_IA32e_enable(%p)\n", cdp); | |
94 | ||
95 | if ((rdmsr64(MSR_IA32_EFER) & MSR_IA32_EFER_LMA) == 0) | |
96 | panic("cpu_IA32e_enable() MSR_IA32_EFER_LMA not asserted"); | |
97 | ||
98 | cdp->cpu_kernel_cr3 = kernel64_cr3; | |
99 | ||
100 | postcode(CPU_IA32_ENABLE_EXIT); | |
101 | } | |
102 | ||
103 | void | |
104 | cpu_IA32e_disable(cpu_data_t *cdp) | |
105 | { | |
106 | uint32_t cr0 = get_cr0(); | |
107 | uint64_t efer = rdmsr64(MSR_IA32_EFER); | |
108 | ||
109 | assert(!ml_get_interrupts_enabled()); | |
110 | ||
111 | postcode(CPU_IA32_DISABLE_ENTRY); | |
112 | ||
113 | if ((rdmsr64(MSR_IA32_EFER) & MSR_IA32_EFER_LMA) == 0) | |
114 | panic("cpu_IA32e_disable() MSR_IA32_EFER_LMA clear on entry"); | |
115 | ||
116 | /* Turn paging off - works because we're identity mapped */ | |
117 | set_cr0(cr0 & ~CR0_PG); | |
118 | ||
119 | /* pop in legacy top level phys pg addr */ | |
120 | set_cr3((vm_offset_t) lo_kernel_cr3); | |
121 | ||
122 | wrmsr64(MSR_IA32_EFER, efer & ~MSR_IA32_EFER_LME); /* reset mode */ | |
123 | ||
124 | /* Turn paging on */ | |
125 | set_cr0(cr0 | CR0_PG); | |
126 | ||
127 | /* this call is required to re-activate paging */ | |
128 | kprintf("cpu_IA32e_disable(%p)\n", cdp); | |
129 | ||
130 | if ((rdmsr64(MSR_IA32_EFER) & MSR_IA32_EFER_LMA) != 0) | |
131 | panic("cpu_IA32e_disable() MSR_IA32_EFER_LMA not cleared"); | |
132 | ||
133 | cdp->cpu_kernel_cr3 = 0ULL; | |
134 | ||
135 | postcode(CPU_IA32_DISABLE_EXIT); | |
136 | } | |
137 | ||
138 | void | |
139 | fix_desc64(void *descp, int count) | |
140 | { | |
141 | struct fake_descriptor64 *fakep; | |
142 | union { | |
143 | struct real_gate64 gate; | |
144 | struct real_descriptor64 desc; | |
145 | } real; | |
146 | int i; | |
147 | ||
148 | fakep = (struct fake_descriptor64 *) descp; | |
149 | ||
150 | for (i = 0; i < count; i++, fakep++) { | |
151 | /* | |
152 | * Construct the real decriptor locally. | |
153 | */ | |
154 | ||
155 | bzero((void *) &real, sizeof(real)); | |
156 | ||
157 | switch (fakep->access & ACC_TYPE) { | |
158 | case 0: | |
159 | break; | |
160 | case ACC_CALL_GATE: | |
161 | case ACC_INTR_GATE: | |
162 | case ACC_TRAP_GATE: | |
163 | real.gate.offset_low16 = fakep->offset[0] & 0xFFFF; | |
164 | real.gate.selector16 = fakep->lim_or_seg & 0xFFFF; | |
165 | real.gate.IST = fakep->size_or_IST & 0x7; | |
166 | real.gate.access8 = fakep->access; | |
167 | real.gate.offset_high16 = (fakep->offset[0]>>16)&0xFFFF; | |
168 | real.gate.offset_top32 = (uint32_t)fakep->offset[1]; | |
169 | break; | |
170 | default: /* Otherwise */ | |
171 | real.desc.limit_low16 = fakep->lim_or_seg & 0xFFFF; | |
172 | real.desc.base_low16 = fakep->offset[0] & 0xFFFF; | |
173 | real.desc.base_med8 = (fakep->offset[0] >> 16) & 0xFF; | |
174 | real.desc.access8 = fakep->access; | |
175 | real.desc.limit_high4 = (fakep->lim_or_seg >> 16) & 0xFF; | |
176 | real.desc.granularity4 = fakep->size_or_IST; | |
177 | real.desc.base_high8 = (fakep->offset[0] >> 24) & 0xFF; | |
178 | real.desc.base_top32 = (uint32_t) fakep->offset[1]; | |
179 | } | |
180 | ||
181 | /* | |
182 | * Now copy back over the fake structure. | |
183 | */ | |
184 | bcopy((void *) &real, (void *) fakep, sizeof(real)); | |
185 | } | |
186 | } | |
187 | ||
188 | #if DEBUG | |
189 | extern void dump_gdt(void *); | |
190 | extern void dump_ldt(void *); | |
191 | extern void dump_idt(void *); | |
192 | extern void dump_tss(void *); | |
193 | extern void dump_frame32(x86_saved_state_compat32_t *scp); | |
194 | extern void dump_frame64(x86_saved_state64_t *scp); | |
195 | ||
196 | void | |
197 | dump_frame32(x86_saved_state_compat32_t *scp) | |
198 | { | |
199 | unsigned int i; | |
200 | uint32_t *ip = (uint32_t *) scp; | |
201 | ||
202 | kprintf("dump_frame32(0x%08x):\n", scp); | |
203 | ||
204 | for (i = 0; | |
205 | i < sizeof(x86_saved_state_compat32_t)/sizeof(uint32_t); | |
206 | i++, ip++) | |
207 | kprintf("0x%08x: 0x%08x\n", ip, *ip); | |
208 | ||
209 | kprintf("scp->isf64.err: 0x%016llx\n", scp->isf64.err); | |
210 | kprintf("scp->isf64.rip: 0x%016llx\n", scp->isf64.rip); | |
211 | kprintf("scp->isf64.cs: 0x%016llx\n", scp->isf64.cs); | |
212 | kprintf("scp->isf64.rflags: 0x%016llx\n", scp->isf64.rflags); | |
213 | kprintf("scp->isf64.rsp: 0x%016llx\n", scp->isf64.rsp); | |
214 | kprintf("scp->isf64.ss: 0x%016llx\n", scp->isf64.ss); | |
215 | ||
216 | kprintf("scp->iss32.tag: 0x%08x\n", scp->iss32.tag); | |
217 | kprintf("scp->iss32.state.gs: 0x%08x\n", scp->iss32.state.gs); | |
218 | kprintf("scp->iss32.state.fs: 0x%08x\n", scp->iss32.state.fs); | |
219 | kprintf("scp->iss32.state.es: 0x%08x\n", scp->iss32.state.es); | |
220 | kprintf("scp->iss32.state.ds: 0x%08x\n", scp->iss32.state.ds); | |
221 | kprintf("scp->iss32.state.edi: 0x%08x\n", scp->iss32.state.edi); | |
222 | kprintf("scp->iss32.state.esi: 0x%08x\n", scp->iss32.state.esi); | |
223 | kprintf("scp->iss32.state.ebp: 0x%08x\n", scp->iss32.state.ebp); | |
224 | kprintf("scp->iss32.state.cr2: 0x%08x\n", scp->iss32.state.cr2); | |
225 | kprintf("scp->iss32.state.ebx: 0x%08x\n", scp->iss32.state.ebx); | |
226 | kprintf("scp->iss32.state.edx: 0x%08x\n", scp->iss32.state.edx); | |
227 | kprintf("scp->iss32.state.ecx: 0x%08x\n", scp->iss32.state.ecx); | |
228 | kprintf("scp->iss32.state.eax: 0x%08x\n", scp->iss32.state.eax); | |
229 | kprintf("scp->iss32.state.trapno: 0x%08x\n", scp->iss32.state.eax); | |
230 | kprintf("scp->iss32.state.eip: 0x%08x\n", scp->iss32.state.eip); | |
231 | kprintf("scp->iss32.state.cs: 0x%08x\n", scp->iss32.state.cs); | |
232 | kprintf("scp->iss32.state.efl: 0x%08x\n", scp->iss32.state.efl); | |
233 | kprintf("scp->iss32.state.uesp: 0x%08x\n", scp->iss32.state.uesp); | |
234 | kprintf("scp->iss32.state.ss: 0x%08x\n", scp->iss32.state.ss); | |
235 | ||
236 | postcode(0x99); | |
237 | } | |
238 | ||
239 | void | |
240 | dump_frame64(x86_saved_state64_t *scp) | |
241 | { | |
242 | unsigned int i; | |
243 | uint64_t *ip = (uint64_t *) scp; | |
244 | ||
245 | kprintf("dump_frame64(0x%08x):\n", scp); | |
246 | ||
247 | for (i = 0; | |
248 | i < sizeof(x86_saved_state64_t)/sizeof(uint64_t); | |
249 | i++, ip++) | |
250 | kprintf("0x%08x: 0x%016x\n", ip, *ip); | |
251 | ||
252 | kprintf("scp->isf.trapno: 0x%08x\n", scp->isf.trapno); | |
253 | kprintf("scp->isf.trapfn: 0x%08x\n", scp->isf.trapfn); | |
254 | kprintf("scp->isf.err: 0x%016llx\n", scp->isf.err); | |
255 | kprintf("scp->isf.rip: 0x%016llx\n", scp->isf.rip); | |
256 | kprintf("scp->isf.cs: 0x%016llx\n", scp->isf.cs); | |
257 | kprintf("scp->isf.rflags: 0x%016llx\n", scp->isf.rflags); | |
258 | kprintf("scp->isf.rsp: 0x%016llx\n", scp->isf.rsp); | |
259 | kprintf("scp->isf.ss: 0x%016llx\n", scp->isf.ss); | |
260 | ||
261 | kprintf("scp->fs: 0x%016llx\n", scp->fs); | |
262 | kprintf("scp->gs: 0x%016llx\n", scp->gs); | |
263 | kprintf("scp->rax: 0x%016llx\n", scp->rax); | |
264 | kprintf("scp->rcx: 0x%016llx\n", scp->rcx); | |
265 | kprintf("scp->rbx: 0x%016llx\n", scp->rbx); | |
266 | kprintf("scp->rbp: 0x%016llx\n", scp->rbp); | |
267 | kprintf("scp->r11: 0x%016llx\n", scp->r11); | |
268 | kprintf("scp->r12: 0x%016llx\n", scp->r12); | |
269 | kprintf("scp->r13: 0x%016llx\n", scp->r13); | |
270 | kprintf("scp->r14: 0x%016llx\n", scp->r14); | |
271 | kprintf("scp->r15: 0x%016llx\n", scp->r15); | |
272 | kprintf("scp->cr2: 0x%016llx\n", scp->cr2); | |
273 | kprintf("scp->v_arg8: 0x%016llx\n", scp->v_arg8); | |
274 | kprintf("scp->v_arg7: 0x%016llx\n", scp->v_arg7); | |
275 | kprintf("scp->v_arg6: 0x%016llx\n", scp->v_arg6); | |
276 | kprintf("scp->r9: 0x%016llx\n", scp->r9); | |
277 | kprintf("scp->r8: 0x%016llx\n", scp->r8); | |
278 | kprintf("scp->r10: 0x%016llx\n", scp->r10); | |
279 | kprintf("scp->rdx: 0x%016llx\n", scp->rdx); | |
280 | kprintf("scp->rsi: 0x%016llx\n", scp->rsi); | |
281 | kprintf("scp->rdi: 0x%016llx\n", scp->rdi); | |
282 | ||
283 | postcode(0x98); | |
284 | } | |
285 | ||
286 | void | |
287 | dump_gdt(void *gdtp) | |
288 | { | |
289 | unsigned int i; | |
290 | uint32_t *ip = (uint32_t *) gdtp; | |
291 | ||
292 | kprintf("GDT:\n", ip); | |
293 | for (i = 0; i < GDTSZ; i++, ip += 2) { | |
294 | kprintf("%p: 0x%08x\n", ip+0, *(ip+0)); | |
295 | kprintf("%p: 0x%08x\n", ip+1, *(ip+1)); | |
296 | } | |
297 | } | |
298 | ||
299 | void | |
300 | dump_ldt(void *ldtp) | |
301 | { | |
302 | unsigned int i; | |
303 | uint32_t *ip = (uint32_t *) ldtp; | |
304 | ||
305 | kprintf("LDT:\n", ip); | |
306 | for (i = 0; i < LDTSZ_MIN; i++, ip += 2) { | |
307 | kprintf("%p: 0x%08x\n", ip+0, *(ip+0)); | |
308 | kprintf("%p: 0x%08x\n", ip+1, *(ip+1)); | |
309 | } | |
310 | } | |
311 | ||
312 | void | |
313 | dump_idt(void *idtp) | |
314 | { | |
315 | unsigned int i; | |
316 | uint32_t *ip = (uint32_t *) idtp; | |
317 | ||
318 | kprintf("IDT64:\n", ip); | |
319 | for (i = 0; i < 16; i++, ip += 4) { | |
320 | kprintf("%p: 0x%08x\n", ip+0, *(ip+0)); | |
321 | kprintf("%p: 0x%08x\n", ip+1, *(ip+1)); | |
322 | kprintf("%p: 0x%08x\n", ip+2, *(ip+2)); | |
323 | kprintf("%p: 0x%08x\n", ip+3, *(ip+3)); | |
324 | } | |
325 | } | |
326 | ||
327 | void | |
328 | dump_tss(void *tssp) | |
329 | { | |
330 | unsigned int i; | |
331 | uint32_t *ip = (uint32_t *) tssp; | |
332 | ||
333 | kprintf("TSS64:\n", ip); | |
334 | for (i = 0; i < sizeof(master_ktss64)/sizeof(uint32_t); i++, ip++) { | |
335 | kprintf("%p: 0x%08x\n", ip+0, *(ip+0)); | |
336 | } | |
337 | } | |
338 | #endif /* DEBUG */ |