1/* $OpenBSD: vm_machdep.c,v 1.12 2023/06/10 19:30:48 kettenis Exp $ */ 2/* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */ 3 4/*- 5 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 6 * Copyright (c) 1982, 1986 The Regents of the University of California. 7 * Copyright (c) 1989, 1990 William Jolitz 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * the Systems Programming Group of the University of Utah Computer 12 * Science Department, and William Jolitz. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 39 */ 40 41/* 42 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 43 */ 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/proc.h> 48#include <sys/malloc.h> 49#include <sys/vnode.h> 50#include <sys/buf.h> 51#include <sys/user.h> 52#include <sys/exec.h> 53#include <sys/ptrace.h> 54#include <sys/signalvar.h> 55 56#include <uvm/uvm_extern.h> 57 58#include <machine/cpu.h> 59#include <machine/fpu.h> 60#include <machine/reg.h> 61 62/* 63 * Finish a fork operation, with process p2 nearly set up. 64 * Copy and update the kernel stack and pcb, making the child 65 * ready to run, and marking it so that it can return differently 66 * than the parent. Returns 1 in the child process, 0 in the parent. 67 */ 68void 69cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb, 70 void (*func)(void *), void *arg) 71{ 72 struct pmap *pm = p2->p_vmspace->vm_map.pmap; 73 struct pmap *pm1 = p1->p_vmspace->vm_map.pmap; 74 struct pcb *pcb = &p2->p_addr->u_pcb; 75 struct pcb *pcb1 = &p1->p_addr->u_pcb; 76 struct trapframe *tf; 77 struct switchframe *sf; 78 79 memcpy(pm->pm_apiakey, pm1->pm_apiakey, sizeof(pm->pm_apiakey)); 80 memcpy(pm->pm_apdakey, pm1->pm_apdakey, sizeof(pm->pm_apdakey)); 81 memcpy(pm->pm_apibkey, pm1->pm_apibkey, sizeof(pm->pm_apibkey)); 82 memcpy(pm->pm_apdbkey, pm1->pm_apdbkey, sizeof(pm->pm_apdbkey)); 83 memcpy(pm->pm_apgakey, pm1->pm_apgakey, sizeof(pm->pm_apgakey)); 84 85 /* Save FPU state to PCB if necessary. */ 86 if (pcb1->pcb_flags & PCB_FPU) 87 fpu_save(p1); 88 89 /* Copy the pcb. */ 90 *pcb = p1->p_addr->u_pcb; 91 92 tf = (struct trapframe *)((u_long)p2->p_addr 93 + USPACE 94 - sizeof(struct trapframe) 95 - 0x10); 96 97 tf = (struct trapframe *)STACKALIGN(tf); 98 pcb->pcb_tf = tf; 99 *tf = *p1->p_addr->u_pcb.pcb_tf; 100 101 if (stack != NULL) 102 tf->tf_sp = STACKALIGN(stack); 103 if (tcb != NULL) 104 pcb->pcb_tcb = tcb; 105 106 sf = (struct switchframe *)tf - 1; 107 sf->sf_x19 = (uint64_t)func; 108 sf->sf_x20 = (uint64_t)arg; 109 sf->sf_lr = (uint64_t)&proc_trampoline; 110 pcb->pcb_sp = (uint64_t)sf; 111} 112 113/* 114 * cpu_exit is called as the last action during exit. 115 * 116 * We clean up a little and then call sched_exit() with the old proc as an 117 * argument. 118 */ 119void 120cpu_exit(struct proc *p) 121{ 122 pmap_deactivate(p); 123 sched_exit(p); 124} 125 126struct kmem_va_mode kv_physwait = { 127 .kv_map = &phys_map, 128 .kv_wait = 1, 129}; 130 131/* 132 * Map a user I/O request into kernel virtual address space. 133 * Note: the pages are already locked by uvm_vslock(), so we 134 * do not need to pass an access_type to pmap_enter(). 135 */ 136void 137vmapbuf(struct buf *bp, vsize_t len) 138{ 139 vaddr_t faddr, taddr, off; 140 paddr_t fpa; 141 142 if ((bp->b_flags & B_PHYS) == 0) 143 panic("vmapbuf"); 144 faddr = trunc_page((vaddr_t)(bp->b_saveaddr = bp->b_data)); 145 off = (vaddr_t)bp->b_data - faddr; 146 len = round_page(off + len); 147 taddr = (vaddr_t)km_alloc(len, &kv_physwait, &kp_none, &kd_waitok); 148 bp->b_data = (caddr_t)(taddr + off); 149 /* 150 * The region is locked, so we expect that pmap_pte() will return 151 * non-NULL. 152 * XXX: unwise to expect this in a multithreaded environment. 153 * anything can happen to a pmap between the time we lock a 154 * region, release the pmap lock, and then relock it for 155 * the pmap_extract(). 156 * 157 * no need to flush TLB since we expect nothing to be mapped 158 * where we just allocated (TLB will be flushed when our 159 * mapping is removed). 160 */ 161 while (len) { 162 (void) pmap_extract(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map), 163 faddr, &fpa); 164 pmap_kenter_pa(taddr, fpa, PROT_READ | PROT_WRITE); 165 faddr += PAGE_SIZE; 166 taddr += PAGE_SIZE; 167 len -= PAGE_SIZE; 168 } 169 pmap_update(pmap_kernel()); 170} 171 172/* 173 * Unmap a previously-mapped user I/O request. 174 */ 175void 176vunmapbuf(struct buf *bp, vsize_t len) 177{ 178 vaddr_t addr, off; 179 180 if ((bp->b_flags & B_PHYS) == 0) 181 panic("vunmapbuf"); 182 addr = trunc_page((vaddr_t)bp->b_data); 183 off = (vaddr_t)bp->b_data - addr; 184 len = round_page(off + len); 185 pmap_kremove(addr, len); 186 pmap_update(pmap_kernel()); 187 km_free((void *)addr, len, &kv_physwait, &kp_none); 188 bp->b_data = bp->b_saveaddr; 189 bp->b_saveaddr = NULL; 190} 191