Annotation of XNU/osfmk/i386/db_interface.c, revision 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.