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