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

Annotation of sys/arch/alpha/alpha/vm_machdep.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: vm_machdep.c,v 1.33 2007/05/27 20:59:24 miod Exp $ */
        !             2: /* $NetBSD: vm_machdep.c,v 1.55 2000/03/29 03:49:48 simonb Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: Chris G. Demetriou
        !             9:  *
        !            10:  * Permission to use, copy, modify and distribute this software and
        !            11:  * its documentation is hereby granted, provided that both the copyright
        !            12:  * notice and this permission notice appear in all copies of the
        !            13:  * software, derivative works or modified versions, and any portions
        !            14:  * thereof, and that both notices appear in supporting documentation.
        !            15:  *
        !            16:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            17:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            19:  *
        !            20:  * Carnegie Mellon requests users of this software to return to
        !            21:  *
        !            22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            23:  *  School of Computer Science
        !            24:  *  Carnegie Mellon University
        !            25:  *  Pittsburgh PA 15213-3890
        !            26:  *
        !            27:  * any improvements or extensions that they make and grant Carnegie the
        !            28:  * rights to redistribute these changes.
        !            29:  */
        !            30:
        !            31: #include <sys/param.h>
        !            32: #include <sys/systm.h>
        !            33: #include <sys/proc.h>
        !            34: #include <sys/signalvar.h>
        !            35: #include <sys/malloc.h>
        !            36: #include <sys/buf.h>
        !            37: #include <sys/vnode.h>
        !            38: #include <sys/user.h>
        !            39: #include <sys/core.h>
        !            40: #include <sys/exec.h>
        !            41:
        !            42: #include <uvm/uvm_extern.h>
        !            43:
        !            44: #include <machine/cpu.h>
        !            45: #include <machine/pmap.h>
        !            46: #include <machine/reg.h>
        !            47:
        !            48:
        !            49: /*
        !            50:  * Dump the machine specific header information at the start of a core dump.
        !            51:  */
        !            52: int
        !            53: cpu_coredump(p, vp, cred, chdr)
        !            54:        struct proc *p;
        !            55:        struct vnode *vp;
        !            56:        struct ucred *cred;
        !            57:        struct core *chdr;
        !            58: {
        !            59:        int error;
        !            60:        struct md_coredump cpustate;
        !            61:        struct coreseg cseg;
        !            62:
        !            63:        CORE_SETMAGIC(*chdr, COREMAGIC, MID_ALPHA, 0);
        !            64:        chdr->c_hdrsize = ALIGN(sizeof(*chdr));
        !            65:        chdr->c_seghdrsize = ALIGN(sizeof(cseg));
        !            66:        chdr->c_cpusize = sizeof(cpustate);
        !            67:
        !            68:        cpustate.md_tf = *p->p_md.md_tf;
        !            69:        cpustate.md_tf.tf_regs[FRAME_SP] = alpha_pal_rdusp();   /* XXX */
        !            70:        if (p->p_md.md_flags & MDP_FPUSED) {
        !            71:                if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
        !            72:                        fpusave_proc(p, 1);
        !            73:                cpustate.md_fpstate = p->p_addr->u_pcb.pcb_fp;
        !            74:        } else
        !            75:                bzero(&cpustate.md_fpstate, sizeof(cpustate.md_fpstate));
        !            76:
        !            77:        CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ALPHA, CORE_CPU);
        !            78:        cseg.c_addr = 0;
        !            79:        cseg.c_size = chdr->c_cpusize;
        !            80:
        !            81:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
        !            82:            (off_t)chdr->c_hdrsize, UIO_SYSSPACE,
        !            83:            IO_NODELOCKED|IO_UNIT, cred, NULL, p);
        !            84:        if (error)
        !            85:                return error;
        !            86:
        !            87:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cpustate, sizeof(cpustate),
        !            88:            (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
        !            89:            IO_NODELOCKED|IO_UNIT, cred, NULL, p);
        !            90:
        !            91:        if (!error)
        !            92:                chdr->c_nseg++;
        !            93:
        !            94:        return error;
        !            95: }
        !            96:
        !            97: /*
        !            98:  * cpu_exit is called as the last action during exit.
        !            99:  * We block interrupts and call switch_exit.  switch_exit switches
        !           100:  * to proc0's PCB and stack, then jumps into the middle of cpu_switch,
        !           101:  * as if it were switching from proc0.
        !           102:  */
        !           103: void
        !           104: cpu_exit(p)
        !           105:        struct proc *p;
        !           106: {
        !           107:
        !           108:        if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
        !           109:                fpusave_proc(p, 0);
        !           110:
        !           111:        /*
        !           112:         * Deactivate the exiting address space before the vmspace
        !           113:         * is freed.  Note that we will continue to run on this
        !           114:         * vmspace's context until the switch to proc0 in switch_exit().
        !           115:         */
        !           116:        pmap_deactivate(p);
        !           117:
        !           118:        (void) splhigh();
        !           119:        switch_exit(p);
        !           120:        /* NOTREACHED */
        !           121: }
        !           122:
        !           123: /*
        !           124:  * Finish a fork operation, with process p2 nearly set up.
        !           125:  * Copy and update the pcb and trap frame, making the child ready to run.
        !           126:  *
        !           127:  * Rig the child's kernel stack so that it will start out in
        !           128:  * switch_trampoline() and call child_return() with p2 as an
        !           129:  * argument. This causes the newly-created child process to go
        !           130:  * directly to user level with an apparent return value of 0 from
        !           131:  * fork(), while the parent process returns normally.
        !           132:  *
        !           133:  * p1 is the process being forked;
        !           134:  *
        !           135:  * If an alternate user-level stack is requested (with non-zero values
        !           136:  * in both the stack and stacksize args), set up the user stack pointer
        !           137:  * accordingly.
        !           138:  */
        !           139: void
        !           140: cpu_fork(p1, p2, stack, stacksize, func, arg)
        !           141:        struct proc *p1, *p2;
        !           142:        void *stack;
        !           143:        size_t stacksize;
        !           144:        void (*func)(void *);
        !           145:        void *arg;
        !           146: {
        !           147:        struct user *up = p2->p_addr;
        !           148:
        !           149:        p2->p_md.md_tf = p1->p_md.md_tf;
        !           150:
        !           151: #ifndef NO_IEEE
        !           152:        p2->p_md.md_flags = p1->p_md.md_flags & (MDP_FPUSED | MDP_FP_C);
        !           153: #else
        !           154:        p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED;
        !           155: #endif
        !           156:
        !           157:        /*
        !           158:         * Cache the physical address of the pcb, so we can
        !           159:         * swap to it easily.
        !           160:         */
        !           161:        p2->p_md.md_pcbpaddr = (void *)vtophys((vaddr_t)&up->u_pcb);
        !           162:
        !           163:        /*
        !           164:         * Copy floating point state from the FP chip to the PCB
        !           165:         * if this process has state stored there.
        !           166:         */
        !           167:        if (p1->p_addr->u_pcb.pcb_fpcpu != NULL)
        !           168:                fpusave_proc(p1, 1);
        !           169:
        !           170:        /*
        !           171:         * Copy pcb and stack from proc p1 to p2.
        !           172:         * We do this as cheaply as possible, copying only the active
        !           173:         * part of the stack.  The stack and pcb need to agree;
        !           174:         */
        !           175:        p2->p_addr->u_pcb = p1->p_addr->u_pcb;
        !           176:        p2->p_addr->u_pcb.pcb_hw.apcb_usp = alpha_pal_rdusp();
        !           177:
        !           178:        /*
        !           179:         * Arrange for a non-local goto when the new process
        !           180:         * is started, to resume here, returning nonzero from setjmp.
        !           181:         */
        !           182: #ifdef DIAGNOSTIC
        !           183:        /*
        !           184:         * If p1 != curproc && p1 == &proc0, we are creating a kernel
        !           185:         * thread.
        !           186:         */
        !           187:        if (p1 != curproc && p1 != &proc0)
        !           188:                panic("cpu_fork: curproc");
        !           189:        if ((up->u_pcb.pcb_hw.apcb_flags & ALPHA_PCB_FLAGS_FEN) != 0)
        !           190:                printf("DANGER WILL ROBINSON: FEN SET IN cpu_fork!\n");
        !           191: #endif
        !           192:
        !           193:        /*
        !           194:         * create the child's kernel stack, from scratch.
        !           195:         */
        !           196:        {
        !           197:                struct trapframe *p2tf;
        !           198:
        !           199:                /*
        !           200:                 * Pick a stack pointer, leaving room for a trapframe;
        !           201:                 * copy trapframe from parent so return to user mode
        !           202:                 * will be to right address, with correct registers.
        !           203:                 */
        !           204:                p2tf = p2->p_md.md_tf = (struct trapframe *)
        !           205:                    ((char *)p2->p_addr + USPACE - sizeof(struct trapframe));
        !           206:                bcopy(p1->p_md.md_tf, p2->p_md.md_tf,
        !           207:                    sizeof(struct trapframe));
        !           208:
        !           209:                /*
        !           210:                 * Set up return-value registers as fork() libc stub expects.
        !           211:                 */
        !           212:                p2tf->tf_regs[FRAME_V0] = p1->p_pid;    /* parent's pid */
        !           213:                p2tf->tf_regs[FRAME_A3] = 0;            /* no error */
        !           214:                p2tf->tf_regs[FRAME_A4] = 1;            /* is child */
        !           215:
        !           216:                /*
        !           217:                 * If specificed, give the child a different stack.
        !           218:                 */
        !           219:                if (stack != NULL)
        !           220:                        p2tf->tf_regs[FRAME_SP] = (u_long)stack + stacksize;
        !           221:
        !           222:                /*
        !           223:                 * Arrange for continuation at child_return(), which
        !           224:                 * will return to exception_return().  Note that the child
        !           225:                 * process doesn't stay in the kernel for long!
        !           226:                 */
        !           227:                up->u_pcb.pcb_hw.apcb_ksp = (u_int64_t)p2tf;
        !           228:                up->u_pcb.pcb_context[0] = (u_int64_t)func;
        !           229:                up->u_pcb.pcb_context[1] =
        !           230:                    (u_int64_t)exception_return;        /* s1: ra */
        !           231:                up->u_pcb.pcb_context[2] = (u_int64_t)arg;
        !           232:                up->u_pcb.pcb_context[7] =
        !           233:                    (u_int64_t)switch_trampoline;       /* ra: assembly magic */
        !           234:                up->u_pcb.pcb_context[8] = ALPHA_PSL_IPL_0; /* ps: IPL */
        !           235:        }
        !           236: }
        !           237:
        !           238: /*
        !           239:  * Map a user I/O request into kernel virtual address space.
        !           240:  * Note: the pages are already locked by uvm_vslock(), so we
        !           241:  * do not need to pass an access_type to pmap_enter().
        !           242:  */
        !           243: void
        !           244: vmapbuf(bp, len)
        !           245:        struct buf *bp;
        !           246:        vsize_t len;
        !           247: {
        !           248:        vaddr_t faddr, taddr, off;
        !           249:        paddr_t pa;
        !           250:        struct proc *p;
        !           251:
        !           252:        if ((bp->b_flags & B_PHYS) == 0)
        !           253:                panic("vmapbuf");
        !           254:        p = bp->b_proc;
        !           255:        faddr = trunc_page((vaddr_t)bp->b_saveaddr = bp->b_data);
        !           256:        off = (vaddr_t)bp->b_data - faddr;
        !           257:        len = round_page(off + len);
        !           258:        taddr = uvm_km_valloc_wait(phys_map, len);
        !           259:        bp->b_data = (caddr_t)(taddr + off);
        !           260:        len = atop(len);
        !           261:        while (len--) {
        !           262:                if (pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),
        !           263:                    faddr, &pa) == FALSE)
        !           264:                        panic("vmapbuf: null page frame");
        !           265:                pmap_enter(vm_map_pmap(phys_map), taddr, trunc_page(pa),
        !           266:                    VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
        !           267:                faddr += PAGE_SIZE;
        !           268:                taddr += PAGE_SIZE;
        !           269:        }
        !           270:        pmap_update(vm_map_pmap(phys_map));
        !           271: }
        !           272:
        !           273: /*
        !           274:  * Unmap a previously-mapped user I/O request.
        !           275:  */
        !           276: void
        !           277: vunmapbuf(bp, len)
        !           278:        struct buf *bp;
        !           279:        vsize_t len;
        !           280: {
        !           281:        vaddr_t addr, off;
        !           282:
        !           283:        if ((bp->b_flags & B_PHYS) == 0)
        !           284:                panic("vunmapbuf");
        !           285:        addr = trunc_page((vaddr_t)bp->b_data);
        !           286:        off = (vaddr_t)bp->b_data - addr;
        !           287:        len = round_page(off + len);
        !           288:        pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
        !           289:        pmap_update(vm_map_pmap(phys_map));
        !           290:        uvm_km_free_wakeup(phys_map, addr, len);
        !           291:        bp->b_data = bp->b_saveaddr;
        !           292:        bp->b_saveaddr = NULL;
        !           293: }

CVSweb