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