Annotation of sys/arch/powerpc/powerpc/vm_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: vm_machdep.c,v 1.44 2007/06/20 17:29:36 miod Exp $ */
! 2: /* $NetBSD: vm_machdep.c,v 1.1 1996/09/30 16:34:57 ws Exp $ */
! 3:
! 4: /*
! 5: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
! 6: * Copyright (C) 1995, 1996 TooLs GmbH.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. All advertising materials mentioning features or use of this software
! 18: * must display the following acknowledgement:
! 19: * This product includes software developed by TooLs GmbH.
! 20: * 4. The name of TooLs GmbH may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 27: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34: #include <sys/param.h>
! 35: #include <sys/core.h>
! 36: #include <sys/exec.h>
! 37: #include <sys/pool.h>
! 38: #include <sys/proc.h>
! 39: #include <sys/signalvar.h>
! 40: #include <sys/user.h>
! 41: #include <sys/vnode.h>
! 42: #include <sys/ptrace.h>
! 43:
! 44: #include <uvm/uvm_extern.h>
! 45:
! 46: #include <machine/pcb.h>
! 47: #include <machine/fpu.h>
! 48:
! 49: /*
! 50: * Finish a fork operation, with process p2 nearly set up.
! 51: */
! 52: void
! 53: cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
! 54: void (*func)(void *), void *arg)
! 55: {
! 56: struct trapframe *tf;
! 57: struct callframe *cf;
! 58: struct switchframe *sf;
! 59: caddr_t stktop1, stktop2;
! 60: extern void fork_trampoline(void);
! 61: struct pcb *pcb = &p2->p_addr->u_pcb;
! 62: struct cpu_info *ci = curcpu();
! 63:
! 64: if (p1 == ci->ci_fpuproc)
! 65: save_fpu();
! 66: *pcb = p1->p_addr->u_pcb;
! 67:
! 68: #ifdef ALTIVEC
! 69: if (p1->p_addr->u_pcb.pcb_vr != NULL) {
! 70: if (p1 == ci->ci_vecproc)
! 71: save_vec(p1);
! 72: pcb->pcb_vr = pool_get(&ppc_vecpl, PR_WAITOK);
! 73: *pcb->pcb_vr = *p1->p_addr->u_pcb.pcb_vr;
! 74: } else
! 75: pcb->pcb_vr = NULL;
! 76:
! 77: #endif /* ALTIVEC */
! 78:
! 79: pcb->pcb_pm = p2->p_vmspace->vm_map.pmap;
! 80:
! 81: pmap_extract(pmap_kernel(),
! 82: (vaddr_t)pcb->pcb_pm, (paddr_t *)&pcb->pcb_pmreal);
! 83:
! 84: /*
! 85: * Setup the trap frame for the new process
! 86: */
! 87: stktop1 = (caddr_t)trapframe(p1);
! 88: stktop2 = (caddr_t)trapframe(p2);
! 89: bcopy(stktop1, stktop2, sizeof(struct trapframe));
! 90:
! 91: /*
! 92: * If specified, give the child a different stack.
! 93: */
! 94: if (stack != NULL) {
! 95: tf = trapframe(p2);
! 96: tf->fixreg[1] = (register_t)stack + stacksize;
! 97: }
! 98:
! 99: stktop2 = (caddr_t)((u_long)stktop2 & ~15); /* Align stack pointer */
! 100:
! 101: /*
! 102: * There happens to be a callframe, too.
! 103: */
! 104: cf = (struct callframe *)stktop2;
! 105: cf->lr = (int)fork_trampoline;
! 106:
! 107: /*
! 108: * Below the trap frame, there is another call frame:
! 109: */
! 110: stktop2 -= 16;
! 111: cf = (struct callframe *)stktop2;
! 112: cf->r31 = (register_t)func;
! 113: cf->r30 = (register_t)arg;
! 114:
! 115: /*
! 116: * Below that, we allocate the switch frame:
! 117: */
! 118: /* must match SFRAMELEN in genassym */
! 119: stktop2 -= roundup(sizeof *sf, 16);
! 120:
! 121: sf = (struct switchframe *)stktop2;
! 122: bzero((void *)sf, sizeof *sf); /* just in case */
! 123: sf->sp = (int)cf;
! 124: sf->user_sr = pmap_kernel()->pm_sr[PPC_USER_SR]; /* just in case */
! 125: pcb->pcb_sp = (int)stktop2;
! 126: pcb->pcb_spl = 0;
! 127: }
! 128:
! 129: /*
! 130: * cpu_exit is called as the last action during exit.
! 131: * We release the address space and machine-dependent resources,
! 132: * including the memory for the user structure and kernel stack.
! 133: *
! 134: * Since we don't have curproc anymore, we cannot sleep, and therefor
! 135: * this is at least incorrect for the multiprocessor version.
! 136: * Not sure whether we can get away with this in the single proc version. XXX
! 137: */
! 138: void
! 139: cpu_exit(struct proc *p)
! 140: {
! 141: struct cpu_info *ci = curcpu();
! 142: #ifdef ALTIVEC
! 143: struct pcb *pcb = &p->p_addr->u_pcb;
! 144: #endif /* ALTIVEC */
! 145:
! 146: /* XXX What if the state is on the other cpu? */
! 147: if (p == ci->ci_fpuproc) /* release the fpu */
! 148: ci->ci_fpuproc = NULL;
! 149:
! 150: #ifdef ALTIVEC
! 151: /* XXX What if the state is on the other cpu? */
! 152: if (p == ci->ci_vecproc)
! 153: ci->ci_vecproc = NULL; /* release the Altivec Unit */
! 154: if (pcb->pcb_vr != NULL)
! 155: pool_put(&ppc_vecpl, pcb->pcb_vr);
! 156: #endif /* ALTIVEC */
! 157:
! 158: (void)splsched();
! 159: switchexit(p);
! 160: }
! 161:
! 162: /*
! 163: * Write the machine-dependent part of a core dump.
! 164: */
! 165: int
! 166: cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
! 167: struct core *chdr)
! 168: {
! 169: struct coreseg cseg;
! 170: struct md_coredump md_core;
! 171: int error;
! 172:
! 173: CORE_SETMAGIC(*chdr, COREMAGIC, MID_POWERPC, 0);
! 174: chdr->c_hdrsize = ALIGN(sizeof *chdr);
! 175: chdr->c_seghdrsize = ALIGN(sizeof cseg);
! 176: chdr->c_cpusize = sizeof md_core;
! 177:
! 178: process_read_regs(p, &(md_core.regs));
! 179:
! 180: CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_POWERPC, CORE_CPU);
! 181: cseg.c_addr = 0;
! 182: cseg.c_size = chdr->c_cpusize;
! 183:
! 184: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
! 185: (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT,
! 186: cred, NULL, p);
! 187: if (error)
! 188: return error;
! 189:
! 190: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof md_core,
! 191: (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
! 192: IO_NODELOCKED|IO_UNIT, cred, NULL, p);
! 193: if (error)
! 194: return error;
! 195:
! 196: chdr->c_nseg++;
! 197: return 0;
! 198: }
! 199:
! 200: /*
! 201: * Map an IO request into kernel virtual address space.
! 202: */
! 203: void
! 204: vmapbuf(struct buf *bp, vsize_t len)
! 205: {
! 206: vaddr_t faddr, taddr, off;
! 207: paddr_t pa;
! 208:
! 209: #ifdef DIAGNOSTIC
! 210: if (!(bp->b_flags & B_PHYS))
! 211: panic("vmapbuf");
! 212: #endif
! 213: faddr = trunc_page((vaddr_t)(bp->b_saveaddr = bp->b_data));
! 214: off = (vaddr_t)bp->b_data - faddr;
! 215: len = round_page(off + len);
! 216: taddr = uvm_km_valloc_wait(phys_map, len);
! 217: bp->b_data = (caddr_t)(taddr + off);
! 218: for (; len > 0; len -= NBPG) {
! 219: pmap_extract(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map),
! 220: faddr, &pa);
! 221: pmap_enter(vm_map_pmap(phys_map), taddr, pa,
! 222: VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
! 223: faddr += NBPG;
! 224: taddr += NBPG;
! 225: }
! 226: pmap_update(vm_map_pmap(phys_map));
! 227: }
! 228:
! 229: /*
! 230: * Free the io map addresses associated with this IO operation.
! 231: */
! 232: void
! 233: vunmapbuf(struct buf *bp, vsize_t len)
! 234: {
! 235: vaddr_t addr, off;
! 236:
! 237: #ifdef DIAGNOSTIC
! 238: if (!(bp->b_flags & B_PHYS))
! 239: panic("vunmapbuf");
! 240: #endif
! 241: addr = trunc_page((vaddr_t)bp->b_data);
! 242: off = (vaddr_t)bp->b_data - addr;
! 243: len = round_page(off + len);
! 244: pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
! 245: pmap_update(vm_map_pmap(phys_map));
! 246: uvm_km_free_wakeup(phys_map, addr, len);
! 247: bp->b_data = bp->b_saveaddr;
! 248: bp->b_saveaddr = 0;
! 249: }
CVSweb