Annotation of sys/arch/amd64/amd64/db_interface.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_interface.c,v 1.11 2007/01/15 23:19:05 jsg Exp $ */
! 2: /* $NetBSD: db_interface.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
! 3:
! 4: /*
! 5: * Mach Operating System
! 6: * Copyright (c) 1991,1990 Carnegie Mellon University
! 7: * All Rights Reserved.
! 8: *
! 9: * Permission to use, copy, modify and distribute this software and its
! 10: * documentation is hereby granted, provided that both the copyright
! 11: * notice and this permission notice appear in all copies of the
! 12: * software, derivative works or modified versions, and any portions
! 13: * thereof, and that both notices appear in supporting documentation.
! 14: *
! 15: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 16: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
! 17: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 18: *
! 19: * Carnegie Mellon requests users of this software to return to
! 20: *
! 21: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 22: * School of Computer Science
! 23: * Carnegie Mellon University
! 24: * Pittsburgh PA 15213-3890
! 25: *
! 26: * any improvements or extensions that they make and grant Carnegie the
! 27: * rights to redistribute these changes.
! 28: *
! 29: * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
! 30: */
! 31:
! 32: /*
! 33: * Interface to new debugger.
! 34: */
! 35:
! 36: #include <sys/param.h>
! 37: #include <sys/proc.h>
! 38: #include <sys/reboot.h>
! 39: #include <sys/systm.h>
! 40:
! 41: #include <uvm/uvm_extern.h>
! 42:
! 43: #include <dev/cons.h>
! 44:
! 45: #include <machine/cpufunc.h>
! 46: #include <machine/db_machdep.h>
! 47: #include <machine/cpuvar.h>
! 48: #include <machine/i82093var.h>
! 49: #include <machine/i82489reg.h>
! 50: #include <machine/atomic.h>
! 51:
! 52: #include <ddb/db_sym.h>
! 53: #include <ddb/db_command.h>
! 54: #include <ddb/db_extern.h>
! 55: #include <ddb/db_access.h>
! 56: #include <ddb/db_output.h>
! 57: #include <ddb/db_var.h>
! 58:
! 59: #include "acpi.h"
! 60: #if NACPI > 0
! 61: #include <dev/acpi/acpidebug.h>
! 62: #endif /* NACPI > 0 */
! 63:
! 64: extern label_t *db_recover;
! 65: extern char *trap_type[];
! 66: extern int trap_types;
! 67: extern boolean_t db_cmd_loop_done;
! 68:
! 69: #ifdef MULTIPROCESSOR
! 70: struct mutex ddb_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
! 71: volatile int ddb_state = DDB_STATE_NOT_RUNNING;
! 72: volatile cpuid_t ddb_active_cpu;
! 73: boolean_t db_switch_cpu;
! 74: long db_switch_to_cpu;
! 75: #endif
! 76:
! 77: int db_active;
! 78: db_regs_t ddb_regs;
! 79:
! 80: void kdbprinttrap(int, int);
! 81: #ifdef MULTIPROCESSOR
! 82: void db_cpuinfo_cmd(db_expr_t, int, db_expr_t, char *);
! 83: void db_startproc_cmd(db_expr_t, int, db_expr_t, char *);
! 84: void db_stopproc_cmd(db_expr_t, int, db_expr_t, char *);
! 85: void db_ddbproc_cmd(db_expr_t, int, db_expr_t, char *);
! 86: int db_cpuid2apic(int);
! 87: #endif
! 88:
! 89: /*
! 90: * Print trap reason.
! 91: */
! 92: void
! 93: kdbprinttrap(int type, int code)
! 94: {
! 95: db_printf("kernel: ");
! 96: if (type >= trap_types || type < 0)
! 97: db_printf("type %d", type);
! 98: else
! 99: db_printf("%s", trap_type[type]);
! 100: db_printf(" trap, code=%x\n", code);
! 101: }
! 102:
! 103: /*
! 104: * kdb_trap - field a TRACE or BPT trap
! 105: */
! 106: int
! 107: kdb_trap(int type, int code, db_regs_t *regs)
! 108: {
! 109: int s;
! 110:
! 111: switch (type) {
! 112: case T_BPTFLT: /* breakpoint */
! 113: case T_TRCTRAP: /* single_step */
! 114: case T_NMI: /* NMI */
! 115: case -1: /* keyboard interrupt */
! 116: break;
! 117: default:
! 118: if (!db_panic)
! 119: return (0);
! 120:
! 121: kdbprinttrap(type, code);
! 122: if (db_recover != 0) {
! 123: db_error("Faulted in DDB; continuing...\n");
! 124: /*NOTREACHED*/
! 125: }
! 126: }
! 127:
! 128: #ifdef MULTIPROCESSOR
! 129: mtx_enter(&ddb_mp_mutex);
! 130: if (ddb_state == DDB_STATE_EXITING)
! 131: ddb_state = DDB_STATE_NOT_RUNNING;
! 132: mtx_leave(&ddb_mp_mutex);
! 133: while (db_enter_ddb()) {
! 134: #endif
! 135:
! 136: ddb_regs = *regs;
! 137:
! 138: ddb_regs.tf_cs &= 0xffff;
! 139: ddb_regs.tf_ds &= 0xffff;
! 140: ddb_regs.tf_es &= 0xffff;
! 141: ddb_regs.tf_fs &= 0xffff;
! 142: ddb_regs.tf_gs &= 0xffff;
! 143: ddb_regs.tf_ss &= 0xffff;
! 144:
! 145: s = splhigh();
! 146: db_active++;
! 147: cnpollc(TRUE);
! 148: db_trap(type, code);
! 149: cnpollc(FALSE);
! 150: db_active--;
! 151: splx(s);
! 152:
! 153: *regs = ddb_regs;
! 154:
! 155: #ifdef MULTIPROCESSOR
! 156: if (!db_switch_cpu)
! 157: ddb_state = DDB_STATE_EXITING;
! 158: }
! 159: #endif
! 160: return (1);
! 161: }
! 162:
! 163:
! 164: #ifdef MULTIPROCESSOR
! 165: int
! 166: db_cpuid2apic(int id)
! 167: {
! 168: int apic;
! 169:
! 170: for (apic = 0; apic < X86_MAXPROCS; apic++) {
! 171: if (cpu_info[apic] != NULL &&
! 172: CPU_INFO_UNIT(cpu_info[apic]) == id)
! 173: return (apic);
! 174: }
! 175: return (-1);
! 176: }
! 177:
! 178: void
! 179: db_cpuinfo_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 180: {
! 181: int i;
! 182:
! 183: for (i = 0; i < X86_MAXPROCS; i++) {
! 184: if (cpu_info[i] != NULL) {
! 185: db_printf("%c%4d: ", (i == cpu_number()) ? '*' : ' ',
! 186: CPU_INFO_UNIT(cpu_info[i]));
! 187: switch(cpu_info[i]->ci_ddb_paused) {
! 188: case CI_DDB_RUNNING:
! 189: db_printf("running\n");
! 190: break;
! 191: case CI_DDB_SHOULDSTOP:
! 192: db_printf("stopping\n");
! 193: break;
! 194: case CI_DDB_STOPPED:
! 195: db_printf("stopped\n");
! 196: break;
! 197: case CI_DDB_ENTERDDB:
! 198: db_printf("entering ddb\n");
! 199: break;
! 200: case CI_DDB_INDDB:
! 201: db_printf("ddb\n");
! 202: break;
! 203: default:
! 204: db_printf("? (%d)\n",
! 205: cpu_info[i]->ci_ddb_paused);
! 206: break;
! 207: }
! 208: }
! 209: }
! 210: }
! 211:
! 212: void
! 213: db_startproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 214: {
! 215: int apic;
! 216:
! 217: if (have_addr) {
! 218: apic = db_cpuid2apic(addr);
! 219: if (apic >= 0 && apic < X86_MAXPROCS &&
! 220: cpu_info[apic] != NULL && apic != cpu_number())
! 221: db_startcpu(apic);
! 222: else
! 223: db_printf("Invalid cpu %d\n", (int)addr);
! 224: } else {
! 225: for (apic = 0; apic < X86_MAXPROCS; apic++) {
! 226: if (cpu_info[apic] != NULL && apic != cpu_number()) {
! 227: db_startcpu(apic);
! 228: }
! 229: }
! 230: }
! 231: }
! 232:
! 233: void
! 234: db_stopproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 235: {
! 236: int apic;
! 237:
! 238: if (have_addr) {
! 239: apic = db_cpuid2apic(addr);
! 240: if (apic >= 0 && apic < X86_MAXPROCS &&
! 241: cpu_info[apic] != NULL && apic != cpu_number())
! 242: db_stopcpu(apic);
! 243: else
! 244: db_printf("Invalid cpu %d\n", (int)addr);
! 245: } else {
! 246: for (apic = 0; apic < X86_MAXPROCS; apic++) {
! 247: if (cpu_info[apic] != NULL && apic != cpu_number()) {
! 248: db_stopcpu(apic);
! 249: }
! 250: }
! 251: }
! 252: }
! 253:
! 254: void
! 255: db_ddbproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 256: {
! 257: int apic;
! 258:
! 259: if (have_addr) {
! 260: apic = db_cpuid2apic(addr);
! 261: if (apic >= 0 && apic < X86_MAXPROCS &&
! 262: cpu_info[apic] != NULL && apic != cpu_number()) {
! 263: db_stopcpu(apic);
! 264: db_switch_to_cpu = apic;
! 265: db_switch_cpu = 1;
! 266: db_cmd_loop_done = 1;
! 267: } else {
! 268: db_printf("Invalid cpu %d\n", (int)addr);
! 269: }
! 270: } else {
! 271: db_printf("CPU not specified\n");
! 272: }
! 273: }
! 274:
! 275: int
! 276: db_enter_ddb(void)
! 277: {
! 278: int i;
! 279:
! 280: mtx_enter(&ddb_mp_mutex);
! 281:
! 282: /* If we are first in, grab ddb and stop all other CPUs */
! 283: if (ddb_state == DDB_STATE_NOT_RUNNING) {
! 284: ddb_active_cpu = cpu_number();
! 285: ddb_state = DDB_STATE_RUNNING;
! 286: curcpu()->ci_ddb_paused = CI_DDB_INDDB;
! 287: mtx_leave(&ddb_mp_mutex);
! 288: for (i = 0; i < X86_MAXPROCS; i++) {
! 289: if (cpu_info[i] != NULL && i != cpu_number() &&
! 290: cpu_info[i]->ci_ddb_paused != CI_DDB_STOPPED) {
! 291: cpu_info[i]->ci_ddb_paused = CI_DDB_SHOULDSTOP;
! 292: x86_send_ipi(cpu_info[i], X86_IPI_DDB);
! 293: }
! 294: }
! 295: return (1);
! 296: }
! 297:
! 298: /* Leaving ddb completely. Start all other CPUs and return 0 */
! 299: if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_EXITING) {
! 300: for (i = 0; i < X86_MAXPROCS; i++) {
! 301: if (cpu_info[i] != NULL) {
! 302: cpu_info[i]->ci_ddb_paused = CI_DDB_RUNNING;
! 303: }
! 304: }
! 305: mtx_leave(&ddb_mp_mutex);
! 306: return (0);
! 307: }
! 308:
! 309: /* We're switching to another CPU. db_ddbproc_cmd() has made sure
! 310: * it is waiting for ddb, we just have to set ddb_active_cpu. */
! 311: if (ddb_active_cpu == cpu_number() && db_switch_cpu) {
! 312: curcpu()->ci_ddb_paused = CI_DDB_SHOULDSTOP;
! 313: db_switch_cpu = 0;
! 314: ddb_active_cpu = db_switch_to_cpu;
! 315: cpu_info[db_switch_to_cpu]->ci_ddb_paused = CI_DDB_ENTERDDB;
! 316: }
! 317:
! 318: /* Wait until we should enter ddb or resume */
! 319: while (ddb_active_cpu != cpu_number() &&
! 320: curcpu()->ci_ddb_paused != CI_DDB_RUNNING) {
! 321: if (curcpu()->ci_ddb_paused == CI_DDB_SHOULDSTOP)
! 322: curcpu()->ci_ddb_paused = CI_DDB_STOPPED;
! 323: mtx_leave(&ddb_mp_mutex);
! 324:
! 325: /* Busy wait without locking, we'll confirm with lock later */
! 326: while (ddb_active_cpu != cpu_number() &&
! 327: curcpu()->ci_ddb_paused != CI_DDB_RUNNING)
! 328: ; /* Do nothing */
! 329:
! 330: mtx_enter(&ddb_mp_mutex);
! 331: }
! 332:
! 333: /* Either enter ddb or exit */
! 334: if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_RUNNING) {
! 335: curcpu()->ci_ddb_paused = CI_DDB_INDDB;
! 336: mtx_leave(&ddb_mp_mutex);
! 337: return (1);
! 338: } else {
! 339: mtx_leave(&ddb_mp_mutex);
! 340: return (0);
! 341: }
! 342: }
! 343:
! 344: void
! 345: db_startcpu(int cpu)
! 346: {
! 347: if (cpu != cpu_number() && cpu_info[cpu] != NULL) {
! 348: mtx_enter(&ddb_mp_mutex);
! 349: cpu_info[cpu]->ci_ddb_paused = CI_DDB_RUNNING;
! 350: mtx_leave(&ddb_mp_mutex);
! 351: }
! 352: }
! 353:
! 354: void
! 355: db_stopcpu(int cpu)
! 356: {
! 357: mtx_enter(&ddb_mp_mutex);
! 358: if (cpu != cpu_number() && cpu_info[cpu] != NULL &&
! 359: cpu_info[cpu]->ci_ddb_paused != CI_DDB_STOPPED) {
! 360: cpu_info[cpu]->ci_ddb_paused = CI_DDB_SHOULDSTOP;
! 361: mtx_leave(&ddb_mp_mutex);
! 362: x86_send_ipi(cpu_info[cpu], X86_IPI_DDB);
! 363: } else {
! 364: mtx_leave(&ddb_mp_mutex);
! 365: }
! 366: }
! 367:
! 368: void
! 369: x86_ipi_db(struct cpu_info *ci)
! 370: {
! 371: Debugger();
! 372: }
! 373: #endif /* MULTIPROCESSOR */
! 374:
! 375: #if NACPI > 0
! 376: struct db_command db_acpi_cmds[] = {
! 377: { "disasm", db_acpi_disasm, CS_OWN, NULL },
! 378: { "showval", db_acpi_showval, CS_OWN, NULL },
! 379: { "tree", db_acpi_tree, 0, NULL },
! 380: { "trace", db_acpi_trace, 0, NULL },
! 381: { NULL, NULL, 0, NULL }
! 382: };
! 383: #endif /* NACPI > 0 */
! 384:
! 385: struct db_command db_machine_command_table[] = {
! 386: #ifdef MULTIPROCESSOR
! 387: { "cpuinfo", db_cpuinfo_cmd, 0, 0 },
! 388: { "startcpu", db_startproc_cmd, 0, 0 },
! 389: { "stopcpu", db_stopproc_cmd, 0, 0 },
! 390: { "ddbcpu", db_ddbproc_cmd, 0, 0 },
! 391: #endif
! 392: #if NACPI > 0
! 393: { "acpi", NULL, 0, db_acpi_cmds },
! 394: #endif /* NACPI > 0 */
! 395: { (char *)0, },
! 396: };
! 397:
! 398: void
! 399: db_machine_init(void)
! 400: {
! 401: #ifdef MULTIPROCESSOR
! 402: int i;
! 403: #endif
! 404:
! 405: db_machine_commands_install(db_machine_command_table);
! 406: #ifdef MULTIPROCESSOR
! 407: for (i = 0; i < X86_MAXPROCS; i++) {
! 408: if (cpu_info[i] != NULL)
! 409: cpu_info[i]->ci_ddb_paused = CI_DDB_RUNNING;
! 410: }
! 411: #endif
! 412: }
! 413:
! 414: void
! 415: Debugger(void)
! 416: {
! 417: breakpoint();
! 418: }
CVSweb