vm_machdep.c revision 101945
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 101945 2002-08-15 21:41:20Z rwatson $
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#include <i386/include/psl.h>
98
99/*
100 * quick version of vm_fault
101 */
102int
103vm_fault_quick(v, prot)
104	caddr_t v;
105	int prot;
106{
107	int r;
108	if (prot & VM_PROT_WRITE)
109		r = subyte(v, fubyte(v));
110	else
111		r = fubyte(v);
112	return(r);
113}
114
115void
116cpu_thread_exit(struct thread *td)
117{
118}
119
120void
121cpu_thread_setup(struct thread *td)
122{
123}
124
125void
126cpu_save_upcall(struct thread *td, struct kse *newkse)
127{
128}
129
130void
131cpu_set_upcall(struct thread *td, void *pcb)
132{
133}
134
135void
136cpu_set_args(struct thread *td, struct kse *ke)
137{
138}
139
140void
141cpu_free_kse_mdstorage(struct kse *ke)
142{
143}
144
145int
146cpu_export_context(struct thread *td)
147{
148       return (0);
149}
150
151
152/*
153 * Finish a fork operation, with process p2 nearly set up.
154 * Copy and update the pcb, set up the stack so that the child
155 * ready to run and return to user mode.
156 */
157void
158cpu_fork(td1, p2, td2, flags)
159	register struct thread *td1;
160	register struct proc *p2;
161	register struct thread *td2;
162	int flags;
163{
164	struct proc *p1;
165	struct trapframe *p2tf;
166	u_int64_t bspstore, *p1bs, *p2bs, rnatloc, rnat;
167
168	KASSERT(td1 == curthread || td1 == &thread0,
169	    ("cpu_fork: p1 not curproc and not proc0"));
170
171	if ((flags & RFPROC) == 0)
172		return;
173
174	p1 = td1->td_proc;
175	td2->td_pcb = (struct pcb *)
176	    (td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
177	td2->td_md.md_flags = td1->td_md.md_flags & (MDP_FPUSED | MDP_UAC_MASK);
178
179	/*
180	 * Copy floating point state from the FP chip to the PCB
181	 * if this process has state stored there.
182	 */
183	ia64_fpstate_save(td1, 0);
184
185	/*
186	 * Copy pcb and stack from proc p1 to p2.  We do this as
187	 * cheaply as possible, copying only the active part of the
188	 * stack.  The stack and pcb need to agree. Make sure that the
189	 * new process has FEN disabled.
190	 */
191	bcopy(td1->td_pcb, td2->td_pcb, sizeof(struct pcb));
192
193	/*
194	 * Set the floating point state.
195	 */
196#if 0
197	if ((td2->td_pcb->pcb_fp_control & IEEE_INHERIT) == 0) {
198		td2->td_pcb->pcb_fp_control = 0;
199		td2->td_pcb->pcb_fp.fpr_cr = (FPCR_DYN_NORMAL
200						   | FPCR_INVD | FPCR_DZED
201						   | FPCR_OVFD | FPCR_INED
202						   | FPCR_UNFD);
203	}
204#endif
205
206	/*
207	 * Arrange for a non-local goto when the new process
208	 * is started, to resume here, returning nonzero from setjmp.
209	 */
210#ifdef DIAGNOSTIC
211	if (td1 == curthread)
212		ia64_fpstate_check(td1);
213#endif
214
215	/*
216	 * create the child's kernel stack, from scratch.
217	 *
218	 * Pick a stack pointer, leaving room for a trapframe;
219	 * copy trapframe from parent so return to user mode
220	 * will be to right address, with correct registers. Clear the
221	 * high-fp enable for the new process so that it is forced to
222	 * load its state from the pcb.
223	 */
224	td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
225	bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
226	td2->td_frame->tf_cr_ipsr |= IA64_PSR_DFH;
227
228	/*
229	 * Set up return-value registers as fork() libc stub expects.
230	 */
231	p2tf = td2->td_frame;
232	if (p2tf->tf_cr_ipsr & IA64_PSR_IS) {
233		p2tf->tf_r[FRAME_R8] = 0; /* child returns zero (eax) */
234		p2tf->tf_r[FRAME_R10] = 1; /* is child (edx) */
235		td2->td_pcb->pcb_eflag &= ~PSL_C; /* no error */
236	} else {
237		p2tf->tf_r[FRAME_R8] = 0; /* child's pid (linux) 	*/
238		p2tf->tf_r[FRAME_R9] = 1; /* is child (FreeBSD) 	*/
239		p2tf->tf_r[FRAME_R10] = 0; /* no error	 		*/
240	}
241
242	/*
243	 * Turn off RSE for a moment and work out our current
244	 * ar.bspstore. This assumes that td1==curthread. Also
245	 * flush dirty regs to ensure that the user's stacked
246	 * regs are written out to backing store.
247	 *
248	 * We could cope with td1!=curthread by digging values
249	 * out of its PCB but I don't see the point since
250	 * current usage only allows &thread0 when creating kernel
251	 * threads and &thread0 doesn't have any dirty regs.
252	 */
253
254	p1bs = (u_int64_t *)td1->td_kstack;
255	p2bs = (u_int64_t *)td2->td_kstack;
256
257	if (td1 == curthread) {
258		__asm __volatile("mov ar.rsc=0;;");
259		__asm __volatile("flushrs;;" ::: "memory");
260		__asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore));
261	} else {
262		bspstore = (u_int64_t) p1bs;
263	}
264
265	/*
266	 * Copy enough of td1's backing store to include all
267	 * the user's stacked regs.
268	 */
269	bcopy(p1bs, p2bs, td1->td_frame->tf_ndirty);
270	/*
271	 * To calculate the ar.rnat for td2, we need to decide
272	 * if td1's ar.bspstore has advanced past the place
273	 * where the last ar.rnat which covers the user's
274	 * saved registers would be placed. If so, we read
275	 * that one from memory, otherwise we take td1's
276	 * current ar.rnat. If we are simply spawning a new kthread
277	 * from &thread0 we don't care about ar.rnat.
278	 */
279	if (td1 == curthread) {
280		rnatloc = (u_int64_t)p1bs + td1->td_frame->tf_ndirty;
281		rnatloc |= 0x1f8;
282		if (bspstore > rnatloc)
283			rnat = *(u_int64_t *) rnatloc;
284		else
285			__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
286
287		/*
288		 * Switch the RSE back on.
289		 */
290		__asm __volatile("mov ar.rsc=3;;");
291	} else {
292		rnat = 0;
293	}
294
295	/*
296	 * Setup the child's pcb so that its ar.bspstore
297	 * starts just above the region which we copied. This
298	 * should work since the child will normally return
299	 * straight into exception_restore. Also initialise its
300	 * pmap to the containing proc's vmspace.
301	 */
302	td2->td_pcb->pcb_bspstore = (u_int64_t)p2bs + td1->td_frame->tf_ndirty;
303	td2->td_pcb->pcb_rnat = rnat;
304	td2->td_pcb->pcb_pfs = 0;
305	td2->td_pcb->pcb_pmap = (u_int64_t)
306		vmspace_pmap(td2->td_proc->p_vmspace);
307
308	/*
309	 * Arrange for continuation at fork_return(), which
310	 * will return to exception_restore().  Note that the
311	 * child process doesn't stay in the kernel for long!
312	 *
313	 * The extra 16 bytes subtracted from sp is part of the ia64
314	 * ABI - a function can assume that the 16 bytes above sp are
315	 * available as scratch space.
316	 */
317	td2->td_pcb->pcb_sp = (u_int64_t)p2tf - 16;
318	td2->td_pcb->pcb_r4 = (u_int64_t)fork_return;
319	td2->td_pcb->pcb_r5 = FDESC_FUNC(exception_restore);
320	td2->td_pcb->pcb_r6 = (u_int64_t)td2;
321	td2->td_pcb->pcb_b0 = FDESC_FUNC(fork_trampoline);
322}
323
324/*
325 * Intercept the return address from a freshly forked process that has NOT
326 * been scheduled yet.
327 *
328 * This is needed to make kernel threads stay in kernel mode.
329 */
330void
331cpu_set_fork_handler(td, func, arg)
332	struct thread *td;
333	void (*func)(void *);
334	void *arg;
335{
336	td->td_pcb->pcb_r4 = (u_int64_t) func;
337	td->td_pcb->pcb_r6 = (u_int64_t) arg;
338}
339
340/*
341 * cpu_exit is called as the last action during exit.
342 * We drop the fp state (if we have it) and switch to a live one.
343 * When the proc is reaped, cpu_wait() will gc the VM state.
344 */
345void
346cpu_exit(td)
347	register struct thread *td;
348{
349
350	ia64_fpstate_drop(td);
351}
352
353void
354cpu_sched_exit(td)
355	register struct thread *td;
356{
357}
358
359void
360cpu_wait(p)
361	struct proc *p;
362{
363}
364
365/*
366 * Dump the machine specific header information at the start of a core dump.
367 */
368int
369cpu_coredump(td, vp, cred)
370	struct thread *td;
371	struct vnode *vp;
372	struct ucred *cred;
373{
374	int error;
375
376	error = vn_rdwr(UIO_WRITE, vp, (caddr_t) td->td_proc->p_uarea,
377	    ctob(UAREA_PAGES), (off_t)0,
378	    UIO_SYSSPACE, IO_UNIT, cred, NOCRED, (int *)NULL, td);
379	if (error)
380		return error;
381	error = vn_rdwr(UIO_WRITE, vp, (caddr_t) td->td_kstack,
382	    ctob(KSTACK_PAGES), (off_t)0,
383	    UIO_SYSSPACE, IO_UNIT, cred, NOCRED,(int *)NULL, td);
384	return error;
385}
386
387/*
388 * Map an IO request into kernel virtual address space.
389 *
390 * All requests are (re)mapped into kernel VA space.
391 * Notice that we use b_bufsize for the size of the buffer
392 * to be mapped.  b_bcount might be modified by the driver.
393 */
394void
395vmapbuf(bp)
396	register struct buf *bp;
397{
398	register caddr_t addr, v, kva;
399	vm_offset_t pa;
400
401	GIANT_REQUIRED;
402
403	if ((bp->b_flags & B_PHYS) == 0)
404		panic("vmapbuf");
405
406	for (v = bp->b_saveaddr, addr = (caddr_t)trunc_page(bp->b_data);
407	    addr < bp->b_data + bp->b_bufsize;
408	    addr += PAGE_SIZE, v += PAGE_SIZE) {
409		/*
410		 * Do the vm_fault if needed; do the copy-on-write thing
411		 * when reading stuff off device into memory.
412		 */
413		vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data,
414			(bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ);
415		pa = trunc_page(pmap_kextract((vm_offset_t) addr));
416		if (pa == 0)
417			panic("vmapbuf: page not present");
418		vm_page_hold(PHYS_TO_VM_PAGE(pa));
419		pmap_kenter((vm_offset_t) v, pa);
420	}
421
422	kva = bp->b_saveaddr;
423	bp->b_saveaddr = bp->b_data;
424	bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK);
425}
426
427/*
428 * Free the io map PTEs associated with this IO operation.
429 * We also invalidate the TLB entries and restore the original b_addr.
430 */
431void
432vunmapbuf(bp)
433	register struct buf *bp;
434{
435	register caddr_t addr;
436	vm_offset_t pa;
437
438	GIANT_REQUIRED;
439
440	if ((bp->b_flags & B_PHYS) == 0)
441		panic("vunmapbuf");
442
443	for (addr = (caddr_t)trunc_page(bp->b_data);
444	    addr < bp->b_data + bp->b_bufsize;
445	    addr += PAGE_SIZE) {
446		pa = trunc_page(pmap_kextract((vm_offset_t) addr));
447		pmap_kremove((vm_offset_t) addr);
448		vm_page_unhold(PHYS_TO_VM_PAGE(pa));
449	}
450
451	bp->b_data = bp->b_saveaddr;
452}
453
454/*
455 * Force reset the processor by invalidating the entire address space!
456 */
457void
458cpu_reset()
459{
460
461	cpu_boot(0);
462}
463
464/*
465 * Software interrupt handler for queued VM system processing.
466 */
467void
468swi_vm(void *dummy)
469{
470#if 0
471	if (busdma_swi_pending != 0)
472		busdma_swi();
473#endif
474}
475
476/*
477 * Tell whether this address is in some physical memory region.
478 * Currently used by the kernel coredump code in order to avoid
479 * dumping the ``ISA memory hole'' which could cause indefinite hangs,
480 * or other unpredictable behaviour.
481 */
482
483
484int
485is_physical_memory(addr)
486	vm_offset_t addr;
487{
488	/*
489	 * stuff other tests for known memory-mapped devices (PCI?)
490	 * here
491	 */
492
493	return 1;
494}
495