Annotation of sys/arch/powerpc/powerpc/vm_machdep.c, Revision 1.1.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