Annotation of sys/arch/sh/sh/vm_machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: vm_machdep.c,v 1.9 2007/05/27 20:59:26 miod Exp $ */
2: /* $NetBSD: vm_machdep.c,v 1.53 2006/08/31 16:49:21 matt Exp $ */
3:
4: /*
5: * Copyright (c) 2007 Miodrag Vallat.
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, this permission notice, and the disclaimer below
10: * appear in all copies.
11: *
12: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19: */
20: /*-
21: * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved.
22: * Copyright (c) 1982, 1986 The Regents of the University of California.
23: * All rights reserved.
24: *
25: * This code is derived from software contributed to Berkeley by
26: * the Systems Programming Group of the University of Utah Computer
27: * Science Department, and William Jolitz.
28: *
29: * Redistribution and use in source and binary forms, with or without
30: * modification, are permitted provided that the following conditions
31: * are met:
32: * 1. Redistributions of source code must retain the above copyright
33: * notice, this list of conditions and the following disclaimer.
34: * 2. Redistributions in binary form must reproduce the above copyright
35: * notice, this list of conditions and the following disclaimer in the
36: * documentation and/or other materials provided with the distribution.
37: * 3. Neither the name of the University nor the names of its contributors
38: * may be used to endorse or promote products derived from this software
39: * without specific prior written permission.
40: *
41: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51: * SUCH DAMAGE.
52: *
53: * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
54: */
55: /*-
56: * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
57: * Copyright (c) 1989, 1990 William Jolitz
58: * All rights reserved.
59: *
60: * This code is derived from software contributed to Berkeley by
61: * the Systems Programming Group of the University of Utah Computer
62: * Science Department, and William Jolitz.
63: *
64: * Redistribution and use in source and binary forms, with or without
65: * modification, are permitted provided that the following conditions
66: * are met:
67: * 1. Redistributions of source code must retain the above copyright
68: * notice, this list of conditions and the following disclaimer.
69: * 2. Redistributions in binary form must reproduce the above copyright
70: * notice, this list of conditions and the following disclaimer in the
71: * documentation and/or other materials provided with the distribution.
72: * 3. All advertising materials mentioning features or use of this software
73: * must display the following acknowledgement:
74: * This product includes software developed by the University of
75: * California, Berkeley and its contributors.
76: * 4. Neither the name of the University nor the names of its contributors
77: * may be used to endorse or promote products derived from this software
78: * without specific prior written permission.
79: *
80: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90: * SUCH DAMAGE.
91: *
92: * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
93: */
94:
95: /*
96: * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
97: */
98:
99: #include <sys/param.h>
100: #include <sys/systm.h>
101: #include <sys/proc.h>
102: #include <sys/malloc.h>
103: #include <sys/vnode.h>
104: #include <sys/buf.h>
105: #include <sys/user.h>
106: #include <sys/core.h>
107: #include <sys/exec.h>
108: #include <sys/ptrace.h>
109: #include <sys/signalvar.h>
110:
111: #include <uvm/uvm_extern.h>
112:
113: #include <sh/locore.h>
114: #include <sh/cpu.h>
115: #include <sh/reg.h>
116: #include <sh/mmu.h>
117: #include <sh/cache.h>
118:
119: extern void proc_trampoline(void);
120:
121: /*
122: * Finish a fork operation, with process p2 nearly set up.
123: * Copy and update the pcb and trap frame, making the child ready to run.
124: *
125: * Rig the child's kernel stack so that it will start out in
126: * proc_trampoline() and call child_return() with p2 as an
127: * argument. This causes the newly-created child process to go
128: * directly to user level with an apparent return value of 0 from
129: * fork(), while the parent process returns normally.
130: *
131: * p1 is the process being forked; if p1 == &proc0, we are creating
132: * a kernel thread, and the return path and argument are specified with
133: * `func' and `arg'.
134: *
135: * If an alternate user-level stack is requested (with non-zero values
136: * in both the stack and stacksize args), set up the user stack pointer
137: * accordingly.
138: */
139: void
140: cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
141: void (*func)(void *), void *arg)
142: {
143: struct pcb *pcb;
144: struct trapframe *tf;
145: struct switchframe *sf;
146: vaddr_t spbase, fptop;
147: #define P1ADDR(x) (SH3_PHYS_TO_P1SEG(*__pmap_kpte_lookup(x) & PG_PPN))
148:
149: KDASSERT(p1 == curproc || p1 == &proc0);
150:
151: bzero(&p2->p_md, sizeof(p2->p_md));
152:
153: /* Copy flags */
154: p2->p_md.md_flags = p1->p_md.md_flags;
155:
156: pcb = NULL; /* XXXGCC: -Wuninitialized */
157: #ifdef SH3
158: /*
159: * Convert frame pointer top to P1. because SH3 can't make
160: * wired TLB entry, context store space accessing must not cause
161: * exception. For SH3, we are 4K page, P3/P1 conversion don't
162: * cause virtual-aliasing.
163: */
164: if (CPU_IS_SH3)
165: pcb = (struct pcb *)P1ADDR((vaddr_t)&p2->p_addr->u_pcb);
166: #endif /* SH3 */
167: #ifdef SH4
168: /* SH4 can make wired entry, no need to convert to P1. */
169: if (CPU_IS_SH4)
170: pcb = &p2->p_addr->u_pcb;
171: #endif /* SH4 */
172:
173: p2->p_md.md_pcb = pcb;
174: fptop = (vaddr_t)pcb + PAGE_SIZE;
175:
176: /* set up the kernel stack pointer */
177: spbase = (vaddr_t)p2->p_addr + PAGE_SIZE;
178: #ifdef P1_STACK
179: /* Convert to P1 from P3 */
180: /*
181: * wbinv u-area to avoid cache-aliasing, since kernel stack
182: * is accessed from P1 instead of P3.
183: */
184: if (SH_HAS_VIRTUAL_ALIAS)
185: sh_dcache_wbinv_range((vaddr_t)p2->p_addr, USPACE);
186: spbase = P1ADDR(spbase);
187: #else /* !P1_STACK */
188: /* Prepare u-area PTEs */
189: #ifdef SH3
190: if (CPU_IS_SH3)
191: sh3_switch_setup(p2);
192: #endif
193: #ifdef SH4
194: if (CPU_IS_SH4)
195: sh4_switch_setup(p2);
196: #endif
197: #endif /* !P1_STACK */
198:
199: #ifdef KSTACK_DEBUG
200: /* Fill magic number for tracking */
201: memset((char *)fptop - PAGE_SIZE + sizeof(struct user), 0x5a,
202: PAGE_SIZE - sizeof(struct user));
203: memset((char *)spbase, 0xa5, (USPACE - PAGE_SIZE));
204: memset(&pcb->pcb_sf, 0xb4, sizeof(struct switchframe));
205: #endif /* KSTACK_DEBUG */
206:
207: /*
208: * Copy the user context.
209: */
210: p2->p_md.md_regs = tf = (struct trapframe *)fptop - 1;
211: memcpy(tf, p1->p_md.md_regs, sizeof(struct trapframe));
212:
213: /*
214: * If specified, give the child a different stack.
215: */
216: if (stack != NULL)
217: tf->tf_r15 = (u_int)stack + stacksize;
218:
219: /* Setup switch frame */
220: sf = &pcb->pcb_sf;
221: sf->sf_r11 = (int)arg; /* proc_trampoline hook func's arg */
222: sf->sf_r12 = (int)func; /* proc_trampoline hook func */
223: sf->sf_r15 = spbase + USPACE - PAGE_SIZE;/* current stack pointer */
224: sf->sf_r7_bank = sf->sf_r15; /* stack top */
225: sf->sf_r6_bank = (vaddr_t)tf; /* current frame pointer */
226: /* when switch to me, jump to proc_trampoline */
227: sf->sf_pr = (int)proc_trampoline;
228: /*
229: * Enable interrupt when switch frame is restored, since
230: * kernel thread begin to run without restoring trapframe.
231: */
232: sf->sf_sr = PSL_MD; /* kernel mode, interrupt enable */
233:
234: #ifdef SH4
235: if (CPU_IS_SH4) {
236: /*
237: * Propagate floating point registers to the new process
238: * (they are not in the trapframe).
239: */
240: if (p1 == curproc)
241: fpu_save(&p1->p_md.md_pcb->pcb_fp);
242: bcopy(&p1->p_md.md_pcb->pcb_fp, &pcb->pcb_fp,
243: sizeof(struct fpreg));
244: }
245: #endif
246: }
247:
248: /*
249: * Dump the machine specific segment at the start of a core dump.
250: */
251: struct md_core {
252: struct reg intreg;
253: struct fpreg fpreg;
254: };
255:
256: int
257: cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
258: struct core *chdr)
259: {
260: struct md_core md_core;
261: struct coreseg cseg;
262: int error;
263:
264: CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
265: chdr->c_hdrsize = ALIGN(sizeof(*chdr));
266: chdr->c_seghdrsize = ALIGN(sizeof(cseg));
267: chdr->c_cpusize = sizeof(md_core);
268:
269: /* Save integer registers. */
270: error = process_read_regs(p, &md_core.intreg);
271: if (error)
272: return error;
273:
274: #ifdef SH4
275: if (CPU_IS_SH4) {
276: error = process_read_fpregs(p, &md_core.fpreg);
277: if (error)
278: return error;
279: }
280: #endif
281: #ifdef SH3
282: if (CPU_IS_SH3)
283: bzero(&md_core.fpreg, sizeof(md_core.fpreg));
284: #endif
285:
286: CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
287: cseg.c_addr = 0;
288: cseg.c_size = chdr->c_cpusize;
289:
290: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
291: (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred,
292: NULL, p);
293: if (error)
294: return error;
295:
296: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
297: (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
298: IO_NODELOCKED | IO_UNIT, cred, NULL, p);
299: if (error)
300: return error;
301:
302: chdr->c_nseg++;
303: return 0;
304: }
305:
306: /*
307: * Map an IO request into kernel virtual address space.
308: * All requests are (re)mapped into kernel VA space via the phys_map
309: * (a name with only slightly more meaning than "kernel_map")
310: */
311:
312: void
313: vmapbuf(struct buf *bp, vsize_t len)
314: {
315: vaddr_t faddr, taddr, off;
316: paddr_t fpa;
317: pmap_t kpmap, upmap;
318:
319: if ((bp->b_flags & B_PHYS) == 0)
320: panic("vmapbuf");
321: bp->b_saveaddr = bp->b_data;
322: faddr = trunc_page((vaddr_t)bp->b_data);
323: off = (vaddr_t)bp->b_data - faddr;
324: len = round_page(off + len);
325: taddr = uvm_km_valloc_wait(phys_map, len);
326: bp->b_data = (caddr_t)(taddr + off);
327: /*
328: * The region is locked, so we expect that pmap_pte() will return
329: * non-NULL.
330: * XXX: unwise to expect this in a multithreaded environment.
331: * anything can happen to a pmap between the time we lock a
332: * region, release the pmap lock, and then relock it for
333: * the pmap_extract().
334: *
335: * no need to flush TLB since we expect nothing to be mapped
336: * where we we just allocated (TLB will be flushed when our
337: * mapping is removed).
338: */
339: upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
340: kpmap = vm_map_pmap(phys_map);
341: while (len) {
342: pmap_extract(upmap, faddr, &fpa);
343: pmap_enter(kpmap, taddr, fpa,
344: VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
345: faddr += PAGE_SIZE;
346: taddr += PAGE_SIZE;
347: len -= PAGE_SIZE;
348: }
349: pmap_update(kpmap);
350: }
351:
352: /*
353: * Free the io map PTEs associated with this IO operation.
354: * We also invalidate the TLB entries and restore the original b_addr.
355: */
356: void
357: vunmapbuf(struct buf *bp, vsize_t len)
358: {
359: vaddr_t addr, off;
360: pmap_t kpmap;
361:
362: if ((bp->b_flags & B_PHYS) == 0)
363: panic("vunmapbuf");
364: addr = trunc_page((vaddr_t)bp->b_data);
365: off = (vaddr_t)bp->b_data - addr;
366: len = round_page(off + len);
367: kpmap = vm_map_pmap(phys_map);
368: pmap_remove(kpmap, addr, addr + len);
369: pmap_update(kpmap);
370: uvm_km_free_wakeup(phys_map, addr, len);
371: bp->b_data = bp->b_saveaddr;
372: bp->b_saveaddr = 0;
373: }
CVSweb