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

Annotation of sys/arch/m88k/m88k/vm_machdep.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: vm_machdep.c,v 1.15 2007/06/20 17:29:36 miod Exp $    */
                      2:
                      3: /*
                      4:  * Copyright (c) 1998 Steve Murphree, Jr.
                      5:  * Copyright (c) 1996 Nivas Madhur
                      6:  * Copyright (c) 1993 Adam Glass
                      7:  * Copyright (c) 1988 University of Utah.
                      8:  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
                      9:  * All rights reserved.
                     10:  *
                     11:  * This code is derived from software contributed to Berkeley by
                     12:  * the Systems Programming Group of the University of Utah Computer
                     13:  * Science Department.
                     14:  *
                     15:  * Redistribution and use in source and binary forms, with or without
                     16:  * modification, are permitted provided that the following conditions
                     17:  * are met:
                     18:  * 1. Redistributions of source code must retain the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer.
                     20:  * 2. Redistributions in binary form must reproduce the above copyright
                     21:  *    notice, this list of conditions and the following disclaimer in the
                     22:  *    documentation and/or other materials provided with the distribution.
                     23:  * 3. Neither the name of the University nor the names of its contributors
                     24:  *    may be used to endorse or promote products derived from this software
                     25:  *    without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     28:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     29:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     30:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     31:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     32:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     33:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     34:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     35:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     36:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     37:  * SUCH DAMAGE.
                     38:  *
                     39:  *     from: Utah $Hdr: vm_machdep.c 1.21 91/04/06$
                     40:  *     from: @(#)vm_machdep.c  7.10 (Berkeley) 5/7/91
                     41:  *     vm_machdep.c,v 1.3 1993/07/07 07:09:32 cgd Exp
                     42:  */
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/signalvar.h>
                     48: #include <sys/malloc.h>
                     49: #include <sys/buf.h>
                     50: #include <sys/user.h>
                     51: #include <sys/vnode.h>
                     52: #include <sys/core.h>
                     53: #include <sys/exec.h>
                     54: #include <sys/ptrace.h>
                     55:
                     56: #include <uvm/uvm_extern.h>
                     57:
                     58: #include <machine/mmu.h>
                     59: #include <machine/cmmu.h>
                     60: #include <machine/cpu.h>
                     61: #include <machine/trap.h>
                     62:
                     63: extern void proc_do_uret(struct proc *);
                     64: extern void savectx(struct pcb *);
                     65: extern void switch_exit(struct proc *);
                     66:
                     67: /*
                     68:  * Finish a fork operation, with process p2 nearly set up.
                     69:  * Copy and update the kernel stack and pcb, making the child
                     70:  * ready to run, and marking it so that it can return differently
                     71:  * than the parent.  Returns 1 in the child process, 0 in the parent.
                     72:  * We currently double-map the user area so that the stack is at the same
                     73:  * address in each process; in the future we will probably relocate
                     74:  * the frame pointers on the stack after copying.
                     75:  */
                     76:
                     77: void
                     78: cpu_fork(p1, p2, stack, stacksize, func, arg)
                     79:        struct proc *p1, *p2;
                     80:        void *stack;
                     81:        size_t stacksize;
                     82:        void (*func)(void *);
                     83:        void *arg;
                     84: {
                     85:        struct switchframe *p2sf;
                     86:        struct ksigframe {
                     87:                void (*func)(void *);
                     88:                void *proc;
                     89:        } *ksfp;
                     90:        extern void proc_trampoline(void);
                     91:
                     92:        /* Copy pcb from p1 to p2. */
                     93:        if (p1 == curproc) {
                     94:                /* Sync the PCB before we copy it. */
                     95:                savectx(curpcb);
                     96:        }
                     97: #ifdef DIAGNOSTIC
                     98:        else if (p1 != &proc0)
                     99:                panic("cpu_fork: curproc");
                    100: #endif
                    101:
                    102:        bcopy(&p1->p_addr->u_pcb, &p2->p_addr->u_pcb, sizeof(struct pcb));
                    103:        p2->p_md.md_tf = (struct trapframe *)USER_REGS(p2);
                    104:
                    105:        /*
                    106:         * Create a switch frame for proc 2
                    107:         */
                    108:        p2sf = (struct switchframe *)((char *)p2->p_addr + USPACE - 8) - 1;
                    109:
                    110:        p2sf->sf_pc = (u_int)proc_do_uret;
                    111:        p2sf->sf_proc = p2;
                    112:        p2->p_addr->u_pcb.kernel_state.pcb_sp = (u_int)p2sf;
                    113:
                    114:        /*
                    115:         * If specified, give the child a different stack.
                    116:         */
                    117:        if (stack != NULL)
                    118:                USER_REGS(p2)->r[31] = (u_int)stack + stacksize;
                    119:
                    120:        ksfp = (struct ksigframe *)p2->p_addr->u_pcb.kernel_state.pcb_sp - 1;
                    121:
                    122:        ksfp->func = func;
                    123:        ksfp->proc = arg;
                    124:
                    125:        /*
                    126:         * When this process resumes, r31 will be ksfp and
                    127:         * the process will be at the beginning of proc_trampoline().
                    128:         * proc_trampoline will execute the function func, pop off
                    129:         * ksfp frame, and call the function in the switchframe
                    130:         * now exposed.
                    131:         */
                    132:
                    133:        p2->p_addr->u_pcb.kernel_state.pcb_sp = (u_int)ksfp;
                    134:        p2->p_addr->u_pcb.kernel_state.pcb_pc = (u_int)proc_trampoline;
                    135: }
                    136:
                    137: /*
                    138:  * cpu_exit is called as the last action during exit.
                    139:  * We release the address space and machine-dependent resources,
                    140:  * including the memory for the user structure and kernel stack.
                    141:  * Once finished, we call switch_exit, which switches to a temporary
                    142:  * pcb and stack and never returns.  We block memory allocation
                    143:  * until switch_exit has made things safe again.
                    144:  */
                    145: void
                    146: cpu_exit(struct proc *p)
                    147: {
                    148:        splhigh();
                    149:
                    150:        pmap_deactivate(p);
                    151:        switch_exit(p);
                    152:        /* NOTREACHED */
                    153: }
                    154:
                    155: /*
                    156:  * Dump the machine specific header information at the start of a core dump.
                    157:  */
                    158: int
                    159: cpu_coredump(p, vp, cred, chdr)
                    160:        struct proc *p;
                    161:        struct vnode *vp;
                    162:        struct ucred *cred;
                    163:        struct core *chdr;
                    164: {
                    165:        struct reg reg;
                    166:        struct coreseg cseg;
                    167:        int error;
                    168:
                    169:        CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
                    170:        chdr->c_hdrsize = ALIGN(sizeof(*chdr));
                    171:        chdr->c_seghdrsize = ALIGN(sizeof(cseg));
                    172:        chdr->c_cpusize = sizeof(reg);
                    173:
                    174:        /* Save registers. */
                    175:        error = process_read_regs(p, &reg);
                    176:        if (error)
                    177:                return error;
                    178:
                    179:        CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
                    180:        cseg.c_addr = 0;
                    181:        cseg.c_size = chdr->c_cpusize;
                    182:
                    183:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
                    184:            (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
                    185:            NULL, p);
                    186:        if (error)
                    187:                return error;
                    188:
                    189:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&reg, sizeof(reg),
                    190:            (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
                    191:            IO_NODELOCKED|IO_UNIT, cred, NULL, p);
                    192:        if (error)
                    193:                return error;
                    194:
                    195:        chdr->c_nseg++;
                    196:        return 0;
                    197: }
                    198:
                    199: /*
                    200:  * Map an IO request into kernel virtual address space via phys_map.
                    201:  */
                    202: void
                    203: vmapbuf(bp, len)
                    204:        struct buf *bp;
                    205:        vsize_t len;
                    206: {
                    207:        caddr_t addr;
                    208:        vaddr_t ova, kva, off;
                    209:        paddr_t pa;
                    210:        struct pmap *pmap;
                    211:        u_int pg;
                    212:
                    213: #ifdef DIAGNOSTIC
                    214:        if ((bp->b_flags & B_PHYS) == 0)
                    215:                panic("vmapbuf");
                    216: #endif
                    217:
                    218:        addr = (caddr_t)trunc_page((vaddr_t)(bp->b_saveaddr = bp->b_data));
                    219:        off = (vaddr_t)bp->b_saveaddr & PGOFSET;
                    220:        len = round_page(off + len);
                    221:        pmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
                    222:
                    223:        /*
                    224:         * You may ask: Why phys_map? kernel_map should be OK - after all,
                    225:         * we are mapping user va to kernel va or remapping some
                    226:         * kernel va to another kernel va. The answer is TLB flushing
                    227:         * when the address gets a new mapping.
                    228:         */
                    229:
                    230:        ova = kva = uvm_km_valloc_wait(phys_map, len);
                    231:
                    232:        /*
                    233:         * Flush the TLB for the range [kva, kva + off]. Strictly speaking,
                    234:         * we should do this in vunmapbuf(), but we do it lazily here, when
                    235:         * new pages get mapped in.
                    236:         */
                    237:
                    238:        cmmu_flush_tlb(cpu_number(), 1, kva, btoc(len));
                    239:
                    240:        bp->b_data = (caddr_t)(kva + off);
                    241:        for (pg = atop(len); pg != 0; pg--) {
                    242:                if (pmap_extract(pmap, (vaddr_t)addr, &pa) == FALSE)
                    243:                        panic("vmapbuf: null page frame");
                    244:                pmap_enter(vm_map_pmap(phys_map), kva, pa,
                    245:                           VM_PROT_READ | VM_PROT_WRITE,
                    246:                           VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
                    247:                addr += PAGE_SIZE;
                    248:                kva += PAGE_SIZE;
                    249:        }
                    250:        /* make sure snooping will be possible... */
                    251:        pmap_cache_ctrl(pmap_kernel(), ova, ova + len, CACHE_GLOBAL);
                    252:        pmap_update(pmap_kernel());
                    253: }
                    254:
                    255: /*
                    256:  * Free the io map PTEs associated with this IO operation.
                    257:  * We also restore the original b_addr.
                    258:  */
                    259: void
                    260: vunmapbuf(bp, len)
                    261:        struct buf *bp;
                    262:        vsize_t len;
                    263: {
                    264:        vaddr_t addr, off;
                    265:
                    266: #ifdef DIAGNOSTIC
                    267:        if ((bp->b_flags & B_PHYS) == 0)
                    268:                panic("vunmapbuf");
                    269: #endif
                    270:
                    271:        addr = trunc_page((vaddr_t)bp->b_data);
                    272:        off = (vaddr_t)bp->b_data & PGOFSET;
                    273:        len = round_page(off + len);
                    274:        pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
                    275:        pmap_update(vm_map_pmap(phys_map));
                    276:        uvm_km_free_wakeup(phys_map, addr, len);
                    277:        bp->b_data = bp->b_saveaddr;
                    278:        bp->b_saveaddr = 0;
                    279: }

CVSweb