1/* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31 32#include <platforms.h> 33#include <time_stamp.h> 34#include <mach_mp_debug.h> 35#include <mach_ldebug.h> 36#include <db_machine_commands.h> 37 38#include <kern/spl.h> 39#include <kern/cpu_number.h> 40#include <kern/kern_types.h> 41#include <kern/misc_protos.h> 42#include <vm/pmap.h> 43 44#include <ppc/mem.h> 45#include <ppc/db_machdep.h> 46#include <ppc/trap.h> 47#include <ppc/setjmp.h> 48#include <ppc/pmap.h> 49#include <ppc/misc_protos.h> 50#include <ppc/cpu_internal.h> 51#include <ppc/exception.h> 52#include <ppc/db_machdep.h> 53#include <ppc/mappings.h> 54#include <ppc/Firmware.h> 55#include <ppc/serial_io.h> /* for switch_to_serial_console */ 56 57#include <mach/vm_param.h> 58#include <mach/machine/vm_types.h> 59#include <vm/vm_map.h> 60#include <kern/thread.h> 61#include <kern/task.h> 62#include <kern/debug.h> 63#include <kern/machine.h> /* for halt_all_cpus() */ 64#include <pexpert/pexpert.h> 65#include <IOKit/IOPlatformExpert.h> 66 67#include <ddb/db_command.h> 68#include <ddb/db_task_thread.h> 69#include <ddb/db_run.h> 70#include <ddb/db_trap.h> 71#include <ddb/db_output.h> 72#include <ddb/db_access.h> 73#include <ddb/db_sym.h> 74#include <ddb/db_break.h> 75#include <ddb/db_watch.h> 76 77struct savearea *ppc_last_saved_statep; 78struct savearea ppc_nested_saved_state; 79unsigned ppc_last_kdb_sp; 80 81extern int debugger_cpu; /* Current cpu running debugger */ 82 83int db_all_set_up = 0; 84 85 86#if !MACH_KDP 87void kdp_register_send_receive(void); 88#endif 89 90/* 91 * Enter KDB through a keyboard trap. 92 * We show the registers as of the keyboard interrupt 93 * instead of those at its call to KDB. 94 */ 95struct int_regs { 96 /* XXX more registers ? */ 97 struct ppc_interrupt_state *is; 98}; 99 100extern int TRAP_TYPES; 101 102/* 103 * Code used to synchronize kdb among all cpus, one active at a time, switch 104 * from on to another using kdb_on! #cpu or cpu #cpu 105 */ 106 107decl_simple_lock_data(, kdb_lock) /* kdb lock */ 108 109#define db_simple_lock_init(l, e) hw_lock_init(&((l)->interlock)) 110#define db_simple_lock_try(l) hw_lock_try(&((l)->interlock)) 111#define db_simple_unlock(l) hw_lock_unlock(&((l)->interlock)) 112 113extern volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus holding 114 breakpoints (ie: cpus that did not 115 insert back breakpoints) */ 116extern boolean_t db_breakpoints_inserted; 117 118/* Forward */ 119 120extern void kdbprinttrap( 121 int type, 122 int code, 123 int *pc, 124 int sp); 125extern void db_write_bytes_user_space( 126 vm_offset_t addr, 127 int size, 128 char *data, 129 task_t task); 130extern int db_search_null( 131 task_t task, 132 unsigned *svaddr, 133 unsigned evaddr, 134 unsigned *skaddr, 135 int flag); 136extern int kdb_enter(int); 137extern void kdb_leave(void); 138extern void lock_kdb(void); 139extern void unlock_kdb(void); 140 141#if DB_MACHINE_COMMANDS 142struct db_command ppc_db_commands[] = { 143 { "lt", db_low_trace, CS_MORE|CS_SET_DOT, 0 }, 144 { (char *)0, 0, 0, 0 } 145}; 146#endif /* DB_MACHINE_COMMANDS */ 147 148#if !MACH_KDP 149void kdp_register_send_receive(void) {} 150#endif 151 152extern jmp_buf_t *db_recover; 153 154/* 155 * kdb_trap - field a TRACE or BPT trap 156 */ 157void 158kdb_trap( 159 int type, 160 struct savearea *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 = %llx\n", 186 regs->save_srr0); 187 db_error(""); 188 /*NOTREACHED*/ 189 } 190 kdbprinttrap(type, code, (int *)®s->save_srr0, regs->save_r1); 191 } 192 193 getPerProc()->db_saved_state = 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->save_srr0, 215 BKPT_SIZE, 216 FALSE, 217 db_target_space(current_thread(), 218 trap_from_user)) 219 == BKPT_INST)) 220 regs->save_srr0 += BKPT_SIZE; 221 222 getPerProc()->db_saved_state = 0; 223 switch_to_old_console(previous_console_device); 224 225} 226 227 228/* 229 * Print trap reason. 230 */ 231 232void 233kdbprinttrap( 234 int type, 235 int code, 236 int *pc, 237 int sp) 238{ 239 printf("kernel: "); 240 if (type > TRAP_TYPES) 241 db_printf("type %d", type); 242 else 243 db_printf("%s", trap_type[type]); 244 db_printf(" trap, code=%x pc@%x = %x sp=%x\n", 245 code, pc, *(int *)pc, sp); 246 db_run_mode = STEP_CONTINUE; 247} 248 249/* 250 * 251 */ 252static addr64_t 253db_vtophys(pmap_t pmap, vm_offset_t va) 254{ 255 ppnum_t pp; 256 addr64_t pa; 257 258 pp = pmap_find_phys(pmap, (addr64_t)va); 259 260 if (pp == 0) return(0); /* Couldn't find it */ 261 262 pa = ((addr64_t)pp << 12) | (addr64_t)(va & 0xFFF); /* Get physical address */ 263 264 return(pa); 265} 266 267/* 268 * Read bytes from task address space for debugger. 269 */ 270void 271db_read_bytes( 272 vm_offset_t addr, 273 int size, 274 char *data, 275 task_t task) 276{ 277 int n,max; 278 addr64_t phys_dst; 279 addr64_t phys_src; 280 pmap_t pmap; 281 282 while (size > 0) { 283 if (task != NULL) 284 pmap = task->map->pmap; 285 else 286 pmap = kernel_pmap; 287 288 phys_src = db_vtophys(pmap, (vm_offset_t)addr); 289 if (phys_src == 0) { 290 db_printf("\nno memory is assigned to src address %08x\n", 291 addr); 292 db_error(0); 293 /* NOTREACHED */ 294 } 295 296 phys_dst = db_vtophys(kernel_pmap, (vm_offset_t)data); 297 if (phys_dst == 0) { 298 db_printf("\nno memory is assigned to dst address %08x\n", 299 data); 300 db_error(0); 301 /* NOTREACHED */ 302 } 303 304 /* don't over-run any page boundaries - check src range */ 305 max = round_page_64(phys_src + 1) - phys_src; 306 if (max > size) 307 max = size; 308 /* Check destination won't run over boundary either */ 309 n = round_page_64(phys_dst + 1) - phys_dst; 310 311 if (n < max) max = n; 312 size -= max; 313 addr += max; 314 phys_copy(phys_src, phys_dst, max); 315 316 /* resync I+D caches */ 317 sync_cache64(phys_dst, max); 318 319 phys_src += max; 320 phys_dst += max; 321 } 322} 323 324/* 325 * Write bytes to task address space for debugger. 326 */ 327void 328db_write_bytes( 329 vm_offset_t addr, 330 int size, 331 char *data, 332 task_t task) 333{ 334 int n,max; 335 addr64_t phys_dst; 336 addr64_t phys_src; 337 pmap_t pmap; 338 339 while (size > 0) { 340 341 phys_src = db_vtophys(kernel_pmap, (vm_offset_t)data); 342 if (phys_src == 0) { 343 db_printf("\nno memory is assigned to src address %08x\n", 344 data); 345 db_error(0); 346 /* NOTREACHED */ 347 } 348 349 /* space stays as kernel space unless in another task */ 350 if (task == NULL) pmap = kernel_pmap; 351 else pmap = task->map->pmap; 352 353 phys_dst = db_vtophys(pmap, (vm_offset_t)addr); 354 if (phys_dst == 0) { 355 db_printf("\nno memory is assigned to dst address %08x\n", 356 addr); 357 db_error(0); 358 /* NOTREACHED */ 359 } 360 361 /* don't over-run any page boundaries - check src range */ 362 max = round_page_64(phys_src + 1) - phys_src; 363 if (max > size) 364 max = size; 365 /* Check destination won't run over boundary either */ 366 n = round_page_64(phys_dst + 1) - phys_dst; 367 if (n < max) 368 max = n; 369 size -= max; 370 addr += max; 371 phys_copy(phys_src, phys_dst, max); 372 373 /* resync I+D caches */ 374 sync_cache64(phys_dst, max); 375 376 phys_src += max; 377 phys_dst += max; 378 } 379} 380 381boolean_t 382db_check_access( 383 vm_offset_t addr, 384 int size, 385 task_t task) 386{ 387 register int n; 388 389 if (task == kernel_task || task == TASK_NULL) { 390 if (kernel_task == TASK_NULL) return(TRUE); 391 task = kernel_task; 392 } else if (task == TASK_NULL) { 393 if (current_thread() == THR_ACT_NULL) return(FALSE); 394 task = current_thread()->task; 395 } 396 397 while (size > 0) { 398 if(!pmap_find_phys(task->map->pmap, (addr64_t)addr)) return (FALSE); /* Fail if page not mapped */ 399 n = trunc_page_32(addr+PPC_PGBYTES) - addr; 400 if (n > size) 401 n = size; 402 size -= n; 403 addr += n; 404 } 405 return(TRUE); 406} 407 408boolean_t 409db_phys_eq( 410 task_t task1, 411 vm_offset_t addr1, 412 task_t task2, 413 vm_offset_t addr2) 414{ 415 addr64_t physa, physb; 416 417 if ((addr1 & (PPC_PGBYTES-1)) != (addr2 & (PPC_PGBYTES-1))) /* Is byte displacement the same? */ 418 return FALSE; 419 420 if (task1 == TASK_NULL) { /* See if there is a task active */ 421 if (current_thread() == THR_ACT_NULL) /* See if there is a current task */ 422 return FALSE; 423 task1 = current_thread()->task; /* If so, use that one */ 424 } 425 426 if(!(physa = db_vtophys(task1->map->pmap, (vm_offset_t)trunc_page_32(addr1)))) return FALSE; /* Get real address of the first */ 427 if(!(physb = db_vtophys(task2->map->pmap, (vm_offset_t)trunc_page_32(addr2)))) return FALSE; /* Get real address of the second */ 428 429 return (physa == physb); /* Check if they are equal, then return... */ 430} 431 432#define DB_USER_STACK_ADDR (0xc0000000) 433#define DB_NAME_SEARCH_LIMIT (DB_USER_STACK_ADDR-(PPC_PGBYTES*3)) 434 435boolean_t 436db_phys_cmp(__unused vm_offset_t a1, __unused vm_offset_t a2, 437 __unused vm_size_t s1) 438{ 439 db_printf("db_phys_cmp: not implemented\n"); 440 return 0; 441} 442 443 444int 445db_search_null(__unused task_t task, __unused unsigned *svaddr, 446 __unused unsigned evaddr, __unused unsigned *skaddr, 447 __unused int flag) 448{ 449 db_printf("db_search_null: not implemented\n"); 450 return(-1); 451} 452 453struct proc; 454unsigned char *getProcName(struct proc *proc); 455 456void 457db_task_name( 458 task_t task) 459{ 460 register unsigned char *p; 461 unsigned char tname[33]; 462 int i; 463 464 p = 0; 465 tname[0] = 0; 466 467 if(task->bsd_info) p = getProcName((struct proc *)(task->bsd_info)); /* Point to task name */ 468 469 if(p) { 470 for(i = 0; i < 32; i++) { /* Move no more than 32 bytes */ 471 tname[i] = p[i]; 472 if(p[i] == 0) break; 473 } 474 tname[i] = 0; 475 db_printf("%s", tname); 476 } 477 else db_printf("no name"); 478} 479 480extern int kdb_flag; 481void 482db_machdep_init(void) 483{ 484#define KDB_READY 0x1 485 kdb_flag |= KDB_READY; 486} 487 488 489#ifdef __STDC__ 490//#define KDB_SAVE(type, name) extern type name; type name##_save = name 491#define KDB_SAVE(type, name) type name##_save = name 492#define KDB_RESTORE(name) name = name##_save 493#else /* __STDC__ */ 494#define KDB_SAVE(type, name) type name/**/_save = name 495//#define KDB_SAVE(type, name) extern type name; type name/**/_save = name 496#define KDB_RESTORE(name) name = name/**/_save 497#endif /* __STDC__ */ 498 499#define KDB_SAVE_CTXT() \ 500 KDB_SAVE(int, db_run_mode); \ 501 KDB_SAVE(boolean_t, db_sstep_print); \ 502 KDB_SAVE(int, db_loop_count); \ 503 KDB_SAVE(int, db_call_depth); \ 504 KDB_SAVE(int, db_inst_count); \ 505 KDB_SAVE(int, db_last_inst_count); \ 506 KDB_SAVE(int, db_load_count); \ 507 KDB_SAVE(int, db_store_count); \ 508 KDB_SAVE(boolean_t, db_cmd_loop_done); \ 509 KDB_SAVE(jmp_buf_t *, db_recover); \ 510 KDB_SAVE(db_addr_t, db_dot); \ 511 KDB_SAVE(db_addr_t, db_last_addr); \ 512 KDB_SAVE(db_addr_t, db_prev); \ 513 KDB_SAVE(db_addr_t, db_next); \ 514 KDB_SAVE(db_regs_t, ddb_regs); 515 516#define KDB_RESTORE_CTXT() \ 517 KDB_RESTORE(db_run_mode); \ 518 KDB_RESTORE(db_sstep_print); \ 519 KDB_RESTORE(db_loop_count); \ 520 KDB_RESTORE(db_call_depth); \ 521 KDB_RESTORE(db_inst_count); \ 522 KDB_RESTORE(db_last_inst_count); \ 523 KDB_RESTORE(db_load_count); \ 524 KDB_RESTORE(db_store_count); \ 525 KDB_RESTORE(db_cmd_loop_done); \ 526 KDB_RESTORE(db_recover); \ 527 KDB_RESTORE(db_dot); \ 528 KDB_RESTORE(db_last_addr); \ 529 KDB_RESTORE(db_prev); \ 530 KDB_RESTORE(db_next); \ 531 KDB_RESTORE(ddb_regs); 532 533extern boolean_t db_sstep_print; 534extern int db_loop_count; 535extern int db_call_depth; 536extern int db_inst_count; 537extern int db_last_inst_count; 538extern int db_load_count; 539extern int db_store_count; 540extern boolean_t db_cmd_loop_done; 541extern void unlock_debugger(void); 542extern void lock_debugger(void); 543/* 544 * switch to another cpu 545 */ 546void 547kdb_on( 548 int cpu) 549{ 550 KDB_SAVE_CTXT(); 551 if (cpu < 0 || cpu >= (int)real_ncpus || !PerProcTable[cpu].ppe_vaddr->debugger_active) 552 return; 553 db_set_breakpoints(); 554 db_set_watchpoints(); 555 debugger_cpu = cpu; 556 unlock_debugger(); 557 lock_debugger(); 558 db_clear_breakpoints(); 559 db_clear_watchpoints(); 560 KDB_RESTORE_CTXT(); 561 if (debugger_cpu == -1) {/* someone continued */ 562 debugger_cpu = cpu_number(); 563 db_continue_cmd(0, 0, 0, NULL); 564 } 565} 566 567/* 568 * system reboot 569 */ 570 571void 572db_reboot(__unused db_expr_t addr, __unused boolean_t have_addr, 573 __unused db_expr_t count, char *modif) 574{ 575 boolean_t reboot = TRUE; 576 char *cp, c; 577 578 cp = modif; 579 while ((c = *cp++) != 0) { 580 if (c == 'r') /* reboot */ 581 reboot = TRUE; 582 if (c == 'h') /* halt */ 583 reboot = FALSE; 584 } 585 if(!reboot) halt_all_cpus(FALSE); /* If no reboot, try to be clean about it */ 586 587 if (PE_halt_restart) 588 (*PE_halt_restart)(kPERestartCPU); 589 db_printf("Sorry, system can't reboot automatically yet... You need to do it by hand...\n"); 590 591} 592