vm_machdep.c revision 90361
1/*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * Copyright (c) 1989, 1990 William Jolitz
4 * Copyright (c) 1994 John Dyson
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department, and William Jolitz.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the University of
22 *	California, Berkeley and its contributors.
23 * 4. 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: @(#)vm_machdep.c	7.3 (Berkeley) 5/13/91
40 *	Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
41 * $FreeBSD: head/sys/ia64/ia64/vm_machdep.c 90361 2002-02-07 20:58:47Z julian $
42 */
43/*
44 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
45 * All rights reserved.
46 *
47 * Author: Chris G. Demetriou
48 *
49 * Permission to use, copy, modify and distribute this software and
50 * its documentation is hereby granted, provided that both the copyright
51 * notice and this permission notice appear in all copies of the
52 * software, derivative works or modified versions, and any portions
53 * thereof, and that both notices appear in supporting documentation.
54 *
55 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
56 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
57 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
58 *
59 * Carnegie Mellon requests users of this software to return to
60 *
61 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
62 *  School of Computer Science
63 *  Carnegie Mellon University
64 *  Pittsburgh PA 15213-3890
65 *
66 * any improvements or extensions that they make and grant Carnegie the
67 * rights to redistribute these changes.
68 */
69
70#include <sys/param.h>
71#include <sys/systm.h>
72#include <sys/proc.h>
73#include <sys/malloc.h>
74#include <sys/bio.h>
75#include <sys/buf.h>
76#include <sys/vnode.h>
77#include <sys/vmmeter.h>
78#include <sys/kernel.h>
79#include <sys/sysctl.h>
80#include <sys/unistd.h>
81
82#include <machine/clock.h>
83#include <machine/cpu.h>
84#include <machine/fpu.h>
85#include <machine/md_var.h>
86
87#include <vm/vm.h>
88#include <vm/vm_param.h>
89#include <sys/lock.h>
90#include <vm/vm_kern.h>
91#include <vm/vm_page.h>
92#include <vm/vm_map.h>
93#include <vm/vm_extern.h>
94
95#include <sys/user.h>
96
97/*
98 * quick version of vm_fault
99 */
100int
101vm_fault_quick(v, prot)
102	caddr_t v;
103	int prot;
104{
105	int r;
106	if (prot & VM_PROT_WRITE)
107		r = subyte(v, fubyte(v));
108	else
109		r = fubyte(v);
110	return(r);
111}
112
113struct ia64_fdesc {
114	u_int64_t	func;
115	u_int64_t	gp;
116};
117
118#define FDESC_FUNC(fn)	(((struct ia64_fdesc *) fn)->func)
119#define FDESC_GP(fn)	(((struct ia64_fdesc *) fn)->gp)
120
121/*
122 * Finish a fork operation, with process p2 nearly set up.
123 * Copy and update the pcb, set up the stack so that the child
124 * ready to run and return to user mode.
125 */
126void
127cpu_fork(td1, p2, td2, flags)
128	register struct thread *td1;
129	register struct proc *p2;
130	register struct thread *td2;
131	int flags;
132{
133	struct proc *p1;
134	struct trapframe *p2tf;
135	u_int64_t bspstore, *p1bs, *p2bs, rnatloc, rnat;
136
137	if ((flags & RFPROC) == 0)
138		return;
139
140	p1 = td1->td_proc;
141	td2->td_pcb = (struct pcb *)
142	    (td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
143	td2->td_md.md_flags = td1->td_md.md_flags & (MDP_FPUSED | MDP_UAC_MASK);
144
145	/*
146	 * Copy floating point state from the FP chip to the PCB
147	 * if this process has state stored there.
148	 */
149	ia64_fpstate_save(td1, 0);
150
151	/*
152	 * Copy pcb and stack from proc p1 to p2.  We do this as
153	 * cheaply as possible, copying only the active part of the
154	 * stack.  The stack and pcb need to agree. Make sure that the
155	 * new process has FEN disabled.
156	 */
157	bcopy(td1->td_pcb, td2->td_pcb, sizeof(struct pcb));
158
159	/*
160	 * Set the floating point state.
161	 */
162#if 0
163	if ((td2->td_pcb->pcb_fp_control & IEEE_INHERIT) == 0) {
164		td2->td_pcb->pcb_fp_control = 0;
165		td2->td_pcb->pcb_fp.fpr_cr = (FPCR_DYN_NORMAL
166						   | FPCR_INVD | FPCR_DZED
167						   | FPCR_OVFD | FPCR_INED
168						   | FPCR_UNFD);
169	}
170#endif
171
172	/*
173	 * Arrange for a non-local goto when the new process
174	 * is started, to resume here, returning nonzero from setjmp.
175	 */
176#ifdef DIAGNOSTIC
177	if (td1 != curthread)
178		panic("cpu_fork: curproc");
179	ia64_fpstate_check(td1);
180#endif
181
182	/*
183	 * create the child's kernel stack, from scratch.
184	 *
185	 * Pick a stack pointer, leaving room for a trapframe;
186	 * copy trapframe from parent so return to user mode
187	 * will be to right address, with correct registers.
188	 */
189	td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
190	bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
191
192	/*
193	 * Set up return-value registers as fork() libc stub expects.
194	 */
195	p2tf = td2->td_frame;
196	p2tf->tf_r[FRAME_R8] = 0; 	/* child's pid (linux) 	*/
197	p2tf->tf_r[FRAME_R9] = 1;	/* is child (FreeBSD) 	*/
198	p2tf->tf_r[FRAME_R10] = 0;	/* no error 		*/
199
200	/*
201	 * Turn off RSE for a moment and work out our current
202	 * ar.bspstore. This assumes that td1==curthread. Also
203	 * flush dirty regs to ensure that the user's stacked
204	 * regs are written out to backing store.
205	 *
206	 * We could cope with td1!=curthread by digging values
207	 * out of its PCB but I don't see the point since
208	 * current usage never allows it.
209	 */
210	__asm __volatile("mov ar.rsc=0;;");
211	__asm __volatile("flushrs;;" ::: "memory");
212	__asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore));
213
214	p1bs = (u_int64_t *)td1->td_kstack;
215	p2bs = (u_int64_t *)td2->td_kstack;
216
217	/*
218	 * Copy enough of td1's backing store to include all
219	 * the user's stacked regs.
220	 */
221	bcopy(p1bs, p2bs, td1->td_frame->tf_ndirty);
222	/*
223	 * To calculate the ar.rnat for td2, we need to decide
224	 * if td1's ar.bspstore has advanced past the place
225	 * where the last ar.rnat which covers the user's
226	 * saved registers would be placed. If so, we read
227	 * that one from memory, otherwise we take td1's
228	 * current ar.rnat.
229	 */
230	rnatloc = (u_int64_t)p1bs + td1->td_frame->tf_ndirty;
231	rnatloc |= 0x1f8;
232	if (bspstore > rnatloc)
233		rnat = *(u_int64_t *) rnatloc;
234	else
235		__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
236
237	/*
238	 * Switch the RSE back on.
239	 */
240	__asm __volatile("mov ar.rsc=3;;");
241
242	/*
243	 * Setup the child's pcb so that its ar.bspstore
244	 * starts just above the region which we copied. This
245	 * should work since the child will normally return
246	 * straight into exception_restore.
247	 */
248	td2->td_pcb->pcb_bspstore = (u_int64_t)p2bs + td1->td_frame->tf_ndirty;
249	td2->td_pcb->pcb_rnat = rnat;
250	td2->td_pcb->pcb_pfs = 0;
251
252	/*
253	 * Arrange for continuation at fork_return(), which
254	 * will return to exception_restore().  Note that the
255	 * child process doesn't stay in the kernel for long!
256	 *
257	 * The extra 16 bytes subtracted from sp is part of the ia64
258	 * ABI - a function can assume that the 16 bytes above sp are
259	 * available as scratch space.
260	 */
261	td2->td_pcb->pcb_sp = (u_int64_t)p2tf - 16;
262	td2->td_pcb->pcb_r4 = (u_int64_t)fork_return;
263	td2->td_pcb->pcb_r5 = FDESC_FUNC(exception_restore);
264	td2->td_pcb->pcb_r6 = (u_int64_t)td2;
265	td2->td_pcb->pcb_b0 = FDESC_FUNC(fork_trampoline);
266}
267
268/*
269 * Intercept the return address from a freshly forked process that has NOT
270 * been scheduled yet.
271 *
272 * This is needed to make kernel threads stay in kernel mode.
273 */
274void
275cpu_set_fork_handler(td, func, arg)
276	struct thread *td;
277	void (*func) __P((void *));
278	void *arg;
279{
280	td->td_pcb->pcb_r4 = (u_int64_t) func;
281	td->td_pcb->pcb_r6 = (u_int64_t) arg;
282}
283
284/*
285 * cpu_exit is called as the last action during exit.
286 * We drop the fp state (if we have it) and switch to a live one.
287 * When the proc is reaped, cpu_wait() will gc the VM state.
288 */
289void
290cpu_exit(td)
291	register struct thread *td;
292{
293
294	ia64_fpstate_drop(td);
295}
296
297void
298cpu_wait(p)
299	struct proc *p;
300{
301}
302
303/* Temporary helper */
304void
305cpu_throw(void)
306{
307
308	cpu_switch();
309	panic("cpu_throw() didn't");
310}
311
312/*
313 * Dump the machine specific header information at the start of a core dump.
314 */
315int
316cpu_coredump(td, vp, cred)
317	struct thread *td;
318	struct vnode *vp;
319	struct ucred *cred;
320{
321	int error;
322
323	error = vn_rdwr(UIO_WRITE, vp, (caddr_t) td->td_proc->p_uarea,
324	    ctob(UAREA_PAGES), (off_t)0,
325	    UIO_SYSSPACE, IO_UNIT, cred, (int *)NULL, td);
326	if (error)
327		return error;
328	error = vn_rdwr(UIO_WRITE, vp, (caddr_t) td->td_kstack,
329	    ctob(KSTACK_PAGES), (off_t)0,
330	    UIO_SYSSPACE, IO_UNIT, cred, (int *)NULL, td);
331	return error;
332}
333
334/*
335 * Map an IO request into kernel virtual address space.
336 *
337 * All requests are (re)mapped into kernel VA space.
338 * Notice that we use b_bufsize for the size of the buffer
339 * to be mapped.  b_bcount might be modified by the driver.
340 */
341void
342vmapbuf(bp)
343	register struct buf *bp;
344{
345	register caddr_t addr, v, kva;
346	vm_offset_t pa;
347
348	GIANT_REQUIRED;
349
350	if ((bp->b_flags & B_PHYS) == 0)
351		panic("vmapbuf");
352
353	for (v = bp->b_saveaddr, addr = (caddr_t)trunc_page(bp->b_data);
354	    addr < bp->b_data + bp->b_bufsize;
355	    addr += PAGE_SIZE, v += PAGE_SIZE) {
356		/*
357		 * Do the vm_fault if needed; do the copy-on-write thing
358		 * when reading stuff off device into memory.
359		 */
360		vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data,
361			(bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ);
362		pa = trunc_page(pmap_kextract((vm_offset_t) addr));
363		if (pa == 0)
364			panic("vmapbuf: page not present");
365		vm_page_hold(PHYS_TO_VM_PAGE(pa));
366		pmap_kenter((vm_offset_t) v, pa);
367	}
368
369	kva = bp->b_saveaddr;
370	bp->b_saveaddr = bp->b_data;
371	bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK);
372}
373
374/*
375 * Free the io map PTEs associated with this IO operation.
376 * We also invalidate the TLB entries and restore the original b_addr.
377 */
378void
379vunmapbuf(bp)
380	register struct buf *bp;
381{
382	register caddr_t addr;
383	vm_offset_t pa;
384
385	GIANT_REQUIRED;
386
387	if ((bp->b_flags & B_PHYS) == 0)
388		panic("vunmapbuf");
389
390	for (addr = (caddr_t)trunc_page(bp->b_data);
391	    addr < bp->b_data + bp->b_bufsize;
392	    addr += PAGE_SIZE) {
393		pa = trunc_page(pmap_kextract((vm_offset_t) addr));
394		pmap_kremove((vm_offset_t) addr);
395		vm_page_unhold(PHYS_TO_VM_PAGE(pa));
396	}
397
398	bp->b_data = bp->b_saveaddr;
399}
400
401/*
402 * Force reset the processor by invalidating the entire address space!
403 */
404void
405cpu_reset()
406{
407
408	cpu_boot(0);
409}
410
411int
412grow_stack(p, sp)
413	struct proc *p;
414	size_t sp;
415{
416	int rv;
417
418	rv = vm_map_growstack (p, sp);
419	if (rv != KERN_SUCCESS)
420		return (0);
421
422	return (1);
423}
424
425/*
426 * Software interrupt handler for queued VM system processing.
427 */
428void
429swi_vm(void *dummy)
430{
431#if 0
432	if (busdma_swi_pending != 0)
433		busdma_swi();
434#endif
435}
436
437/*
438 * Tell whether this address is in some physical memory region.
439 * Currently used by the kernel coredump code in order to avoid
440 * dumping the ``ISA memory hole'' which could cause indefinite hangs,
441 * or other unpredictable behaviour.
442 */
443
444
445int
446is_physical_memory(addr)
447	vm_offset_t addr;
448{
449	/*
450	 * stuff other tests for known memory-mapped devices (PCI?)
451	 * here
452	 */
453
454	return 1;
455}
456