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