Annotation of sys/arch/hppa64/hppa64/vm_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: vm_machdep.c,v 1.7 2007/06/20 17:29:35 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
! 16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20:
! 21: #include <sys/param.h>
! 22: #include <sys/systm.h>
! 23: #include <sys/proc.h>
! 24: #include <sys/signalvar.h>
! 25: #include <sys/malloc.h>
! 26: #include <sys/buf.h>
! 27: #include <sys/vnode.h>
! 28: #include <sys/user.h>
! 29: #include <sys/ptrace.h>
! 30: #include <sys/exec.h>
! 31: #include <sys/core.h>
! 32:
! 33: #include <machine/psl.h>
! 34: #include <machine/pmap.h>
! 35: #include <machine/pcb.h>
! 36:
! 37: #include <uvm/uvm.h>
! 38:
! 39:
! 40: /*
! 41: * Dump the machine specific header information at the start of a core dump.
! 42: */
! 43: int
! 44: cpu_coredump(p, vp, cred, core)
! 45: struct proc *p;
! 46: struct vnode *vp;
! 47: struct ucred *cred;
! 48: struct core *core;
! 49: {
! 50: struct md_coredump md_core;
! 51: struct coreseg cseg;
! 52: off_t off;
! 53: int error;
! 54:
! 55: CORE_SETMAGIC(*core, COREMAGIC, MID_HPPA20, 0);
! 56: core->c_hdrsize = ALIGN(sizeof(*core));
! 57: core->c_seghdrsize = ALIGN(sizeof(cseg));
! 58: core->c_cpusize = sizeof(md_core);
! 59:
! 60: process_read_regs(p, &md_core.md_reg);
! 61: process_read_fpregs(p, &md_core.md_fpreg);
! 62:
! 63: CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_HPPA20, CORE_CPU);
! 64: cseg.c_addr = 0;
! 65: cseg.c_size = core->c_cpusize;
! 66:
! 67: #define write(vp, addr, n) \
! 68: vn_rdwr(UIO_WRITE, (vp), (caddr_t)(addr), (n), off, \
! 69: UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p)
! 70:
! 71: off = core->c_hdrsize;
! 72: if ((error = write(vp, &cseg, core->c_seghdrsize)))
! 73: return error;
! 74: off += core->c_seghdrsize;
! 75: if ((error = write(vp, &md_core, sizeof md_core)))
! 76: return error;
! 77:
! 78: #undef write
! 79: core->c_nseg++;
! 80:
! 81: return error;
! 82: }
! 83:
! 84: void
! 85: cpu_fork(p1, p2, stack, stacksize, func, arg)
! 86: struct proc *p1, *p2;
! 87: void *stack;
! 88: size_t stacksize;
! 89: void (*func)(void *);
! 90: void *arg;
! 91: {
! 92: extern paddr_t fpu_curpcb; /* from locore.S */
! 93: extern register_t switch_tramp_p;
! 94: extern u_int fpu_enable;
! 95:
! 96: struct pcb *pcbp;
! 97: struct trapframe *tf;
! 98: register_t sp, osp;
! 99: paddr_t pa;
! 100:
! 101: #ifdef DIAGNOSTIC
! 102: if (round_page(sizeof(struct user) + sizeof(*tf)) > PAGE_SIZE)
! 103: panic("USPACE too small for user");
! 104: #endif
! 105: if (p1->p_md.md_regs->tf_cr30 == fpu_curpcb) {
! 106: mtctl(fpu_enable, CR_CCR);
! 107: fpu_save(fpu_curpcb);
! 108: mtctl(0, CR_CCR);
! 109: }
! 110:
! 111: pcbp = &p2->p_addr->u_pcb;
! 112: bcopy(&p1->p_addr->u_pcb, pcbp, sizeof(*pcbp));
! 113: /* space is cached for the copy{in,out}'s pleasure */
! 114: pcbp->pcb_space = p2->p_vmspace->vm_map.pmap->pm_space;
! 115: pcbp->pcb_uva = (vaddr_t)p2->p_addr;
! 116: /* reset any of the pending FPU exceptions from parent */
! 117: pcbp->pcb_fpregs[0] = HPPA_FPU_FORK(pcbp->pcb_fpregs[0]);
! 118: pcbp->pcb_fpregs[1] = 0;
! 119: pcbp->pcb_fpregs[2] = 0;
! 120: pcbp->pcb_fpregs[3] = 0;
! 121: fdcache(HPPA_SID_KERNEL, (vaddr_t)&pcbp->pcb_fpregs[0], 8 * 4);
! 122:
! 123: sp = (register_t)p2->p_addr + PAGE_SIZE;
! 124: p2->p_md.md_regs = tf = (struct trapframe *)sp;
! 125: sp += sizeof(struct trapframe);
! 126: bcopy(p1->p_md.md_regs, tf, sizeof(*tf));
! 127:
! 128: /*
! 129: * Stash the physical for the pcb of U for later perusal
! 130: */
! 131: if (!pmap_extract(pmap_kernel(), (vaddr_t)p2->p_addr, &pa))
! 132: panic("pmap_extract(%p) failed", p2->p_addr);
! 133:
! 134: tf->tf_cr30 = pa;
! 135:
! 136: tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 =
! 137: tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 =
! 138: tf->tf_iisq[0] = tf->tf_iisq[1] =
! 139: p2->p_vmspace->vm_map.pmap->pm_space;
! 140: tf->tf_pidr1 = tf->tf_pidr2 = pmap_sid2pid(tf->tf_sr0);
! 141:
! 142: /*
! 143: * theoretically these could be inherited from the father,
! 144: * but just in case.
! 145: */
! 146: tf->tf_sr7 = HPPA_SID_KERNEL;
! 147: tf->tf_eiem = mfctl(CR_EIEM);
! 148: tf->tf_ipsw = PSL_C | PSL_Q | PSL_P | PSL_D | PSL_I /* | PSL_L */;
! 149:
! 150: /*
! 151: * If specified, give the child a different stack.
! 152: */
! 153: if (stack != NULL)
! 154: tf->tf_sp = (register_t)stack;
! 155:
! 156: /*
! 157: * Build stack frames for the cpu_switch & co.
! 158: */
! 159: osp = sp + HPPA_FRAME_SIZE;
! 160: *(register_t*)(osp - HPPA_FRAME_SIZE) = 0;
! 161: *(register_t*)(osp + HPPA_FRAME_RP) = switch_tramp_p;
! 162: *(register_t*)(osp) = (osp - HPPA_FRAME_SIZE);
! 163:
! 164: sp = osp + HPPA_FRAME_SIZE + 20*8; /* frame + calee-save registers */
! 165: *(register_t*)(sp - HPPA_FRAME_SIZE + 0) = (register_t)arg;
! 166: *(register_t*)(sp - HPPA_FRAME_SIZE + 8) = KERNMODE(func);
! 167: *(register_t*)(sp - HPPA_FRAME_SIZE + 16) = 0; /* cpl */
! 168: pcbp->pcb_ksp = sp;
! 169: fdcache(HPPA_SID_KERNEL, (vaddr_t)p2->p_addr, sp - (vaddr_t)p2->p_addr);
! 170: }
! 171:
! 172: void
! 173: cpu_exit(p)
! 174: struct proc *p;
! 175: {
! 176: extern paddr_t fpu_curpcb; /* from locore.S */
! 177: struct trapframe *tf = p->p_md.md_regs;
! 178:
! 179: if (fpu_curpcb == tf->tf_cr30) {
! 180: fpu_exit();
! 181: fpu_curpcb = 0;
! 182: }
! 183:
! 184: exit2(p);
! 185: cpu_switch(p);
! 186: }
! 187:
! 188: void
! 189: cpu_wait(p)
! 190: struct proc *p;
! 191: {
! 192: }
! 193:
! 194: /*
! 195: * Map an IO request into kernel virtual address space.
! 196: */
! 197: void
! 198: vmapbuf(bp, len)
! 199: struct buf *bp;
! 200: vsize_t len;
! 201: {
! 202: struct pmap *pm = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
! 203: vaddr_t kva, uva;
! 204: vsize_t size, off;
! 205:
! 206: #ifdef DIAGNOSTIC
! 207: if ((bp->b_flags & B_PHYS) == 0)
! 208: panic("vmapbuf");
! 209: #endif
! 210: bp->b_saveaddr = bp->b_data;
! 211: uva = trunc_page((vaddr_t)bp->b_data);
! 212: off = (vaddr_t)bp->b_data - uva;
! 213: size = round_page(off + len);
! 214:
! 215: /*
! 216: * We do it on our own here to be able to specify an offset to uvm_map
! 217: * so that we can get all benefits of PMAP_PREFER.
! 218: * - art@
! 219: */
! 220: kva = uvm_km_valloc_prefer_wait(phys_map, size, uva);
! 221: fdcache(pm->pm_space, uva, size);
! 222: bp->b_data = (caddr_t)(kva + off);
! 223: while (size > 0) {
! 224: paddr_t pa;
! 225:
! 226: if (pmap_extract(pm, uva, &pa) == FALSE)
! 227: panic("vmapbuf: null page frame");
! 228: else
! 229: pmap_kenter_pa(kva, pa, UVM_PROT_RW);
! 230: uva += PAGE_SIZE;
! 231: kva += PAGE_SIZE;
! 232: size -= PAGE_SIZE;
! 233: }
! 234: pmap_update(pmap_kernel());
! 235: }
! 236:
! 237: /*
! 238: * Unmap IO request from the kernel virtual address space.
! 239: */
! 240: void
! 241: vunmapbuf(bp, len)
! 242: struct buf *bp;
! 243: vsize_t len;
! 244: {
! 245: vaddr_t addr, off;
! 246:
! 247: #ifdef DIAGNOSTIC
! 248: if ((bp->b_flags & B_PHYS) == 0)
! 249: panic("vunmapbuf");
! 250: #endif
! 251: addr = trunc_page((vaddr_t)bp->b_data);
! 252: off = (vaddr_t)bp->b_data - addr;
! 253: len = round_page(off + len);
! 254: pmap_kremove(addr, len);
! 255: pmap_update(pmap_kernel());
! 256: uvm_km_free_wakeup(phys_map, addr, len);
! 257: bp->b_data = bp->b_saveaddr;
! 258: bp->b_saveaddr = NULL;
! 259: }
CVSweb