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$ 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/lock.h> 74#include <sys/malloc.h> 75#include <sys/bio.h> 76#include <sys/buf.h> 77#include <sys/sysent.h> 78#include <sys/vnode.h> 79#include <sys/vmmeter.h> 80#include <sys/kernel.h> 81#include <sys/mbuf.h> 82#include <sys/sysctl.h> 83#include <sys/unistd.h> 84 85#include <machine/cpu.h> 86#include <machine/fpu.h> 87#include <machine/md_var.h> 88#include <machine/pcb.h> 89 90#include <vm/vm.h> 91#include <vm/vm_param.h> 92#include <vm/vm_kern.h> 93#include <vm/vm_page.h> 94#include <vm/vm_map.h> 95#include <vm/vm_extern.h> 96 97void 98cpu_thread_exit(struct thread *td) 99{ 100 101 /* Throw away the high FP registers. */ 102 ia64_highfp_drop(td); 103} 104 105void 106cpu_thread_clean(struct thread *td) 107{ 108} 109 110void 111cpu_thread_alloc(struct thread *td) 112{ 113 intptr_t sp; 114 115 sp = td->td_kstack + td->td_kstack_pages * PAGE_SIZE; 116 sp -= sizeof(struct pcb); 117 td->td_pcb = (struct pcb *)sp; 118 sp -= sizeof(struct trapframe); 119 td->td_frame = (struct trapframe *)sp; 120 td->td_frame->tf_length = sizeof(struct trapframe); 121} 122 123void 124cpu_thread_free(struct thread *td) 125{ 126} 127 128void 129cpu_thread_swapin(struct thread *td) 130{ 131} 132 133void 134cpu_thread_swapout(struct thread *td) 135{ 136 137 ia64_highfp_save(td); 138} 139 140void 141cpu_set_syscall_retval(struct thread *td, int error) 142{ 143 struct proc *p; 144 struct trapframe *tf; 145 146 if (error == EJUSTRETURN) 147 return; 148 149 tf = td->td_frame; 150 151 /* 152 * Save the "raw" error code in r10. We use this to handle 153 * syscall restarts (see do_ast()). 154 */ 155 tf->tf_scratch.gr10 = error; 156 if (error == 0) { 157 tf->tf_scratch.gr8 = td->td_retval[0]; 158 tf->tf_scratch.gr9 = td->td_retval[1]; 159 } else if (error != ERESTART) { 160 p = td->td_proc; 161 if (error < p->p_sysent->sv_errsize) 162 error = p->p_sysent->sv_errtbl[error]; 163 /* 164 * Translated error codes are returned in r8. User 165 */ 166 tf->tf_scratch.gr8 = error; 167 } 168} 169 170void 171cpu_set_upcall(struct thread *td, struct thread *td0) 172{ 173 struct pcb *pcb; 174 struct trapframe *tf; 175 176 ia64_highfp_save(td0); 177 178 tf = td->td_frame; 179 KASSERT(tf != NULL, ("foo")); 180 bcopy(td0->td_frame, tf, sizeof(*tf)); 181 tf->tf_length = sizeof(struct trapframe); 182 tf->tf_flags = FRAME_SYSCALL; 183 tf->tf_special.ndirty = 0; 184 tf->tf_special.bspstore &= ~0x1ffUL; 185 tf->tf_scratch.gr8 = 0; 186 tf->tf_scratch.gr9 = 1; 187 tf->tf_scratch.gr10 = 0; 188 189 pcb = td->td_pcb; 190 KASSERT(pcb != NULL, ("foo")); 191 bcopy(td0->td_pcb, pcb, sizeof(*pcb)); 192 pcb->pcb_special.bspstore = td->td_kstack; 193 pcb->pcb_special.pfs = 0; 194 pcb->pcb_current_pmap = vmspace_pmap(td0->td_proc->p_vmspace); 195 pcb->pcb_special.sp = (uintptr_t)tf - 16; 196 pcb->pcb_special.rp = FDESC_FUNC(fork_trampoline); 197 cpu_set_fork_handler(td, (void (*)(void*))fork_return, td); 198 199 /* Setup to release the spin count in fork_exit(). */ 200 td->td_md.md_spinlock_count = 1; 201 td->td_md.md_saved_intr = 1; 202} 203 204void 205cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 206 stack_t *stack) 207{ 208 struct ia64_fdesc *fd; 209 struct trapframe *tf; 210 uint64_t ndirty, sp; 211 212 tf = td->td_frame; 213 ndirty = tf->tf_special.ndirty + (tf->tf_special.bspstore & 0x1ffUL); 214 215 KASSERT((ndirty & ~PAGE_MASK) == 0, 216 ("Whoa there! We have more than 8KB of dirty registers!")); 217 218 fd = (struct ia64_fdesc *)entry; 219 sp = (uint64_t)stack->ss_sp; 220 221 bzero(&tf->tf_special, sizeof(tf->tf_special)); 222 tf->tf_special.iip = fuword(&fd->func); 223 tf->tf_special.gp = fuword(&fd->gp); 224 tf->tf_special.sp = (sp + stack->ss_size - 16) & ~15; 225 tf->tf_special.rsc = 0xf; 226 tf->tf_special.fpsr = IA64_FPSR_DEFAULT; 227 tf->tf_special.psr = IA64_PSR_IC | IA64_PSR_I | IA64_PSR_IT | 228 IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | IA64_PSR_BN | 229 IA64_PSR_CPL_USER; 230 231 if (tf->tf_flags & FRAME_SYSCALL) { 232 tf->tf_special.cfm = (3UL<<62) | (1UL<<7) | 1UL; 233 tf->tf_special.bspstore = sp + 8; 234 suword((caddr_t)sp, (uint64_t)arg); 235 } else { 236 tf->tf_special.cfm = (1UL<<63) | (1UL<<7) | 1UL; 237 tf->tf_special.bspstore = sp; 238 tf->tf_special.ndirty = 8; 239 sp = td->td_kstack + ndirty - 8; 240 if ((sp & 0x1ff) == 0x1f8) { 241 *(uint64_t*)sp = 0; 242 tf->tf_special.ndirty += 8; 243 sp -= 8; 244 } 245 *(uint64_t*)sp = (uint64_t)arg; 246 } 247} 248 249int 250cpu_set_user_tls(struct thread *td, void *tls_base) 251{ 252 td->td_frame->tf_special.tp = (unsigned long)tls_base; 253 return (0); 254} 255 256/* 257 * Finish a fork operation, with process p2 nearly set up. 258 * Copy and update the pcb, set up the stack so that the child 259 * ready to run and return to user mode. 260 */ 261void 262cpu_fork(struct thread *td1, struct proc *p2 __unused, struct thread *td2, 263 int flags) 264{ 265 char *stackp; 266 uint64_t ndirty; 267 268 KASSERT(td1 == curthread || td1 == &thread0, 269 ("cpu_fork: td1 not curthread and not thread0")); 270 271 if ((flags & RFPROC) == 0) 272 return; 273 274 /* 275 * Save the preserved registers and the high FP registers in the 276 * PCB if we're the parent (ie td1 == curthread) so that we have 277 * a valid PCB. This also causes a RSE flush. We don't have to 278 * do that otherwise, because there wouldn't be anything important 279 * to save. 280 */ 281 if (td1 == curthread) { 282 if (savectx(td1->td_pcb) != 0) 283 panic("unexpected return from savectx()"); 284 ia64_highfp_save(td1); 285 } 286 287 /* 288 * create the child's kernel stack and backing store. We basicly 289 * create an image of the parent's stack and backing store and 290 * adjust where necessary. 291 */ 292 stackp = (char *)(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE); 293 294 stackp -= sizeof(struct pcb); 295 td2->td_pcb = (struct pcb *)stackp; 296 bcopy(td1->td_pcb, td2->td_pcb, sizeof(struct pcb)); 297 298 stackp -= sizeof(struct trapframe); 299 td2->td_frame = (struct trapframe *)stackp; 300 bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe)); 301 td2->td_frame->tf_length = sizeof(struct trapframe); 302 ndirty = td2->td_frame->tf_special.ndirty + 303 (td2->td_frame->tf_special.bspstore & 0x1ffUL); 304 bcopy((void*)td1->td_kstack, (void*)td2->td_kstack, ndirty); 305 306 /* Set-up the return values as expected by the fork() libc stub. */ 307 if (td2->td_frame->tf_special.psr & IA64_PSR_IS) { 308 td2->td_frame->tf_scratch.gr8 = 0; 309 td2->td_frame->tf_scratch.gr10 = 1; 310 } else { 311 td2->td_frame->tf_scratch.gr8 = 0; 312 td2->td_frame->tf_scratch.gr9 = 1; 313 td2->td_frame->tf_scratch.gr10 = 0; 314 } 315 316 td2->td_pcb->pcb_special.bspstore = td2->td_kstack + ndirty; 317 td2->td_pcb->pcb_special.pfs = 0; 318 td2->td_pcb->pcb_current_pmap = vmspace_pmap(td2->td_proc->p_vmspace); 319 320 td2->td_pcb->pcb_special.sp = (uintptr_t)stackp - 16; 321 td2->td_pcb->pcb_special.rp = FDESC_FUNC(fork_trampoline); 322 cpu_set_fork_handler(td2, (void (*)(void*))fork_return, td2); 323 324 /* Setup to release the spin count in fork_exit(). */ 325 td2->td_md.md_spinlock_count = 1; 326 td2->td_md.md_saved_intr = 1; 327} 328 329/* 330 * Intercept the return address from a freshly forked process that has NOT 331 * been scheduled yet. 332 * 333 * This is needed to make kernel threads stay in kernel mode. 334 */ 335void 336cpu_set_fork_handler(td, func, arg) 337 struct thread *td; 338 void (*func)(void *); 339 void *arg; 340{ 341 td->td_frame->tf_scratch.gr2 = (u_int64_t)func; 342 td->td_frame->tf_scratch.gr3 = (u_int64_t)arg; 343} 344 345/* 346 * cpu_exit is called as the last action during exit. 347 * We drop the fp state (if we have it) and switch to a live one. 348 */ 349void 350cpu_exit(struct thread *td) 351{ 352} 353 354/* 355 * Software interrupt handler for queued VM system processing. 356 */ 357void 358swi_vm(void *dummy) 359{ 360 361 if (busdma_swi_pending != 0) 362 busdma_swi(); 363} 364