]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
91447636 | 2 | * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. |
1c79356b | 3 | * |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
8f6c56a5 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
1c79356b | 27 | */ |
1c79356b A |
28 | |
29 | #include <mach/mach_types.h> | |
30 | #include <mach/exception_types.h> | |
31 | #include <ppc/exception.h> | |
32 | #include <ppc/proc_reg.h> | |
33 | #include <kdp/kdp_internal.h> | |
34 | #include <ppc/savearea.h> | |
35 | #include <kern/debug.h> | |
91447636 | 36 | #include <IOKit/IOPlatformExpert.h> |
1c79356b | 37 | |
4452a7af A |
38 | |
39 | #include <kern/thread.h> | |
40 | #include <ppc/thread.h> | |
41 | #include <vm/vm_map.h> | |
42 | #include <ppc/pmap.h> | |
43 | ||
1c79356b A |
44 | #define KDP_TEST_HARNESS 0 |
45 | #if KDP_TEST_HARNESS | |
46 | #define dprintf(x) kprintf x | |
47 | #else | |
48 | #define dprintf(x) | |
49 | #endif | |
50 | ||
51 | void print_saved_state(void *); | |
52 | void kdp_call(void); | |
9bccf70c | 53 | void kdp_trap( unsigned int, struct savearea *saved_state); |
1c79356b A |
54 | int kdp_getc(void); |
55 | boolean_t kdp_call_kdb(void); | |
56 | ||
4452a7af A |
57 | extern pmap_t kdp_pmap; |
58 | extern uint32_t kdp_src_high32; | |
59 | ||
60 | ||
61 | extern unsigned kdp_vm_read(caddr_t src, caddr_t dst, unsigned len); | |
62 | ||
63 | int | |
64 | machine_trace_thread(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p); | |
65 | ||
66 | int | |
67 | machine_trace_thread64(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p); | |
68 | ||
69 | unsigned | |
70 | machine_read64(addr64_t srcaddr, caddr_t dstaddr, uint32_t len); | |
71 | ||
1c79356b A |
72 | void |
73 | kdp_exception( | |
74 | unsigned char *pkt, | |
75 | int *len, | |
76 | unsigned short *remote_port, | |
77 | unsigned int exception, | |
78 | unsigned int code, | |
79 | unsigned int subcode | |
80 | ) | |
81 | { | |
82 | struct { | |
83 | kdp_exception_t pkt; | |
84 | kdp_exc_info_t exc; | |
85 | } aligned_pkt; | |
86 | kdp_exception_t *rq = (kdp_exception_t *)&aligned_pkt; | |
87 | ||
88 | bcopy((char *)pkt, (char *)rq, sizeof(*rq)); | |
89 | rq->hdr.request = KDP_EXCEPTION; | |
90 | rq->hdr.is_reply = 0; | |
91 | rq->hdr.seq = kdp.exception_seq; | |
92 | rq->hdr.key = 0; | |
93 | rq->hdr.len = sizeof (*rq) + sizeof(kdp_exc_info_t); | |
94 | ||
95 | rq->n_exc_info = 1; | |
96 | rq->exc_info[0].cpu = 0; | |
97 | rq->exc_info[0].exception = exception; | |
98 | rq->exc_info[0].code = code; | |
99 | rq->exc_info[0].subcode = subcode; | |
100 | ||
101 | rq->hdr.len += rq->n_exc_info * sizeof (kdp_exc_info_t); | |
102 | ||
103 | bcopy((char *)rq, (char *)pkt, rq->hdr.len); | |
104 | ||
105 | kdp.exception_ack_needed = TRUE; | |
106 | ||
107 | *remote_port = kdp.exception_port; | |
108 | *len = rq->hdr.len; | |
109 | } | |
110 | ||
111 | boolean_t | |
112 | kdp_exception_ack( | |
113 | unsigned char *pkt, | |
114 | int len | |
115 | ) | |
116 | { | |
117 | kdp_exception_ack_t aligned_pkt; | |
118 | kdp_exception_ack_t *rq = (kdp_exception_ack_t *)&aligned_pkt; | |
119 | ||
120 | if (len < sizeof (*rq)) | |
121 | return(FALSE); | |
122 | ||
123 | bcopy((char *)pkt, (char *)rq, sizeof(*rq)); | |
124 | ||
125 | if (!rq->hdr.is_reply || rq->hdr.request != KDP_EXCEPTION) | |
126 | return(FALSE); | |
127 | ||
128 | dprintf(("kdp_exception_ack seq %x %x\n", rq->hdr.seq, kdp.exception_seq)); | |
129 | ||
130 | if (rq->hdr.seq == kdp.exception_seq) { | |
131 | kdp.exception_ack_needed = FALSE; | |
132 | kdp.exception_seq++; | |
133 | } | |
134 | return(TRUE); | |
135 | } | |
136 | ||
137 | static void | |
138 | kdp_getintegerstate( | |
139 | struct ppc_thread_state *state | |
140 | ) | |
141 | { | |
9bccf70c | 142 | struct savearea *saved_state; |
1c79356b A |
143 | |
144 | saved_state = kdp.saved_state; | |
145 | ||
146 | bzero((char *)state,sizeof (struct ppc_thread_state)) ; | |
147 | ||
55e303ae A |
148 | state->srr0 = (unsigned int)saved_state->save_srr0; |
149 | state->srr1 = (unsigned int)saved_state->save_srr1; | |
150 | state->r0 = (unsigned int)saved_state->save_r0; | |
151 | state->r1 = (unsigned int)saved_state->save_r1; | |
152 | state->r2 = (unsigned int)saved_state->save_r2; | |
153 | state->r3 = (unsigned int)saved_state->save_r3; | |
154 | state->r4 = (unsigned int)saved_state->save_r4; | |
155 | state->r5 = (unsigned int)saved_state->save_r5; | |
156 | state->r6 = (unsigned int)saved_state->save_r6; | |
157 | state->r7 = (unsigned int)saved_state->save_r7; | |
158 | state->r8 = (unsigned int)saved_state->save_r8; | |
159 | state->r9 = (unsigned int)saved_state->save_r9; | |
160 | state->r10 = (unsigned int)saved_state->save_r10; | |
161 | state->r11 = (unsigned int)saved_state->save_r11; | |
162 | state->r12 = (unsigned int)saved_state->save_r12; | |
163 | state->r13 = (unsigned int)saved_state->save_r13; | |
164 | state->r14 = (unsigned int)saved_state->save_r14; | |
165 | state->r15 = (unsigned int)saved_state->save_r15; | |
166 | state->r16 = (unsigned int)saved_state->save_r16; | |
167 | state->r17 = (unsigned int)saved_state->save_r17; | |
168 | state->r18 = (unsigned int)saved_state->save_r18; | |
169 | state->r19 = (unsigned int)saved_state->save_r19; | |
170 | state->r20 = (unsigned int)saved_state->save_r20; | |
171 | state->r21 = (unsigned int)saved_state->save_r21; | |
172 | state->r22 = (unsigned int)saved_state->save_r22; | |
173 | state->r23 = (unsigned int)saved_state->save_r23; | |
174 | state->r24 = (unsigned int)saved_state->save_r24; | |
175 | state->r25 = (unsigned int)saved_state->save_r25; | |
176 | state->r26 = (unsigned int)saved_state->save_r26; | |
177 | state->r27 = (unsigned int)saved_state->save_r27; | |
178 | state->r28 = (unsigned int)saved_state->save_r28; | |
179 | state->r29 = (unsigned int)saved_state->save_r29; | |
180 | state->r30 = (unsigned int)saved_state->save_r30; | |
181 | state->r31 = (unsigned int)saved_state->save_r31; | |
182 | state->cr = (unsigned int)saved_state->save_cr; | |
183 | state->xer = (unsigned int)saved_state->save_xer; | |
184 | state->lr = (unsigned int)saved_state->save_lr; | |
185 | state->ctr = (unsigned int)saved_state->save_ctr; | |
186 | } | |
187 | ||
188 | static void | |
189 | kdp_getintegerstate64( | |
190 | struct ppc_thread_state64 *state | |
191 | ) | |
192 | { | |
193 | struct savearea *saved_state; | |
194 | ||
195 | saved_state = kdp.saved_state; | |
196 | ||
197 | bzero((char *)state,sizeof (struct ppc_thread_state64)) ; | |
198 | ||
9bccf70c A |
199 | state->srr0 = saved_state->save_srr0; |
200 | state->srr1 = saved_state->save_srr1; | |
201 | state->r0 = saved_state->save_r0; | |
202 | state->r1 = saved_state->save_r1; | |
203 | state->r2 = saved_state->save_r2; | |
204 | state->r3 = saved_state->save_r3; | |
205 | state->r4 = saved_state->save_r4; | |
206 | state->r5 = saved_state->save_r5; | |
207 | state->r6 = saved_state->save_r6; | |
208 | state->r7 = saved_state->save_r7; | |
209 | state->r8 = saved_state->save_r8; | |
210 | state->r9 = saved_state->save_r9; | |
211 | state->r10 = saved_state->save_r10; | |
212 | state->r11 = saved_state->save_r11; | |
213 | state->r12 = saved_state->save_r12; | |
214 | state->r13 = saved_state->save_r13; | |
215 | state->r14 = saved_state->save_r14; | |
216 | state->r15 = saved_state->save_r15; | |
217 | state->r16 = saved_state->save_r16; | |
218 | state->r17 = saved_state->save_r17; | |
219 | state->r18 = saved_state->save_r18; | |
220 | state->r19 = saved_state->save_r19; | |
221 | state->r20 = saved_state->save_r20; | |
222 | state->r21 = saved_state->save_r21; | |
223 | state->r22 = saved_state->save_r22; | |
224 | state->r23 = saved_state->save_r23; | |
225 | state->r24 = saved_state->save_r24; | |
226 | state->r25 = saved_state->save_r25; | |
227 | state->r26 = saved_state->save_r26; | |
228 | state->r27 = saved_state->save_r27; | |
229 | state->r28 = saved_state->save_r28; | |
230 | state->r29 = saved_state->save_r29; | |
231 | state->r30 = saved_state->save_r30; | |
232 | state->r31 = saved_state->save_r31; | |
233 | state->cr = saved_state->save_cr; | |
234 | state->xer = saved_state->save_xer; | |
235 | state->lr = saved_state->save_lr; | |
236 | state->ctr = saved_state->save_ctr; | |
1c79356b A |
237 | } |
238 | ||
239 | kdp_error_t | |
240 | kdp_machine_read_regs( | |
241 | unsigned int cpu, | |
242 | unsigned int flavor, | |
243 | char *data, | |
244 | int *size | |
245 | ) | |
246 | { | |
247 | switch (flavor) { | |
248 | ||
249 | case PPC_THREAD_STATE: | |
250 | dprintf(("kdp_readregs THREAD_STATE\n")); | |
251 | kdp_getintegerstate((struct ppc_thread_state *)data); | |
252 | *size = PPC_THREAD_STATE_COUNT * sizeof(int); | |
253 | return KDPERR_NO_ERROR; | |
55e303ae A |
254 | |
255 | case PPC_THREAD_STATE64: | |
256 | dprintf(("kdp_readregs THREAD_STATE\n")); | |
257 | kdp_getintegerstate64((struct ppc_thread_state64 *)data); | |
258 | *size = PPC_THREAD_STATE64_COUNT * sizeof(int); | |
259 | return KDPERR_NO_ERROR; | |
260 | ||
1c79356b A |
261 | case PPC_FLOAT_STATE: |
262 | dprintf(("kdp_readregs THREAD_FPSTATE\n")); | |
263 | bzero((char *)data ,sizeof(struct ppc_float_state)); | |
264 | *size = PPC_FLOAT_STATE_COUNT * sizeof(int); | |
265 | return KDPERR_NO_ERROR; | |
55e303ae | 266 | |
1c79356b A |
267 | default: |
268 | dprintf(("kdp_readregs bad flavor %d\n")); | |
269 | return KDPERR_BADFLAVOR; | |
270 | } | |
271 | } | |
272 | ||
273 | static void | |
274 | kdp_setintegerstate( | |
275 | struct ppc_thread_state *state | |
276 | ) | |
277 | { | |
9bccf70c | 278 | struct savearea *saved_state; |
1c79356b A |
279 | |
280 | saved_state = kdp.saved_state; | |
281 | ||
9bccf70c A |
282 | saved_state->save_srr0 = state->srr0; |
283 | saved_state->save_srr1 = state->srr1; | |
284 | saved_state->save_r0 = state->r0; | |
285 | saved_state->save_r1 = state->r1; | |
286 | saved_state->save_r2 = state->r2; | |
287 | saved_state->save_r3 = state->r3; | |
288 | saved_state->save_r4 = state->r4; | |
289 | saved_state->save_r5 = state->r5; | |
290 | saved_state->save_r6 = state->r6; | |
291 | saved_state->save_r7 = state->r7; | |
292 | saved_state->save_r8 = state->r8; | |
293 | saved_state->save_r9 = state->r9; | |
294 | saved_state->save_r10 = state->r10; | |
295 | saved_state->save_r11 = state->r11; | |
296 | saved_state->save_r12 = state->r12; | |
297 | saved_state->save_r13 = state->r13; | |
298 | saved_state->save_r14 = state->r14; | |
299 | saved_state->save_r15 = state->r15; | |
300 | saved_state->save_r16 = state->r16; | |
301 | saved_state->save_r17 = state->r17; | |
302 | saved_state->save_r18 = state->r18; | |
303 | saved_state->save_r19 = state->r19; | |
304 | saved_state->save_r20 = state->r20; | |
305 | saved_state->save_r21 = state->r21; | |
306 | saved_state->save_r22 = state->r22; | |
307 | saved_state->save_r23 = state->r23; | |
308 | saved_state->save_r24 = state->r24; | |
309 | saved_state->save_r25 = state->r25; | |
310 | saved_state->save_r26 = state->r26; | |
311 | saved_state->save_r27 = state->r27; | |
312 | saved_state->save_r28 = state->r28; | |
313 | saved_state->save_r29 = state->r29; | |
314 | saved_state->save_r30 = state->r30; | |
315 | saved_state->save_r31 = state->r31; | |
316 | saved_state->save_cr = state->cr; | |
317 | saved_state->save_xer = state->xer; | |
318 | saved_state->save_lr = state->lr; | |
319 | saved_state->save_ctr = state->ctr; | |
1c79356b A |
320 | } |
321 | ||
55e303ae A |
322 | static void |
323 | kdp_setintegerstate64( | |
324 | struct ppc_thread_state64 *state | |
325 | ) | |
326 | { | |
327 | struct savearea *saved_state; | |
328 | ||
329 | saved_state = kdp.saved_state; | |
330 | ||
331 | saved_state->save_srr0 = state->srr0; | |
332 | saved_state->save_srr1 = state->srr1; | |
333 | saved_state->save_r0 = state->r0; | |
334 | saved_state->save_r1 = state->r1; | |
335 | saved_state->save_r2 = state->r2; | |
336 | saved_state->save_r3 = state->r3; | |
337 | saved_state->save_r4 = state->r4; | |
338 | saved_state->save_r5 = state->r5; | |
339 | saved_state->save_r6 = state->r6; | |
340 | saved_state->save_r7 = state->r7; | |
341 | saved_state->save_r8 = state->r8; | |
342 | saved_state->save_r9 = state->r9; | |
343 | saved_state->save_r10 = state->r10; | |
344 | saved_state->save_r11 = state->r11; | |
345 | saved_state->save_r12 = state->r12; | |
346 | saved_state->save_r13 = state->r13; | |
347 | saved_state->save_r14 = state->r14; | |
348 | saved_state->save_r15 = state->r15; | |
349 | saved_state->save_r16 = state->r16; | |
350 | saved_state->save_r17 = state->r17; | |
351 | saved_state->save_r18 = state->r18; | |
352 | saved_state->save_r19 = state->r19; | |
353 | saved_state->save_r20 = state->r20; | |
354 | saved_state->save_r21 = state->r21; | |
355 | saved_state->save_r22 = state->r22; | |
356 | saved_state->save_r23 = state->r23; | |
357 | saved_state->save_r24 = state->r24; | |
358 | saved_state->save_r25 = state->r25; | |
359 | saved_state->save_r26 = state->r26; | |
360 | saved_state->save_r27 = state->r27; | |
361 | saved_state->save_r28 = state->r28; | |
362 | saved_state->save_r29 = state->r29; | |
363 | saved_state->save_r30 = state->r30; | |
364 | saved_state->save_r31 = state->r31; | |
365 | saved_state->save_cr = state->cr; | |
366 | saved_state->save_xer = state->xer; | |
367 | saved_state->save_lr = state->lr; | |
368 | saved_state->save_ctr = state->ctr; | |
369 | } | |
370 | ||
1c79356b A |
371 | kdp_error_t |
372 | kdp_machine_write_regs( | |
373 | unsigned int cpu, | |
374 | unsigned int flavor, | |
375 | char *data, | |
376 | int *size | |
377 | ) | |
378 | { | |
379 | switch (flavor) { | |
380 | ||
381 | case PPC_THREAD_STATE: | |
382 | dprintf(("kdp_writeregs THREAD_STATE\n")); | |
383 | kdp_setintegerstate((struct ppc_thread_state *)data); | |
384 | ||
385 | #if KDP_TEST_HARNESS | |
386 | DumpTheSave((struct savearea *)data); /* (TEST/DEBUG) */ | |
387 | #endif | |
388 | return KDPERR_NO_ERROR; | |
55e303ae A |
389 | |
390 | case PPC_THREAD_STATE64: | |
391 | dprintf(("kdp_writeregs THREAD_STATE64\n")); | |
392 | kdp_setintegerstate64((struct ppc_thread_state64 *)data); | |
393 | ||
394 | #if KDP_TEST_HARNESS | |
395 | DumpTheSave((struct savearea *)data); /* (TEST/DEBUG) */ | |
396 | #endif | |
397 | return KDPERR_NO_ERROR; | |
1c79356b A |
398 | case PPC_FLOAT_STATE: |
399 | dprintf(("kdp_writeregs THREAD_FPSTATE\n")); | |
400 | return KDPERR_NO_ERROR; | |
55e303ae | 401 | |
1c79356b A |
402 | default: |
403 | dprintf(("kdp_writeregs bad flavor %d\n")); | |
404 | return KDPERR_BADFLAVOR; | |
405 | } | |
406 | } | |
407 | ||
408 | void | |
409 | kdp_machine_hostinfo( | |
410 | kdp_hostinfo_t *hostinfo | |
411 | ) | |
412 | { | |
1c79356b A |
413 | int i; |
414 | ||
415 | hostinfo->cpus_mask = 0; | |
0b4e3aa0 | 416 | hostinfo->cpu_type = 0; |
1c79356b A |
417 | |
418 | for (i = 0; i < machine_info.max_cpus; i++) { | |
91447636 A |
419 | if ((PerProcTable[i].ppe_vaddr == (struct per_proc_info *)NULL) || |
420 | !(PerProcTable[i].ppe_vaddr->running)) | |
1c79356b A |
421 | continue; |
422 | ||
423 | hostinfo->cpus_mask |= (1 << i); | |
424 | if (hostinfo->cpu_type == 0) { | |
91447636 A |
425 | hostinfo->cpu_type = slot_type(i); |
426 | hostinfo->cpu_subtype = slot_subtype(i); | |
1c79356b A |
427 | } |
428 | } | |
429 | } | |
430 | ||
431 | void | |
432 | kdp_panic( | |
433 | const char *msg | |
434 | ) | |
435 | { | |
436 | printf("kdp panic: %s\n", msg); | |
437 | while(1) {} | |
438 | } | |
439 | ||
440 | ||
441 | void | |
442 | kdp_reboot(void) | |
443 | { | |
91447636 A |
444 | printf("Attempting system restart..."); |
445 | /* Call the platform specific restart*/ | |
446 | if (PE_halt_restart) | |
447 | (*PE_halt_restart)(kPERestartCPU); | |
448 | /* If we do reach this, give up */ | |
449 | halt_all_cpus(TRUE); | |
1c79356b A |
450 | } |
451 | ||
452 | int | |
453 | kdp_intr_disbl(void) | |
454 | { | |
455 | return (splhigh()); | |
456 | } | |
457 | ||
458 | void | |
459 | kdp_intr_enbl(int s) | |
460 | { | |
461 | splx(s); | |
462 | } | |
463 | ||
464 | void | |
465 | kdp_us_spin(int usec) | |
466 | { | |
467 | extern void delay(int); | |
468 | ||
469 | delay(usec/100); | |
470 | } | |
471 | ||
472 | void print_saved_state(void *state) | |
473 | { | |
474 | struct ppc_thread_state *saved_state; | |
475 | ||
476 | saved_state = state; | |
477 | ||
478 | printf("pc = 0x%x\n", saved_state->srr0); | |
479 | printf("msr = 0x%x\n", saved_state->srr1); | |
480 | printf("rp = 0x%x\n", saved_state->lr); | |
481 | printf("sp = 0x%x\n", saved_state->r1); | |
482 | ||
483 | } | |
484 | ||
485 | void | |
486 | kdp_call() | |
487 | { | |
488 | Debugger("inline call to debugger(machine_startup)"); | |
489 | } | |
490 | ||
491 | /* | |
492 | * table to convert system specific code to generic codes for kdb | |
493 | */ | |
494 | int kdp_trap_codes[] = { | |
495 | EXC_BAD_ACCESS, /* 0x0000 INVALID EXCEPTION */ | |
496 | EXC_BAD_ACCESS, /* 0x0100 System reset */ | |
497 | EXC_BAD_ACCESS, /* 0x0200 Machine check */ | |
498 | EXC_BAD_ACCESS, /* 0x0300 Data access */ | |
499 | EXC_BAD_ACCESS, /* 0x0400 Instruction access */ | |
500 | EXC_BAD_ACCESS, /* 0x0500 External interrupt */ | |
501 | EXC_BAD_ACCESS, /* 0x0600 Alignment */ | |
502 | EXC_BREAKPOINT, /* 0x0700 Program - fp exc, ill/priv instr, trap */ | |
503 | EXC_ARITHMETIC, /* 0x0800 Floating point disabled */ | |
504 | EXC_SOFTWARE, /* 0x0900 Decrementer */ | |
505 | EXC_BAD_ACCESS, /* 0x0A00 I/O controller interface */ | |
506 | EXC_BAD_ACCESS, /* 0x0B00 INVALID EXCEPTION */ | |
507 | EXC_SOFTWARE, /* 0x0C00 System call exception */ | |
508 | EXC_BREAKPOINT, /* 0x0D00 Trace */ | |
509 | EXC_SOFTWARE, /* 0x0E00 FP assist */ | |
510 | EXC_SOFTWARE, /* 0x0F00 Performance monitoring */ | |
511 | EXC_ARITHMETIC, /* 0x0F20 Altivec disabled */ | |
512 | EXC_BAD_ACCESS, /* 0x1000 Instruction PTE miss */ | |
513 | EXC_BAD_ACCESS, /* 0x1100 Data load PTE miss */ | |
514 | EXC_BAD_ACCESS, /* 0x1200 Data store PTE miss */ | |
515 | EXC_BREAKPOINT, /* 0x1300 Instruction bkpt */ | |
516 | EXC_SOFTWARE, /* 0x1400 System management */ | |
517 | EXC_BAD_ACCESS, /* 0x1500 INVALID EXCEPTION */ | |
518 | EXC_ARITHMETIC, /* 0x1600 Altivec Assist */ | |
519 | EXC_BAD_ACCESS, /* 0x1700 INVALID EXCEPTION */ | |
520 | EXC_BAD_ACCESS, /* 0x1800 INVALID EXCEPTION */ | |
521 | EXC_BAD_ACCESS, /* 0x1900 INVALID EXCEPTION */ | |
522 | EXC_BAD_ACCESS, /* 0x1A00 INVALID EXCEPTION */ | |
523 | EXC_BAD_ACCESS, /* 0x1B00 INVALID EXCEPTION */ | |
524 | EXC_BAD_ACCESS, /* 0x1C00 INVALID EXCEPTION */ | |
525 | EXC_BAD_ACCESS, /* 0x1D00 INVALID EXCEPTION */ | |
526 | EXC_BAD_ACCESS, /* 0x1E00 INVALID EXCEPTION */ | |
527 | EXC_BAD_ACCESS, /* 0x1F00 INVALID EXCEPTION */ | |
528 | EXC_BREAKPOINT, /* 0x2000 Run Mode/Trace */ | |
529 | EXC_BAD_ACCESS, /* 0x2100 INVALID EXCEPTION */ | |
530 | EXC_BAD_ACCESS, /* 0x2200 INVALID EXCEPTION */ | |
531 | EXC_BAD_ACCESS, /* 0x2300 INVALID EXCEPTION */ | |
532 | EXC_BAD_ACCESS, /* 0x2400 INVALID EXCEPTION */ | |
533 | EXC_BAD_ACCESS, /* 0x2500 INVALID EXCEPTION */ | |
534 | EXC_BAD_ACCESS, /* 0x2600 INVALID EXCEPTION */ | |
535 | EXC_BAD_ACCESS, /* 0x2700 INVALID EXCEPTION */ | |
536 | EXC_BAD_ACCESS, /* 0x2800 INVALID EXCEPTION */ | |
537 | EXC_BAD_ACCESS, /* 0x2900 INVALID EXCEPTION */ | |
538 | EXC_BAD_ACCESS, /* 0x2A00 INVALID EXCEPTION */ | |
539 | EXC_BAD_ACCESS, /* 0x2B00 INVALID EXCEPTION */ | |
540 | EXC_BAD_ACCESS, /* 0x2C00 INVALID EXCEPTION */ | |
541 | EXC_BAD_ACCESS, /* 0x2D00 INVALID EXCEPTION */ | |
542 | EXC_BAD_ACCESS, /* 0x2E00 INVALID EXCEPTION */ | |
543 | EXC_BAD_ACCESS, /* 0x2F00 INVALID EXCEPTION */ | |
544 | EXC_SOFTWARE /* 0x3000 AST trap (software) */ | |
545 | }; | |
546 | ||
547 | int | |
548 | kdp_getc() | |
549 | { | |
550 | return(cnmaygetc()); | |
551 | } | |
552 | ||
553 | int kdp_backtrace; | |
554 | int kdp_sr_dump; | |
555 | int kdp_dabr; | |
556 | int kdp_noisy; | |
557 | ||
558 | #define kdp_code(x) kdp_trap_codes[((x)==T_AST?0x31:(x)/T_VECTOR_SIZE)] | |
559 | ||
560 | void | |
561 | kdp_trap( | |
562 | unsigned int exception, | |
9bccf70c | 563 | struct savearea *saved_state |
1c79356b A |
564 | ) |
565 | { | |
566 | unsigned int *fp; | |
55e303ae | 567 | unsigned int sp; |
9bccf70c | 568 | struct savearea *state; |
1c79356b A |
569 | |
570 | if (kdp_noisy) { | |
571 | if (kdp_backtrace) { | |
572 | printf("\nvector=%x, \n", exception/4); | |
9bccf70c | 573 | sp = saved_state->save_r1; |
1c79356b A |
574 | printf("stack backtrace - sp(%x) ", sp); |
575 | fp = (unsigned int *) *((unsigned int *)sp); | |
576 | while (fp) { | |
577 | printf("0x%08x ", fp[2]); | |
578 | fp = (unsigned int *)*fp; | |
579 | } | |
580 | printf("\n"); | |
581 | } | |
582 | #ifdef XXX | |
583 | if (kdp_sr_dump) { | |
584 | dump_segment_registers(); | |
585 | } | |
586 | #endif | |
587 | ||
9bccf70c | 588 | printf("vector=%d ", exception/4); |
1c79356b | 589 | } |
1c79356b A |
590 | kdp_raise_exception(kdp_code(exception), 0, 0, saved_state); |
591 | ||
592 | if (kdp_noisy) | |
593 | printf("kdp_trap: kdp_raise_exception() ret\n"); | |
594 | ||
55e303ae | 595 | if ((unsigned int)(saved_state->save_srr0) == 0x7c800008) |
9bccf70c A |
596 | saved_state->save_srr0 += 4; /* BKPT_SIZE */ |
597 | ||
598 | if(saved_state->save_srr1 & (MASK(MSR_SE) | MASK(MSR_BE))) { /* Are we just stepping or continuing */ | |
1c79356b A |
599 | db_run_mode = STEP_ONCE; /* We are stepping */ |
600 | } | |
601 | else db_run_mode = STEP_CONTINUE; /* Otherwise we are continuing */ | |
9bccf70c | 602 | |
1c79356b A |
603 | #ifdef XXX |
604 | mtspr(dabr, kdp_dabr); | |
605 | #endif | |
606 | } | |
607 | ||
608 | boolean_t | |
609 | kdp_call_kdb( | |
610 | void) | |
611 | { | |
612 | switch_debugger=1; | |
613 | return(TRUE); | |
614 | } | |
615 | ||
9bccf70c | 616 | void kdp_print_registers(struct savearea *state) |
1c79356b A |
617 | { |
618 | int i; | |
619 | for (i=0; i<32; i++) { | |
620 | if ((i % 8) == 0) | |
621 | printf("\n%4d :",i); | |
9bccf70c | 622 | printf(" %08x",*(&state->save_r0+i)); |
1c79356b A |
623 | } |
624 | printf("\n"); | |
9bccf70c A |
625 | printf("cr = 0x%08x\t\t",state->save_cr); |
626 | printf("xer = 0x%08x\n",state->save_xer); | |
627 | printf("lr = 0x%08x\t\t",state->save_lr); | |
628 | printf("ctr = 0x%08x\n",state->save_ctr); | |
629 | printf("srr0(iar) = 0x%08x\t\t",state->save_srr0); | |
630 | printf("srr1(msr) = 0x%08B\n",state->save_srr1, | |
1c79356b A |
631 | "\x10\x11""EE\x12PR\x13""FP\x14ME\x15""FE0\x16SE\x18" |
632 | "FE1\x19""AL\x1a""EP\x1bIT\x1c""DT"); | |
1c79356b A |
633 | printf("\n"); |
634 | } | |
635 | ||
636 | void | |
637 | kdp_print_backtrace( | |
638 | unsigned int exception, | |
9bccf70c | 639 | struct savearea *saved_state) |
1c79356b | 640 | { |
9bccf70c A |
641 | extern void kdp_print_registers(struct savearea *); |
642 | extern void print_backtrace(struct savearea *); | |
1c79356b A |
643 | |
644 | disableDebugOuput = FALSE; | |
645 | debug_mode = TRUE; | |
646 | printf("re-entering kdp:\n"); | |
647 | printf("vector=%x, \n", exception/4); | |
648 | kdp_print_registers(saved_state); | |
649 | print_backtrace(saved_state); | |
650 | printf("panic: We are hanging here...\n"); | |
651 | while(1); | |
652 | } | |
9bccf70c | 653 | |
91447636 | 654 | unsigned int kdp_ml_get_breakinsn(void) |
9bccf70c A |
655 | { |
656 | return 0x7fe00008; | |
657 | } | |
4452a7af A |
658 | #define LR_OFFSET 8 |
659 | #define LR_OFFSET64 16 | |
660 | ||
661 | int | |
662 | machine_trace_thread(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p) | |
663 | { | |
664 | uint32_t *tracebuf = (uint32_t *)tracepos; | |
665 | uint32_t fence = 0; | |
666 | uint32_t stackptr = 0; | |
667 | uint32_t stacklimit = 0xb0000000; | |
668 | int framecount = 0; | |
669 | uint32_t init_srr0 = 0; | |
670 | uint32_t prevsp = 0; | |
671 | uint32_t framesize = 2 * sizeof(vm_offset_t); | |
672 | ||
673 | if (user_p) { | |
674 | /* Examine the user savearea */ | |
675 | init_srr0 = thread->machine.upcb->save_srr0; | |
676 | stackptr = thread->machine.upcb->save_r1; | |
677 | /* This bound isn't useful, but it doesn't hinder us */ | |
678 | stacklimit = 0xffffffff; | |
679 | kdp_pmap = thread->task->map->pmap; | |
680 | } | |
681 | else { | |
682 | stackptr = thread->machine.pcb->save_r1; | |
683 | init_srr0 = thread->machine.pcb->save_srr0; | |
684 | } | |
685 | /* Fill in the "current" program counter */ | |
686 | *tracebuf++ = init_srr0; | |
687 | ||
688 | for (framecount = 0; framecount < nframes; framecount++) { | |
689 | /* Bounds check */ | |
690 | if ((tracebound - ((uint32_t) tracebuf)) < (4 * framesize)) { | |
691 | tracebuf--; | |
692 | break; | |
693 | } | |
694 | ||
695 | *tracebuf++ = stackptr; | |
696 | /* Invalid frame, or hit fence */ | |
697 | if (!stackptr || (stackptr == fence)) { | |
698 | break; | |
699 | } | |
700 | /* Stack grows downward */ | |
701 | if (stackptr < prevsp) { | |
702 | break; | |
703 | } | |
704 | /* Unaligned frame */ | |
705 | if (stackptr & 0x000000F) { | |
706 | break; | |
707 | } | |
708 | if (stackptr > stacklimit) { | |
709 | break; | |
710 | } | |
711 | /* Assume there's a saved link register, and read it */ | |
712 | if (kdp_vm_read((caddr_t) (stackptr + LR_OFFSET), (caddr_t) tracebuf, sizeof(caddr_t)) != sizeof(caddr_t)) { | |
713 | break; | |
714 | } | |
715 | ||
716 | tracebuf++; | |
717 | prevsp = stackptr; | |
718 | /* Next frame */ | |
719 | if (kdp_vm_read((caddr_t) stackptr, (caddr_t) &stackptr, sizeof(caddr_t)) != sizeof(caddr_t)) { | |
720 | *tracebuf++ = 0; | |
721 | break; | |
722 | } | |
723 | } | |
724 | /* Reset the target pmap */ | |
725 | kdp_pmap = 0; | |
726 | return ((uint32_t) tracebuf - tracepos); | |
727 | } | |
728 | ||
729 | /* Routine to encapsulate the 64-bit address read hack*/ | |
730 | unsigned | |
731 | machine_read64(addr64_t srcaddr, caddr_t dstaddr, uint32_t len) | |
732 | { | |
733 | uint32_t kdp_vm_read_low32; | |
734 | unsigned retval; | |
735 | ||
736 | kdp_src_high32 = srcaddr >> 32; | |
737 | kdp_vm_read_low32 = srcaddr & 0x00000000FFFFFFFFUL; | |
738 | retval = kdp_vm_read((caddr_t)kdp_vm_read_low32, dstaddr, len); | |
739 | kdp_src_high32 = 0; | |
740 | return retval; | |
741 | } | |
742 | ||
743 | int | |
744 | machine_trace_thread64(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p) | |
745 | { | |
746 | uint64_t *tracebuf = (uint64_t *)tracepos; | |
747 | uint32_t fence = 0; | |
748 | addr64_t stackptr = 0; | |
749 | uint64_t stacklimit = 0xb0000000; | |
750 | int framecount = 0; | |
751 | addr64_t init_srr0 = 0; | |
752 | addr64_t prevsp = 0; | |
753 | unsigned framesize = 2 * sizeof(addr64_t); | |
754 | ||
755 | if (user_p) { | |
756 | init_srr0 = thread->machine.upcb->save_srr0; | |
757 | stackptr = thread->machine.upcb->save_r1; | |
758 | stacklimit = 0xffffffffffffffffULL; | |
759 | kdp_pmap = thread->task->map->pmap; | |
760 | } | |
761 | else { | |
762 | stackptr = thread->machine.pcb->save_r1; | |
763 | init_srr0 = thread->machine.pcb->save_srr0; | |
764 | } | |
765 | ||
766 | *tracebuf++ = init_srr0; | |
767 | ||
768 | for (framecount = 0; framecount < nframes; framecount++) { | |
769 | ||
770 | if ((tracebound - ((uint32_t) tracebuf)) < (4 * framesize)) { | |
771 | tracebuf--; | |
772 | break; | |
773 | } | |
774 | ||
775 | *tracebuf++ = stackptr; | |
776 | ||
777 | if (!stackptr || (stackptr == fence)){ | |
778 | break; | |
779 | } | |
780 | if (stackptr < prevsp) { | |
781 | break; | |
782 | } | |
783 | if (stackptr & 0x000000F) { | |
784 | break; | |
785 | } | |
786 | if (stackptr > stacklimit) { | |
787 | break; | |
788 | } | |
789 | ||
790 | if (machine_read64(stackptr+LR_OFFSET64, (caddr_t) tracebuf, sizeof(addr64_t)) != sizeof(addr64_t)) { | |
791 | break; | |
792 | } | |
793 | tracebuf++; | |
794 | ||
795 | prevsp = stackptr; | |
796 | if (machine_read64(stackptr, (caddr_t) &stackptr, sizeof(addr64_t)) != sizeof(addr64_t)) { | |
797 | *tracebuf++ = 0; | |
798 | break; | |
799 | } | |
800 | } | |
801 | ||
802 | kdp_pmap = 0; | |
803 | ||
804 | return ((uint32_t) tracebuf - tracepos); | |
805 | } |