trap.c revision 233748
180708Sjake/*- 281899Sjake * Copyright (c) 2001, Jake Burkholder 381185Sjake * Copyright (C) 1994, David Greenman 481185Sjake * Copyright (c) 1990, 1993 581185Sjake * The Regents of the University of California. All rights reserved. 681185Sjake * 781185Sjake * This code is derived from software contributed to Berkeley by 881185Sjake * the University of Utah, and William Jolitz. 981185Sjake * 1081185Sjake * Redistribution and use in source and binary forms, with or without 1181185Sjake * modification, are permitted provided that the following conditions 1281185Sjake * are met: 1381185Sjake * 1. Redistributions of source code must retain the above copyright 1481185Sjake * notice, this list of conditions and the following disclaimer. 1581185Sjake * 2. Redistributions in binary form must reproduce the above copyright 1681185Sjake * notice, this list of conditions and the following disclaimer in the 1781185Sjake * documentation and/or other materials provided with the distribution. 1881185Sjake * 4. Neither the name of the University nor the names of its contributors 1981185Sjake * may be used to endorse or promote products derived from this software 2081185Sjake * without specific prior written permission. 2181185Sjake * 2281337Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2381185Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2481185Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2581337Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2681185Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2781185Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2881185Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2981185Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3081185Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3181185Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3281185Sjake * SUCH DAMAGE. 3381185Sjake * 34181701Smarius * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 35181701Smarius * from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19 3680708Sjake */ 3780708Sjake 38157445Smarius#include <sys/cdefs.h> 39157445Smarius__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/trap.c 233748 2012-03-31 14:03:16Z marius $"); 40157445Smarius 4180709Sjake#include "opt_ddb.h" 4282903Sjake#include "opt_ktr.h" 4380709Sjake 4480708Sjake#include <sys/param.h> 45131950Smarcel#include <sys/kdb.h> 4698037Sjake#include <sys/kernel.h> 4784849Stmm#include <sys/bus.h> 4884849Stmm#include <sys/interrupt.h> 4982903Sjake#include <sys/ktr.h> 5081135Stmm#include <sys/lock.h> 5180709Sjake#include <sys/mutex.h> 5280709Sjake#include <sys/systm.h> 53204152Smarius#include <sys/pcpu.h> 5482006Sjake#include <sys/pioctl.h> 55120965Srobert#include <sys/ptrace.h> 5680708Sjake#include <sys/proc.h> 5791783Sjake#include <sys/smp.h> 58120937Srobert#include <sys/signalvar.h> 5982006Sjake#include <sys/syscall.h> 6098037Sjake#include <sys/sysctl.h> 6181135Stmm#include <sys/sysent.h> 6282006Sjake#include <sys/vmmeter.h> 63155814Srwatson#include <security/audit/audit.h> 6480708Sjake 65182773Smarius#include <dev/ofw/openfirm.h> 66182773Smarius 6780709Sjake#include <vm/vm.h> 6881185Sjake#include <vm/pmap.h> 6981185Sjake#include <vm/vm_extern.h> 7080709Sjake#include <vm/vm_param.h> 7180709Sjake#include <vm/vm_kern.h> 7281185Sjake#include <vm/vm_map.h> 7380709Sjake#include <vm/vm_page.h> 7480709Sjake 75105939Sjake#include <machine/cpu.h> 7680708Sjake#include <machine/frame.h> 7781387Sjake#include <machine/intr_machdep.h> 78190107Smarius#include <machine/ofw_machdep.h> 79200215Smarius#include <machine/pcb.h> 8091783Sjake#include <machine/smp.h> 8180709Sjake#include <machine/trap.h> 8282006Sjake#include <machine/tstate.h> 8380709Sjake#include <machine/tte.h> 8480709Sjake#include <machine/tlb.h> 8580709Sjake#include <machine/tsb.h> 8682006Sjake#include <machine/watch.h> 8780708Sjake 8880709Sjakevoid trap(struct trapframe *tf); 8984186Sjakevoid syscall(struct trapframe *tf); 9080708Sjake 91206086Smariusstatic int trap_cecc(void); 9288642Sjakestatic int trap_pfault(struct thread *td, struct trapframe *tf); 9382903Sjake 94101955Sjakeextern char copy_fault[]; 95101955Sjakeextern char copy_nofault_begin[]; 96101955Sjakeextern char copy_nofault_end[]; 9784186Sjake 98101955Sjakeextern char fs_fault[]; 99101955Sjakeextern char fs_nofault_begin[]; 100101955Sjakeextern char fs_nofault_end[]; 101101955Sjakeextern char fs_nofault_intr_begin[]; 102101955Sjakeextern char fs_nofault_intr_end[]; 103101955Sjake 104116659Sjmgextern char fas_fault[]; 105116659Sjmgextern char fas_nofault_begin[]; 106116659Sjmgextern char fas_nofault_end[]; 107116659Sjmg 108190107Smariusconst char *const trap_msg[] = { 10980709Sjake "reserved", 11080709Sjake "instruction access exception", 11180709Sjake "instruction access error", 11288642Sjake "instruction access protection", 11388642Sjake "illtrap instruction", 11480709Sjake "illegal instruction", 11580709Sjake "privileged opcode", 11680709Sjake "floating point disabled", 11780709Sjake "floating point exception ieee 754", 11880709Sjake "floating point exception other", 11980709Sjake "tag overflow", 12080709Sjake "division by zero", 12180709Sjake "data access exception", 12280709Sjake "data access error", 12388642Sjake "data access protection", 12480709Sjake "memory address not aligned", 12580709Sjake "privileged action", 12688642Sjake "async data error", 12788642Sjake "trap instruction 16", 12888642Sjake "trap instruction 17", 12988642Sjake "trap instruction 18", 13088642Sjake "trap instruction 19", 13188642Sjake "trap instruction 20", 13288642Sjake "trap instruction 21", 13388642Sjake "trap instruction 22", 13488642Sjake "trap instruction 23", 13588642Sjake "trap instruction 24", 13688642Sjake "trap instruction 25", 13788642Sjake "trap instruction 26", 13888642Sjake "trap instruction 27", 13988642Sjake "trap instruction 28", 14088642Sjake "trap instruction 29", 14188642Sjake "trap instruction 30", 14288642Sjake "trap instruction 31", 143114650Sjake "fast instruction access mmu miss", 144114650Sjake "fast data access mmu miss", 14588642Sjake "interrupt", 14680709Sjake "physical address watchpoint", 14780709Sjake "virtual address watchpoint", 14880709Sjake "corrected ecc error", 14982903Sjake "spill", 15082903Sjake "fill", 15182903Sjake "fill", 15280709Sjake "breakpoint", 15388642Sjake "clean window", 15488642Sjake "range check", 15588642Sjake "fix alignment", 15688642Sjake "integer overflow", 15782006Sjake "syscall", 15885236Sjake "restore physical watchpoint", 15985236Sjake "restore virtual watchpoint", 16088781Sjake "kernel stack fault", 16180709Sjake}; 16280709Sjake 163157445Smariusstatic const int trap_sig[] = { 164105939Sjake SIGILL, /* reserved */ 165105939Sjake SIGILL, /* instruction access exception */ 166105939Sjake SIGILL, /* instruction access error */ 167105939Sjake SIGILL, /* instruction access protection */ 168105939Sjake SIGILL, /* illtrap instruction */ 169105939Sjake SIGILL, /* illegal instruction */ 170105939Sjake SIGBUS, /* privileged opcode */ 171105939Sjake SIGFPE, /* floating point disabled */ 172105939Sjake SIGFPE, /* floating point exception ieee 754 */ 173105939Sjake SIGFPE, /* floating point exception other */ 174105939Sjake SIGEMT, /* tag overflow */ 175105939Sjake SIGFPE, /* division by zero */ 176105939Sjake SIGILL, /* data access exception */ 177105939Sjake SIGILL, /* data access error */ 178105939Sjake SIGBUS, /* data access protection */ 179105939Sjake SIGBUS, /* memory address not aligned */ 180105939Sjake SIGBUS, /* privileged action */ 181105939Sjake SIGBUS, /* async data error */ 182105939Sjake SIGILL, /* trap instruction 16 */ 183105939Sjake SIGILL, /* trap instruction 17 */ 184105939Sjake SIGILL, /* trap instruction 18 */ 185105939Sjake SIGILL, /* trap instruction 19 */ 186105939Sjake SIGILL, /* trap instruction 20 */ 187105939Sjake SIGILL, /* trap instruction 21 */ 188105939Sjake SIGILL, /* trap instruction 22 */ 189105939Sjake SIGILL, /* trap instruction 23 */ 190105939Sjake SIGILL, /* trap instruction 24 */ 191105939Sjake SIGILL, /* trap instruction 25 */ 192105939Sjake SIGILL, /* trap instruction 26 */ 193105939Sjake SIGILL, /* trap instruction 27 */ 194105939Sjake SIGILL, /* trap instruction 28 */ 195105939Sjake SIGILL, /* trap instruction 29 */ 196105939Sjake SIGILL, /* trap instruction 30 */ 197105939Sjake SIGILL, /* trap instruction 31 */ 198114650Sjake SIGSEGV, /* fast instruction access mmu miss */ 199114650Sjake SIGSEGV, /* fast data access mmu miss */ 200105939Sjake -1, /* interrupt */ 201105939Sjake -1, /* physical address watchpoint */ 202105939Sjake -1, /* virtual address watchpoint */ 203105939Sjake -1, /* corrected ecc error */ 204105939Sjake SIGILL, /* spill */ 205105939Sjake SIGILL, /* fill */ 206105939Sjake SIGILL, /* fill */ 207105939Sjake SIGTRAP, /* breakpoint */ 208105939Sjake SIGILL, /* clean window */ 209105939Sjake SIGILL, /* range check */ 210105939Sjake SIGILL, /* fix alignment */ 211105939Sjake SIGILL, /* integer overflow */ 212105996Sjake SIGSYS, /* syscall */ 213105939Sjake -1, /* restore physical watchpoint */ 214105939Sjake -1, /* restore virtual watchpoint */ 215105939Sjake -1, /* kernel stack fault */ 216105939Sjake}; 217105939Sjake 218233747SmariusCTASSERT(sizeof(trap_msg) / sizeof(*trap_msg) == T_MAX); 219233747SmariusCTASSERT(sizeof(trap_sig) / sizeof(*trap_sig) == T_MAX); 220233747Smarius 221105733SjakeCTASSERT(sizeof(struct trapframe) == 256); 222105733Sjake 22398037Sjakeint debugger_on_signal = 0; 22498037SjakeSYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW, 22598037Sjake &debugger_on_signal, 0, ""); 22698037Sjake 227206086Smariusu_int corrected_ecc = 0; 228206086SmariusSYSCTL_UINT(_machdep, OID_AUTO, corrected_ecc, CTLFLAG_RD, &corrected_ecc, 0, 229206086Smarius "corrected ECC errors"); 230206086Smarius 231182773Smarius/* 232182773Smarius * SUNW,set-trap-table allows to take over %tba from the PROM, which 233182773Smarius * will turn off interrupts and handle outstanding ones while doing so, 234182773Smarius * in a safe way. 235182773Smarius */ 23680708Sjakevoid 237182773Smariussun4u_set_traptable(void *tba_addr) 238182773Smarius{ 239182773Smarius static struct { 240182773Smarius cell_t name; 241182773Smarius cell_t nargs; 242182773Smarius cell_t nreturns; 243182773Smarius cell_t tba_addr; 244182773Smarius } args = { 245182773Smarius (cell_t)"SUNW,set-trap-table", 246206449Smarius 1, 247206449Smarius 0, 248182773Smarius }; 249182773Smarius 250182773Smarius args.tba_addr = (cell_t)tba_addr; 251186347Snwhitehorn ofw_entry(&args); 252182773Smarius} 253182773Smarius 254182773Smariusvoid 25580709Sjaketrap(struct trapframe *tf) 25680708Sjake{ 25783366Sjulian struct thread *td; 25881135Stmm struct proc *p; 25981387Sjake int error; 26081135Stmm int sig; 261157445Smarius register_t addr; 262151316Sdavidxu ksiginfo_t ksi; 26380709Sjake 264181701Smarius td = curthread; 26581185Sjake 266105939Sjake CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td, 267105939Sjake trap_msg[tf->tf_type & ~T_KERNEL], 268105939Sjake (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil)); 269105939Sjake 270170291Sattilio PCPU_INC(cnt.v_trap); 27184186Sjake 272105939Sjake if ((tf->tf_tstate & TSTATE_PRIV) == 0) { 273105939Sjake KASSERT(td != NULL, ("trap: curthread NULL")); 274105939Sjake KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); 27584186Sjake 276105939Sjake p = td->td_proc; 277155455Sphk td->td_pticks = 0; 27883366Sjulian td->td_frame = tf; 279157445Smarius addr = tf->tf_tpc; 28090894Sjulian if (td->td_ucred != p->p_ucred) 28190894Sjulian cred_update_thread(td); 28281135Stmm 283105939Sjake switch (tf->tf_type) { 284105939Sjake case T_DATA_MISS: 285105939Sjake case T_DATA_PROTECTION: 286157445Smarius addr = tf->tf_sfar; 287157445Smarius /* FALLTHROUGH */ 288105939Sjake case T_INSTRUCTION_MISS: 289105939Sjake sig = trap_pfault(td, tf); 290105939Sjake break; 291105939Sjake case T_FILL: 292105939Sjake sig = rwindow_load(td, tf, 2); 293105939Sjake break; 294105939Sjake case T_FILL_RET: 295105939Sjake sig = rwindow_load(td, tf, 1); 296105939Sjake break; 297105939Sjake case T_SPILL: 298105939Sjake sig = rwindow_save(td); 299105939Sjake break; 300206086Smarius case T_CORRECTED_ECC_ERROR: 301206086Smarius sig = trap_cecc(); 302206086Smarius break; 303105939Sjake default: 304233748Smarius if (tf->tf_type > T_MAX) 305206086Smarius panic("trap: bad trap type %#lx (user)", 306206086Smarius tf->tf_type); 307206086Smarius else if (trap_sig[tf->tf_type] == -1) 308206086Smarius panic("trap: %s (user)", 309206086Smarius trap_msg[tf->tf_type]); 310105939Sjake sig = trap_sig[tf->tf_type]; 311105939Sjake break; 312105939Sjake } 31384186Sjake 314105939Sjake if (sig != 0) { 315105939Sjake /* Translate fault for emulators. */ 316105939Sjake if (p->p_sysent->sv_transtrap != NULL) { 317105939Sjake sig = p->p_sysent->sv_transtrap(sig, 318105939Sjake tf->tf_type); 319105939Sjake } 320105939Sjake if (debugger_on_signal && 321105939Sjake (sig == 4 || sig == 10 || sig == 11)) 322174898Srwatson kdb_enter(KDB_WHY_TRAPSIG, "trapsig"); 323151316Sdavidxu ksiginfo_init_trap(&ksi); 324151316Sdavidxu ksi.ksi_signo = sig; 325151316Sdavidxu ksi.ksi_code = (int)tf->tf_type; /* XXX not POSIX */ 326157445Smarius ksi.ksi_addr = (void *)addr; 327151354Sdavidxu ksi.ksi_trapno = (int)tf->tf_type; 328151316Sdavidxu trapsignal(td, &ksi); 32984186Sjake } 33084186Sjake 331155455Sphk userret(td, tf); 332105939Sjake mtx_assert(&Giant, MA_NOTOWNED); 333181701Smarius } else { 334105939Sjake KASSERT((tf->tf_type & T_KERNEL) != 0, 335105939Sjake ("trap: kernel trap isn't")); 336105939Sjake 337131950Smarcel if (kdb_active) { 338131950Smarcel kdb_reenter(); 339131950Smarcel return; 340131950Smarcel } 341131950Smarcel 342105939Sjake switch (tf->tf_type & ~T_KERNEL) { 343105939Sjake case T_BREAKPOINT: 344105939Sjake case T_KSTACK_FAULT: 345131950Smarcel error = (kdb_trap(tf->tf_type, 0, tf) == 0); 346131950Smarcel TF_DONE(tf); 347105939Sjake break; 348105939Sjake#ifdef notyet 349105939Sjake case T_PA_WATCHPOINT: 350105939Sjake case T_VA_WATCHPOINT: 351105939Sjake error = db_watch_trap(tf); 352105939Sjake break; 35380709Sjake#endif 354105939Sjake case T_DATA_MISS: 355105939Sjake case T_DATA_PROTECTION: 356105939Sjake case T_INSTRUCTION_MISS: 357105939Sjake error = trap_pfault(td, tf); 358101955Sjake break; 359105939Sjake case T_DATA_EXCEPTION: 360105939Sjake case T_MEM_ADDRESS_NOT_ALIGNED: 361105939Sjake if ((tf->tf_sfsr & MMU_SFSR_FV) != 0 && 362105939Sjake MMU_SFSR_GET_ASI(tf->tf_sfsr) == ASI_AIUP) { 363105939Sjake if (tf->tf_tpc >= (u_long)copy_nofault_begin && 364105939Sjake tf->tf_tpc <= (u_long)copy_nofault_end) { 365105939Sjake tf->tf_tpc = (u_long)copy_fault; 366105939Sjake tf->tf_tnpc = tf->tf_tpc + 4; 367105939Sjake error = 0; 368105939Sjake break; 369105939Sjake } 370105939Sjake if (tf->tf_tpc >= (u_long)fs_nofault_begin && 371105939Sjake tf->tf_tpc <= (u_long)fs_nofault_end) { 372105939Sjake tf->tf_tpc = (u_long)fs_fault; 373105939Sjake tf->tf_tnpc = tf->tf_tpc + 4; 374105939Sjake error = 0; 375105939Sjake break; 376105939Sjake } 377105939Sjake } 378181701Smarius error = 1; 379105939Sjake break; 380116659Sjmg case T_DATA_ERROR: 381116659Sjmg /* 382157513Smarius * Handle PCI poke/peek as per UltraSPARC IIi 383157513Smarius * User's Manual 16.2.1, modulo checking the 384157513Smarius * TPC as USIII CPUs generate a precise trap 385157513Smarius * instead of a special deferred one. 386116659Sjmg */ 387116659Sjmg if (tf->tf_tpc > (u_long)fas_nofault_begin && 388157513Smarius tf->tf_tpc < (u_long)fas_nofault_end) { 389122464Sjake cache_flush(); 390204152Smarius cache_enable(PCPU_GET(impl)); 391116659Sjmg tf->tf_tpc = (u_long)fas_fault; 392116659Sjmg tf->tf_tnpc = tf->tf_tpc + 4; 393116659Sjmg error = 0; 394116659Sjmg break; 395116659Sjmg } 396116659Sjmg error = 1; 397116659Sjmg break; 398206086Smarius case T_CORRECTED_ECC_ERROR: 399206086Smarius error = trap_cecc(); 400206086Smarius break; 401105939Sjake default: 402105939Sjake error = 1; 403105939Sjake break; 404101955Sjake } 405105939Sjake 406206086Smarius if (error != 0) { 407206086Smarius tf->tf_type &= ~T_KERNEL; 408233748Smarius if (tf->tf_type > T_MAX) 409206086Smarius panic("trap: bad trap type %#lx (kernel)", 410206086Smarius tf->tf_type); 411233747Smarius panic("trap: %s (kernel)", trap_msg[tf->tf_type]); 412206086Smarius } 41380709Sjake } 41484186Sjake CTR1(KTR_TRAP, "trap: td=%p return", td); 41580708Sjake} 41681185Sjake 41788642Sjakestatic int 418206086Smariustrap_cecc(void) 419206086Smarius{ 420206086Smarius u_long eee; 421206086Smarius 422206086Smarius /* 423206086Smarius * Turn off (non-)correctable error reporting while we're dealing 424206086Smarius * with the error. 425206086Smarius */ 426206086Smarius eee = ldxa(0, ASI_ESTATE_ERROR_EN_REG); 427206086Smarius stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee & ~(AA_ESTATE_NCEEN | 428206086Smarius AA_ESTATE_CEEN)); 429206086Smarius /* Flush the caches in order ensure no corrupt data got installed. */ 430206086Smarius cache_flush(); 431206086Smarius /* Ensure the caches are still turned on (should be). */ 432206086Smarius cache_enable(PCPU_GET(impl)); 433218909Sbrucec /* Clear the error from the AFSR. */ 434206086Smarius stxa_sync(0, ASI_AFSR, ldxa(0, ASI_AFSR)); 435206086Smarius corrected_ecc++; 436206086Smarius printf("corrected ECC error\n"); 437206086Smarius /* Turn (non-)correctable error reporting back on. */ 438206086Smarius stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee); 439206086Smarius return (0); 440206086Smarius} 441206086Smarius 442206086Smariusstatic int 44388642Sjaketrap_pfault(struct thread *td, struct trapframe *tf) 44481185Sjake{ 44581185Sjake struct vmspace *vm; 44683366Sjulian struct proc *p; 44781185Sjake vm_offset_t va; 44882903Sjake vm_prot_t prot; 449182122Smarius vm_map_entry_t entry; 45082903Sjake u_long ctx; 45182903Sjake int type; 45281185Sjake int rv; 45381185Sjake 454105939Sjake if (td == NULL) 455105939Sjake return (-1); 45688642Sjake KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL")); 457105939Sjake KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL")); 458105939Sjake KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL")); 45981185Sjake 460105939Sjake p = td->td_proc; 461105939Sjake 46282903Sjake rv = KERN_SUCCESS; 46388642Sjake ctx = TLB_TAR_CTX(tf->tf_tar); 46482903Sjake type = tf->tf_type & ~T_KERNEL; 46588642Sjake va = TLB_TAR_VA(tf->tf_tar); 46681185Sjake 46788642Sjake CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx", 468181701Smarius td, p->p_vmspace->vm_pmap.pm_context[curcpu], va, ctx); 46981185Sjake 470199868Salc if (type == T_DATA_PROTECTION) 47182903Sjake prot = VM_PROT_WRITE; 472199868Salc else { 47388642Sjake if (type == T_DATA_MISS) 47482903Sjake prot = VM_PROT_READ; 47581387Sjake else 47682903Sjake prot = VM_PROT_READ | VM_PROT_EXECUTE; 47782903Sjake } 47881185Sjake 47988642Sjake if (ctx != TLB_CTX_KERNEL) { 48088642Sjake if ((tf->tf_tstate & TSTATE_PRIV) != 0 && 481101955Sjake (tf->tf_tpc >= (u_long)fs_nofault_intr_begin && 482181701Smarius tf->tf_tpc <= (u_long)fs_nofault_intr_end)) { 483101955Sjake tf->tf_tpc = (u_long)fs_fault; 484101955Sjake tf->tf_tnpc = tf->tf_tpc + 4; 485101955Sjake return (0); 486101955Sjake } 48788642Sjake 48888642Sjake /* 48988642Sjake * This is a fault on non-kernel virtual memory. 49088642Sjake */ 49188642Sjake vm = p->p_vmspace; 49288642Sjake 49388642Sjake /* 49488642Sjake * Keep swapout from messing with us during this 49588642Sjake * critical time. 49688642Sjake */ 49788642Sjake PROC_LOCK(p); 49888642Sjake ++p->p_lock; 49988642Sjake PROC_UNLOCK(p); 50088642Sjake 50195139Sjake /* Fault in the user page. */ 502199868Salc rv = vm_fault(&vm->vm_map, va, prot, VM_FAULT_NORMAL); 50388642Sjake 50488642Sjake /* 50588642Sjake * Now the process can be swapped again. 50688642Sjake */ 50788642Sjake PROC_LOCK(p); 50888642Sjake --p->p_lock; 50988642Sjake PROC_UNLOCK(p); 51082903Sjake } else { 51188642Sjake /* 512101955Sjake * This is a fault on kernel virtual memory. Attempts to 513101955Sjake * access kernel memory from user mode cause privileged 514101955Sjake * action traps, not page fault. 51588642Sjake */ 51688642Sjake KASSERT(tf->tf_tstate & TSTATE_PRIV, 51788642Sjake ("trap_pfault: fault on nucleus context from user mode")); 51888642Sjake 519182122Smarius if (tf->tf_tpc >= (u_long)copy_nofault_begin && 520182122Smarius tf->tf_tpc <= (u_long)copy_nofault_end) { 521182122Smarius vm_map_lock_read(kernel_map); 522182122Smarius if (vm_map_lookup_entry(kernel_map, va, &entry) && 523182122Smarius (entry->eflags & MAP_ENTRY_NOFAULT) != 0) { 524182122Smarius tf->tf_tpc = (u_long)copy_fault; 525182122Smarius tf->tf_tnpc = tf->tf_tpc + 4; 526182122Smarius vm_map_unlock_read(kernel_map); 527182122Smarius return (0); 528182122Smarius } 529182122Smarius vm_map_unlock_read(kernel_map); 530182122Smarius } 531182122Smarius 53288642Sjake /* 533181701Smarius * We don't have to worry about process locking or stacks in 534181701Smarius * the kernel. 53588642Sjake */ 53688642Sjake rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL); 53781185Sjake } 53888642Sjake 53988642Sjake CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d", 54088642Sjake td, va, rv); 54181185Sjake if (rv == KERN_SUCCESS) 54281185Sjake return (0); 543101955Sjake if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) { 544101955Sjake if (tf->tf_tpc >= (u_long)fs_nofault_begin && 545101955Sjake tf->tf_tpc <= (u_long)fs_nofault_end) { 546101955Sjake tf->tf_tpc = (u_long)fs_fault; 54781185Sjake tf->tf_tnpc = tf->tf_tpc + 4; 54881185Sjake return (0); 54981185Sjake } 550101955Sjake if (tf->tf_tpc >= (u_long)copy_nofault_begin && 551101955Sjake tf->tf_tpc <= (u_long)copy_nofault_end) { 552101955Sjake tf->tf_tpc = (u_long)copy_fault; 553101955Sjake tf->tf_tnpc = tf->tf_tpc + 4; 554101955Sjake return (0); 555101955Sjake } 55681185Sjake } 55788642Sjake return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); 55881185Sjake} 55982006Sjake 56082006Sjake/* Maximum number of arguments that can be passed via the out registers. */ 56182006Sjake#define REG_MAXARGS 6 56282006Sjake 563208453Skibint 564208453Skibcpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) 565202900Smarius{ 566202900Smarius struct trapframe *tf; 567202900Smarius struct proc *p; 568208453Skib register_t *argp; 569202900Smarius int reg; 570202900Smarius int regcnt; 571202900Smarius int error; 572202900Smarius 573202900Smarius p = td->td_proc; 574202900Smarius tf = td->td_frame; 575202900Smarius reg = 0; 576202900Smarius regcnt = REG_MAXARGS; 577202900Smarius 578202900Smarius sa->code = tf->tf_global[1]; 579202900Smarius 580208453Skib if (sa->code == SYS_syscall || sa->code == SYS___syscall) { 581202900Smarius sa->code = tf->tf_out[reg++]; 582202900Smarius regcnt--; 583202900Smarius } 584202900Smarius 585202900Smarius if (p->p_sysent->sv_mask) 586202900Smarius sa->code &= p->p_sysent->sv_mask; 587202900Smarius if (sa->code >= p->p_sysent->sv_size) 588202900Smarius sa->callp = &p->p_sysent->sv_table[0]; 589202900Smarius else 590202900Smarius sa->callp = &p->p_sysent->sv_table[sa->code]; 591202900Smarius 592202900Smarius sa->narg = sa->callp->sy_narg; 593202900Smarius KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]), 594202900Smarius ("Too many syscall arguments!")); 595202900Smarius error = 0; 596208453Skib argp = sa->args; 597202900Smarius bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt); 598202900Smarius if (sa->narg > regcnt) 599202900Smarius error = copyin((void *)(tf->tf_out[6] + SPOFF + 600202900Smarius offsetof(struct frame, fr_pad[6])), &sa->args[regcnt], 601202900Smarius (sa->narg - regcnt) * sizeof(sa->args[0])); 602208453Skib if (error == 0) { 603208453Skib td->td_retval[0] = 0; 604208453Skib td->td_retval[1] = 0; 605208453Skib } 606202900Smarius 607202900Smarius return (error); 608202900Smarius} 609202900Smarius 610225474Skib#include "../../kern/subr_syscall.c" 611225474Skib 61282006Sjake/* 613202900Smarius * Syscall handler 614202900Smarius * The arguments to the syscall are passed in the out registers by the caller, 615202900Smarius * and are saved in the trap frame. The syscall number is passed in %g1 (and 616202900Smarius * also saved in the trap frame). 61782006Sjake */ 61882006Sjakevoid 61984186Sjakesyscall(struct trapframe *tf) 62082006Sjake{ 621208453Skib struct thread *td; 622202900Smarius struct syscall_args sa; 62382006Sjake int error; 62482006Sjake 625181701Smarius td = curthread; 626208453Skib td->td_frame = tf; 627208453Skib 628105939Sjake KASSERT(td != NULL, ("trap: curthread NULL")); 629105939Sjake KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); 63084186Sjake 63182006Sjake /* 63282006Sjake * For syscalls, we don't want to retry the faulting instruction 63382006Sjake * (usually), instead we need to advance one instruction. 63482006Sjake */ 635199135Skib td->td_pcb->pcb_tpc = tf->tf_tpc; 63686146Stmm TF_DONE(tf); 63782006Sjake 638208453Skib error = syscallenter(td, &sa); 639208453Skib syscallret(td, error, &sa); 64082006Sjake} 641