|
|
1.1 root 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: * @OSF_COPYRIGHT@
24: */
25:
26: #include <cpus.h>
27: #include <platforms.h>
28: #include <time_stamp.h>
29: #include <mach_mp_debug.h>
30: #include <mach_ldebug.h>
31: #include <db_machine_commands.h>
32:
33: #include <kern/spl.h>
34: #include <kern/cpu_number.h>
35: #include <kern/kern_types.h>
36: #include <kern/misc_protos.h>
37: #include <vm/pmap.h>
38:
39: #include <ppc/mem.h>
40: #include <ppc/thread.h>
41: #include <ppc/db_machdep.h>
42: #include <ppc/trap.h>
43: #include <ppc/setjmp.h>
44: #include <ppc/pmap.h>
45: #include <ppc/misc_protos.h>
46: #include <ppc/exception.h>
47: #include <ppc/db_machdep.h>
48: #include <ppc/mappings.h>
49: #include <ppc/Firmware.h>
50:
51: #include <mach/vm_param.h>
52: #include <mach/machine/vm_types.h>
53: #include <vm/vm_map.h>
54: #include <kern/thread.h>
55: #include <kern/task.h>
56: #include <kern/debug.h>
57:
58: #include <ddb/db_command.h>
59: #include <ddb/db_task_thread.h>
60: #include <ddb/db_run.h>
61: #include <ddb/db_trap.h>
62: #include <ddb/db_output.h>
63: #include <ddb/db_access.h>
64: #include <ddb/db_sym.h>
65: #include <ddb/db_break.h>
66: #include <ddb/db_watch.h>
67:
68: struct ppc_saved_state *ppc_last_saved_statep;
69: struct ppc_saved_state ppc_nested_saved_state;
70: unsigned ppc_last_kdb_sp;
71:
72: extern int debugger_active[NCPUS]; /* Debugger active on CPU */
73: extern int debugger_cpu; /* Current cpu running debugger */
74:
75: int db_all_set_up = 0;
76:
77:
78: #if !MACH_KDP
79: void kdp_register_send_receive(void);
80: #endif
81:
82: /*
83: * Enter KDB through a keyboard trap.
84: * We show the registers as of the keyboard interrupt
85: * instead of those at its call to KDB.
86: */
87: struct int_regs {
88: /* XXX more registers ? */
89: struct ppc_interrupt_state *is;
90: };
91:
92: extern char * trap_type[];
93: extern int TRAP_TYPES;
94:
95: /*
96: * Code used to synchronize kdb among all cpus, one active at a time, switch
97: * from on to another using kdb_on! #cpu or cpu #cpu
98: */
99:
100: decl_simple_lock_data(, kdb_lock) /* kdb lock */
101:
102: #define db_simple_lock_init(l, e) hw_lock_init(&((l)->interlock))
103: #define db_simple_lock_try(l) hw_lock_try(&((l)->interlock))
104: #define db_simple_unlock(l) hw_lock_unlock(&((l)->interlock))
105:
106: extern volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus holding
107: breakpoints (ie: cpus that did not
108: insert back breakpoints) */
109: extern boolean_t db_breakpoints_inserted;
110:
111: /* Forward */
112:
113: extern void kdbprinttrap(
114: int type,
115: int code,
116: int *pc,
117: int sp);
118: extern int db_user_to_kernel_address(
119: task_t task,
120: vm_offset_t addr,
121: unsigned *kaddr,
122: int flag);
123: extern void db_write_bytes_user_space(
124: vm_offset_t addr,
125: int size,
126: char *data,
127: task_t task);
128: extern int db_search_null(
129: task_t task,
130: unsigned *svaddr,
131: unsigned evaddr,
132: unsigned *skaddr,
133: int flag);
134: extern int kdb_enter(int);
135: extern void kdb_leave(void);
136: extern void lock_kdb(void);
137: extern void unlock_kdb(void);
138:
139: #if DB_MACHINE_COMMANDS
140: struct db_command ppc_db_commands[] = {
141: { "lt", db_low_trace, CS_MORE|CS_SET_DOT, 0 },
142: { (char *)0, 0, 0, 0 }
143: };
144: #endif /* DB_MACHINE_COMMANDS */
145:
146: #if !MACH_KDP
147: void kdp_register_send_receive(void) {}
148: #endif
149:
150: extern jmp_buf_t *db_recover;
151: spl_t saved_ipl[NCPUS]; /* just to know what IPL was before trap */
152: struct ppc_saved_state *saved_state[NCPUS];
153:
154: /*
155: * kdb_trap - field a TRACE or BPT trap
156: */
157: void
158: kdb_trap(
159: int type,
160: struct ppc_saved_state *regs)
161: {
162: boolean_t trap_from_user;
163: int previous_console_device;
164: int code=0;
165:
166: previous_console_device=switch_to_serial_console();
167:
168: switch (type) {
169: case T_TRACE: /* single_step */
170: case T_PROGRAM: /* breakpoint */
171: #if 0
172: case T_WATCHPOINT: /* watchpoint */
173: #endif
174: case -1: /* keyboard interrupt */
175: break;
176:
177: default:
178: if (db_recover) {
179: ppc_nested_saved_state = *regs;
180: db_printf("Caught ");
181: if (type > TRAP_TYPES)
182: db_printf("type %d", type);
183: else
184: db_printf("%s", trap_type[type]);
185: db_printf(" trap, pc = %x\n",
186: regs->srr0);
187: db_error("");
188: /*NOTREACHED*/
189: }
190: kdbprinttrap(type, code, (int *)®s->srr0, regs->r1);
191: }
192:
193: saved_state[cpu_number()] = regs;
194:
195: ppc_last_saved_statep = regs;
196: ppc_last_kdb_sp = (unsigned) &type;
197:
198: if (!IS_USER_TRAP(regs)) {
199: bzero((char *)&ddb_regs, sizeof (ddb_regs));
200: ddb_regs = *regs;
201: trap_from_user = FALSE;
202:
203: }
204: else {
205: ddb_regs = *regs;
206: trap_from_user = TRUE;
207: }
208:
209: db_task_trap(type, code, trap_from_user);
210:
211: *regs = ddb_regs;
212:
213: if ((type == T_PROGRAM) &&
214: (db_get_task_value(regs->srr0,
215: BKPT_SIZE,
216: FALSE,
217: db_target_space(current_act(),
218: trap_from_user))
219: == BKPT_INST))
220: regs->srr0 += BKPT_SIZE;
221:
222: kdb_exit:
223: saved_state[cpu_number()] = 0;
224: switch_to_old_console(previous_console_device);
225:
226: }
227:
228:
229: /*
230: * Print trap reason.
231: */
232:
233: void
234: kdbprinttrap(
235: int type,
236: int code,
237: int *pc,
238: int sp)
239: {
240: printf("kernel: ");
241: if (type > TRAP_TYPES)
242: db_printf("type %d", type);
243: else
244: db_printf("%s", trap_type[type]);
245: db_printf(" trap, code=%x pc@%x = %x sp=%x\n",
246: code, pc, *(int *)pc, sp);
247: db_run_mode = STEP_CONTINUE;
248: }
249:
250: /*
251: *
252: */
253: vm_offset_t db_vtophys(
254: space_t space,
255: vm_offset_t va)
256: {
257: register mapping *mp;
258: register vm_offset_t pa;
259:
260: pa = (vm_offset_t)LRA(space,(void *)va);
261:
262: if (pa != 0)
263: return(pa);
264:
265: mp = hw_lock_phys_vir(space, va);
266: if((unsigned int)mp&1) {
267: return 0;
268: }
269:
270: if(!mp) {
271: return 0;
272: }
273:
274: mp = hw_cpv(mp); /* Convert to virtual address */
275:
276: if(!mp->physent) {
277: pa = (vm_offset_t)((mp->PTEr & -PAGE_SIZE) | ((unsigned int)va & (PAGE_SIZE-1)));
278: } else {
279: pa = (vm_offset_t)((mp->physent->pte1 & -PAGE_SIZE) | ((unsigned int)va & (PAGE_SIZE-1)));
280: hw_unlock_bit((unsigned int *)&mp->physent->phys_link, PHYS_LOCK);
281: }
282:
283: return(pa);
284: }
285:
286: int
287: db_user_to_kernel_address(
288: task_t task,
289: vm_offset_t addr,
290: unsigned *kaddr,
291: int flag)
292: {
293: unsigned int sr_val, raddr;
294:
295: raddr = (unsigned int)db_vtophys(task->map->pmap->space, trunc_page(addr)); /* Get the real address */
296:
297: if (!raddr) {
298: if (flag) {
299: db_printf("\nno memory is assigned to address %08x\n", addr);
300: db_error(0);
301: /* NOTREACHED */
302: }
303: return -1;
304: }
305: sr_val = SEG_REG_PROT | task->map->pmap->space
306: | ((addr >> 8) & 0x00F00000);
307:
308: mtsr(SR_COPYIN_NUM, sr_val);
309: sync();
310: *kaddr = (addr & 0x0fffffff) | (SR_COPYIN_NUM << 28);
311: return(0);
312: }
313:
314: /*
315: * Read bytes from task address space for debugger.
316: */
317: void
318: db_read_bytes(
319: vm_offset_t addr,
320: int size,
321: char *data,
322: task_t task)
323: {
324: int n,max;
325: unsigned phys_dst;
326: unsigned phys_src;
327: unsigned int space;
328:
329: while (size > 0) {
330: if (task != NULL)
331: space = task->map->pmap->space;
332: else
333: space = PPC_SID_KERNEL;
334:
335: phys_src = (unsigned int)db_vtophys(space, trunc_page(addr));
336: if (phys_src == 0) {
337: db_printf("\nno memory is assigned to src address %08x\n",
338: addr);
339: db_error(0);
340: /* NOTREACHED */
341: }
342: phys_src = phys_src| (addr & page_mask);
343:
344: space = PPC_SID_KERNEL;
345:
346: phys_dst = (unsigned int)db_vtophys(space, trunc_page(data));
347: if (phys_dst == 0) {
348: db_printf("\nno memory is assigned to dst address %08x\n",
349: data);
350: db_error(0);
351: /* NOTREACHED */
352: }
353:
354: phys_dst = phys_dst | (((vm_offset_t) data) & page_mask);
355:
356: /* don't over-run any page boundaries - check src range */
357: max = ppc_round_page(phys_src) - phys_src;
358: if (max > size)
359: max = size;
360: /* Check destination won't run over boundary either */
361: n = ppc_round_page(phys_dst) - phys_dst;
362: if (n < max)
363: max = n;
364: size -= max;
365: addr += max;
366: phys_copy(phys_src, phys_dst, max);
367:
368: /* resync I+D caches */
369: sync_cache(phys_dst, max);
370:
371: phys_src += max;
372: phys_dst += max;
373: }
374: }
375:
376: /*
377: * Write bytes to task address space for debugger.
378: */
379: void
380: db_write_bytes(
381: vm_offset_t addr,
382: int size,
383: char *data,
384: task_t task)
385: {
386: int n,max;
387: unsigned phys_dst;
388: unsigned phys_src;
389: unsigned int space;
390:
391: while (size > 0) {
392: space = PPC_SID_KERNEL;
393:
394: phys_src = (unsigned int)db_vtophys(space, trunc_page(data));
395: if (phys_src == 0) {
396: db_printf("\nno memory is assigned to src address %08x\n",
397: data);
398: db_error(0);
399: /* NOTREACHED */
400: }
401:
402: phys_src = phys_src | (((vm_offset_t) data) & page_mask);
403:
404: /* space stays as kernel space unless in another task */
405: if (task != NULL)
406: space = task->map->pmap->space;
407:
408: phys_dst = (unsigned int)db_vtophys(space, trunc_page(addr));
409: if (phys_dst == 0) {
410: db_printf("\nno memory is assigned to dst address %08x\n",
411: addr);
412: db_error(0);
413: /* NOTREACHED */
414: }
415: phys_dst = phys_dst| (addr & page_mask);
416:
417: /* don't over-run any page boundaries - check src range */
418: max = ppc_round_page(phys_src) - phys_src;
419: if (max > size)
420: max = size;
421: /* Check destination won't run over boundary either */
422: n = ppc_round_page(phys_dst) - phys_dst;
423: if (n < max)
424: max = n;
425: size -= max;
426: addr += max;
427: phys_copy(phys_src, phys_dst, max);
428:
429: /* resync I+D caches */
430: sync_cache(phys_dst, max);
431:
432: phys_src += max;
433: phys_dst += max;
434: }
435: }
436:
437: boolean_t
438: db_check_access(
439: vm_offset_t addr,
440: int size,
441: task_t task)
442: {
443: register int n;
444: unsigned int kern_addr;
445:
446: if (task == kernel_task || task == TASK_NULL) {
447: if (kernel_task == TASK_NULL)
448: return(TRUE);
449: task = kernel_task;
450: } else if (task == TASK_NULL) {
451: if (current_act() == THR_ACT_NULL)
452: return(FALSE);
453: task = current_act()->task;
454: }
455: while (size > 0) {
456: if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0)
457: return(FALSE);
458: n = ppc_trunc_page(addr+PPC_PGBYTES) - addr;
459: if (n > size)
460: n = size;
461: size -= n;
462: addr += n;
463: }
464: return(TRUE);
465: }
466:
467: boolean_t
468: db_phys_eq(
469: task_t task1,
470: vm_offset_t addr1,
471: task_t task2,
472: vm_offset_t addr2)
473: {
474: vm_offset_t *physa, *physb;
475:
476: if ((addr1 & (PPC_PGBYTES-1)) != (addr2 & (PPC_PGBYTES-1))) /* Is byte displacement the same? */
477: return FALSE;
478:
479: if (task1 == TASK_NULL) { /* See if there is a task active */
480: if (current_act() == THR_ACT_NULL) /* See if there is a current task */
481: return FALSE;
482: task1 = current_act()->task; /* If so, use that one */
483: }
484:
485: if(!(physa = db_vtophys(task1->map->pmap->space, trunc_page(addr1)))) return FALSE; /* Get real address of the first */
486: if(!(physb = db_vtophys(task2->map->pmap->space, trunc_page(addr2)))) return FALSE; /* Get real address of the second */
487:
488: return (physa == physb); /* Check if they are equal, then return... */
489: }
490:
491: #define DB_USER_STACK_ADDR (0xc0000000)
492: #define DB_NAME_SEARCH_LIMIT (DB_USER_STACK_ADDR-(PPC_PGBYTES*3))
493:
494: int
495: db_search_null(
496: task_t task,
497: unsigned *svaddr,
498: unsigned evaddr,
499: unsigned *skaddr,
500: int flag)
501: {
502: register unsigned vaddr;
503: register unsigned *kaddr;
504:
505: kaddr = (unsigned *)*skaddr;
506: for (vaddr = *svaddr; vaddr > evaddr; ) {
507: if (vaddr % PPC_PGBYTES == 0) {
508: vaddr -= sizeof(unsigned);
509: if (db_user_to_kernel_address(task, vaddr, skaddr, 0) < 0)
510: return(-1);
511: kaddr = (unsigned *)*skaddr;
512: } else {
513: vaddr -= sizeof(unsigned);
514: kaddr--;
515: }
516: if ((*kaddr == 0) ^ (flag == 0)) {
517: *svaddr = vaddr;
518: *skaddr = (unsigned)kaddr;
519: return(0);
520: }
521: }
522: return(-1);
523: }
524:
525: void
526: db_task_name(
527: task_t task)
528: {
529: register char *p;
530: register int n;
531: unsigned int vaddr, kaddr;
532:
533: vaddr = DB_USER_STACK_ADDR;
534: kaddr = 0;
535:
536: /*
537: * skip nulls at the end
538: */
539: if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 0) < 0) {
540: db_printf(DB_NULL_TASK_NAME);
541: return;
542: }
543: /*
544: * search start of args
545: */
546: if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 1) < 0) {
547: db_printf(DB_NULL_TASK_NAME);
548: return;
549: }
550:
551: n = DB_TASK_NAME_LEN-1;
552: p = (char *)kaddr + sizeof(unsigned);
553: for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR && n > 0;
554: vaddr++, p++, n--) {
555: if (vaddr % PPC_PGBYTES == 0) {
556: if (db_user_to_kernel_address(task, vaddr, &kaddr, 0) <0)
557: return;
558: p = (char*)kaddr;
559: }
560: db_printf("%c", (*p < ' ' || *p > '~')? ' ': *p);
561: }
562: while (n-- >= 0) /* compare with >= 0 for one more space */
563: db_printf(" ");
564: }
565:
566: void
567: db_machdep_init(void) {
568: #define KDB_READY 0x1
569: extern int kdb_flag;
570:
571: kdb_flag |= KDB_READY;
572: }
573:
574:
575: #ifdef __STDC__
576: #define KDB_SAVE(type, name) extern type name; type name##_save = name
577: #define KDB_RESTORE(name) name = name##_save
578: #else /* __STDC__ */
579: #define KDB_SAVE(type, name) extern type name; type name/**/_save = name
580: #define KDB_RESTORE(name) name = name/**/_save
581: #endif /* __STDC__ */
582:
583: #define KDB_SAVE_CTXT() \
584: KDB_SAVE(int, db_run_mode); \
585: KDB_SAVE(boolean_t, db_sstep_print); \
586: KDB_SAVE(int, db_loop_count); \
587: KDB_SAVE(int, db_call_depth); \
588: KDB_SAVE(int, db_inst_count); \
589: KDB_SAVE(int, db_last_inst_count); \
590: KDB_SAVE(int, db_load_count); \
591: KDB_SAVE(int, db_store_count); \
592: KDB_SAVE(boolean_t, db_cmd_loop_done); \
593: KDB_SAVE(jmp_buf_t *, db_recover); \
594: KDB_SAVE(db_addr_t, db_dot); \
595: KDB_SAVE(db_addr_t, db_last_addr); \
596: KDB_SAVE(db_addr_t, db_prev); \
597: KDB_SAVE(db_addr_t, db_next); \
598: KDB_SAVE(db_regs_t, ddb_regs);
599:
600: #define KDB_RESTORE_CTXT() \
601: KDB_RESTORE(db_run_mode); \
602: KDB_RESTORE(db_sstep_print); \
603: KDB_RESTORE(db_loop_count); \
604: KDB_RESTORE(db_call_depth); \
605: KDB_RESTORE(db_inst_count); \
606: KDB_RESTORE(db_last_inst_count); \
607: KDB_RESTORE(db_load_count); \
608: KDB_RESTORE(db_store_count); \
609: KDB_RESTORE(db_cmd_loop_done); \
610: KDB_RESTORE(db_recover); \
611: KDB_RESTORE(db_dot); \
612: KDB_RESTORE(db_last_addr); \
613: KDB_RESTORE(db_prev); \
614: KDB_RESTORE(db_next); \
615: KDB_RESTORE(ddb_regs);
616:
617: /*
618: * switch to another cpu
619: */
620: void
621: kdb_on(
622: int cpu)
623: {
624: KDB_SAVE_CTXT();
625: if (cpu < 0 || cpu >= NCPUS || !debugger_active[cpu])
626: return;
627: db_set_breakpoints();
628: db_set_watchpoints();
629: debugger_cpu = cpu;
630: unlock_debugger();
631: lock_debugger();
632: db_clear_breakpoints();
633: db_clear_watchpoints();
634: KDB_RESTORE_CTXT();
635: if (debugger_cpu == -1) {/* someone continued */
636: debugger_cpu = cpu_number();
637: db_continue_cmd(0, 0, 0, "");
638: }
639: }
640:
641: /*
642: * system reboot
643: */
644: void db_reboot(
645: db_expr_t addr,
646: boolean_t have_addr,
647: db_expr_t count,
648: char *modif)
649: {
650: boolean_t reboot = TRUE;
651: char *cp, c;
652:
653: cp = modif;
654: while ((c = *cp++) != 0) {
655: if (c == 'r') /* reboot */
656: reboot = TRUE;
657: if (c == 'h') /* halt */
658: reboot = FALSE;
659: }
660: halt_all_cpus(reboot);
661: }
662:
663: /*
664: * Switch to gdb
665: */
666: void
667: db_to_gdb(
668: void)
669: {
670: extern unsigned int switch_debugger;
671:
672: switch_debugger=1;
673: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.