1 /** $MirOS: src/sys/arch/sparc/sparc/vm_machdep.c,v 1.3 2008/10/18 17:46:10 tg Exp $ */
2 /* $OpenBSD: vm_machdep.c,v 1.45 2002/12/10 23:45:02 miod Exp $ */
3 /* $NetBSD: vm_machdep.c,v 1.30 1997/03/10 23:55:40 pk Exp $ */
4
5 /*
6 * Copyright (c) 1996
7 * The President and Fellows of Harvard College. All rights reserved.
8 * Copyright (c) 1992, 1993
9 * The Regents of the University of California. All rights reserved.
10 *
11 * This software was developed by the Computer Systems Engineering group
12 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
13 * contributed to Berkeley.
14 *
15 * All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Lawrence Berkeley Laboratory.
19 * This product includes software developed by Harvard University.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. All advertising materials mentioning features or use of this software
30 * must display the following acknowledgement:
31 * This product includes software developed by Harvard University.
32 * This product includes software developed by the University of
33 * California, Berkeley and its contributors.
34 * 4. Neither the name of the University nor the names of its contributors
35 * may be used to endorse or promote products derived from this software
36 * without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * @(#)vm_machdep.c 8.2 (Berkeley) 9/23/93
51 */
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/proc.h>
56 #include <sys/signalvar.h>
57 #include <sys/user.h>
58 #include <sys/core.h>
59 #include <sys/malloc.h>
60 #include <sys/buf.h>
61 #include <sys/exec.h>
62 #include <sys/vnode.h>
63 #include <sys/extent.h>
64
65 #include <uvm/uvm_extern.h>
66
67 #include <machine/cpu.h>
68 #include <machine/frame.h>
69 #include <machine/trap.h>
70
71 #include <sparc/sparc/cpuvar.h>
72
73 /*
74 * Move pages from one kernel virtual address to another.
75 */
76 void
pagemove(from,to,size)77 pagemove(from, to, size)
78 register caddr_t from, to;
79 size_t size;
80 {
81 paddr_t pa;
82
83 #ifdef DEBUG
84 if ((size & PAGE_MASK) != 0 ||
85 ((vaddr_t)from & PAGE_MASK) != 0 ||
86 ((vaddr_t)to & PAGE_MASK) != 0)
87 panic("pagemove 1");
88 #endif
89 while (size > 0) {
90 if (pmap_extract(pmap_kernel(), (vaddr_t)from, &pa) == FALSE)
91 panic("pagemove 2");
92 pmap_kremove((vaddr_t)from, PAGE_SIZE);
93 pmap_kenter_pa((vaddr_t)to, pa, VM_PROT_READ|VM_PROT_WRITE);
94 from += PAGE_SIZE;
95 to += PAGE_SIZE;
96 size -= PAGE_SIZE;
97 }
98 pmap_update(pmap_kernel());
99 }
100
101 /*
102 * Wrapper for dvma_mapin() in kernel space,
103 * so drivers need not include VM goo to get at kernel_map.
104 */
105 caddr_t
kdvma_mapin(va,len,canwait)106 kdvma_mapin(va, len, canwait)
107 caddr_t va;
108 int len, canwait;
109 {
110 return ((caddr_t)dvma_mapin(kernel_map, (vaddr_t)va, len, canwait));
111 }
112
113 #if defined(SUN4M)
114 extern int has_iocache;
115 #endif
116
117 caddr_t
dvma_malloc_space(size_t len,void * kaddr,int flags,int space)118 dvma_malloc_space(size_t len, void *kaddr, int flags, int space)
119 {
120 vaddr_t kva;
121 vaddr_t dva;
122
123 len = round_page(len);
124 kva = (vaddr_t)malloc(len, M_DEVBUF, flags);
125 if (kva == 0)
126 return (NULL);
127
128 #if defined(SUN4M)
129 if (!has_iocache)
130 #endif
131 kvm_uncache((caddr_t)kva, atop(len));
132
133 *(vaddr_t *)kaddr = kva;
134 dva = dvma_mapin_space(kernel_map, kva, len, (flags & M_NOWAIT) ? 0 : 1, space);
135 if (dva == 0) {
136 free((void *)kva, M_DEVBUF);
137 return (NULL);
138 }
139 return (caddr_t)dva;
140 }
141
142 void
dvma_free(dva,len,kaddr)143 dvma_free(dva, len, kaddr)
144 caddr_t dva;
145 size_t len;
146 void *kaddr;
147 {
148 vaddr_t kva = *(vaddr_t *)kaddr;
149
150 len = round_page(len);
151
152 dvma_mapout((vaddr_t)dva, kva, len);
153 /*
154 * Even if we're freeing memory here, we can't be sure that it will
155 * be unmapped, so we must recache the memory range to avoid impact
156 * on other kernel subsystems.
157 */
158 #if defined(SUN4M)
159 if (!has_iocache)
160 #endif
161 kvm_recache(kaddr, atop(len));
162 free((void *)kva, M_DEVBUF);
163 }
164
165 u_long dvma_cachealign = 0;
166
167 /*
168 * Map a range [va, va+len] of wired virtual addresses in the given map
169 * to a kernel address in DVMA space.
170 */
171 vaddr_t
dvma_mapin_space(map,va,len,canwait,space)172 dvma_mapin_space(map, va, len, canwait, space)
173 struct vm_map *map;
174 vaddr_t va;
175 int len, canwait, space;
176 {
177 vaddr_t kva, tva;
178 int npf, s;
179 paddr_t pa;
180 vaddr_t off;
181 vaddr_t ova;
182 int olen;
183 int error;
184
185 if (dvma_cachealign == 0)
186 dvma_cachealign = PAGE_SIZE;
187
188 ova = va;
189 olen = len;
190
191 off = va & PAGE_MASK;
192 va &= ~PAGE_MASK;
193 len = round_page(len + off);
194 npf = btoc(len);
195
196 s = splhigh();
197 if (space & M_SPACE_D24)
198 error = extent_alloc_subregion(dvmamap_extent,
199 DVMA_D24_BASE, DVMA_D24_END, len, dvma_cachealign,
200 va & (dvma_cachealign - 1), 0,
201 canwait ? EX_WAITSPACE : EX_NOWAIT, &tva);
202 else
203 error = extent_alloc(dvmamap_extent, len, dvma_cachealign,
204 va & (dvma_cachealign - 1), 0,
205 canwait ? EX_WAITSPACE : EX_NOWAIT, &tva);
206 splx(s);
207 if (error)
208 return (0);
209 kva = tva;
210
211 while (npf--) {
212 if (pmap_extract(vm_map_pmap(map), va, &pa) == FALSE)
213 panic("dvma_mapin: null page frame");
214 pa = trunc_page(pa);
215
216 #if defined(SUN4M)
217 if (CPU_ISSUN4M) {
218 iommu_enter(tva, pa);
219 } else
220 #endif
221 {
222 /*
223 * pmap_enter distributes this mapping to all
224 * contexts... maybe we should avoid this extra work
225 */
226 #ifdef notyet
227 #if defined(SUN4)
228 if (have_iocache)
229 pa |= PG_IOC;
230 #endif
231 #endif
232 /* XXX - this should probably be pmap_kenter */
233 pmap_enter(pmap_kernel(), tva, pa | PMAP_NC,
234 VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
235 }
236
237 tva += PAGE_SIZE;
238 va += PAGE_SIZE;
239 }
240 pmap_update(pmap_kernel());
241
242 /*
243 * XXX Only have to do this on write.
244 */
245 if (CACHEINFO.c_vactype == VAC_WRITEBACK) /* XXX */
246 cpuinfo.cache_flush((caddr_t)ova, olen); /* XXX */
247
248 return kva + off;
249 }
250
251 /*
252 * Remove double map of `va' in DVMA space at `kva'.
253 */
254 void
dvma_mapout(kva,va,len)255 dvma_mapout(kva, va, len)
256 vaddr_t kva, va;
257 int len;
258 {
259 int s, off;
260 int error;
261 int klen;
262
263 off = (int)kva & PGOFSET;
264 kva -= off;
265 klen = round_page(len + off);
266
267 #if defined(SUN4M)
268 if (CPU_ISSUN4M)
269 iommu_remove(kva, klen);
270 else
271 #endif
272 {
273 pmap_remove(pmap_kernel(), kva, kva + klen);
274 pmap_update(pmap_kernel());
275 }
276
277 s = splhigh();
278 error = extent_free(dvmamap_extent, kva, klen, EX_NOWAIT);
279 if (error)
280 printf("dvma_mapout: extent_free failed\n");
281 splx(s);
282
283 if (CACHEINFO.c_vactype != VAC_NONE)
284 cpuinfo.cache_flush((caddr_t)va, len);
285 }
286
287 /*
288 * Map an IO request into kernel virtual address space.
289 */
290 void
vmapbuf(struct buf * bp,vsize_t sz)291 vmapbuf(struct buf *bp, vsize_t sz)
292 {
293 vaddr_t uva, kva;
294 vsize_t size, off;
295 struct pmap *pmap;
296 paddr_t pa;
297
298 #ifdef DIAGNOSTIC
299 if ((bp->b_flags & B_PHYS) == 0)
300 panic("vmapbuf");
301 #endif
302 pmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
303
304 bp->b_saveaddr = bp->b_data;
305 uva = trunc_page((vaddr_t)bp->b_data);
306 off = (vaddr_t)bp->b_data - uva;
307 size = round_page(off + sz);
308 /*
309 * Note that this is an expanded version of:
310 * kva = uvm_km_valloc_wait(kernel_map, size);
311 * We do it on our own here to be able to specify an offset to uvm_map
312 * so that we can get all benefits of PMAP_PREFER.
313 */
314 kva = uvm_km_valloc_prefer_wait(kernel_map, size, uva);
315 bp->b_data = (caddr_t)(kva + off);
316
317 while (size > 0) {
318 if (pmap_extract(pmap, uva, &pa) == FALSE)
319 panic("vmapbuf: null page frame");
320
321 /*
322 * Don't enter uncached if cache is mandatory.
323 *
324 * XXX - there are probably other cases where we don't need
325 * to uncache, but for now we're conservative.
326 */
327 if (!(cpuinfo.flags & CPUFLG_CACHE_MANDATORY))
328 pa |= PMAP_NC;
329
330 pmap_enter(pmap_kernel(), kva, pa,
331 VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
332
333 uva += PAGE_SIZE;
334 kva += PAGE_SIZE;
335 size -= PAGE_SIZE;
336 }
337 pmap_update(pmap_kernel());
338 }
339
340 /*
341 * Free the io map addresses associated with this IO operation.
342 */
343 void
vunmapbuf(bp,sz)344 vunmapbuf(bp, sz)
345 register struct buf *bp;
346 vsize_t sz;
347 {
348 register vaddr_t kva;
349 register vsize_t size, off;
350
351 if ((bp->b_flags & B_PHYS) == 0)
352 panic("vunmapbuf");
353
354 kva = trunc_page((vaddr_t)bp->b_data);
355 off = (vaddr_t)bp->b_data - kva;
356 size = round_page(sz + off);
357
358 uvm_km_free_wakeup(kernel_map, kva, size);
359 bp->b_data = bp->b_saveaddr;
360 bp->b_saveaddr = NULL;
361 if (CACHEINFO.c_vactype != VAC_NONE)
362 cpuinfo.cache_flush(bp->b_un.b_addr, bp->b_bcount - bp->b_resid);
363 }
364
365
366 /*
367 * The offset of the topmost frame in the kernel stack.
368 */
369 #define TOPFRAMEOFF (USPACE-sizeof(struct trapframe)-sizeof(struct frame))
370
371 /*
372 * Finish a fork operation, with process p2 nearly set up.
373 * Copy and update the pcb, making the child ready to run, and marking
374 * it so that it can return differently than the parent.
375 *
376 * This function relies on the fact that the pcb is
377 * the first element in struct user.
378 */
379 void
cpu_fork(p1,p2,stack,stacksize,func,arg)380 cpu_fork(p1, p2, stack, stacksize, func, arg)
381 struct proc *p1, *p2;
382 void *stack;
383 size_t stacksize;
384 void (*func)(void *);
385 void *arg;
386 {
387 struct pcb *opcb = &p1->p_addr->u_pcb;
388 struct pcb *npcb = &p2->p_addr->u_pcb;
389 struct trapframe *tf2;
390 struct rwindow *rp;
391
392 /*
393 * Save all user registers to p1's stack or, in the case of
394 * user registers and invalid stack pointers, to opcb.
395 * We then copy the whole pcb to p2; when switch() selects p2
396 * to run, it will run at the `proc_trampoline' stub, rather
397 * than returning at the copying code below.
398 *
399 * If process p1 has an FPU state, we must copy it. If it is
400 * the FPU user, we must save the FPU state first.
401 */
402
403 if (p1 == curproc) {
404 write_user_windows();
405 opcb->pcb_psr = getpsr();
406 }
407 #ifdef DIAGNOSTIC
408 else if (p1 != &proc0)
409 panic("cpu_fork: curproc");
410 #endif
411
412 bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb));
413 if (p1->p_md.md_fpstate) {
414 if (p1 == cpuinfo.fpproc)
415 savefpstate(p1->p_md.md_fpstate);
416 p2->p_md.md_fpstate = malloc(sizeof(struct fpstate),
417 M_SUBPROC, M_WAITOK);
418 bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate,
419 sizeof(struct fpstate));
420 } else
421 p2->p_md.md_fpstate = NULL;
422
423 /*
424 * Setup (kernel) stack frame that will by-pass the child
425 * out of the kernel. (The trap frame invariably resides at
426 * the tippity-top of the u. area.)
427 */
428 tf2 = p2->p_md.md_tf = (struct trapframe *)
429 ((int)npcb + USPACE - sizeof(*tf2));
430
431 /* Copy parent's trapframe */
432 *tf2 = *(struct trapframe *)((int)opcb + USPACE - sizeof(*tf2));
433
434 /*
435 * If specified, give the child a different stack.
436 */
437 if (stack != NULL)
438 tf2->tf_out[6] = (u_int)stack + stacksize;
439
440 /* Duplicate efforts of syscall(), but slightly differently */
441 if (tf2->tf_global[1] & SYSCALL_G2RFLAG) {
442 /* jmp %g2 (or %g7, deprecated) on success */
443 tf2->tf_npc = tf2->tf_global[2];
444 } else {
445 /*
446 * old system call convention: clear C on success
447 * note: proc_trampoline() sets a fresh psr when
448 * returning to user mode.
449 */
450 /*tf2->tf_psr &= ~PSR_C; -* success */
451 }
452
453 /* Set return values in child mode */
454 tf2->tf_out[0] = 0;
455 tf2->tf_out[1] = 1;
456
457 /* Construct kernel frame to return to in cpu_switch() */
458 rp = (struct rwindow *)((u_int)npcb + TOPFRAMEOFF);
459 rp->rw_local[0] = (int)func; /* Function to call */
460 rp->rw_local[1] = (int)arg; /* and its argument */
461
462 npcb->pcb_pc = (int)proc_trampoline - 8;
463 npcb->pcb_sp = (int)rp;
464 npcb->pcb_psr &= ~PSR_CWP; /* Run in window #0 */
465 npcb->pcb_wim = 1; /* Fence at window #1 */
466
467 }
468
469 /*
470 * cpu_exit is called as the last action during exit.
471 *
472 * We clean up a little and then call switchexit() with the old proc
473 * as an argument. switchexit() switches to the idle context, schedules
474 * the old vmspace and stack to be freed, then selects a new process to
475 * run.
476 */
477 void
cpu_exit(p)478 cpu_exit(p)
479 struct proc *p;
480 {
481 register struct fpstate *fs;
482
483 if ((fs = p->p_md.md_fpstate) != NULL) {
484 if (p == cpuinfo.fpproc) {
485 savefpstate(fs);
486 cpuinfo.fpproc = NULL;
487 }
488 free((void *)fs, M_SUBPROC);
489 }
490
491 switchexit(p);
492 /* NOTREACHED */
493 }
494
495 /*
496 * cpu_coredump is called to write a core dump header.
497 * (should this be defined elsewhere? machdep.c?)
498 */
499 int
cpu_coredump(p,vp,cred,chdr)500 cpu_coredump(p, vp, cred, chdr)
501 struct proc *p;
502 struct vnode *vp;
503 struct ucred *cred;
504 struct core *chdr;
505 {
506 int error;
507 struct md_coredump md_core;
508 struct coreseg cseg;
509
510 CORE_SETMAGIC(*chdr, COREMAGIC, MID_SPARC, 0);
511 chdr->c_hdrsize = ALIGN(sizeof(*chdr));
512 chdr->c_seghdrsize = ALIGN(sizeof(cseg));
513 chdr->c_cpusize = sizeof(md_core);
514
515 md_core.md_tf = *p->p_md.md_tf;
516 md_core.md_wcookie = p->p_addr->u_pcb.pcb_wcookie;
517 if (p->p_md.md_fpstate) {
518 if (p == cpuinfo.fpproc)
519 savefpstate(p->p_md.md_fpstate);
520 md_core.md_fpstate = *p->p_md.md_fpstate;
521 } else
522 bzero((caddr_t)&md_core.md_fpstate, sizeof(struct fpstate));
523
524 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_SPARC, CORE_CPU);
525 cseg.c_addr = 0;
526 cseg.c_size = chdr->c_cpusize;
527 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
528 (off_t)chdr->c_hdrsize, UIO_SYSSPACE,
529 IO_NODELOCKED|IO_UNIT, cred, NULL, p);
530 if (error)
531 return error;
532
533 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
534 (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
535 IO_NODELOCKED|IO_UNIT, cred, NULL, p);
536 if (!error)
537 chdr->c_nseg++;
538
539 return error;
540 }
541