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