subr_kdb.c revision 228424
1139804Simp/*- 2131903Smarcel * Copyright (c) 2004 The FreeBSD Project 3131903Smarcel * All rights reserved. 4131903Smarcel * 5131903Smarcel * Redistribution and use in source and binary forms, with or without 6131903Smarcel * modification, are permitted provided that the following conditions 7131903Smarcel * are met: 8131903Smarcel * 9131903Smarcel * 1. Redistributions of source code must retain the above copyright 10131903Smarcel * notice, this list of conditions and the following disclaimer. 11131903Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12131903Smarcel * notice, this list of conditions and the following disclaimer in the 13131903Smarcel * documentation and/or other materials provided with the distribution. 14131903Smarcel * 15131903Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16131903Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17131903Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18131903Smarcel * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19131903Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20131903Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21131903Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22131903Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23131903Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24131903Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25131903Smarcel */ 26131903Smarcel 27131903Smarcel#include <sys/cdefs.h> 28131903Smarcel__FBSDID("$FreeBSD: head/sys/kern/subr_kdb.c 228424 2011-12-11 21:02:01Z avg $"); 29131903Smarcel 30147674Speter#include "opt_kdb.h" 31212964Savg#include "opt_stack.h" 32147674Speter 33131903Smarcel#include <sys/param.h> 34131903Smarcel#include <sys/systm.h> 35131903Smarcel#include <sys/kdb.h> 36131903Smarcel#include <sys/kernel.h> 37131903Smarcel#include <sys/malloc.h> 38131903Smarcel#include <sys/pcpu.h> 39131903Smarcel#include <sys/proc.h> 40218825Smdf#include <sys/sbuf.h> 41131903Smarcel#include <sys/smp.h> 42212964Savg#include <sys/stack.h> 43131903Smarcel#include <sys/sysctl.h> 44131903Smarcel 45131903Smarcel#include <machine/kdb.h> 46131903Smarcel#include <machine/pcb.h> 47131903Smarcel 48151634Sjhb#ifdef SMP 49145727Sdwhite#include <machine/smp.h> 50145727Sdwhite#endif 51145727Sdwhite 52131903Smarcelint kdb_active = 0; 53191948Simpstatic void *kdb_jmpbufp = NULL; 54131903Smarcelstruct kdb_dbbe *kdb_dbbe = NULL; 55191948Simpstatic struct pcb kdb_pcb; 56131903Smarcelstruct pcb *kdb_thrctx = NULL; 57131903Smarcelstruct thread *kdb_thread = NULL; 58131903Smarcelstruct trapframe *kdb_frame = NULL; 59131903Smarcel 60225203Srwatson#ifdef BREAK_TO_DEBUGGER 61225203Srwatson#define KDB_BREAK_TO_DEBUGGER 1 62225203Srwatson#else 63225203Srwatson#define KDB_BREAK_TO_DEBUGGER 0 64225203Srwatson#endif 65225203Srwatson 66225203Srwatson#ifdef ALT_BREAK_TO_DEBUGGER 67225203Srwatson#define KDB_ALT_BREAK_TO_DEBUGGER 1 68225203Srwatson#else 69225203Srwatson#define KDB_ALT_BREAK_TO_DEBUGGER 0 70225203Srwatson#endif 71225203Srwatson 72225203Srwatsonstatic int kdb_break_to_debugger = KDB_BREAK_TO_DEBUGGER; 73225203Srwatsonstatic int kdb_alt_break_to_debugger = KDB_ALT_BREAK_TO_DEBUGGER; 74225203Srwatson 75131903SmarcelKDB_BACKEND(null, NULL, NULL, NULL); 76131903SmarcelSET_DECLARE(kdb_dbbe_set, struct kdb_dbbe); 77131903Smarcel 78131903Smarcelstatic int kdb_sysctl_available(SYSCTL_HANDLER_ARGS); 79131903Smarcelstatic int kdb_sysctl_current(SYSCTL_HANDLER_ARGS); 80131903Smarcelstatic int kdb_sysctl_enter(SYSCTL_HANDLER_ARGS); 81151725Speterstatic int kdb_sysctl_panic(SYSCTL_HANDLER_ARGS); 82151725Speterstatic int kdb_sysctl_trap(SYSCTL_HANDLER_ARGS); 83159726Syarstatic int kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS); 84131903Smarcel 85227309Sedstatic SYSCTL_NODE(_debug, OID_AUTO, kdb, CTLFLAG_RW, NULL, "KDB nodes"); 86131903Smarcel 87191948SimpSYSCTL_PROC(_debug_kdb, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, NULL, 88191948Simp 0, kdb_sysctl_available, "A", "list of available KDB backends"); 89131903Smarcel 90191948SimpSYSCTL_PROC(_debug_kdb, OID_AUTO, current, CTLTYPE_STRING | CTLFLAG_RW, NULL, 91191948Simp 0, kdb_sysctl_current, "A", "currently selected KDB backend"); 92131903Smarcel 93226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, enter, 94226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 95131903Smarcel kdb_sysctl_enter, "I", "set to enter the debugger"); 96131903Smarcel 97226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, panic, 98226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 99151725Speter kdb_sysctl_panic, "I", "set to panic the kernel"); 100151725Speter 101226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, trap, 102226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 103159726Syar kdb_sysctl_trap, "I", "set to cause a page fault via data access"); 104151725Speter 105226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, 106226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 107159726Syar kdb_sysctl_trap_code, "I", "set to cause a page fault via code access"); 108159726Syar 109226089SobrienSYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger, 110226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_TUN | CTLFLAG_SECURE, 111226089Sobrien &kdb_break_to_debugger, 0, "Enable break to debugger"); 112225203SrwatsonTUNABLE_INT("debug.kdb.break_to_debugger", &kdb_break_to_debugger); 113225203Srwatson 114226089SobrienSYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger, 115226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_TUN | CTLFLAG_SECURE, 116226089Sobrien &kdb_alt_break_to_debugger, 0, "Enable alternative break to debugger"); 117225203SrwatsonTUNABLE_INT("debug.kdb.alt_break_to_debugger", &kdb_alt_break_to_debugger); 118225203Srwatson 119133737Srwatson/* 120174898Srwatson * Flag to indicate to debuggers why the debugger was entered. 121174898Srwatson */ 122174898Srwatsonconst char * volatile kdb_why = KDB_WHY_UNSET; 123174898Srwatson 124131903Smarcelstatic int 125131903Smarcelkdb_sysctl_available(SYSCTL_HANDLER_ARGS) 126131903Smarcel{ 127218825Smdf struct kdb_dbbe **iter; 128218825Smdf struct sbuf sbuf; 129131903Smarcel int error; 130131903Smarcel 131218825Smdf sbuf_new_for_sysctl(&sbuf, NULL, 64, req); 132131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 133218825Smdf if ((*iter)->dbbe_active == 0) 134218825Smdf sbuf_printf(&sbuf, "%s ", (*iter)->dbbe_name); 135131903Smarcel } 136218825Smdf error = sbuf_finish(&sbuf); 137218825Smdf sbuf_delete(&sbuf); 138131903Smarcel return (error); 139131903Smarcel} 140131903Smarcel 141131903Smarcelstatic int 142131903Smarcelkdb_sysctl_current(SYSCTL_HANDLER_ARGS) 143131903Smarcel{ 144131903Smarcel char buf[16]; 145131903Smarcel int error; 146131903Smarcel 147218825Smdf if (kdb_dbbe != NULL) 148218825Smdf strlcpy(buf, kdb_dbbe->dbbe_name, sizeof(buf)); 149218825Smdf else 150131982Smarcel *buf = '\0'; 151131903Smarcel error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 152131903Smarcel if (error != 0 || req->newptr == NULL) 153131903Smarcel return (error); 154131903Smarcel if (kdb_active) 155131903Smarcel return (EBUSY); 156132001Smarcel return (kdb_dbbe_select(buf)); 157131903Smarcel} 158131903Smarcel 159131903Smarcelstatic int 160131903Smarcelkdb_sysctl_enter(SYSCTL_HANDLER_ARGS) 161131903Smarcel{ 162131903Smarcel int error, i; 163131903Smarcel 164131903Smarcel error = sysctl_wire_old_buffer(req, sizeof(int)); 165131903Smarcel if (error == 0) { 166131903Smarcel i = 0; 167131903Smarcel error = sysctl_handle_int(oidp, &i, 0, req); 168131903Smarcel } 169131903Smarcel if (error != 0 || req->newptr == NULL) 170131903Smarcel return (error); 171131903Smarcel if (kdb_active) 172131903Smarcel return (EBUSY); 173174898Srwatson kdb_enter(KDB_WHY_SYSCTL, "sysctl debug.kdb.enter"); 174131903Smarcel return (0); 175131903Smarcel} 176131903Smarcel 177151725Speterstatic int 178151725Speterkdb_sysctl_panic(SYSCTL_HANDLER_ARGS) 179151725Speter{ 180151725Speter int error, i; 181151725Speter 182151725Speter error = sysctl_wire_old_buffer(req, sizeof(int)); 183151725Speter if (error == 0) { 184151725Speter i = 0; 185151725Speter error = sysctl_handle_int(oidp, &i, 0, req); 186151725Speter } 187151725Speter if (error != 0 || req->newptr == NULL) 188151725Speter return (error); 189151725Speter panic("kdb_sysctl_panic"); 190151725Speter return (0); 191151725Speter} 192151725Speter 193151725Speterstatic int 194151725Speterkdb_sysctl_trap(SYSCTL_HANDLER_ARGS) 195151725Speter{ 196151725Speter int error, i; 197151725Speter int *addr = (int *)0x10; 198151725Speter 199151725Speter error = sysctl_wire_old_buffer(req, sizeof(int)); 200151725Speter if (error == 0) { 201151725Speter i = 0; 202151725Speter error = sysctl_handle_int(oidp, &i, 0, req); 203151725Speter } 204151725Speter if (error != 0 || req->newptr == NULL) 205151725Speter return (error); 206151725Speter return (*addr); 207151725Speter} 208151725Speter 209159726Syarstatic int 210159726Syarkdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS) 211159726Syar{ 212159726Syar int error, i; 213159726Syar void (*fp)(u_int, u_int, u_int) = (void *)0xdeadc0de; 214159726Syar 215159726Syar error = sysctl_wire_old_buffer(req, sizeof(int)); 216159726Syar if (error == 0) { 217159726Syar i = 0; 218159726Syar error = sysctl_handle_int(oidp, &i, 0, req); 219159726Syar } 220159726Syar if (error != 0 || req->newptr == NULL) 221159726Syar return (error); 222159726Syar (*fp)(0x11111111, 0x22222222, 0x33333333); 223159726Syar return (0); 224159726Syar} 225159726Syar 226178766Spetervoid 227178766Speterkdb_panic(const char *msg) 228178766Speter{ 229223758Sattilio 230178766Speter printf("KDB: panic\n"); 231209062Savg panic("%s", msg); 232178766Speter} 233178766Speter 234178766Spetervoid 235178766Speterkdb_reboot(void) 236178766Speter{ 237178766Speter 238178766Speter printf("KDB: reboot requested\n"); 239178766Speter shutdown_nice(0); 240178766Speter} 241178766Speter 242131903Smarcel/* 243131903Smarcel * Solaris implements a new BREAK which is initiated by a character sequence 244131903Smarcel * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the 245131903Smarcel * Remote Console. 246131903Smarcel * 247131903Smarcel * Note that this function may be called from almost anywhere, with interrupts 248131903Smarcel * disabled and with unknown locks held, so it must not access data other than 249131903Smarcel * its arguments. Its up to the caller to ensure that the state variable is 250131903Smarcel * consistent. 251131903Smarcel */ 252131903Smarcel 253131903Smarcel#define KEY_CR 13 /* CR '\r' */ 254131903Smarcel#define KEY_TILDE 126 /* ~ */ 255131903Smarcel#define KEY_CRTLB 2 /* ^B */ 256178766Speter#define KEY_CRTLP 16 /* ^P */ 257178766Speter#define KEY_CRTLR 18 /* ^R */ 258131903Smarcel 259223099Sgibbs/* States of th KDB "alternate break sequence" detecting state machine. */ 260223099Sgibbsenum { 261223099Sgibbs KDB_ALT_BREAK_SEEN_NONE, 262223099Sgibbs KDB_ALT_BREAK_SEEN_CR, 263223099Sgibbs KDB_ALT_BREAK_SEEN_CR_TILDE, 264223099Sgibbs}; 265223099Sgibbs 266131903Smarcelint 267225203Srwatsonkdb_break(void) 268131903Smarcel{ 269225203Srwatson 270225203Srwatson if (!kdb_break_to_debugger) 271225203Srwatson return (0); 272225203Srwatson kdb_enter(KDB_WHY_BREAK, "Break to debugger"); 273225203Srwatson return (KDB_REQ_DEBUGGER); 274225203Srwatson} 275225203Srwatson 276225203Srwatsonstatic int 277225203Srwatsonkdb_alt_break_state(int key, int *state) 278225203Srwatson{ 279131903Smarcel int brk; 280131903Smarcel 281223099Sgibbs /* All states transition to KDB_ALT_BREAK_SEEN_CR on a CR. */ 282223099Sgibbs if (key == KEY_CR) { 283223099Sgibbs *state = KDB_ALT_BREAK_SEEN_CR; 284223099Sgibbs return (0); 285223099Sgibbs } 286223099Sgibbs 287131903Smarcel brk = 0; 288178766Speter switch (*state) { 289223099Sgibbs case KDB_ALT_BREAK_SEEN_CR: 290223099Sgibbs *state = KDB_ALT_BREAK_SEEN_NONE; 291178766Speter if (key == KEY_TILDE) 292223099Sgibbs *state = KDB_ALT_BREAK_SEEN_CR_TILDE; 293131903Smarcel break; 294223099Sgibbs case KDB_ALT_BREAK_SEEN_CR_TILDE: 295223099Sgibbs *state = KDB_ALT_BREAK_SEEN_NONE; 296178766Speter if (key == KEY_CRTLB) 297178766Speter brk = KDB_REQ_DEBUGGER; 298178766Speter else if (key == KEY_CRTLP) 299178766Speter brk = KDB_REQ_PANIC; 300178766Speter else if (key == KEY_CRTLR) 301178766Speter brk = KDB_REQ_REBOOT; 302223099Sgibbs break; 303223099Sgibbs case KDB_ALT_BREAK_SEEN_NONE: 304223099Sgibbs default: 305223099Sgibbs *state = KDB_ALT_BREAK_SEEN_NONE; 306223099Sgibbs break; 307131903Smarcel } 308131903Smarcel return (brk); 309131903Smarcel} 310131903Smarcel 311225203Srwatsonstatic int 312225203Srwatsonkdb_alt_break_internal(int key, int *state, int force_gdb) 313225203Srwatson{ 314225203Srwatson int brk; 315225203Srwatson 316225203Srwatson if (!kdb_alt_break_to_debugger) 317225203Srwatson return (0); 318225203Srwatson brk = kdb_alt_break_state(key, state); 319225203Srwatson switch (brk) { 320225203Srwatson case KDB_REQ_DEBUGGER: 321225203Srwatson if (force_gdb) 322225203Srwatson kdb_dbbe_select("gdb"); 323225203Srwatson kdb_enter(KDB_WHY_BREAK, "Break to debugger"); 324225203Srwatson break; 325225203Srwatson 326225203Srwatson case KDB_REQ_PANIC: 327225203Srwatson if (force_gdb) 328225203Srwatson kdb_dbbe_select("gdb"); 329225203Srwatson kdb_panic("Panic sequence on console"); 330225203Srwatson break; 331225203Srwatson 332225203Srwatson case KDB_REQ_REBOOT: 333225203Srwatson kdb_reboot(); 334225203Srwatson break; 335225203Srwatson } 336225203Srwatson return (0); 337225203Srwatson} 338225203Srwatson 339225203Srwatsonint 340225203Srwatsonkdb_alt_break(int key, int *state) 341225203Srwatson{ 342225203Srwatson 343225203Srwatson return (kdb_alt_break_internal(key, state, 0)); 344225203Srwatson} 345225203Srwatson 346131903Smarcel/* 347225203Srwatson * This variation on kdb_alt_break() is used only by dcons, which has its own 348225203Srwatson * configuration flag to force GDB use regardless of the global KDB 349225203Srwatson * configuration. 350225203Srwatson */ 351225203Srwatsonint 352225203Srwatsonkdb_alt_break_gdb(int key, int *state) 353225203Srwatson{ 354225203Srwatson 355225203Srwatson return (kdb_alt_break_internal(key, state, 1)); 356225203Srwatson} 357225203Srwatson 358225203Srwatson/* 359131903Smarcel * Print a backtrace of the calling thread. The backtrace is generated by 360131903Smarcel * the selected debugger, provided it supports backtraces. If no debugger 361131903Smarcel * is selected or the current debugger does not support backtraces, this 362131903Smarcel * function silently returns. 363131903Smarcel */ 364131903Smarcel 365131903Smarcelvoid 366191948Simpkdb_backtrace(void) 367131903Smarcel{ 368131903Smarcel 369131903Smarcel if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) { 370131903Smarcel printf("KDB: stack backtrace:\n"); 371131903Smarcel kdb_dbbe->dbbe_trace(); 372131903Smarcel } 373212964Savg#ifdef STACK 374212964Savg else { 375212964Savg struct stack st; 376212964Savg 377212964Savg printf("KDB: stack backtrace:\n"); 378212964Savg stack_save(&st); 379212994Savg stack_print_ddb(&st); 380212964Savg } 381212964Savg#endif 382131903Smarcel} 383131903Smarcel 384131903Smarcel/* 385132001Smarcel * Set/change the current backend. 386132001Smarcel */ 387132001Smarcel 388132001Smarcelint 389132001Smarcelkdb_dbbe_select(const char *name) 390132001Smarcel{ 391132001Smarcel struct kdb_dbbe *be, **iter; 392132001Smarcel 393132001Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 394132001Smarcel be = *iter; 395132001Smarcel if (be->dbbe_active == 0 && strcmp(be->dbbe_name, name) == 0) { 396132001Smarcel kdb_dbbe = be; 397132001Smarcel return (0); 398132001Smarcel } 399132001Smarcel } 400132001Smarcel return (EINVAL); 401132001Smarcel} 402132001Smarcel 403132001Smarcel/* 404131903Smarcel * Enter the currently selected debugger. If a message has been provided, 405131903Smarcel * it is printed first. If the debugger does not support the enter method, 406131903Smarcel * it is entered by using breakpoint(), which enters the debugger through 407174898Srwatson * kdb_trap(). The 'why' argument will contain a more mechanically usable 408174898Srwatson * string than 'msg', and is relied upon by DDB scripting to identify the 409174898Srwatson * reason for entering the debugger so that the right script can be run. 410131903Smarcel */ 411131903Smarcelvoid 412174898Srwatsonkdb_enter(const char *why, const char *msg) 413131903Smarcel{ 414131903Smarcel 415131903Smarcel if (kdb_dbbe != NULL && kdb_active == 0) { 416131903Smarcel if (msg != NULL) 417131903Smarcel printf("KDB: enter: %s\n", msg); 418174898Srwatson kdb_why = why; 419131903Smarcel breakpoint(); 420174898Srwatson kdb_why = KDB_WHY_UNSET; 421131903Smarcel } 422131903Smarcel} 423131903Smarcel 424131903Smarcel/* 425131903Smarcel * Initialize the kernel debugger interface. 426131903Smarcel */ 427131903Smarcel 428131903Smarcelvoid 429191948Simpkdb_init(void) 430131903Smarcel{ 431131903Smarcel struct kdb_dbbe *be, **iter; 432131903Smarcel int cur_pri, pri; 433131903Smarcel 434131903Smarcel kdb_active = 0; 435131903Smarcel kdb_dbbe = NULL; 436131903Smarcel cur_pri = -1; 437131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 438131903Smarcel be = *iter; 439131903Smarcel pri = (be->dbbe_init != NULL) ? be->dbbe_init() : -1; 440131903Smarcel be->dbbe_active = (pri >= 0) ? 0 : -1; 441131903Smarcel if (pri > cur_pri) { 442131903Smarcel cur_pri = pri; 443131903Smarcel kdb_dbbe = be; 444131903Smarcel } 445131903Smarcel } 446131903Smarcel if (kdb_dbbe != NULL) { 447131903Smarcel printf("KDB: debugger backends:"); 448131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 449131903Smarcel be = *iter; 450131903Smarcel if (be->dbbe_active == 0) 451131903Smarcel printf(" %s", be->dbbe_name); 452131903Smarcel } 453131903Smarcel printf("\n"); 454131903Smarcel printf("KDB: current backend: %s\n", 455131903Smarcel kdb_dbbe->dbbe_name); 456131903Smarcel } 457131903Smarcel} 458131903Smarcel 459131903Smarcel/* 460131903Smarcel * Handle contexts. 461131903Smarcel */ 462131903Smarcel 463131903Smarcelvoid * 464131903Smarcelkdb_jmpbuf(jmp_buf new) 465131903Smarcel{ 466131903Smarcel void *old; 467131903Smarcel 468131903Smarcel old = kdb_jmpbufp; 469131903Smarcel kdb_jmpbufp = new; 470131903Smarcel return (old); 471131903Smarcel} 472131903Smarcel 473131903Smarcelvoid 474131903Smarcelkdb_reenter(void) 475131903Smarcel{ 476131903Smarcel 477131903Smarcel if (!kdb_active || kdb_jmpbufp == NULL) 478131903Smarcel return; 479131903Smarcel 480131903Smarcel longjmp(kdb_jmpbufp, 1); 481131903Smarcel /* NOTREACHED */ 482131903Smarcel} 483131903Smarcel 484131903Smarcel/* 485131903Smarcel * Thread related support functions. 486131903Smarcel */ 487131903Smarcel 488131903Smarcelstruct pcb * 489131903Smarcelkdb_thr_ctx(struct thread *thr) 490145727Sdwhite{ 491157448Smarcel#if defined(SMP) && defined(KDB_STOPPEDPCB) 492151631Sjhb struct pcpu *pc; 493151634Sjhb#endif 494157448Smarcel 495151631Sjhb if (thr == curthread) 496151631Sjhb return (&kdb_pcb); 497145727Sdwhite 498157448Smarcel#if defined(SMP) && defined(KDB_STOPPEDPCB) 499222531Snwhitehorn STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { 500222813Sattilio if (pc->pc_curthread == thr && 501223758Sattilio CPU_ISSET(pc->pc_cpuid, &stopped_cpus)) 502157448Smarcel return (KDB_STOPPEDPCB(pc)); 503151631Sjhb } 504151634Sjhb#endif 505151631Sjhb return (thr->td_pcb); 506145727Sdwhite} 507131903Smarcel 508131903Smarcelstruct thread * 509131903Smarcelkdb_thr_first(void) 510131903Smarcel{ 511131903Smarcel struct proc *p; 512131903Smarcel struct thread *thr; 513131903Smarcel 514131903Smarcel p = LIST_FIRST(&allproc); 515131903Smarcel while (p != NULL) { 516172207Sjeff if (p->p_flag & P_INMEM) { 517131903Smarcel thr = FIRST_THREAD_IN_PROC(p); 518131903Smarcel if (thr != NULL) 519131903Smarcel return (thr); 520131903Smarcel } 521131903Smarcel p = LIST_NEXT(p, p_list); 522131903Smarcel } 523131903Smarcel return (NULL); 524131903Smarcel} 525131903Smarcel 526131903Smarcelstruct thread * 527132481Smarcelkdb_thr_from_pid(pid_t pid) 528131903Smarcel{ 529132481Smarcel struct proc *p; 530132481Smarcel 531132481Smarcel p = LIST_FIRST(&allproc); 532132481Smarcel while (p != NULL) { 533172207Sjeff if (p->p_flag & P_INMEM && p->p_pid == pid) 534132481Smarcel return (FIRST_THREAD_IN_PROC(p)); 535132481Smarcel p = LIST_NEXT(p, p_list); 536132481Smarcel } 537132481Smarcel return (NULL); 538132481Smarcel} 539132481Smarcel 540132481Smarcelstruct thread * 541132481Smarcelkdb_thr_lookup(lwpid_t tid) 542132481Smarcel{ 543131903Smarcel struct thread *thr; 544131903Smarcel 545131903Smarcel thr = kdb_thr_first(); 546131903Smarcel while (thr != NULL && thr->td_tid != tid) 547131903Smarcel thr = kdb_thr_next(thr); 548131903Smarcel return (thr); 549131903Smarcel} 550131903Smarcel 551131903Smarcelstruct thread * 552131903Smarcelkdb_thr_next(struct thread *thr) 553131903Smarcel{ 554131903Smarcel struct proc *p; 555131903Smarcel 556131903Smarcel p = thr->td_proc; 557131903Smarcel thr = TAILQ_NEXT(thr, td_plist); 558131903Smarcel do { 559131903Smarcel if (thr != NULL) 560131903Smarcel return (thr); 561131903Smarcel p = LIST_NEXT(p, p_list); 562172207Sjeff if (p != NULL && (p->p_flag & P_INMEM)) 563131903Smarcel thr = FIRST_THREAD_IN_PROC(p); 564131903Smarcel } while (p != NULL); 565131903Smarcel return (NULL); 566131903Smarcel} 567131903Smarcel 568131903Smarcelint 569131903Smarcelkdb_thr_select(struct thread *thr) 570131903Smarcel{ 571131903Smarcel if (thr == NULL) 572131903Smarcel return (EINVAL); 573131903Smarcel kdb_thread = thr; 574131903Smarcel kdb_thrctx = kdb_thr_ctx(thr); 575131903Smarcel return (0); 576131903Smarcel} 577131903Smarcel 578131903Smarcel/* 579131903Smarcel * Enter the debugger due to a trap. 580131903Smarcel */ 581131903Smarcel 582131903Smarcelint 583131903Smarcelkdb_trap(int type, int code, struct trapframe *tf) 584131903Smarcel{ 585223758Sattilio#ifdef SMP 586223758Sattilio cpuset_t other_cpus; 587223758Sattilio#endif 588218825Smdf struct kdb_dbbe *be; 589157442Smarcel register_t intr; 590157442Smarcel int handled; 591228424Savg#ifdef SMP 592228424Savg int did_stop_cpus; 593228424Savg#endif 594131903Smarcel 595218825Smdf be = kdb_dbbe; 596218825Smdf if (be == NULL || be->dbbe_trap == NULL) 597131903Smarcel return (0); 598131903Smarcel 599131903Smarcel /* We reenter the debugger through kdb_reenter(). */ 600131903Smarcel if (kdb_active) 601131903Smarcel return (0); 602131903Smarcel 603157437Smarcel intr = intr_disable(); 604131903Smarcel 605131903Smarcel#ifdef SMP 606228424Savg if (!SCHEDULER_STOPPED()) { 607228424Savg other_cpus = all_cpus; 608228424Savg CPU_CLR(PCPU_GET(cpuid), &other_cpus); 609228424Savg stop_cpus_hard(other_cpus); 610228424Savg did_stop_cpus = 1; 611228424Savg } else 612228424Savg did_stop_cpus = 0; 613131903Smarcel#endif 614131903Smarcel 615157450Smarcel kdb_active++; 616157450Smarcel 617135808Smarcel kdb_frame = tf; 618135808Smarcel 619131903Smarcel /* Let MD code do its thing first... */ 620131903Smarcel kdb_cpu_trap(type, code); 621131903Smarcel 622135407Smarcel makectx(tf, &kdb_pcb); 623135407Smarcel kdb_thr_select(curthread); 624135407Smarcel 625218825Smdf for (;;) { 626218825Smdf handled = be->dbbe_trap(type, code); 627218825Smdf if (be == kdb_dbbe) 628218825Smdf break; 629218825Smdf be = kdb_dbbe; 630218825Smdf if (be == NULL || be->dbbe_trap == NULL) 631218825Smdf break; 632218825Smdf printf("Switching to %s back-end\n", be->dbbe_name); 633218825Smdf } 634131903Smarcel 635157450Smarcel kdb_active--; 636157450Smarcel 637131903Smarcel#ifdef SMP 638228424Savg if (did_stop_cpus) 639228424Savg restart_cpus(stopped_cpus); 640131903Smarcel#endif 641131903Smarcel 642157437Smarcel intr_restore(intr); 643131903Smarcel 644131903Smarcel return (handled); 645131903Smarcel} 646