Annotation of XNU/osfmk/i386/db_interface.c, revision 1.1.1.1

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 *)&regs->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)&regs->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()] = &regs;
                    418: 
                    419: #if    NCPUS > 1
                    420:        if (!kdb_enter(regs.eip))
                    421:                goto kdb_exit;
                    422: #endif /* NCPUS > 1 */
                    423: 
                    424:        bcopy((char *)&regs, (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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.