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

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

1.1     ! nbrk        1: /*     $OpenBSD: vm_machdep.c,v 1.34 2007/06/20 17:29:36 miod Exp $    */
        !             2: /*     $NetBSD: vm_machdep.c,v 1.67 2000/06/29 07:14:34 mrg Exp $           */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed at Ludd, University of Lule}.
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: #include <sys/types.h>
        !            35: #include <sys/param.h>
        !            36: #include <sys/systm.h>
        !            37: #include <sys/proc.h>
        !            38: #include <sys/signalvar.h>
        !            39: #include <sys/user.h>
        !            40: #include <sys/exec.h>
        !            41: #include <sys/vnode.h>
        !            42: #include <sys/core.h>
        !            43: #include <sys/mount.h>
        !            44: #include <sys/device.h>
        !            45:
        !            46: #include <uvm/uvm_extern.h>
        !            47:
        !            48: #include <machine/vmparam.h>
        !            49: #include <machine/mtpr.h>
        !            50: #include <machine/pmap.h>
        !            51: #include <machine/pte.h>
        !            52: #include <machine/macros.h>
        !            53: #include <machine/trap.h>
        !            54: #include <machine/pcb.h>
        !            55: #include <machine/frame.h>
        !            56: #include <machine/cpu.h>
        !            57: #include <machine/sid.h>
        !            58:
        !            59: #include <sys/syscallargs.h>
        !            60:
        !            61: /*
        !            62:  * Finish a fork operation, with process p2 nearly set up.
        !            63:  * Copy and update the pcb and trap frame, making the child ready to run.
        !            64:  *
        !            65:  * Rig the child's kernel stack so that it will start out in
        !            66:  * proc_trampoline() and call child_return() with p2 as an
        !            67:  * argument. This causes the newly-created child process to go
        !            68:  * directly to user level with an apparent return value of 0 from
        !            69:  * fork(), while the parent process returns normally.
        !            70:  *
        !            71:  * p1 is the process being forked;
        !            72:  *
        !            73:  * If an alternate user-level stack is requested (with non-zero values
        !            74:  * in both the stack and stacksize args), set up the user stack pointer
        !            75:  * accordingly.
        !            76:  *
        !            77:  * cpu_fork() copies parent process trapframe directly into child PCB
        !            78:  * so that when we swtch() to the child process it will go directly
        !            79:  * back to user mode without any need to jump back through kernel.
        !            80:  * We also take away mapping for the second page after pcb, so that
        !            81:  * we get something like a "red zone".
        !            82:  * No need for either double-map kernel stack or relocate it when
        !            83:  * forking.
        !            84:  */
        !            85: void
        !            86: cpu_fork(p1, p2, stack, stacksize, func, arg)
        !            87:        struct proc *p1, *p2;
        !            88:        void *stack;
        !            89:        size_t stacksize;
        !            90:        void (*func)(void *);
        !            91:        void *arg;
        !            92: {
        !            93:        struct pcb *pcb;
        !            94:        struct trapframe *tf;
        !            95:        struct callsframe *cf;
        !            96:        extern int sret; /* Return address in trap routine */
        !            97:
        !            98: #ifdef DIAGNOSTIC
        !            99:        /*
        !           100:         * if p1 != curproc && p1 == &proc0, we're creating a kernel thread.
        !           101:         */
        !           102:        if (p1 != curproc && p1 != &proc0)
        !           103:                panic("cpu_fork: curproc");
        !           104: #endif
        !           105:
        !           106:        /*
        !           107:         * Copy the trap frame.
        !           108:         */
        !           109:        tf = (struct trapframe *)((u_int)p2->p_addr + USPACE) - 1;
        !           110:        p2->p_addr->u_pcb.framep = tf;
        !           111:        bcopy(p1->p_addr->u_pcb.framep, tf, sizeof(*tf));
        !           112:
        !           113:        /*
        !           114:         * Activate address space for the new process.  The PTEs have
        !           115:         * already been allocated by way of pmap_create().
        !           116:         * This writes the page table registers to the PCB.
        !           117:         */
        !           118:        pmap_activate(p2);
        !           119:
        !           120:        /* Mark guard page invalid in kernel stack */
        !           121:        *kvtopte((u_int)p2->p_addr + REDZONEADDR) &= ~PG_V;
        !           122:
        !           123:        /*
        !           124:         * Set up the calls frame above (below) the trapframe
        !           125:         * and populate it with something good.
        !           126:         * This is so that we can simulate that we were called by a
        !           127:         * CALLS insn in the function given as argument.
        !           128:         */
        !           129:        cf = (struct callsframe *)tf - 1;
        !           130:        cf->ca_cond = 0;
        !           131:        cf->ca_maskpsw = 0x20000000;    /* CALLS stack frame, no registers */
        !           132:        cf->ca_pc = (unsigned)&sret;    /* return PC; userspace trampoline */
        !           133:        cf->ca_argno = 1;
        !           134:        cf->ca_arg1 = (int)arg;
        !           135:
        !           136:        /*
        !           137:         * Set up internal defs in PCB. This matches the "fake" CALLS frame
        !           138:         * that we constructed earlier.
        !           139:         */
        !           140:        pcb = &p2->p_addr->u_pcb;
        !           141:        pcb->iftrap = NULL;
        !           142:        pcb->KSP = (long)cf;
        !           143:        pcb->FP = (long)cf;
        !           144:        pcb->AP = (long)&cf->ca_argno;
        !           145:        pcb->PC = (int)func + 2;        /* Skip save mask */
        !           146:
        !           147:        /*
        !           148:         * If specified, give the child a different stack.
        !           149:         */
        !           150:        if (stack != NULL)
        !           151:                tf->sp = (u_long)stack + stacksize;
        !           152:
        !           153:        tf->r0 = p1->p_pid; /* parent pid. (shouldn't be needed) */
        !           154:        tf->r1 = 1;
        !           155:        tf->psl = PSL_U|PSL_PREVU;
        !           156: }
        !           157:
        !           158: int
        !           159: cpu_exec_aout_makecmds(p, epp)
        !           160:        struct proc *p;
        !           161:        struct exec_package *epp;
        !           162: {
        !           163:        return ENOEXEC;
        !           164: }
        !           165:
        !           166: int
        !           167: sys_sysarch(p, v, retval)
        !           168:        struct proc *p;
        !           169:        void *v;
        !           170:        register_t *retval;
        !           171: {
        !           172:
        !           173:        return (ENOSYS);
        !           174: };
        !           175:
        !           176: /*
        !           177:  * Dump the machine specific header information at the start of a core dump.
        !           178:  * First put all regs in PCB for debugging purposes. This is not an good
        !           179:  * way to do this, but good for my purposes so far.
        !           180:  */
        !           181: int
        !           182: cpu_coredump(p, vp, cred, chdr)
        !           183:        struct proc *p;
        !           184:        struct vnode *vp;
        !           185:        struct ucred *cred;
        !           186:        struct core *chdr;
        !           187: {
        !           188:        struct trapframe *tf;
        !           189:        struct md_coredump state;
        !           190:        struct reg *regs = &state.md_reg;
        !           191:        struct coreseg cseg;
        !           192:        int error;
        !           193:
        !           194:        tf = p->p_addr->u_pcb.framep;
        !           195:        CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
        !           196:        chdr->c_hdrsize = sizeof(struct core);
        !           197:        chdr->c_seghdrsize = sizeof(struct coreseg);
        !           198:        chdr->c_cpusize = sizeof(struct md_coredump);
        !           199:
        !           200:        bcopy(&tf->r0, &regs->r0, 12 * sizeof(int));
        !           201:        regs->ap = tf->ap;
        !           202:        regs->fp = tf->fp;
        !           203:        regs->sp = tf->sp;
        !           204:        regs->pc = tf->pc;
        !           205:        regs->psl = tf->psl;
        !           206:
        !           207:        CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
        !           208:        cseg.c_addr = 0;
        !           209:        cseg.c_size = chdr->c_cpusize;
        !           210:
        !           211:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
        !           212:            (off_t)chdr->c_hdrsize, UIO_SYSSPACE,
        !           213:            IO_NODELOCKED|IO_UNIT, cred, NULL, p);
        !           214:        if (error)
        !           215:                return error;
        !           216:
        !           217:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&state, sizeof(state),
        !           218:            (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
        !           219:            IO_NODELOCKED|IO_UNIT, cred, NULL, p);
        !           220:
        !           221:        if (!error)
        !           222:                chdr->c_nseg++;
        !           223:
        !           224:        return error;
        !           225: }
        !           226:
        !           227: /*
        !           228:  * Map in a bunch of pages read/writeable for the kernel.
        !           229:  */
        !           230: void
        !           231: ioaccess(vaddr, paddr, npgs)
        !           232:        vaddr_t vaddr;
        !           233:        paddr_t paddr;
        !           234:        int npgs;
        !           235: {
        !           236:        u_int *pte = (u_int *)kvtopte(vaddr), template;
        !           237:
        !           238:        template = PG_V | PG_KW | PG_PFNUM(paddr);
        !           239:        while (npgs-- != 0)
        !           240:                *pte++ = template++;
        !           241:        mtpr(0, PR_TBIA);
        !           242: }
        !           243:
        !           244: /*
        !           245:  * Opposite to the above: just forget their mapping.
        !           246:  */
        !           247: void
        !           248: iounaccess(vaddr, npgs)
        !           249:        vaddr_t vaddr;
        !           250:        int npgs;
        !           251: {
        !           252:        u_int *pte = (u_int *)kvtopte(vaddr);
        !           253:
        !           254:        while (npgs-- != 0)
        !           255:                *pte++ = PG_NV;
        !           256:        mtpr(0, PR_TBIA);
        !           257: }
        !           258:
        !           259: /*
        !           260:  * Map a user I/O request into kernel virtual address space.
        !           261:  * Note: the pages are already locked by uvm_vslock(), so we
        !           262:  * do not need to pass an access_type to pmap_enter().
        !           263:  */
        !           264: void
        !           265: vmapbuf(bp, len)
        !           266:        struct buf *bp;
        !           267:        vsize_t len;
        !           268: {
        !           269: #if VAX46 || VAX48 || VAX49 || VAX53
        !           270:        vaddr_t faddr, taddr, off;
        !           271:        paddr_t pa;
        !           272:        struct proc *p;
        !           273:
        !           274:        if (vax_boardtype != VAX_BTYP_46
        !           275:            && vax_boardtype != VAX_BTYP_48
        !           276:            && vax_boardtype != VAX_BTYP_49
        !           277:            && vax_boardtype != VAX_BTYP_1303)
        !           278:                return;
        !           279:        if ((bp->b_flags & B_PHYS) == 0)
        !           280:                panic("vmapbuf");
        !           281:        p = bp->b_proc;
        !           282:        faddr = trunc_page((vaddr_t)(bp->b_saveaddr = bp->b_data));
        !           283:        off = (vaddr_t)bp->b_data - faddr;
        !           284:        len = round_page(off + len);
        !           285:        taddr = uvm_km_valloc_wait(phys_map, len);
        !           286:        bp->b_data = (caddr_t)(taddr + off);
        !           287:        len = atop(len);
        !           288:        while (len--) {
        !           289:                if (pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map), faddr,
        !           290:                                &pa) == FALSE)
        !           291:                        panic("vmapbuf: null page frame");
        !           292:                pmap_enter(vm_map_pmap(phys_map), taddr, trunc_page(pa),
        !           293:                    VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
        !           294:                faddr += PAGE_SIZE;
        !           295:                taddr += PAGE_SIZE;
        !           296:        }
        !           297:        pmap_update(vm_map_pmap(phys_map));
        !           298: #endif
        !           299: }
        !           300:
        !           301: /*
        !           302:  * Unmap a previously-mapped user I/O request.
        !           303:  */
        !           304: void
        !           305: vunmapbuf(bp, len)
        !           306:        struct buf *bp;
        !           307:        vsize_t len;
        !           308: {
        !           309: #if VAX46 || VAX48 || VAX49 || VAX53
        !           310:        vaddr_t addr, off;
        !           311:
        !           312:        if (vax_boardtype != VAX_BTYP_46
        !           313:            && vax_boardtype != VAX_BTYP_48
        !           314:            && vax_boardtype != VAX_BTYP_49
        !           315:            && vax_boardtype != VAX_BTYP_1303)
        !           316:                return;
        !           317:        if ((bp->b_flags & B_PHYS) == 0)
        !           318:                panic("vunmapbuf");
        !           319:        addr = trunc_page((vaddr_t)bp->b_data);
        !           320:        off = (vaddr_t)bp->b_data - addr;
        !           321:        len = round_page(off + len);
        !           322:        pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
        !           323:        pmap_update(vm_map_pmap(phys_map));
        !           324:        uvm_km_free_wakeup(phys_map, addr, len);
        !           325:        bp->b_data = bp->b_saveaddr;
        !           326:        bp->b_saveaddr = NULL;
        !           327: #endif
        !           328: }

CVSweb