]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/ml/i386/kdp_machdep.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / osfmk / kdp / ml / i386 / kdp_machdep.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
1c79356b
A
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
39void print_saved_state(void *);
40void kdp_call(void);
41void kdp_i386_trap(unsigned int, struct i386_saved_state *, kern_return_t, vm_offset_t);
42int kdp_getc(void);
43
44void
45kdp_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
78boolean_t
79kdp_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
101void
102kdp_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
137void
138kdp_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
164kdp_error_t
165kdp_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
192kdp_error_t
193kdp_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
219void
220kdp_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
242void
243kdp_panic(
244 const char *msg
245)
246{
247 printf("kdp panic: %s\n", msg);
248 __asm__ volatile("hlt");
249}
250
251
252void
253kdp_reboot(void)
254{
255 kdreboot();
256}
257
258int
259kdp_intr_disbl(void)
260{
261 return splhigh();
262}
263
264void
265kdp_intr_enbl(int s)
266{
267 splx(s);
268}
269
270int
271kdp_getc()
272{
273 return cnmaygetc();
274}
275
276void
277kdp_us_spin(int usec)
278{
279 extern void delay(int);
280
281 delay(usec/100);
282}
283
284void 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
297void
298kdp_sync_cache()
299{
300 return; /* No op here. */
301}
302
303void
304kdp_call()
305{
306 __asm__ volatile ("int $3"); /* Let the processor do the work */
307}
308
309
310typedef 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
319void
320kdp_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;
342invalid:
343 printf("invalid frame pointer %x\n",frame->prev);
344}
345
346void
347kdp_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
9bccf70c 422 kdp_i386_backtrace((void *) saved_state->ebp, 10);
1c79356b
A
423
424 kdp_raise_exception(exception, code, subcode, saved_state);
425}
426
427boolean_t
428kdp_call_kdb(
429 void)
430{
431 return(FALSE);
432}
9bccf70c
A
433
434unsigned int kdp_ml_get_breakinsn()
435{
436 return 0xcc;
437}