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: stable/10/sys/kern/subr_kdb.c 325460 2017-11-05 22:34:27Z ngie $"); 29131903Smarcel 30147674Speter#include "opt_kdb.h" 31212964Savg#include "opt_stack.h" 32147674Speter 33131903Smarcel#include <sys/param.h> 34131903Smarcel#include <sys/systm.h> 35228632Savg#include <sys/cons.h> 36131903Smarcel#include <sys/kdb.h> 37131903Smarcel#include <sys/kernel.h> 38131903Smarcel#include <sys/malloc.h> 39131903Smarcel#include <sys/pcpu.h> 40131903Smarcel#include <sys/proc.h> 41218825Smdf#include <sys/sbuf.h> 42131903Smarcel#include <sys/smp.h> 43212964Savg#include <sys/stack.h> 44131903Smarcel#include <sys/sysctl.h> 45131903Smarcel 46131903Smarcel#include <machine/kdb.h> 47131903Smarcel#include <machine/pcb.h> 48131903Smarcel 49151634Sjhb#ifdef SMP 50145727Sdwhite#include <machine/smp.h> 51145727Sdwhite#endif 52145727Sdwhite 53131903Smarcelint kdb_active = 0; 54191948Simpstatic void *kdb_jmpbufp = NULL; 55131903Smarcelstruct kdb_dbbe *kdb_dbbe = NULL; 56191948Simpstatic struct pcb kdb_pcb; 57131903Smarcelstruct pcb *kdb_thrctx = NULL; 58131903Smarcelstruct thread *kdb_thread = NULL; 59131903Smarcelstruct trapframe *kdb_frame = NULL; 60131903Smarcel 61225203Srwatson#ifdef BREAK_TO_DEBUGGER 62225203Srwatson#define KDB_BREAK_TO_DEBUGGER 1 63225203Srwatson#else 64225203Srwatson#define KDB_BREAK_TO_DEBUGGER 0 65225203Srwatson#endif 66225203Srwatson 67225203Srwatson#ifdef ALT_BREAK_TO_DEBUGGER 68225203Srwatson#define KDB_ALT_BREAK_TO_DEBUGGER 1 69225203Srwatson#else 70225203Srwatson#define KDB_ALT_BREAK_TO_DEBUGGER 0 71225203Srwatson#endif 72225203Srwatson 73225203Srwatsonstatic int kdb_break_to_debugger = KDB_BREAK_TO_DEBUGGER; 74225203Srwatsonstatic int kdb_alt_break_to_debugger = KDB_ALT_BREAK_TO_DEBUGGER; 75225203Srwatson 76234190SjhbKDB_BACKEND(null, NULL, NULL, NULL, NULL); 77131903SmarcelSET_DECLARE(kdb_dbbe_set, struct kdb_dbbe); 78131903Smarcel 79131903Smarcelstatic int kdb_sysctl_available(SYSCTL_HANDLER_ARGS); 80131903Smarcelstatic int kdb_sysctl_current(SYSCTL_HANDLER_ARGS); 81131903Smarcelstatic int kdb_sysctl_enter(SYSCTL_HANDLER_ARGS); 82151725Speterstatic int kdb_sysctl_panic(SYSCTL_HANDLER_ARGS); 83151725Speterstatic int kdb_sysctl_trap(SYSCTL_HANDLER_ARGS); 84159726Syarstatic int kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS); 85131903Smarcel 86227309Sedstatic SYSCTL_NODE(_debug, OID_AUTO, kdb, CTLFLAG_RW, NULL, "KDB nodes"); 87131903Smarcel 88191948SimpSYSCTL_PROC(_debug_kdb, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, NULL, 89191948Simp 0, kdb_sysctl_available, "A", "list of available KDB backends"); 90131903Smarcel 91191948SimpSYSCTL_PROC(_debug_kdb, OID_AUTO, current, CTLTYPE_STRING | CTLFLAG_RW, NULL, 92191948Simp 0, kdb_sysctl_current, "A", "currently selected KDB backend"); 93131903Smarcel 94226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, enter, 95226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 96131903Smarcel kdb_sysctl_enter, "I", "set to enter the debugger"); 97131903Smarcel 98226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, panic, 99226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 100151725Speter kdb_sysctl_panic, "I", "set to panic the kernel"); 101151725Speter 102226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, trap, 103226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 104159726Syar kdb_sysctl_trap, "I", "set to cause a page fault via data access"); 105151725Speter 106226089SobrienSYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, 107226089Sobrien CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 108159726Syar kdb_sysctl_trap_code, "I", "set to cause a page fault via code access"); 109159726Syar 110226089SobrienSYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger, 111273736Shselasky CTLFLAG_RWTUN | CTLFLAG_SECURE, 112226089Sobrien &kdb_break_to_debugger, 0, "Enable break to debugger"); 113225203SrwatsonTUNABLE_INT("debug.kdb.break_to_debugger", &kdb_break_to_debugger); 114225203Srwatson 115226089SobrienSYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger, 116273736Shselasky CTLFLAG_RWTUN | CTLFLAG_SECURE, 117226089Sobrien &kdb_alt_break_to_debugger, 0, "Enable alternative break to debugger"); 118225203SrwatsonTUNABLE_INT("debug.kdb.alt_break_to_debugger", &kdb_alt_break_to_debugger); 119225203Srwatson 120133737Srwatson/* 121174898Srwatson * Flag to indicate to debuggers why the debugger was entered. 122174898Srwatson */ 123174898Srwatsonconst char * volatile kdb_why = KDB_WHY_UNSET; 124174898Srwatson 125131903Smarcelstatic int 126131903Smarcelkdb_sysctl_available(SYSCTL_HANDLER_ARGS) 127131903Smarcel{ 128218825Smdf struct kdb_dbbe **iter; 129218825Smdf struct sbuf sbuf; 130131903Smarcel int error; 131131903Smarcel 132218825Smdf sbuf_new_for_sysctl(&sbuf, NULL, 64, req); 133131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 134218825Smdf if ((*iter)->dbbe_active == 0) 135218825Smdf sbuf_printf(&sbuf, "%s ", (*iter)->dbbe_name); 136131903Smarcel } 137218825Smdf error = sbuf_finish(&sbuf); 138218825Smdf sbuf_delete(&sbuf); 139131903Smarcel return (error); 140131903Smarcel} 141131903Smarcel 142131903Smarcelstatic int 143131903Smarcelkdb_sysctl_current(SYSCTL_HANDLER_ARGS) 144131903Smarcel{ 145131903Smarcel char buf[16]; 146131903Smarcel int error; 147131903Smarcel 148218825Smdf if (kdb_dbbe != NULL) 149218825Smdf strlcpy(buf, kdb_dbbe->dbbe_name, sizeof(buf)); 150218825Smdf else 151131982Smarcel *buf = '\0'; 152131903Smarcel error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 153131903Smarcel if (error != 0 || req->newptr == NULL) 154131903Smarcel return (error); 155131903Smarcel if (kdb_active) 156131903Smarcel return (EBUSY); 157132001Smarcel return (kdb_dbbe_select(buf)); 158131903Smarcel} 159131903Smarcel 160131903Smarcelstatic int 161131903Smarcelkdb_sysctl_enter(SYSCTL_HANDLER_ARGS) 162131903Smarcel{ 163131903Smarcel int error, i; 164131903Smarcel 165131903Smarcel error = sysctl_wire_old_buffer(req, sizeof(int)); 166131903Smarcel if (error == 0) { 167131903Smarcel i = 0; 168131903Smarcel error = sysctl_handle_int(oidp, &i, 0, req); 169131903Smarcel } 170131903Smarcel if (error != 0 || req->newptr == NULL) 171131903Smarcel return (error); 172131903Smarcel if (kdb_active) 173131903Smarcel return (EBUSY); 174174898Srwatson kdb_enter(KDB_WHY_SYSCTL, "sysctl debug.kdb.enter"); 175131903Smarcel return (0); 176131903Smarcel} 177131903Smarcel 178151725Speterstatic int 179151725Speterkdb_sysctl_panic(SYSCTL_HANDLER_ARGS) 180151725Speter{ 181151725Speter int error, i; 182151725Speter 183151725Speter error = sysctl_wire_old_buffer(req, sizeof(int)); 184151725Speter if (error == 0) { 185151725Speter i = 0; 186151725Speter error = sysctl_handle_int(oidp, &i, 0, req); 187151725Speter } 188151725Speter if (error != 0 || req->newptr == NULL) 189151725Speter return (error); 190151725Speter panic("kdb_sysctl_panic"); 191151725Speter return (0); 192151725Speter} 193151725Speter 194151725Speterstatic int 195151725Speterkdb_sysctl_trap(SYSCTL_HANDLER_ARGS) 196151725Speter{ 197151725Speter int error, i; 198151725Speter int *addr = (int *)0x10; 199151725Speter 200151725Speter error = sysctl_wire_old_buffer(req, sizeof(int)); 201151725Speter if (error == 0) { 202151725Speter i = 0; 203151725Speter error = sysctl_handle_int(oidp, &i, 0, req); 204151725Speter } 205151725Speter if (error != 0 || req->newptr == NULL) 206151725Speter return (error); 207151725Speter return (*addr); 208151725Speter} 209151725Speter 210159726Syarstatic int 211159726Syarkdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS) 212159726Syar{ 213159726Syar int error, i; 214159726Syar void (*fp)(u_int, u_int, u_int) = (void *)0xdeadc0de; 215159726Syar 216159726Syar error = sysctl_wire_old_buffer(req, sizeof(int)); 217159726Syar if (error == 0) { 218159726Syar i = 0; 219159726Syar error = sysctl_handle_int(oidp, &i, 0, req); 220159726Syar } 221159726Syar if (error != 0 || req->newptr == NULL) 222159726Syar return (error); 223159726Syar (*fp)(0x11111111, 0x22222222, 0x33333333); 224159726Syar return (0); 225159726Syar} 226159726Syar 227178766Spetervoid 228178766Speterkdb_panic(const char *msg) 229178766Speter{ 230223758Sattilio 231178766Speter printf("KDB: panic\n"); 232209062Savg panic("%s", msg); 233178766Speter} 234178766Speter 235178766Spetervoid 236178766Speterkdb_reboot(void) 237178766Speter{ 238178766Speter 239178766Speter printf("KDB: reboot requested\n"); 240178766Speter shutdown_nice(0); 241178766Speter} 242178766Speter 243131903Smarcel/* 244131903Smarcel * Solaris implements a new BREAK which is initiated by a character sequence 245131903Smarcel * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the 246131903Smarcel * Remote Console. 247131903Smarcel * 248131903Smarcel * Note that this function may be called from almost anywhere, with interrupts 249131903Smarcel * disabled and with unknown locks held, so it must not access data other than 250131903Smarcel * its arguments. Its up to the caller to ensure that the state variable is 251131903Smarcel * consistent. 252131903Smarcel */ 253131903Smarcel 254131903Smarcel#define KEY_CR 13 /* CR '\r' */ 255131903Smarcel#define KEY_TILDE 126 /* ~ */ 256131903Smarcel#define KEY_CRTLB 2 /* ^B */ 257178766Speter#define KEY_CRTLP 16 /* ^P */ 258178766Speter#define KEY_CRTLR 18 /* ^R */ 259131903Smarcel 260223099Sgibbs/* States of th KDB "alternate break sequence" detecting state machine. */ 261223099Sgibbsenum { 262223099Sgibbs KDB_ALT_BREAK_SEEN_NONE, 263223099Sgibbs KDB_ALT_BREAK_SEEN_CR, 264223099Sgibbs KDB_ALT_BREAK_SEEN_CR_TILDE, 265223099Sgibbs}; 266223099Sgibbs 267131903Smarcelint 268225203Srwatsonkdb_break(void) 269131903Smarcel{ 270225203Srwatson 271225203Srwatson if (!kdb_break_to_debugger) 272225203Srwatson return (0); 273225203Srwatson kdb_enter(KDB_WHY_BREAK, "Break to debugger"); 274225203Srwatson return (KDB_REQ_DEBUGGER); 275225203Srwatson} 276225203Srwatson 277225203Srwatsonstatic int 278225203Srwatsonkdb_alt_break_state(int key, int *state) 279225203Srwatson{ 280131903Smarcel int brk; 281131903Smarcel 282223099Sgibbs /* All states transition to KDB_ALT_BREAK_SEEN_CR on a CR. */ 283223099Sgibbs if (key == KEY_CR) { 284223099Sgibbs *state = KDB_ALT_BREAK_SEEN_CR; 285223099Sgibbs return (0); 286223099Sgibbs } 287223099Sgibbs 288131903Smarcel brk = 0; 289178766Speter switch (*state) { 290223099Sgibbs case KDB_ALT_BREAK_SEEN_CR: 291223099Sgibbs *state = KDB_ALT_BREAK_SEEN_NONE; 292178766Speter if (key == KEY_TILDE) 293223099Sgibbs *state = KDB_ALT_BREAK_SEEN_CR_TILDE; 294131903Smarcel break; 295223099Sgibbs case KDB_ALT_BREAK_SEEN_CR_TILDE: 296223099Sgibbs *state = KDB_ALT_BREAK_SEEN_NONE; 297178766Speter if (key == KEY_CRTLB) 298178766Speter brk = KDB_REQ_DEBUGGER; 299178766Speter else if (key == KEY_CRTLP) 300178766Speter brk = KDB_REQ_PANIC; 301178766Speter else if (key == KEY_CRTLR) 302178766Speter brk = KDB_REQ_REBOOT; 303223099Sgibbs break; 304223099Sgibbs case KDB_ALT_BREAK_SEEN_NONE: 305223099Sgibbs default: 306223099Sgibbs *state = KDB_ALT_BREAK_SEEN_NONE; 307223099Sgibbs break; 308131903Smarcel } 309131903Smarcel return (brk); 310131903Smarcel} 311131903Smarcel 312225203Srwatsonstatic int 313225203Srwatsonkdb_alt_break_internal(int key, int *state, int force_gdb) 314225203Srwatson{ 315225203Srwatson int brk; 316225203Srwatson 317225203Srwatson if (!kdb_alt_break_to_debugger) 318225203Srwatson return (0); 319225203Srwatson brk = kdb_alt_break_state(key, state); 320225203Srwatson switch (brk) { 321225203Srwatson case KDB_REQ_DEBUGGER: 322225203Srwatson if (force_gdb) 323225203Srwatson kdb_dbbe_select("gdb"); 324225203Srwatson kdb_enter(KDB_WHY_BREAK, "Break to debugger"); 325225203Srwatson break; 326225203Srwatson 327225203Srwatson case KDB_REQ_PANIC: 328225203Srwatson if (force_gdb) 329225203Srwatson kdb_dbbe_select("gdb"); 330225203Srwatson kdb_panic("Panic sequence on console"); 331225203Srwatson break; 332225203Srwatson 333225203Srwatson case KDB_REQ_REBOOT: 334225203Srwatson kdb_reboot(); 335225203Srwatson break; 336225203Srwatson } 337225203Srwatson return (0); 338225203Srwatson} 339225203Srwatson 340225203Srwatsonint 341225203Srwatsonkdb_alt_break(int key, int *state) 342225203Srwatson{ 343225203Srwatson 344225203Srwatson return (kdb_alt_break_internal(key, state, 0)); 345225203Srwatson} 346225203Srwatson 347131903Smarcel/* 348225203Srwatson * This variation on kdb_alt_break() is used only by dcons, which has its own 349225203Srwatson * configuration flag to force GDB use regardless of the global KDB 350225203Srwatson * configuration. 351225203Srwatson */ 352225203Srwatsonint 353225203Srwatsonkdb_alt_break_gdb(int key, int *state) 354225203Srwatson{ 355225203Srwatson 356225203Srwatson return (kdb_alt_break_internal(key, state, 1)); 357225203Srwatson} 358225203Srwatson 359225203Srwatson/* 360131903Smarcel * Print a backtrace of the calling thread. The backtrace is generated by 361131903Smarcel * the selected debugger, provided it supports backtraces. If no debugger 362131903Smarcel * is selected or the current debugger does not support backtraces, this 363131903Smarcel * function silently returns. 364131903Smarcel */ 365131903Smarcel 366131903Smarcelvoid 367191948Simpkdb_backtrace(void) 368131903Smarcel{ 369131903Smarcel 370131903Smarcel if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) { 371131903Smarcel printf("KDB: stack backtrace:\n"); 372131903Smarcel kdb_dbbe->dbbe_trace(); 373131903Smarcel } 374212964Savg#ifdef STACK 375212964Savg else { 376212964Savg struct stack st; 377212964Savg 378212964Savg printf("KDB: stack backtrace:\n"); 379234190Sjhb stack_zero(&st); 380212964Savg stack_save(&st); 381212994Savg stack_print_ddb(&st); 382212964Savg } 383212964Savg#endif 384131903Smarcel} 385131903Smarcel 386131903Smarcel/* 387234190Sjhb * Similar to kdb_backtrace() except that it prints a backtrace of an 388234190Sjhb * arbitrary thread rather than the calling thread. 389234190Sjhb */ 390234190Sjhbvoid 391234190Sjhbkdb_backtrace_thread(struct thread *td) 392234190Sjhb{ 393234190Sjhb 394234190Sjhb if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace_thread != NULL) { 395234190Sjhb printf("KDB: stack backtrace of thread %d:\n", td->td_tid); 396234190Sjhb kdb_dbbe->dbbe_trace_thread(td); 397234190Sjhb } 398234190Sjhb#ifdef STACK 399234190Sjhb else { 400234190Sjhb struct stack st; 401234190Sjhb 402234190Sjhb printf("KDB: stack backtrace of thread %d:\n", td->td_tid); 403234190Sjhb stack_zero(&st); 404234190Sjhb stack_save_td(&st, td); 405234190Sjhb stack_print_ddb(&st); 406234190Sjhb } 407234190Sjhb#endif 408234190Sjhb} 409234190Sjhb 410234190Sjhb/* 411132001Smarcel * Set/change the current backend. 412132001Smarcel */ 413132001Smarcel 414132001Smarcelint 415132001Smarcelkdb_dbbe_select(const char *name) 416132001Smarcel{ 417132001Smarcel struct kdb_dbbe *be, **iter; 418132001Smarcel 419132001Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 420132001Smarcel be = *iter; 421132001Smarcel if (be->dbbe_active == 0 && strcmp(be->dbbe_name, name) == 0) { 422132001Smarcel kdb_dbbe = be; 423132001Smarcel return (0); 424132001Smarcel } 425132001Smarcel } 426132001Smarcel return (EINVAL); 427132001Smarcel} 428132001Smarcel 429132001Smarcel/* 430131903Smarcel * Enter the currently selected debugger. If a message has been provided, 431131903Smarcel * it is printed first. If the debugger does not support the enter method, 432131903Smarcel * it is entered by using breakpoint(), which enters the debugger through 433174898Srwatson * kdb_trap(). The 'why' argument will contain a more mechanically usable 434174898Srwatson * string than 'msg', and is relied upon by DDB scripting to identify the 435174898Srwatson * reason for entering the debugger so that the right script can be run. 436131903Smarcel */ 437131903Smarcelvoid 438174898Srwatsonkdb_enter(const char *why, const char *msg) 439131903Smarcel{ 440131903Smarcel 441131903Smarcel if (kdb_dbbe != NULL && kdb_active == 0) { 442131903Smarcel if (msg != NULL) 443131903Smarcel printf("KDB: enter: %s\n", msg); 444174898Srwatson kdb_why = why; 445131903Smarcel breakpoint(); 446174898Srwatson kdb_why = KDB_WHY_UNSET; 447131903Smarcel } 448131903Smarcel} 449131903Smarcel 450131903Smarcel/* 451131903Smarcel * Initialize the kernel debugger interface. 452131903Smarcel */ 453131903Smarcel 454131903Smarcelvoid 455191948Simpkdb_init(void) 456131903Smarcel{ 457131903Smarcel struct kdb_dbbe *be, **iter; 458131903Smarcel int cur_pri, pri; 459131903Smarcel 460131903Smarcel kdb_active = 0; 461131903Smarcel kdb_dbbe = NULL; 462131903Smarcel cur_pri = -1; 463131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 464131903Smarcel be = *iter; 465131903Smarcel pri = (be->dbbe_init != NULL) ? be->dbbe_init() : -1; 466131903Smarcel be->dbbe_active = (pri >= 0) ? 0 : -1; 467131903Smarcel if (pri > cur_pri) { 468131903Smarcel cur_pri = pri; 469131903Smarcel kdb_dbbe = be; 470131903Smarcel } 471131903Smarcel } 472131903Smarcel if (kdb_dbbe != NULL) { 473131903Smarcel printf("KDB: debugger backends:"); 474131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 475131903Smarcel be = *iter; 476131903Smarcel if (be->dbbe_active == 0) 477131903Smarcel printf(" %s", be->dbbe_name); 478131903Smarcel } 479131903Smarcel printf("\n"); 480131903Smarcel printf("KDB: current backend: %s\n", 481131903Smarcel kdb_dbbe->dbbe_name); 482131903Smarcel } 483131903Smarcel} 484131903Smarcel 485131903Smarcel/* 486131903Smarcel * Handle contexts. 487131903Smarcel */ 488131903Smarcel 489131903Smarcelvoid * 490131903Smarcelkdb_jmpbuf(jmp_buf new) 491131903Smarcel{ 492131903Smarcel void *old; 493131903Smarcel 494131903Smarcel old = kdb_jmpbufp; 495131903Smarcel kdb_jmpbufp = new; 496131903Smarcel return (old); 497131903Smarcel} 498131903Smarcel 499131903Smarcelvoid 500131903Smarcelkdb_reenter(void) 501131903Smarcel{ 502131903Smarcel 503131903Smarcel if (!kdb_active || kdb_jmpbufp == NULL) 504131903Smarcel return; 505131903Smarcel 506257576Skib printf("KDB: reentering\n"); 507257576Skib kdb_backtrace(); 508131903Smarcel longjmp(kdb_jmpbufp, 1); 509131903Smarcel /* NOTREACHED */ 510131903Smarcel} 511131903Smarcel 512131903Smarcel/* 513131903Smarcel * Thread related support functions. 514131903Smarcel */ 515131903Smarcel 516131903Smarcelstruct pcb * 517131903Smarcelkdb_thr_ctx(struct thread *thr) 518325460Sngie{ 519157448Smarcel#if defined(SMP) && defined(KDB_STOPPEDPCB) 520151631Sjhb struct pcpu *pc; 521151634Sjhb#endif 522325460Sngie 523325460Sngie if (thr == curthread) 524151631Sjhb return (&kdb_pcb); 525145727Sdwhite 526157448Smarcel#if defined(SMP) && defined(KDB_STOPPEDPCB) 527222531Snwhitehorn STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { 528222813Sattilio if (pc->pc_curthread == thr && 529223758Sattilio CPU_ISSET(pc->pc_cpuid, &stopped_cpus)) 530157448Smarcel return (KDB_STOPPEDPCB(pc)); 531151631Sjhb } 532151634Sjhb#endif 533151631Sjhb return (thr->td_pcb); 534145727Sdwhite} 535131903Smarcel 536131903Smarcelstruct thread * 537131903Smarcelkdb_thr_first(void) 538131903Smarcel{ 539131903Smarcel struct proc *p; 540131903Smarcel struct thread *thr; 541131903Smarcel 542131903Smarcel p = LIST_FIRST(&allproc); 543131903Smarcel while (p != NULL) { 544172207Sjeff if (p->p_flag & P_INMEM) { 545131903Smarcel thr = FIRST_THREAD_IN_PROC(p); 546131903Smarcel if (thr != NULL) 547131903Smarcel return (thr); 548131903Smarcel } 549131903Smarcel p = LIST_NEXT(p, p_list); 550131903Smarcel } 551131903Smarcel return (NULL); 552131903Smarcel} 553131903Smarcel 554131903Smarcelstruct thread * 555132481Smarcelkdb_thr_from_pid(pid_t pid) 556131903Smarcel{ 557132481Smarcel struct proc *p; 558132481Smarcel 559132481Smarcel p = LIST_FIRST(&allproc); 560132481Smarcel while (p != NULL) { 561172207Sjeff if (p->p_flag & P_INMEM && p->p_pid == pid) 562132481Smarcel return (FIRST_THREAD_IN_PROC(p)); 563132481Smarcel p = LIST_NEXT(p, p_list); 564132481Smarcel } 565132481Smarcel return (NULL); 566132481Smarcel} 567132481Smarcel 568132481Smarcelstruct thread * 569132481Smarcelkdb_thr_lookup(lwpid_t tid) 570132481Smarcel{ 571131903Smarcel struct thread *thr; 572131903Smarcel 573131903Smarcel thr = kdb_thr_first(); 574131903Smarcel while (thr != NULL && thr->td_tid != tid) 575131903Smarcel thr = kdb_thr_next(thr); 576131903Smarcel return (thr); 577131903Smarcel} 578131903Smarcel 579131903Smarcelstruct thread * 580131903Smarcelkdb_thr_next(struct thread *thr) 581131903Smarcel{ 582131903Smarcel struct proc *p; 583131903Smarcel 584131903Smarcel p = thr->td_proc; 585131903Smarcel thr = TAILQ_NEXT(thr, td_plist); 586131903Smarcel do { 587131903Smarcel if (thr != NULL) 588131903Smarcel return (thr); 589131903Smarcel p = LIST_NEXT(p, p_list); 590172207Sjeff if (p != NULL && (p->p_flag & P_INMEM)) 591131903Smarcel thr = FIRST_THREAD_IN_PROC(p); 592131903Smarcel } while (p != NULL); 593131903Smarcel return (NULL); 594131903Smarcel} 595131903Smarcel 596131903Smarcelint 597131903Smarcelkdb_thr_select(struct thread *thr) 598131903Smarcel{ 599131903Smarcel if (thr == NULL) 600131903Smarcel return (EINVAL); 601131903Smarcel kdb_thread = thr; 602131903Smarcel kdb_thrctx = kdb_thr_ctx(thr); 603131903Smarcel return (0); 604131903Smarcel} 605131903Smarcel 606131903Smarcel/* 607131903Smarcel * Enter the debugger due to a trap. 608131903Smarcel */ 609131903Smarcel 610131903Smarcelint 611131903Smarcelkdb_trap(int type, int code, struct trapframe *tf) 612131903Smarcel{ 613223758Sattilio#ifdef SMP 614223758Sattilio cpuset_t other_cpus; 615223758Sattilio#endif 616218825Smdf struct kdb_dbbe *be; 617157442Smarcel register_t intr; 618157442Smarcel int handled; 619228424Savg#ifdef SMP 620228424Savg int did_stop_cpus; 621228424Savg#endif 622131903Smarcel 623218825Smdf be = kdb_dbbe; 624218825Smdf if (be == NULL || be->dbbe_trap == NULL) 625131903Smarcel return (0); 626131903Smarcel 627131903Smarcel /* We reenter the debugger through kdb_reenter(). */ 628131903Smarcel if (kdb_active) 629131903Smarcel return (0); 630131903Smarcel 631157437Smarcel intr = intr_disable(); 632131903Smarcel 633131903Smarcel#ifdef SMP 634228424Savg if (!SCHEDULER_STOPPED()) { 635228424Savg other_cpus = all_cpus; 636228424Savg CPU_CLR(PCPU_GET(cpuid), &other_cpus); 637228424Savg stop_cpus_hard(other_cpus); 638228424Savg did_stop_cpus = 1; 639228424Savg } else 640228424Savg did_stop_cpus = 0; 641131903Smarcel#endif 642131903Smarcel 643157450Smarcel kdb_active++; 644157450Smarcel 645135808Smarcel kdb_frame = tf; 646135808Smarcel 647131903Smarcel /* Let MD code do its thing first... */ 648131903Smarcel kdb_cpu_trap(type, code); 649131903Smarcel 650135407Smarcel makectx(tf, &kdb_pcb); 651135407Smarcel kdb_thr_select(curthread); 652135407Smarcel 653228632Savg cngrab(); 654228632Savg 655218825Smdf for (;;) { 656218825Smdf handled = be->dbbe_trap(type, code); 657218825Smdf if (be == kdb_dbbe) 658218825Smdf break; 659218825Smdf be = kdb_dbbe; 660218825Smdf if (be == NULL || be->dbbe_trap == NULL) 661218825Smdf break; 662218825Smdf printf("Switching to %s back-end\n", be->dbbe_name); 663218825Smdf } 664131903Smarcel 665228632Savg cnungrab(); 666228632Savg 667157450Smarcel kdb_active--; 668157450Smarcel 669131903Smarcel#ifdef SMP 670228424Savg if (did_stop_cpus) 671228424Savg restart_cpus(stopped_cpus); 672131903Smarcel#endif 673131903Smarcel 674157437Smarcel intr_restore(intr); 675131903Smarcel 676131903Smarcel return (handled); 677131903Smarcel} 678