|
|
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: * Mach Operating System ! 27: * Copyright (c) 1991,1990 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: ! 53: /* ! 54: * Interface to new debugger. ! 55: */ ! 56: #include <cpus.h> ! 57: #include <platforms.h> ! 58: #include <time_stamp.h> ! 59: #include <mach_mp_debug.h> ! 60: #include <mach_ldebug.h> ! 61: #include <kern/spl.h> ! 62: #include <kern/cpu_number.h> ! 63: #include <kern/kern_types.h> ! 64: #include <kern/misc_protos.h> ! 65: #include <vm/pmap.h> ! 66: ! 67: #include <i386/thread.h> ! 68: #include <i386/db_machdep.h> ! 69: #include <i386/seg.h> ! 70: #include <i386/trap.h> ! 71: #include <i386/setjmp.h> ! 72: #include <i386/pmap.h> ! 73: #include <i386/misc_protos.h> ! 74: ! 75: #include <mach/vm_param.h> ! 76: #include <vm/vm_map.h> ! 77: #include <kern/thread.h> ! 78: #include <kern/task.h> ! 79: ! 80: #include <ddb/db_command.h> ! 81: #include <ddb/db_task_thread.h> ! 82: #include <ddb/db_run.h> ! 83: #include <ddb/db_trap.h> ! 84: #include <ddb/db_output.h> ! 85: #include <ddb/db_access.h> ! 86: #include <ddb/db_sym.h> ! 87: #include <ddb/db_break.h> ! 88: #include <ddb/db_watch.h> ! 89: ! 90: int db_active = 0; ! 91: int db_pass_thru[NCPUS]; ! 92: struct i386_saved_state *i386_last_saved_statep; ! 93: struct i386_saved_state i386_nested_saved_state; ! 94: unsigned i386_last_kdb_sp; ! 95: ! 96: vm_offset_t db_stacks[NCPUS]; ! 97: ! 98: extern thread_act_t db_default_act; ! 99: ! 100: #if MACH_MP_DEBUG ! 101: extern int masked_state_cnt[]; ! 102: #endif /* MACH_MP_DEBUG */ ! 103: ! 104: /* ! 105: * Enter KDB through a keyboard trap. ! 106: * We show the registers as of the keyboard interrupt ! 107: * instead of those at its call to KDB. ! 108: */ ! 109: struct int_regs { ! 110: int gs; ! 111: int fs; ! 112: int edi; ! 113: int esi; ! 114: int ebp; ! 115: int ebx; ! 116: struct i386_interrupt_state *is; ! 117: }; ! 118: ! 119: extern char * trap_type[]; ! 120: extern int TRAP_TYPES; ! 121: ! 122: /* Forward */ ! 123: ! 124: extern void kdbprinttrap( ! 125: int type, ! 126: int code, ! 127: int *pc, ! 128: int sp); ! 129: extern void kdb_kentry( ! 130: struct int_regs *int_regs); ! 131: extern int db_user_to_kernel_address( ! 132: task_t task, ! 133: vm_offset_t addr, ! 134: unsigned *kaddr, ! 135: int flag); ! 136: extern void db_write_bytes_user_space( ! 137: vm_offset_t addr, ! 138: int size, ! 139: char *data, ! 140: task_t task); ! 141: extern int db_search_null( ! 142: task_t task, ! 143: unsigned *svaddr, ! 144: unsigned evaddr, ! 145: unsigned *skaddr, ! 146: int flag); ! 147: extern int kdb_enter(int); ! 148: extern void kdb_leave(void); ! 149: extern void lock_kdb(void); ! 150: extern void unlock_kdb(void); ! 151: ! 152: /* ! 153: * kdb_trap - field a TRACE or BPT trap ! 154: */ ! 155: ! 156: ! 157: extern jmp_buf_t *db_recover; ! 158: spl_t saved_ipl[NCPUS]; /* just to know what IPL was before trap */ ! 159: struct i386_saved_state *saved_state[NCPUS]; ! 160: ! 161: /* ! 162: * Translate the state saved in a task state segment into an ! 163: * exception frame. Since we "know" we always want the state ! 164: * in a ktss, we hard-wire that in, rather than indexing the gdt ! 165: * with tss_sel to derive a pointer to the desired tss. ! 166: */ ! 167: void ! 168: db_tss_to_frame( ! 169: int tss_sel, ! 170: struct i386_saved_state *regs) ! 171: { ! 172: extern struct i386_tss ktss; ! 173: int mycpu = cpu_number(); ! 174: struct i386_tss *tss; ! 175: ! 176: #if NCPUS == 1 ! 177: tss = &ktss; /* XXX */ ! 178: #else /* NCPUS > 1 */ ! 179: tss = mp_ktss[mycpu]; /* XXX */ ! 180: #endif /* NCPUS > 1 */ ! 181: ! 182: /* ! 183: * ddb will overwrite whatever's in esp, so put esp0 elsewhere, too. ! 184: */ ! 185: regs->esp = tss->esp0; ! 186: regs->efl = tss->eflags; ! 187: regs->eip = tss->eip; ! 188: regs->trapno = tss->ss0; /* XXX */ ! 189: regs->err = tss->esp0; /* XXX */ ! 190: regs->eax = tss->eax; ! 191: regs->ecx = tss->ecx; ! 192: regs->edx = tss->edx; ! 193: regs->ebx = tss->ebx; ! 194: regs->uesp = tss->esp; ! 195: regs->ebp = tss->ebp; ! 196: regs->esi = tss->esi; ! 197: regs->edi = tss->edi; ! 198: regs->es = tss->es; ! 199: regs->ss = tss->ss; ! 200: regs->cs = tss->cs; ! 201: regs->ds = tss->ds; ! 202: regs->fs = tss->fs; ! 203: regs->gs = tss->gs; ! 204: } ! 205: ! 206: /* ! 207: * Compose a call to the debugger from the saved state in regs. (No ! 208: * reason not to do this in C.) ! 209: */ ! 210: boolean_t ! 211: db_trap_from_asm( ! 212: struct i386_saved_state *regs) ! 213: { ! 214: int code; ! 215: int type; ! 216: ! 217: type = regs->trapno; ! 218: code = regs->err; ! 219: return (kdb_trap(type, code, regs)); ! 220: } ! 221: ! 222: int ! 223: kdb_trap( ! 224: int type, ! 225: int code, ! 226: struct i386_saved_state *regs) ! 227: { ! 228: extern char etext; ! 229: boolean_t trap_from_user; ! 230: spl_t s = splhigh(); ! 231: ! 232: switch (type) { ! 233: case T_DEBUG: /* single_step */ ! 234: { ! 235: extern int dr_addr[]; ! 236: int addr; ! 237: int status = dr6(); ! 238: ! 239: if (status & 0xf) { /* hmm hdw break */ ! 240: addr = status & 0x8 ? dr_addr[3] : ! 241: status & 0x4 ? dr_addr[2] : ! 242: status & 0x2 ? dr_addr[1] : ! 243: dr_addr[0]; ! 244: regs->efl |= EFL_RF; ! 245: db_single_step_cmd(addr, 0, 1, "p"); ! 246: } ! 247: } ! 248: case T_INT3: /* breakpoint */ ! 249: case T_WATCHPOINT: /* watchpoint */ ! 250: case -1: /* keyboard interrupt */ ! 251: break; ! 252: ! 253: default: ! 254: if (db_recover) { ! 255: i386_nested_saved_state = *regs; ! 256: db_printf("Caught "); ! 257: if (type < 0 || type > TRAP_TYPES) ! 258: db_printf("type %d", type); ! 259: else ! 260: db_printf("%s", trap_type[type]); ! 261: db_printf(" trap, code = %x, pc = %x\n", ! 262: code, regs->eip); ! 263: splx(s); ! 264: db_error(""); ! 265: /*NOTREACHED*/ ! 266: } ! 267: kdbprinttrap(type, code, (int *)®s->eip, regs->uesp); ! 268: } ! 269: ! 270: #if NCPUS > 1 ! 271: disable_preemption(); ! 272: #endif /* NCPUS > 1 */ ! 273: ! 274: saved_ipl[cpu_number()] = s; ! 275: saved_state[cpu_number()] = regs; ! 276: ! 277: i386_last_saved_statep = regs; ! 278: i386_last_kdb_sp = (unsigned) &type; ! 279: ! 280: #if NCPUS > 1 ! 281: if (!kdb_enter(regs->eip)) ! 282: goto kdb_exit; ! 283: #endif /* NCPUS > 1 */ ! 284: ! 285: /* Should switch to kdb's own stack here. */ ! 286: ! 287: if (!IS_USER_TRAP(regs, &etext)) { ! 288: bzero((char *)&ddb_regs, sizeof (ddb_regs)); ! 289: *(struct i386_saved_state_from_kernel *)&ddb_regs = ! 290: *(struct i386_saved_state_from_kernel *)regs; ! 291: trap_from_user = FALSE; ! 292: } ! 293: else { ! 294: ddb_regs = *regs; ! 295: trap_from_user = TRUE; ! 296: } ! 297: if (!trap_from_user) { ! 298: /* ! 299: * Kernel mode - esp and ss not saved ! 300: */ ! 301: ddb_regs.uesp = (int)®s->uesp; /* kernel stack pointer */ ! 302: ddb_regs.ss = KERNEL_DS; ! 303: } ! 304: ! 305: db_active++; ! 306: db_task_trap(type, code, trap_from_user); ! 307: db_active--; ! 308: ! 309: regs->eip = ddb_regs.eip; ! 310: regs->efl = ddb_regs.efl; ! 311: regs->eax = ddb_regs.eax; ! 312: regs->ecx = ddb_regs.ecx; ! 313: regs->edx = ddb_regs.edx; ! 314: regs->ebx = ddb_regs.ebx; ! 315: if (trap_from_user) { ! 316: /* ! 317: * user mode - saved esp and ss valid ! 318: */ ! 319: regs->uesp = ddb_regs.uesp; /* user stack pointer */ ! 320: regs->ss = ddb_regs.ss & 0xffff; /* user stack segment */ ! 321: } ! 322: regs->ebp = ddb_regs.ebp; ! 323: regs->esi = ddb_regs.esi; ! 324: regs->edi = ddb_regs.edi; ! 325: regs->es = ddb_regs.es & 0xffff; ! 326: regs->cs = ddb_regs.cs & 0xffff; ! 327: regs->ds = ddb_regs.ds & 0xffff; ! 328: regs->fs = ddb_regs.fs & 0xffff; ! 329: regs->gs = ddb_regs.gs & 0xffff; ! 330: ! 331: if ((type == T_INT3) && ! 332: (db_get_task_value(regs->eip, ! 333: BKPT_SIZE, ! 334: FALSE, ! 335: db_target_space(current_act(), ! 336: trap_from_user)) ! 337: == BKPT_INST)) ! 338: regs->eip += BKPT_SIZE; ! 339: ! 340: #if NCPUS > 1 ! 341: kdb_exit: ! 342: kdb_leave(); ! 343: #endif /* NCPUS > 1 */ ! 344: ! 345: saved_state[cpu_number()] = 0; ! 346: ! 347: #if MACH_MP_DEBUG ! 348: masked_state_cnt[cpu_number()] = 0; ! 349: #endif /* MACH_MP_DEBUG */ ! 350: ! 351: #if NCPUS > 1 ! 352: enable_preemption(); ! 353: #endif /* NCPUS > 1 */ ! 354: ! 355: splx(s); ! 356: ! 357: /* Allow continue to upper layers of exception handling if ! 358: * trap was not a debugging trap. ! 359: */ ! 360: ! 361: if (trap_from_user && type != T_DEBUG && type != T_INT3 ! 362: && type != T_WATCHPOINT) ! 363: return 0; ! 364: else ! 365: return (1); ! 366: } ! 367: ! 368: /* ! 369: * Enter KDB through a keyboard trap. ! 370: * We show the registers as of the keyboard interrupt ! 371: * instead of those at its call to KDB. ! 372: */ ! 373: ! 374: spl_t kdb_oldspl; ! 375: ! 376: void ! 377: kdb_kentry( ! 378: struct int_regs *int_regs) ! 379: { ! 380: extern char etext; ! 381: boolean_t trap_from_user; ! 382: struct i386_interrupt_state *is = int_regs->is; ! 383: struct i386_saved_state regs; ! 384: spl_t s; ! 385: ! 386: s = splhigh(); ! 387: kdb_oldspl = s; ! 388: ! 389: if (IS_USER_TRAP(is, &etext)) ! 390: { ! 391: regs.uesp = ((int *)(is+1))[0]; ! 392: regs.ss = ((int *)(is+1))[1]; ! 393: } ! 394: else { ! 395: regs.ss = KERNEL_DS; ! 396: regs.uesp= (int)(is+1); ! 397: } ! 398: regs.efl = is->efl; ! 399: regs.cs = is->cs; ! 400: regs.eip = is->eip; ! 401: regs.eax = is->eax; ! 402: regs.ecx = is->ecx; ! 403: regs.edx = is->edx; ! 404: regs.ebx = int_regs->ebx; ! 405: regs.ebp = int_regs->ebp; ! 406: regs.esi = int_regs->esi; ! 407: regs.edi = int_regs->edi; ! 408: regs.ds = is->ds; ! 409: regs.es = is->es; ! 410: regs.fs = int_regs->fs; ! 411: regs.gs = int_regs->gs; ! 412: ! 413: #if NCPUS > 1 ! 414: disable_preemption(); ! 415: #endif /* NCPUS > 1 */ ! 416: ! 417: saved_state[cpu_number()] = ®s; ! 418: ! 419: #if NCPUS > 1 ! 420: if (!kdb_enter(regs.eip)) ! 421: goto kdb_exit; ! 422: #endif /* NCPUS > 1 */ ! 423: ! 424: bcopy((char *)®s, (char *)&ddb_regs, sizeof (ddb_regs)); ! 425: trap_from_user = IS_USER_TRAP(&ddb_regs, &etext); ! 426: ! 427: db_active++; ! 428: db_task_trap(-1, 0, trap_from_user); ! 429: db_active--; ! 430: ! 431: if (trap_from_user) { ! 432: ((int *)(is+1))[0] = ddb_regs.uesp; ! 433: ((int *)(is+1))[1] = ddb_regs.ss & 0xffff; ! 434: } ! 435: is->efl = ddb_regs.efl; ! 436: is->cs = ddb_regs.cs & 0xffff; ! 437: is->eip = ddb_regs.eip; ! 438: is->eax = ddb_regs.eax; ! 439: is->ecx = ddb_regs.ecx; ! 440: is->edx = ddb_regs.edx; ! 441: int_regs->ebx = ddb_regs.ebx; ! 442: int_regs->ebp = ddb_regs.ebp; ! 443: int_regs->esi = ddb_regs.esi; ! 444: int_regs->edi = ddb_regs.edi; ! 445: is->ds = ddb_regs.ds & 0xffff; ! 446: is->es = ddb_regs.es & 0xffff; ! 447: int_regs->fs = ddb_regs.fs & 0xffff; ! 448: int_regs->gs = ddb_regs.gs & 0xffff; ! 449: ! 450: #if NCPUS > 1 ! 451: kdb_exit: ! 452: kdb_leave(); ! 453: #endif /* NCPUS > 1 */ ! 454: saved_state[cpu_number()] = 0; ! 455: ! 456: #if NCPUS > 1 ! 457: enable_preemption(); ! 458: #endif /* NCPUS > 1 */ ! 459: ! 460: splx(s); ! 461: } ! 462: ! 463: /* ! 464: * Print trap reason. ! 465: */ ! 466: ! 467: void ! 468: kdbprinttrap( ! 469: int type, ! 470: int code, ! 471: int *pc, ! 472: int sp) ! 473: { ! 474: printf("kernel: "); ! 475: if (type < 0 || type > TRAP_TYPES) ! 476: db_printf("type %d", type); ! 477: else ! 478: db_printf("%s", trap_type[type]); ! 479: db_printf(" trap, code=%x eip@%x = %x esp=%x\n", ! 480: code, pc, *(int *)pc, sp); ! 481: db_run_mode = STEP_CONTINUE; ! 482: } ! 483: ! 484: int ! 485: db_user_to_kernel_address( ! 486: task_t task, ! 487: vm_offset_t addr, ! 488: unsigned *kaddr, ! 489: int flag) ! 490: { ! 491: register pt_entry_t *ptp; ! 492: ! 493: ptp = pmap_pte(task->map->pmap, addr); ! 494: if (ptp == PT_ENTRY_NULL || (*ptp & INTEL_PTE_VALID) == 0) { ! 495: if (flag) { ! 496: db_printf("\nno memory is assigned to address %08x\n", addr); ! 497: db_error(0); ! 498: /* NOTREACHED */ ! 499: } ! 500: return(-1); ! 501: } ! 502: *kaddr = (unsigned)ptetokv(*ptp) + (addr & (INTEL_PGBYTES-1)); ! 503: return(0); ! 504: } ! 505: ! 506: /* ! 507: * Read bytes from kernel address space for debugger. ! 508: */ ! 509: ! 510: void ! 511: db_read_bytes( ! 512: vm_offset_t addr, ! 513: int size, ! 514: char *data, ! 515: task_t task) ! 516: { ! 517: register char *src; ! 518: register int n; ! 519: unsigned kern_addr; ! 520: ! 521: src = (char *)addr; ! 522: if (task == kernel_task || task == TASK_NULL) { ! 523: while (--size >= 0) { ! 524: if (addr++ > VM_MAX_KERNEL_ADDRESS) { ! 525: db_printf("\nbad address %x\n", addr); ! 526: db_error(0); ! 527: /* NOTREACHED */ ! 528: } ! 529: *data++ = *src++; ! 530: } ! 531: return; ! 532: } ! 533: while (size > 0) { ! 534: if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0) ! 535: return; ! 536: src = (char *)kern_addr; ! 537: n = intel_trunc_page(addr+INTEL_PGBYTES) - addr; ! 538: if (n > size) ! 539: n = size; ! 540: size -= n; ! 541: addr += n; ! 542: while (--n >= 0) ! 543: *data++ = *src++; ! 544: } ! 545: } ! 546: ! 547: /* ! 548: * Write bytes to kernel address space for debugger. ! 549: */ ! 550: ! 551: void ! 552: db_write_bytes( ! 553: vm_offset_t addr, ! 554: int size, ! 555: char *data, ! 556: task_t task) ! 557: { ! 558: register char *dst; ! 559: ! 560: register pt_entry_t *ptep0 = 0; ! 561: pt_entry_t oldmap0 = 0; ! 562: vm_offset_t addr1; ! 563: register pt_entry_t *ptep1 = 0; ! 564: pt_entry_t oldmap1 = 0; ! 565: extern char etext; ! 566: ! 567: if (task && task != kernel_task) { ! 568: db_write_bytes_user_space(addr, size, data, task); ! 569: return; ! 570: } ! 571: ! 572: ! 573: if (addr >= VM_MIN_KERNEL_LOADED_ADDRESS) { ! 574: db_write_bytes_user_space(addr, size, data, kernel_task); ! 575: return; ! 576: } ! 577: ! 578: if (addr >= VM_MIN_KERNEL_ADDRESS && ! 579: addr <= (vm_offset_t)&etext) ! 580: { ! 581: ptep0 = pmap_pte(kernel_pmap, addr); ! 582: oldmap0 = *ptep0; ! 583: *ptep0 |= INTEL_PTE_WRITE; ! 584: ! 585: addr1 = i386_trunc_page(addr + size - 1); ! 586: if (i386_trunc_page(addr) != addr1) { ! 587: /* data crosses a page boundary */ ! 588: ! 589: ptep1 = pmap_pte(kernel_pmap, addr1); ! 590: oldmap1 = *ptep1; ! 591: *ptep1 |= INTEL_PTE_WRITE; ! 592: } ! 593: flush_tlb(); ! 594: } ! 595: ! 596: dst = (char *)addr; ! 597: ! 598: while (--size >= 0) { ! 599: if (addr++ > VM_MAX_KERNEL_ADDRESS) { ! 600: db_printf("\nbad address %x\n", addr); ! 601: db_error(0); ! 602: /* NOTREACHED */ ! 603: } ! 604: *dst++ = *data++; ! 605: } ! 606: ! 607: if (ptep0) { ! 608: *ptep0 = oldmap0; ! 609: if (ptep1) { ! 610: *ptep1 = oldmap1; ! 611: } ! 612: flush_tlb(); ! 613: } ! 614: } ! 615: ! 616: void ! 617: db_write_bytes_user_space( ! 618: vm_offset_t addr, ! 619: int size, ! 620: char *data, ! 621: task_t task) ! 622: { ! 623: register char *dst; ! 624: register int n; ! 625: unsigned kern_addr; ! 626: ! 627: while (size > 0) { ! 628: if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0) ! 629: return; ! 630: dst = (char *)kern_addr; ! 631: n = intel_trunc_page(addr+INTEL_PGBYTES) - addr; ! 632: if (n > size) ! 633: n = size; ! 634: size -= n; ! 635: addr += n; ! 636: while (--n >= 0) ! 637: *dst++ = *data++; ! 638: } ! 639: } ! 640: ! 641: boolean_t ! 642: db_check_access( ! 643: vm_offset_t addr, ! 644: int size, ! 645: task_t task) ! 646: { ! 647: register n; ! 648: unsigned kern_addr; ! 649: ! 650: if (task == kernel_task || task == TASK_NULL) { ! 651: if (kernel_task == TASK_NULL) ! 652: return(TRUE); ! 653: task = kernel_task; ! 654: } else if (task == TASK_NULL) { ! 655: if (current_act() == THR_ACT_NULL) ! 656: return(FALSE); ! 657: task = current_act()->task; ! 658: } ! 659: while (size > 0) { ! 660: if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0) ! 661: return(FALSE); ! 662: n = intel_trunc_page(addr+INTEL_PGBYTES) - addr; ! 663: if (n > size) ! 664: n = size; ! 665: size -= n; ! 666: addr += n; ! 667: } ! 668: return(TRUE); ! 669: } ! 670: ! 671: boolean_t ! 672: db_phys_eq( ! 673: task_t task1, ! 674: vm_offset_t addr1, ! 675: task_t task2, ! 676: vm_offset_t addr2) ! 677: { ! 678: unsigned kern_addr1, kern_addr2; ! 679: ! 680: if ((addr1 & (INTEL_PGBYTES-1)) != (addr2 & (INTEL_PGBYTES-1))) ! 681: return(FALSE); ! 682: if (task1 == TASK_NULL) { ! 683: if (current_act() == THR_ACT_NULL) ! 684: return(FALSE); ! 685: task1 = current_act()->task; ! 686: } ! 687: if (db_user_to_kernel_address(task1, addr1, &kern_addr1, 0) < 0 || ! 688: db_user_to_kernel_address(task2, addr2, &kern_addr2, 0) < 0) ! 689: return(FALSE); ! 690: return(kern_addr1 == kern_addr2); ! 691: } ! 692: ! 693: #define DB_USER_STACK_ADDR (VM_MIN_KERNEL_ADDRESS) ! 694: #define DB_NAME_SEARCH_LIMIT (DB_USER_STACK_ADDR-(INTEL_PGBYTES*3)) ! 695: ! 696: int ! 697: db_search_null( ! 698: task_t task, ! 699: unsigned *svaddr, ! 700: unsigned evaddr, ! 701: unsigned *skaddr, ! 702: int flag) ! 703: { ! 704: register unsigned vaddr; ! 705: register unsigned *kaddr; ! 706: ! 707: kaddr = (unsigned *)*skaddr; ! 708: for (vaddr = *svaddr; vaddr > evaddr; vaddr -= sizeof(unsigned)) { ! 709: if (vaddr % INTEL_PGBYTES == 0) { ! 710: vaddr -= sizeof(unsigned); ! 711: if (db_user_to_kernel_address(task, vaddr, skaddr, 0) < 0) ! 712: return(-1); ! 713: kaddr = (unsigned *)*skaddr; ! 714: } else { ! 715: vaddr -= sizeof(unsigned); ! 716: kaddr--; ! 717: } ! 718: if ((*kaddr == 0) ^ (flag == 0)) { ! 719: *svaddr = vaddr; ! 720: *skaddr = (unsigned)kaddr; ! 721: return(0); ! 722: } ! 723: } ! 724: return(-1); ! 725: } ! 726: ! 727: void ! 728: db_task_name( ! 729: task_t task) ! 730: { ! 731: register char *p; ! 732: register n; ! 733: unsigned vaddr, kaddr; ! 734: ! 735: vaddr = DB_USER_STACK_ADDR; ! 736: kaddr = 0; ! 737: ! 738: /* ! 739: * skip nulls at the end ! 740: */ ! 741: if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 0) < 0) { ! 742: db_printf(DB_NULL_TASK_NAME); ! 743: return; ! 744: } ! 745: /* ! 746: * search start of args ! 747: */ ! 748: if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 1) < 0) { ! 749: db_printf(DB_NULL_TASK_NAME); ! 750: return; ! 751: } ! 752: ! 753: n = DB_TASK_NAME_LEN-1; ! 754: p = (char *)kaddr + sizeof(unsigned); ! 755: for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR && n > 0; ! 756: vaddr++, p++, n--) { ! 757: if (vaddr % INTEL_PGBYTES == 0) { ! 758: (void)db_user_to_kernel_address(task, vaddr, &kaddr, 0); ! 759: p = (char*)kaddr; ! 760: } ! 761: db_printf("%c", (*p < ' ' || *p > '~')? ' ': *p); ! 762: } ! 763: while (n-- >= 0) /* compare with >= 0 for one more space */ ! 764: db_printf(" "); ! 765: } ! 766: ! 767: #if NCPUS == 1 ! 768: ! 769: void ! 770: db_machdep_init(void) ! 771: { ! 772: db_stacks[0] = (vm_offset_t)(db_stack_store + ! 773: INTSTACK_SIZE - sizeof (natural_t)); ! 774: dbtss.esp0 = (int)(db_task_stack_store + ! 775: INTSTACK_SIZE - sizeof (natural_t)); ! 776: dbtss.esp = dbtss.esp0; ! 777: dbtss.eip = (int)&db_task_start; ! 778: } ! 779: ! 780: #else /* NCPUS > 1 */ ! 781: ! 782: /* ! 783: * Code used to synchronize kdb among all cpus, one active at a time, switch ! 784: * from on to another using kdb_on! #cpu or cpu #cpu ! 785: */ ! 786: ! 787: decl_simple_lock_data(, kdb_lock) /* kdb lock */ ! 788: ! 789: #define db_simple_lock_init(l, e) hw_lock_init(&((l)->interlock)) ! 790: #define db_simple_lock_try(l) hw_lock_try(&((l)->interlock)) ! 791: #define db_simple_unlock(l) hw_lock_unlock(&((l)->interlock)) ! 792: ! 793: int kdb_cpu = -1; /* current cpu running kdb */ ! 794: int kdb_debug = 0; ! 795: int kdb_is_slave[NCPUS]; ! 796: int kdb_active[NCPUS]; ! 797: volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus holding ! 798: breakpoints (ie: cpus that did not ! 799: insert back breakpoints) */ ! 800: extern boolean_t db_breakpoints_inserted; ! 801: ! 802: void ! 803: db_machdep_init(void) ! 804: { ! 805: int c; ! 806: ! 807: db_simple_lock_init(&kdb_lock, ETAP_MISC_KDB); ! 808: for (c = 0; c < NCPUS; ++c) { ! 809: db_stacks[c] = (vm_offset_t) (db_stack_store + ! 810: (INTSTACK_SIZE * (c + 1)) - sizeof (natural_t)); ! 811: if (c == master_cpu) { ! 812: dbtss.esp0 = (int)(db_task_stack_store + ! 813: (INTSTACK_SIZE * (c + 1)) - sizeof (natural_t)); ! 814: dbtss.esp = dbtss.esp0; ! 815: dbtss.eip = (int)&db_task_start; ! 816: /* ! 817: * The TSS for the debugging task on each slave CPU ! 818: * is set up in mp_desc_init(). ! 819: */ ! 820: } ! 821: } ! 822: } ! 823: ! 824: /* ! 825: * Called when entering kdb: ! 826: * Takes kdb lock. If if we were called remotely (slave state) we just ! 827: * wait for kdb_cpu to be equal to cpu_number(). Otherwise enter kdb if ! 828: * not active on another cpu. ! 829: * If db_pass_thru[cpu_number()] > 0, then kdb can't stop now. ! 830: */ ! 831: ! 832: int ! 833: kdb_enter(int pc) ! 834: { ! 835: int my_cpu; ! 836: int retval; ! 837: ! 838: #if NCPUS > 1 ! 839: disable_preemption(); ! 840: #endif /* NCPUS > 1 */ ! 841: ! 842: my_cpu = cpu_number(); ! 843: ! 844: if (db_pass_thru[my_cpu]) { ! 845: retval = 0; ! 846: goto kdb_exit; ! 847: } ! 848: ! 849: kdb_active[my_cpu]++; ! 850: lock_kdb(); ! 851: ! 852: if (kdb_debug) ! 853: db_printf("kdb_enter: cpu %d, is_slave %d, kdb_cpu %d, run mode %d pc %x (%x) holds %d\n", ! 854: my_cpu, kdb_is_slave[my_cpu], kdb_cpu, ! 855: db_run_mode, pc, *(int *)pc, cpus_holding_bkpts); ! 856: if (db_breakpoints_inserted) ! 857: cpus_holding_bkpts++; ! 858: if (kdb_cpu == -1 && !kdb_is_slave[my_cpu]) { ! 859: kdb_cpu = my_cpu; ! 860: remote_kdb(); /* stop other cpus */ ! 861: retval = 1; ! 862: } else if (kdb_cpu == my_cpu) ! 863: retval = 1; ! 864: else ! 865: retval = 0; ! 866: ! 867: kdb_exit: ! 868: #if NCPUS > 1 ! 869: enable_preemption(); ! 870: #endif /* NCPUS > 1 */ ! 871: ! 872: return (retval); ! 873: } ! 874: ! 875: void ! 876: kdb_leave(void) ! 877: { ! 878: int my_cpu; ! 879: boolean_t wait = FALSE; ! 880: ! 881: #if NCPUS > 1 ! 882: disable_preemption(); ! 883: #endif /* NCPUS > 1 */ ! 884: ! 885: my_cpu = cpu_number(); ! 886: ! 887: if (db_run_mode == STEP_CONTINUE) { ! 888: wait = TRUE; ! 889: kdb_cpu = -1; ! 890: } ! 891: if (db_breakpoints_inserted) ! 892: cpus_holding_bkpts--; ! 893: if (kdb_is_slave[my_cpu]) ! 894: kdb_is_slave[my_cpu]--; ! 895: if (kdb_debug) ! 896: db_printf("kdb_leave: cpu %d, kdb_cpu %d, run_mode %d pc %x (%x) holds %d\n", ! 897: my_cpu, kdb_cpu, db_run_mode, ! 898: ddb_regs.eip, *(int *)ddb_regs.eip, ! 899: cpus_holding_bkpts); ! 900: clear_kdb_intr(); ! 901: unlock_kdb(); ! 902: kdb_active[my_cpu]--; ! 903: ! 904: #if NCPUS > 1 ! 905: enable_preemption(); ! 906: #endif /* NCPUS > 1 */ ! 907: ! 908: if (wait) { ! 909: while(cpus_holding_bkpts); ! 910: } ! 911: } ! 912: ! 913: void ! 914: lock_kdb(void) ! 915: { ! 916: int my_cpu; ! 917: register i; ! 918: extern void kdb_console(void); ! 919: ! 920: #if NCPUS > 1 ! 921: disable_preemption(); ! 922: #endif /* NCPUS > 1 */ ! 923: ! 924: my_cpu = cpu_number(); ! 925: ! 926: for(;;) { ! 927: kdb_console(); ! 928: if (kdb_cpu != -1 && kdb_cpu != my_cpu) { ! 929: continue; ! 930: } ! 931: if (db_simple_lock_try(&kdb_lock)) { ! 932: if (kdb_cpu == -1 || kdb_cpu == my_cpu) ! 933: break; ! 934: db_simple_unlock(&kdb_lock); ! 935: } ! 936: } ! 937: ! 938: #if NCPUS > 1 ! 939: enable_preemption(); ! 940: #endif /* NCPUS > 1 */ ! 941: } ! 942: ! 943: #if TIME_STAMP ! 944: extern unsigned old_time_stamp; ! 945: #endif /* TIME_STAMP */ ! 946: ! 947: void ! 948: unlock_kdb(void) ! 949: { ! 950: db_simple_unlock(&kdb_lock); ! 951: #if TIME_STAMP ! 952: old_time_stamp = 0; ! 953: #endif /* TIME_STAMP */ ! 954: } ! 955: ! 956: ! 957: #ifdef __STDC__ ! 958: #define KDB_SAVE(type, name) extern type name; type name##_save = name ! 959: #define KDB_RESTORE(name) name = name##_save ! 960: #else /* __STDC__ */ ! 961: #define KDB_SAVE(type, name) extern type name; type name/**/_save = name ! 962: #define KDB_RESTORE(name) name = name/**/_save ! 963: #endif /* __STDC__ */ ! 964: ! 965: #define KDB_SAVE_CTXT() \ ! 966: KDB_SAVE(int, db_run_mode); \ ! 967: KDB_SAVE(boolean_t, db_sstep_print); \ ! 968: KDB_SAVE(int, db_loop_count); \ ! 969: KDB_SAVE(int, db_call_depth); \ ! 970: KDB_SAVE(int, db_inst_count); \ ! 971: KDB_SAVE(int, db_last_inst_count); \ ! 972: KDB_SAVE(int, db_load_count); \ ! 973: KDB_SAVE(int, db_store_count); \ ! 974: KDB_SAVE(boolean_t, db_cmd_loop_done); \ ! 975: KDB_SAVE(jmp_buf_t *, db_recover); \ ! 976: KDB_SAVE(db_addr_t, db_dot); \ ! 977: KDB_SAVE(db_addr_t, db_last_addr); \ ! 978: KDB_SAVE(db_addr_t, db_prev); \ ! 979: KDB_SAVE(db_addr_t, db_next); \ ! 980: KDB_SAVE(db_regs_t, ddb_regs); ! 981: ! 982: #define KDB_RESTORE_CTXT() \ ! 983: KDB_RESTORE(db_run_mode); \ ! 984: KDB_RESTORE(db_sstep_print); \ ! 985: KDB_RESTORE(db_loop_count); \ ! 986: KDB_RESTORE(db_call_depth); \ ! 987: KDB_RESTORE(db_inst_count); \ ! 988: KDB_RESTORE(db_last_inst_count); \ ! 989: KDB_RESTORE(db_load_count); \ ! 990: KDB_RESTORE(db_store_count); \ ! 991: KDB_RESTORE(db_cmd_loop_done); \ ! 992: KDB_RESTORE(db_recover); \ ! 993: KDB_RESTORE(db_dot); \ ! 994: KDB_RESTORE(db_last_addr); \ ! 995: KDB_RESTORE(db_prev); \ ! 996: KDB_RESTORE(db_next); \ ! 997: KDB_RESTORE(ddb_regs); ! 998: ! 999: /* ! 1000: * switch to another cpu ! 1001: */ ! 1002: ! 1003: void ! 1004: kdb_on( ! 1005: int cpu) ! 1006: { ! 1007: KDB_SAVE_CTXT(); ! 1008: if (cpu < 0 || cpu >= NCPUS || !kdb_active[cpu]) ! 1009: return; ! 1010: db_set_breakpoints(); ! 1011: db_set_watchpoints(); ! 1012: kdb_cpu = cpu; ! 1013: unlock_kdb(); ! 1014: lock_kdb(); ! 1015: db_clear_breakpoints(); ! 1016: db_clear_watchpoints(); ! 1017: KDB_RESTORE_CTXT(); ! 1018: if (kdb_cpu == -1) {/* someone continued */ ! 1019: kdb_cpu = cpu_number(); ! 1020: db_continue_cmd(0, 0, 0, ""); ! 1021: } ! 1022: } ! 1023: ! 1024: #endif /* NCPUS > 1 */ ! 1025: ! 1026: void db_reboot( ! 1027: db_expr_t addr, ! 1028: boolean_t have_addr, ! 1029: db_expr_t count, ! 1030: char *modif) ! 1031: { ! 1032: boolean_t reboot = TRUE; ! 1033: char *cp, c; ! 1034: ! 1035: cp = modif; ! 1036: while ((c = *cp++) != 0) { ! 1037: if (c == 'r') /* reboot */ ! 1038: reboot = TRUE; ! 1039: if (c == 'h') /* halt */ ! 1040: reboot = FALSE; ! 1041: } ! 1042: halt_all_cpus(reboot); ! 1043: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.