exception.s revision 71604
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: head/sys/i386/i386/exception.s 71604 2001-01-24 21:59:25Z jhb $ 34 */ 35 36#include "opt_npx.h" 37 38#include <machine/asmacros.h> 39#include <sys/ipl.h> 40#include <sys/mutex.h> 41#include <machine/lock.h> 42#include <machine/psl.h> 43#include <machine/trap.h> 44#ifdef SMP 45#include <machine/smptests.h> /** various SMP options */ 46#endif 47 48#include "assym.s" 49 50#define SEL_RPL_MASK 0x0003 51 52 .text 53 54/*****************************************************************************/ 55/* Trap handling */ 56/*****************************************************************************/ 57/* 58 * Trap and fault vector routines. 59 * 60 * Most traps are 'trap gates', SDT_SYS386TGT. A trap gate pushes state on 61 * the stack that mostly looks like an interrupt, but does not disable 62 * interrupts. A few of the traps we are use are interrupt gates, 63 * SDT_SYS386IGT, which are nearly the same thing except interrupts are 64 * disabled on entry. 65 * 66 * The cpu will push a certain amount of state onto the kernel stack for 67 * the current process. The amount of state depends on the type of trap 68 * and whether the trap crossed rings or not. See i386/include/frame.h. 69 * At the very least the current EFLAGS (status register, which includes 70 * the interrupt disable state prior to the trap), the code segment register, 71 * and the return instruction pointer are pushed by the cpu. The cpu 72 * will also push an 'error' code for certain traps. We push a dummy 73 * error code for those traps where the cpu doesn't in order to maintain 74 * a consistent frame. We also push a contrived 'trap number'. 75 * 76 * The cpu does not push the general registers, we must do that, and we 77 * must restore them prior to calling 'iret'. The cpu adjusts the %cs and 78 * %ss segment registers, but does not mess with %ds, %es, or %fs. Thus we 79 * must load them with appropriate values for supervisor mode operation. 80 * 81 * On entry to a trap or interrupt WE DO NOT OWN THE MP LOCK. This means 82 * that we must be careful in regards to accessing global variables. We 83 * save (push) the current cpl (our software interrupt disable mask), call 84 * the trap function, then call _doreti to restore the cpl and deal with 85 * ASTs (software interrupts). _doreti will determine if the restoration 86 * of the cpl unmasked any pending interrupts and will issue those interrupts 87 * synchronously prior to doing the iret. 88 * 89 * At the moment we must own the MP lock to do any cpl manipulation, which 90 * means we must own it prior to calling _doreti. The syscall case attempts 91 * to avoid this by handling a reduced set of cases itself and iret'ing. 92 */ 93#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(_X,name); \ 94 .type __CONCAT(_X,name),@function; __CONCAT(_X,name): 95#define TRAP(a) pushl $(a) ; jmp _alltraps 96 97#ifdef BDE_DEBUGGER 98#define BDBTRAP(name) \ 99 ss ; \ 100 cmpb $0,_bdb_exists ; \ 101 je 1f ; \ 102 testb $SEL_RPL_MASK,4(%esp) ; \ 103 jne 1f ; \ 104 ss ; \ 105 .globl __CONCAT(__CONCAT(bdb_,name),_ljmp); \ 106__CONCAT(__CONCAT(bdb_,name),_ljmp): \ 107 ljmp $0,$0 ; \ 1081: 109#else 110#define BDBTRAP(name) 111#endif 112 113#define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; TRAP(a) 114 115MCOUNT_LABEL(user) 116MCOUNT_LABEL(btrap) 117 118IDTVEC(div) 119 pushl $0; TRAP(T_DIVIDE) 120IDTVEC(dbg) 121 BDBTRAP(dbg) 122 pushl $0; BPTTRAP(T_TRCTRAP) 123IDTVEC(nmi) 124 pushl $0; TRAP(T_NMI) 125IDTVEC(bpt) 126 BDBTRAP(bpt) 127 pushl $0; BPTTRAP(T_BPTFLT) 128IDTVEC(ofl) 129 pushl $0; TRAP(T_OFLOW) 130IDTVEC(bnd) 131 pushl $0; TRAP(T_BOUND) 132IDTVEC(ill) 133 pushl $0; TRAP(T_PRIVINFLT) 134IDTVEC(dna) 135 pushl $0; TRAP(T_DNA) 136IDTVEC(fpusegm) 137 pushl $0; TRAP(T_FPOPFLT) 138IDTVEC(tss) 139 TRAP(T_TSSFLT) 140IDTVEC(missing) 141 TRAP(T_SEGNPFLT) 142IDTVEC(stk) 143 TRAP(T_STKFLT) 144IDTVEC(prot) 145 TRAP(T_PROTFLT) 146IDTVEC(page) 147 TRAP(T_PAGEFLT) 148IDTVEC(mchk) 149 pushl $0; TRAP(T_MCHK) 150IDTVEC(rsvd) 151 pushl $0; TRAP(T_RESERVED) 152 153IDTVEC(fpu) 154#ifdef DEV_NPX 155 /* 156 * Handle like an interrupt (except for accounting) so that we can 157 * call npx_intr to clear the error. It would be better to handle 158 * npx interrupts as traps. Nested interrupts would probably have 159 * to be converted to ASTs. 160 */ 161 pushl $0 /* dummy error code */ 162 pushl $0 /* dummy trap type */ 163 pushal 164 pushl %ds 165 pushl %es /* now stack frame is a trap frame */ 166 pushl %fs 167 mov $KDSEL,%ax 168 mov %ax,%ds 169 mov %ax,%es 170 mov $KPSEL,%ax 171 mov %ax,%fs 172 FAKE_MCOUNT(13*4(%esp)) 173 174 MPLOCKED incl _cnt+V_TRAP 175 pushl $0 /* dummy unit to finish intr frame */ 176 177 call _npx_intr 178 179 addl $4,%esp 180 MEXITCOUNT 181 jmp _doreti 182#else /* DEV_NPX */ 183 pushl $0; TRAP(T_ARITHTRAP) 184#endif /* DEV_NPX */ 185 186IDTVEC(align) 187 TRAP(T_ALIGNFLT) 188 189 /* 190 * _alltraps entry point. Interrupts are enabled if this was a trap 191 * gate (TGT), else disabled if this was an interrupt gate (IGT). 192 * Note that int0x80_syscall is a trap gate. Only page faults 193 * use an interrupt gate. 194 */ 195 196 SUPERALIGN_TEXT 197 .globl _alltraps 198 .type _alltraps,@function 199_alltraps: 200 pushal 201 pushl %ds 202 pushl %es 203 pushl %fs 204alltraps_with_regs_pushed: 205 mov $KDSEL,%ax 206 mov %ax,%ds 207 mov %ax,%es 208 mov $KPSEL,%ax 209 mov %ax,%fs 210 FAKE_MCOUNT(13*4(%esp)) 211calltrap: 212 FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */ 213 call _trap 214 215 /* 216 * Return via _doreti to handle ASTs. 217 */ 218 MEXITCOUNT 219 jmp _doreti 220 221/* 222 * SYSCALL CALL GATE (old entry point for a.out binaries) 223 * 224 * The intersegment call has been set up to specify one dummy parameter. 225 * 226 * This leaves a place to put eflags so that the call frame can be 227 * converted to a trap frame. Note that the eflags is (semi-)bogusly 228 * pushed into (what will be) tf_err and then copied later into the 229 * final spot. It has to be done this way because esp can't be just 230 * temporarily altered for the pushfl - an interrupt might come in 231 * and clobber the saved cs/eip. 232 * 233 * We do not obtain the MP lock, but the call to syscall2 might. If it 234 * does it will release the lock prior to returning. 235 */ 236 SUPERALIGN_TEXT 237IDTVEC(syscall) 238 pushfl /* save eflags in tf_err for now */ 239 subl $4,%esp /* skip over tf_trapno */ 240 pushal 241 pushl %ds 242 pushl %es 243 pushl %fs 244 mov $KDSEL,%ax /* switch to kernel segments */ 245 mov %ax,%ds 246 mov %ax,%es 247 mov $KPSEL,%ax 248 mov %ax,%fs 249 movl TF_ERR(%esp),%eax /* copy saved eflags to final spot */ 250 movl %eax,TF_EFLAGS(%esp) 251 movl $7,TF_ERR(%esp) /* sizeof "lcall 7,0" */ 252 FAKE_MCOUNT(13*4(%esp)) 253 call _syscall2 254 MEXITCOUNT 255 cli /* atomic astpending access */ 256 cmpl $0,PCPU(ASTPENDING) /* AST pending? */ 257 je doreti_syscall_ret /* no, get out of here */ 258 jmp _doreti 259 260/* 261 * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80) 262 * 263 * Even though the name says 'int0x80', this is actually a TGT (trap gate) 264 * rather then an IGT (interrupt gate). Thus interrupts are enabled on 265 * entry just as they are for a normal syscall. 266 * 267 * We do not obtain the MP lock, but the call to syscall2 might. If it 268 * does it will release the lock prior to returning. 269 */ 270 SUPERALIGN_TEXT 271IDTVEC(int0x80_syscall) 272 subl $8,%esp /* skip over tf_trapno and tf_err */ 273 pushal 274 pushl %ds 275 pushl %es 276 pushl %fs 277 mov $KDSEL,%ax /* switch to kernel segments */ 278 mov %ax,%ds 279 mov %ax,%es 280 mov $KPSEL,%ax 281 mov %ax,%fs 282 movl $2,TF_ERR(%esp) /* sizeof "int 0x80" */ 283 FAKE_MCOUNT(13*4(%esp)) 284 call _syscall2 285 MEXITCOUNT 286 cli /* atomic astpending access */ 287 cmpl $0,PCPU(ASTPENDING) /* AST pending? */ 288 je doreti_syscall_ret /* no, get out of here */ 289 jmp _doreti 290 291ENTRY(fork_trampoline) 292 pushl %esp /* trapframe pointer */ 293 pushl %ebx /* arg1 */ 294 pushl %esi /* function */ 295 call _fork_exit 296 addl $12,%esp 297 /* cut from syscall */ 298 299 /* 300 * Return via _doreti to handle ASTs. 301 */ 302 MEXITCOUNT 303 jmp _doreti 304 305 306/* 307 * Include vm86 call routines, which want to call _doreti. 308 */ 309#include "i386/i386/vm86bios.s" 310 311/* 312 * Include what was once config+isa-dependent code. 313 * XXX it should be in a stand-alone file. It's still icu-dependent and 314 * belongs in i386/isa. 315 */ 316#include "i386/isa/vector.s" 317 318/* 319 * Include what was once icu-dependent code. 320 * XXX it should be merged into this file (also move the definition of 321 * imen to vector.s or isa.c). 322 * Before including it, set up a normal asm environment so that vector.s 323 * doesn't have to know that stuff is included after it. 324 */ 325 .data 326 ALIGN_DATA 327 .text 328 SUPERALIGN_TEXT 329#include "i386/isa/ipl.s" 330