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