[BACK]Return to db_interface.c CVS log [TXT][DIR] Up to [local] / sys / arch / amd64 / amd64

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