]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/ml/i386/kdp_machdep.c
xnu-517.tar.gz
[apple/xnu.git] / osfmk / kdp / ml / i386 / kdp_machdep.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 #include <mach/mach_types.h>
27 #include <mach/machine.h>
28 #include <mach/exception_types.h>
29 #include <i386/trap.h>
30 #include <i386/mp.h>
31 #include <kdp/kdp_internal.h>
32
33 #define KDP_TEST_HARNESS 0
34 #if KDP_TEST_HARNESS
35 #define dprintf(x) printf x
36 #else
37 #define dprintf(x)
38 #endif
39
40 void print_saved_state(void *);
41 void kdp_call(void);
42 void kdp_i386_trap(unsigned int, struct i386_saved_state *, kern_return_t, vm_offset_t);
43 int kdp_getc(void);
44
45 void
46 kdp_exception(
47 unsigned char *pkt,
48 int *len,
49 unsigned short *remote_port,
50 unsigned int exception,
51 unsigned int code,
52 unsigned int subcode
53 )
54 {
55 kdp_exception_t *rq = (kdp_exception_t *)pkt;
56
57 rq->hdr.request = KDP_EXCEPTION;
58 rq->hdr.is_reply = 0;
59 rq->hdr.seq = kdp.exception_seq;
60 rq->hdr.key = 0;
61 rq->hdr.len = sizeof (*rq);
62
63 rq->n_exc_info = 1;
64 rq->exc_info[0].cpu = 0;
65 rq->exc_info[0].exception = exception;
66 rq->exc_info[0].code = code;
67 rq->exc_info[0].subcode = subcode;
68
69 rq->hdr.len += rq->n_exc_info * sizeof (kdp_exc_info_t);
70
71 bcopy((char *)rq, (char *)pkt, rq->hdr.len);
72
73 kdp.exception_ack_needed = TRUE;
74
75 *remote_port = kdp.exception_port;
76 *len = rq->hdr.len;
77 }
78
79 boolean_t
80 kdp_exception_ack(
81 unsigned char *pkt,
82 int len
83 )
84 {
85 kdp_exception_ack_t *rq = (kdp_exception_ack_t *)pkt;
86
87 if (len < sizeof (*rq))
88 return(FALSE);
89
90 if (!rq->hdr.is_reply || rq->hdr.request != KDP_EXCEPTION)
91 return(FALSE);
92
93 dprintf(("kdp_exception_ack seq %x %x\n", rq->hdr.seq, kdp.exception_seq));
94
95 if (rq->hdr.seq == kdp.exception_seq) {
96 kdp.exception_ack_needed = FALSE;
97 kdp.exception_seq++;
98 }
99 return(TRUE);
100 }
101
102 void
103 kdp_getstate(
104 i386_thread_state_t *state
105 )
106 {
107 struct i386_saved_state *saved_state;
108
109 saved_state = (struct i386_saved_state *)kdp.saved_state;
110
111 *state = (i386_thread_state_t) { 0 };
112 state->eax = saved_state->eax;
113 state->ebx = saved_state->ebx;
114 state->ecx = saved_state->ecx;
115 state->edx = saved_state->edx;
116 state->edi = saved_state->edi;
117 state->esi = saved_state->esi;
118 state->ebp = saved_state->ebp;
119
120 if ((saved_state->cs & 0x3) == 0){ /* Kernel State */
121 state->esp = (unsigned int) &saved_state->uesp;
122 state->ss = KERNEL_DS;
123 } else {
124 state->esp = saved_state->uesp;
125 state->ss = saved_state->ss;
126 }
127
128 state->eflags = saved_state->efl;
129 state->eip = saved_state->eip;
130 state->cs = saved_state->cs;
131 state->ds = saved_state->ds;
132 state->es = saved_state->es;
133 state->fs = saved_state->fs;
134 state->gs = saved_state->gs;
135 }
136
137
138 void
139 kdp_setstate(
140 i386_thread_state_t *state
141 )
142 {
143 struct i386_saved_state *saved_state;
144
145 saved_state = (struct i386_saved_state *)kdp.saved_state;
146
147 saved_state->eax = state->eax;
148 saved_state->ebx = state->ebx;
149 saved_state->ecx = state->ecx;
150 saved_state->edx = state->edx;
151 saved_state->edi = state->edi;
152 saved_state->esi = state->esi;
153 saved_state->ebp = state->ebp;
154 saved_state->efl = state->eflags;
155 #if 0
156 saved_state->frame.eflags &= ~( EFL_VM | EFL_NT | EFL_IOPL | EFL_CLR );
157 saved_state->frame.eflags |= ( EFL_IF | EFL_SET );
158 #endif
159 saved_state->eip = state->eip;
160 saved_state->fs = state->fs;
161 saved_state->gs = state->gs;
162 }
163
164
165 kdp_error_t
166 kdp_machine_read_regs(
167 unsigned int cpu,
168 unsigned int flavor,
169 char *data,
170 int *size
171 )
172 {
173 switch (flavor) {
174
175 case i386_THREAD_STATE:
176 dprintf(("kdp_readregs THREAD_STATE\n"));
177 kdp_getstate((i386_thread_state_t *)data);
178 *size = sizeof (i386_thread_state_t);
179 return KDPERR_NO_ERROR;
180
181 case i386_THREAD_FPSTATE:
182 dprintf(("kdp_readregs THREAD_FPSTATE\n"));
183 *(i386_thread_fpstate_t *)data = (i386_thread_fpstate_t) { 0 };
184 *size = sizeof (i386_thread_fpstate_t);
185 return KDPERR_NO_ERROR;
186
187 default:
188 dprintf(("kdp_readregs bad flavor %d\n"));
189 return KDPERR_BADFLAVOR;
190 }
191 }
192
193 kdp_error_t
194 kdp_machine_write_regs(
195 unsigned int cpu,
196 unsigned int flavor,
197 char *data,
198 int *size
199 )
200 {
201 switch (flavor) {
202
203 case i386_THREAD_STATE:
204 dprintf(("kdp_writeregs THREAD_STATE\n"));
205 kdp_setstate((i386_thread_state_t *)data);
206 return KDPERR_NO_ERROR;
207
208 case i386_THREAD_FPSTATE:
209 dprintf(("kdp_writeregs THREAD_FPSTATE\n"));
210 return KDPERR_NO_ERROR;
211
212 default:
213 dprintf(("kdp_writeregs bad flavor %d\n"));
214 return KDPERR_BADFLAVOR;
215 }
216 }
217
218
219
220 void
221 kdp_machine_hostinfo(
222 kdp_hostinfo_t *hostinfo
223 )
224 {
225 machine_slot_t m;
226 int i;
227
228 hostinfo->cpus_mask = 0;
229
230 for (i = 0; i < machine_info.max_cpus; i++) {
231 m = &machine_slot[i];
232 if (!m->is_cpu)
233 continue;
234
235 hostinfo->cpus_mask |= (1 << i);
236 }
237
238 /* FIXME?? */
239 hostinfo->cpu_type = CPU_TYPE_I386;
240 hostinfo->cpu_subtype = CPU_SUBTYPE_486;
241 }
242
243 void
244 kdp_panic(
245 const char *msg
246 )
247 {
248 printf("kdp panic: %s\n", msg);
249 __asm__ volatile("hlt");
250 }
251
252
253 void
254 kdp_reboot(void)
255 {
256 kdreboot();
257 }
258
259 int
260 kdp_intr_disbl(void)
261 {
262 return splhigh();
263 }
264
265 void
266 kdp_intr_enbl(int s)
267 {
268 splx(s);
269 }
270
271 int
272 kdp_getc()
273 {
274 return cnmaygetc();
275 }
276
277 void
278 kdp_us_spin(int usec)
279 {
280 extern void delay(int);
281
282 delay(usec/100);
283 }
284
285 void print_saved_state(void *state)
286 {
287 struct i386_saved_state *saved_state;
288
289 saved_state = state;
290
291 printf("pc = 0x%x\n", saved_state->eip);
292 printf("cr3= 0x%x\n", saved_state->cr2);
293 printf("rp = TODO FIXME\n");
294 printf("sp = 0x%x\n", saved_state->esp);
295
296 }
297
298 void
299 kdp_sync_cache()
300 {
301 return; /* No op here. */
302 }
303
304 void
305 kdp_call()
306 {
307 __asm__ volatile ("int $3"); /* Let the processor do the work */
308 }
309
310
311 typedef struct _cframe_t {
312 struct _cframe_t *prev;
313 unsigned caller;
314 unsigned args[0];
315 } cframe_t;
316
317
318 #define MAX_FRAME_DELTA 65536
319
320 void
321 kdp_i386_backtrace(void *_frame, int nframes)
322 {
323 cframe_t *frame = (cframe_t *)_frame;
324 int i;
325
326 for (i=0; i<nframes; i++) {
327 if ((vm_offset_t)frame < VM_MIN_KERNEL_ADDRESS ||
328 (vm_offset_t)frame > VM_MAX_KERNEL_ADDRESS) {
329 goto invalid;
330 }
331 printf("frame %x called by %x ",
332 frame, frame->caller);
333 printf("args %x %x %x %x\n",
334 frame->args[0], frame->args[1],
335 frame->args[2], frame->args[3]);
336 if ((frame->prev < frame) || /* wrong direction */
337 ((frame->prev - frame) > MAX_FRAME_DELTA)) {
338 goto invalid;
339 }
340 frame = frame->prev;
341 }
342 return;
343 invalid:
344 printf("invalid frame pointer %x\n",frame);
345 }
346
347 void
348 kdp_i386_trap(
349 unsigned int trapno,
350 struct i386_saved_state *saved_state,
351 kern_return_t result,
352 vm_offset_t va
353 )
354 {
355 unsigned int exception, subcode = 0, code;
356
357 mp_kdp_enter();
358
359 if (trapno != T_INT3 && trapno != T_DEBUG)
360 printf("unexpected kernel trap %x eip %x\n", trapno, saved_state->eip);
361
362 switch (trapno) {
363
364 case T_DIVIDE_ERROR:
365 exception = EXC_ARITHMETIC;
366 code = EXC_I386_DIVERR;
367 break;
368
369 case T_OVERFLOW:
370 exception = EXC_SOFTWARE;
371 code = EXC_I386_INTOFLT;
372 break;
373
374 case T_OUT_OF_BOUNDS:
375 exception = EXC_ARITHMETIC;
376 code = EXC_I386_BOUNDFLT;
377 break;
378
379 case T_INVALID_OPCODE:
380 exception = EXC_BAD_INSTRUCTION;
381 code = EXC_I386_INVOPFLT;
382 break;
383
384 case T_SEGMENT_NOT_PRESENT:
385 exception = EXC_BAD_INSTRUCTION;
386 code = EXC_I386_SEGNPFLT;
387 subcode = saved_state->err;
388 break;
389
390 case T_STACK_FAULT:
391 exception = EXC_BAD_INSTRUCTION;
392 code = EXC_I386_STKFLT;
393 subcode = saved_state->err;
394 break;
395
396 case T_GENERAL_PROTECTION:
397 exception = EXC_BAD_INSTRUCTION;
398 code = EXC_I386_GPFLT;
399 subcode = saved_state->err;
400 break;
401
402 case T_PAGE_FAULT:
403 exception = EXC_BAD_ACCESS;
404 code = result;
405 subcode = va;
406 break;
407
408 case T_WATCHPOINT:
409 exception = EXC_SOFTWARE;
410 code = EXC_I386_ALIGNFLT;
411 break;
412
413 case T_DEBUG:
414 case T_INT3:
415 exception = EXC_BREAKPOINT;
416 code = EXC_I386_BPTFLT;
417 break;
418
419 default:
420 exception = EXC_BAD_INSTRUCTION;
421 code = trapno;
422 break;
423 }
424
425 // kdp_i386_backtrace((void *) saved_state->ebp, 10);
426
427 kdp_raise_exception(exception, code, subcode, saved_state);
428
429 mp_kdp_exit();
430 }
431
432 boolean_t
433 kdp_call_kdb(
434 void)
435 {
436 return(FALSE);
437 }
438
439 unsigned int kdp_ml_get_breakinsn()
440 {
441 return 0xcc;
442 }