]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/ml/ppc/kdp_machdep.c
f84e6a832606aac52441f844d2ee271172ba2c8f
[apple/xnu.git] / osfmk / kdp / ml / ppc / kdp_machdep.c
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 */
22 /*
23 * Copyright (c) 1997 Apple Computer, Inc. All rights reserved.
24 * Copyright (c) 1994 NeXT Computer, Inc. All rights reserved.
25 *
26 * machdep/ppc/kdp_machdep.c
27 *
28 * Machine-dependent code for Remote Debugging Protocol
29 *
30 * March, 1997 Created. Umesh Vaishampayan [umeshv@NeXT.com]
31 *
32 */
33
34 #include <mach/mach_types.h>
35 #include <mach/exception_types.h>
36 #include <ppc/exception.h>
37 #include <ppc/proc_reg.h>
38 #include <kdp/kdp_internal.h>
39 #include <ppc/savearea.h>
40 #include <kern/debug.h>
41
42 #define KDP_TEST_HARNESS 0
43 #if KDP_TEST_HARNESS
44 #define dprintf(x) kprintf x
45 #else
46 #define dprintf(x)
47 #endif
48
49 void print_saved_state(void *);
50 void kdp_call(void);
51 void kdp_trap( unsigned int, struct ppc_thread_state *);
52 int kdp_getc(void);
53 boolean_t kdp_call_kdb(void);
54
55 void
56 kdp_exception(
57 unsigned char *pkt,
58 int *len,
59 unsigned short *remote_port,
60 unsigned int exception,
61 unsigned int code,
62 unsigned int subcode
63 )
64 {
65 struct {
66 kdp_exception_t pkt;
67 kdp_exc_info_t exc;
68 } aligned_pkt;
69 kdp_exception_t *rq = (kdp_exception_t *)&aligned_pkt;
70
71 bcopy((char *)pkt, (char *)rq, sizeof(*rq));
72 rq->hdr.request = KDP_EXCEPTION;
73 rq->hdr.is_reply = 0;
74 rq->hdr.seq = kdp.exception_seq;
75 rq->hdr.key = 0;
76 rq->hdr.len = sizeof (*rq) + sizeof(kdp_exc_info_t);
77
78 rq->n_exc_info = 1;
79 rq->exc_info[0].cpu = 0;
80 rq->exc_info[0].exception = exception;
81 rq->exc_info[0].code = code;
82 rq->exc_info[0].subcode = subcode;
83
84 rq->hdr.len += rq->n_exc_info * sizeof (kdp_exc_info_t);
85
86 bcopy((char *)rq, (char *)pkt, rq->hdr.len);
87
88 kdp.exception_ack_needed = TRUE;
89
90 *remote_port = kdp.exception_port;
91 *len = rq->hdr.len;
92 }
93
94 boolean_t
95 kdp_exception_ack(
96 unsigned char *pkt,
97 int len
98 )
99 {
100 kdp_exception_ack_t aligned_pkt;
101 kdp_exception_ack_t *rq = (kdp_exception_ack_t *)&aligned_pkt;
102
103 if (len < sizeof (*rq))
104 return(FALSE);
105
106 bcopy((char *)pkt, (char *)rq, sizeof(*rq));
107
108 if (!rq->hdr.is_reply || rq->hdr.request != KDP_EXCEPTION)
109 return(FALSE);
110
111 dprintf(("kdp_exception_ack seq %x %x\n", rq->hdr.seq, kdp.exception_seq));
112
113 if (rq->hdr.seq == kdp.exception_seq) {
114 kdp.exception_ack_needed = FALSE;
115 kdp.exception_seq++;
116 }
117 return(TRUE);
118 }
119
120 static void
121 kdp_getintegerstate(
122 struct ppc_thread_state *state
123 )
124 {
125 struct ppc_thread_state *saved_state;
126
127 saved_state = kdp.saved_state;
128
129 bzero((char *)state,sizeof (struct ppc_thread_state)) ;
130
131 state->srr0 = saved_state->srr0;
132 state->srr1 = saved_state->srr1;
133 state->r0 = saved_state->r0;
134 state->r1 = saved_state->r1;
135 state->r2 = saved_state->r2;
136 state->r3 = saved_state->r3;
137 state->r4 = saved_state->r4;
138 state->r5 = saved_state->r5;
139 state->r6 = saved_state->r6;
140 state->r7 = saved_state->r7;
141 state->r8 = saved_state->r8;
142 state->r9 = saved_state->r9;
143 state->r10 = saved_state->r10;
144 state->r11 = saved_state->r11;
145 state->r12 = saved_state->r12;
146 state->r13 = saved_state->r13;
147 state->r14 = saved_state->r14;
148 state->r15 = saved_state->r15;
149 state->r16 = saved_state->r16;
150 state->r17 = saved_state->r17;
151 state->r18 = saved_state->r18;
152 state->r19 = saved_state->r19;
153 state->r20 = saved_state->r20;
154 state->r21 = saved_state->r21;
155 state->r22 = saved_state->r22;
156 state->r23 = saved_state->r23;
157 state->r24 = saved_state->r24;
158 state->r25 = saved_state->r25;
159 state->r26 = saved_state->r26;
160 state->r27 = saved_state->r27;
161 state->r28 = saved_state->r28;
162 state->r29 = saved_state->r29;
163 state->r30 = saved_state->r30;
164 state->r31 = saved_state->r31;
165 state->cr = saved_state->cr;
166 state->xer = saved_state->xer;
167 state->lr = saved_state->lr;
168 state->ctr = saved_state->ctr;
169 state->mq = saved_state->mq; /* This is BOGUS ! (601) ONLY */
170 }
171
172 kdp_error_t
173 kdp_machine_read_regs(
174 unsigned int cpu,
175 unsigned int flavor,
176 char *data,
177 int *size
178 )
179 {
180 switch (flavor) {
181
182 case PPC_THREAD_STATE:
183 dprintf(("kdp_readregs THREAD_STATE\n"));
184 kdp_getintegerstate((struct ppc_thread_state *)data);
185 *size = PPC_THREAD_STATE_COUNT * sizeof(int);
186 return KDPERR_NO_ERROR;
187
188 case PPC_FLOAT_STATE:
189 dprintf(("kdp_readregs THREAD_FPSTATE\n"));
190 bzero((char *)data ,sizeof(struct ppc_float_state));
191 *size = PPC_FLOAT_STATE_COUNT * sizeof(int);
192 return KDPERR_NO_ERROR;
193
194 default:
195 dprintf(("kdp_readregs bad flavor %d\n"));
196 return KDPERR_BADFLAVOR;
197 }
198 }
199
200 static void
201 kdp_setintegerstate(
202 struct ppc_thread_state *state
203 )
204 {
205 struct ppc_thread_state *saved_state;
206
207 saved_state = kdp.saved_state;
208
209 saved_state->srr0 = state->srr0;
210 saved_state->srr1 = state->srr1;
211 saved_state->r0 = state->r0;
212 saved_state->r1 = state->r1;
213 saved_state->r2 = state->r2;
214 saved_state->r3 = state->r3;
215 saved_state->r4 = state->r4;
216 saved_state->r5 = state->r5;
217 saved_state->r6 = state->r6;
218 saved_state->r7 = state->r7;
219 saved_state->r8 = state->r8;
220 saved_state->r9 = state->r9;
221 saved_state->r10 = state->r10;
222 saved_state->r11 = state->r11;
223 saved_state->r12 = state->r12;
224 saved_state->r13 = state->r13;
225 saved_state->r14 = state->r14;
226 saved_state->r15 = state->r15;
227 saved_state->r16 = state->r16;
228 saved_state->r17 = state->r17;
229 saved_state->r18 = state->r18;
230 saved_state->r19 = state->r19;
231 saved_state->r20 = state->r20;
232 saved_state->r21 = state->r21;
233 saved_state->r22 = state->r22;
234 saved_state->r23 = state->r23;
235 saved_state->r24 = state->r24;
236 saved_state->r25 = state->r25;
237 saved_state->r26 = state->r26;
238 saved_state->r27 = state->r27;
239 saved_state->r28 = state->r28;
240 saved_state->r29 = state->r29;
241 saved_state->r30 = state->r30;
242 saved_state->r31 = state->r31;
243 saved_state->cr = state->cr;
244 saved_state->xer = state->xer;
245 saved_state->lr = state->lr;
246 saved_state->ctr = state->ctr;
247 saved_state->mq = state->mq; /* BOGUS! (601)ONLY */
248 }
249
250 kdp_error_t
251 kdp_machine_write_regs(
252 unsigned int cpu,
253 unsigned int flavor,
254 char *data,
255 int *size
256 )
257 {
258 switch (flavor) {
259
260 case PPC_THREAD_STATE:
261 dprintf(("kdp_writeregs THREAD_STATE\n"));
262 kdp_setintegerstate((struct ppc_thread_state *)data);
263
264 #if KDP_TEST_HARNESS
265 DumpTheSave((struct savearea *)data); /* (TEST/DEBUG) */
266 #endif
267 return KDPERR_NO_ERROR;
268
269 case PPC_FLOAT_STATE:
270 dprintf(("kdp_writeregs THREAD_FPSTATE\n"));
271 return KDPERR_NO_ERROR;
272
273 default:
274 dprintf(("kdp_writeregs bad flavor %d\n"));
275 return KDPERR_BADFLAVOR;
276 }
277 }
278
279 void
280 kdp_machine_hostinfo(
281 kdp_hostinfo_t *hostinfo
282 )
283 {
284 machine_slot_t m;
285 int i;
286
287 hostinfo->cpus_mask = 0;
288 hostinfo->cpu_type = 0;
289
290 for (i = 0; i < machine_info.max_cpus; i++) {
291 m = &machine_slot[i];
292 if (!m->is_cpu)
293 continue;
294
295 hostinfo->cpus_mask |= (1 << i);
296 if (hostinfo->cpu_type == 0) {
297 hostinfo->cpu_type = m->cpu_type;
298 hostinfo->cpu_subtype = m->cpu_subtype;
299 }
300 }
301 }
302
303 void
304 kdp_panic(
305 const char *msg
306 )
307 {
308 printf("kdp panic: %s\n", msg);
309 while(1) {}
310 }
311
312
313 void
314 kdp_reboot(void)
315 {
316 halt_all_cpus(TRUE);;
317 }
318
319 int
320 kdp_intr_disbl(void)
321 {
322 return (splhigh());
323 }
324
325 void
326 kdp_intr_enbl(int s)
327 {
328 splx(s);
329 }
330
331 void
332 kdp_us_spin(int usec)
333 {
334 extern void delay(int);
335
336 delay(usec/100);
337 }
338
339 void print_saved_state(void *state)
340 {
341 struct ppc_thread_state *saved_state;
342
343 saved_state = state;
344
345 printf("pc = 0x%x\n", saved_state->srr0);
346 printf("msr = 0x%x\n", saved_state->srr1);
347 printf("rp = 0x%x\n", saved_state->lr);
348 printf("sp = 0x%x\n", saved_state->r1);
349
350 }
351
352 void
353 kdp_call()
354 {
355 Debugger("inline call to debugger(machine_startup)");
356 }
357
358 /*
359 * table to convert system specific code to generic codes for kdb
360 */
361 int kdp_trap_codes[] = {
362 EXC_BAD_ACCESS, /* 0x0000 INVALID EXCEPTION */
363 EXC_BAD_ACCESS, /* 0x0100 System reset */
364 EXC_BAD_ACCESS, /* 0x0200 Machine check */
365 EXC_BAD_ACCESS, /* 0x0300 Data access */
366 EXC_BAD_ACCESS, /* 0x0400 Instruction access */
367 EXC_BAD_ACCESS, /* 0x0500 External interrupt */
368 EXC_BAD_ACCESS, /* 0x0600 Alignment */
369 EXC_BREAKPOINT, /* 0x0700 Program - fp exc, ill/priv instr, trap */
370 EXC_ARITHMETIC, /* 0x0800 Floating point disabled */
371 EXC_SOFTWARE, /* 0x0900 Decrementer */
372 EXC_BAD_ACCESS, /* 0x0A00 I/O controller interface */
373 EXC_BAD_ACCESS, /* 0x0B00 INVALID EXCEPTION */
374 EXC_SOFTWARE, /* 0x0C00 System call exception */
375 EXC_BREAKPOINT, /* 0x0D00 Trace */
376 EXC_SOFTWARE, /* 0x0E00 FP assist */
377 EXC_SOFTWARE, /* 0x0F00 Performance monitoring */
378 EXC_ARITHMETIC, /* 0x0F20 Altivec disabled */
379 EXC_BAD_ACCESS, /* 0x1000 Instruction PTE miss */
380 EXC_BAD_ACCESS, /* 0x1100 Data load PTE miss */
381 EXC_BAD_ACCESS, /* 0x1200 Data store PTE miss */
382 EXC_BREAKPOINT, /* 0x1300 Instruction bkpt */
383 EXC_SOFTWARE, /* 0x1400 System management */
384 EXC_BAD_ACCESS, /* 0x1500 INVALID EXCEPTION */
385 EXC_ARITHMETIC, /* 0x1600 Altivec Assist */
386 EXC_BAD_ACCESS, /* 0x1700 INVALID EXCEPTION */
387 EXC_BAD_ACCESS, /* 0x1800 INVALID EXCEPTION */
388 EXC_BAD_ACCESS, /* 0x1900 INVALID EXCEPTION */
389 EXC_BAD_ACCESS, /* 0x1A00 INVALID EXCEPTION */
390 EXC_BAD_ACCESS, /* 0x1B00 INVALID EXCEPTION */
391 EXC_BAD_ACCESS, /* 0x1C00 INVALID EXCEPTION */
392 EXC_BAD_ACCESS, /* 0x1D00 INVALID EXCEPTION */
393 EXC_BAD_ACCESS, /* 0x1E00 INVALID EXCEPTION */
394 EXC_BAD_ACCESS, /* 0x1F00 INVALID EXCEPTION */
395 EXC_BREAKPOINT, /* 0x2000 Run Mode/Trace */
396 EXC_BAD_ACCESS, /* 0x2100 INVALID EXCEPTION */
397 EXC_BAD_ACCESS, /* 0x2200 INVALID EXCEPTION */
398 EXC_BAD_ACCESS, /* 0x2300 INVALID EXCEPTION */
399 EXC_BAD_ACCESS, /* 0x2400 INVALID EXCEPTION */
400 EXC_BAD_ACCESS, /* 0x2500 INVALID EXCEPTION */
401 EXC_BAD_ACCESS, /* 0x2600 INVALID EXCEPTION */
402 EXC_BAD_ACCESS, /* 0x2700 INVALID EXCEPTION */
403 EXC_BAD_ACCESS, /* 0x2800 INVALID EXCEPTION */
404 EXC_BAD_ACCESS, /* 0x2900 INVALID EXCEPTION */
405 EXC_BAD_ACCESS, /* 0x2A00 INVALID EXCEPTION */
406 EXC_BAD_ACCESS, /* 0x2B00 INVALID EXCEPTION */
407 EXC_BAD_ACCESS, /* 0x2C00 INVALID EXCEPTION */
408 EXC_BAD_ACCESS, /* 0x2D00 INVALID EXCEPTION */
409 EXC_BAD_ACCESS, /* 0x2E00 INVALID EXCEPTION */
410 EXC_BAD_ACCESS, /* 0x2F00 INVALID EXCEPTION */
411 EXC_SOFTWARE /* 0x3000 AST trap (software) */
412 };
413
414 int
415 kdp_getc()
416 {
417 return(cnmaygetc());
418 }
419
420 int kdp_backtrace;
421 int kdp_sr_dump;
422 int kdp_dabr;
423 int kdp_noisy;
424
425 #define kdp_code(x) kdp_trap_codes[((x)==T_AST?0x31:(x)/T_VECTOR_SIZE)]
426
427 void
428 kdp_trap(
429 unsigned int exception,
430 struct ppc_thread_state *saved_state
431 )
432 {
433 unsigned int *fp;
434 unsigned int register sp;
435 struct ppc_thread_state *state;
436
437 if (kdp_noisy) {
438 if (kdp_backtrace) {
439 printf("\nvector=%x, \n", exception/4);
440 #ifdef XXX
441 regDump(saved_state);
442 #endif
443 sp = saved_state->r1;
444 printf("stack backtrace - sp(%x) ", sp);
445 fp = (unsigned int *) *((unsigned int *)sp);
446 while (fp) {
447 printf("0x%08x ", fp[2]);
448 fp = (unsigned int *)*fp;
449 }
450 printf("\n");
451 }
452 #ifdef XXX
453 if (kdp_sr_dump) {
454 dump_segment_registers();
455 }
456 #endif
457
458 printf("vector=%d ", exception/4);
459 }
460
461 kdp_raise_exception(kdp_code(exception), 0, 0, saved_state);
462
463 if (kdp_noisy)
464 printf("kdp_trap: kdp_raise_exception() ret\n");
465
466 if (*((int *)saved_state->srr0) == 0x7c800008)
467 saved_state->srr0 += 4; /* BKPT_SIZE */
468
469 if(saved_state->srr1 & (MASK(MSR_SE) | MASK(MSR_BE))) { /* Are we just stepping or continuing */
470 db_run_mode = STEP_ONCE; /* We are stepping */
471 }
472 else db_run_mode = STEP_CONTINUE; /* Otherwise we are continuing */
473
474
475 #ifdef XXX
476 mtspr(dabr, kdp_dabr);
477 #endif
478 }
479
480 boolean_t
481 kdp_call_kdb(
482 void)
483 {
484 switch_debugger=1;
485 return(TRUE);
486 }
487
488 void kdp_print_registers(struct ppc_saved_state *state)
489 {
490 int i;
491 for (i=0; i<32; i++) {
492 if ((i % 8) == 0)
493 printf("\n%4d :",i);
494 printf(" %08x",*(&state->r0+i));
495 }
496 printf("\n");
497 printf("cr = 0x%08x\t\t",state->cr);
498 printf("xer = 0x%08x\n",state->xer);
499 printf("lr = 0x%08x\t\t",state->lr);
500 printf("ctr = 0x%08x\n",state->ctr);
501 printf("srr0(iar) = 0x%08x\t\t",state->srr0);
502 printf("srr1(msr) = 0x%08B\n",state->srr1,
503 "\x10\x11""EE\x12PR\x13""FP\x14ME\x15""FE0\x16SE\x18"
504 "FE1\x19""AL\x1a""EP\x1bIT\x1c""DT");
505 printf("mq = 0x%08x\t\t",state->mq);
506 printf("sr_copyin = 0x%08x\n",state->sr_copyin);
507 printf("\n");
508 }
509
510 void
511 kdp_print_backtrace(
512 unsigned int exception,
513 struct ppc_saved_state *saved_state)
514 {
515 extern void kdp_print_registers(struct ppc_saved_state *);
516 extern void print_backtrace(struct ppc_saved_state *);
517 extern unsigned int debug_mode, disableDebugOuput;
518
519 disableDebugOuput = FALSE;
520 debug_mode = TRUE;
521 printf("re-entering kdp:\n");
522 printf("vector=%x, \n", exception/4);
523 kdp_print_registers(saved_state);
524 print_backtrace(saved_state);
525 printf("panic: We are hanging here...\n");
526 while(1);
527 }