Annotation of sys/arch/m88k/m88k/vm_machdep.c, Revision 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, ®);
! 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)®, 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