exception.s revision 12827
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 * $Id: exception.s,v 1.11 1995/09/07 21:36:17 davidg Exp $ 34 */ 35 36#include "npx.h" /* NNPX */ 37#include "assym.s" /* system defines */ 38#include <sys/errno.h> /* error return codes */ 39#include <machine/spl.h> /* SWI_AST_MASK ... */ 40#include <machine/psl.h> /* PSL_I */ 41#include <machine/trap.h> /* trap codes */ 42#include <sys/syscall.h> /* syscall numbers */ 43#include <machine/asmacros.h> /* miscellaneous macros */ 44 45#define KDSEL 0x10 /* kernel data selector */ 46#define SEL_RPL_MASK 0x0003 47#define TRAPF_CS_OFF (13 * 4) 48 49 .text 50 51/*****************************************************************************/ 52/* Trap handling */ 53/*****************************************************************************/ 54/* 55 * Trap and fault vector routines 56 */ 57#define IDTVEC(name) ALIGN_TEXT ; .globl _X/**/name ; _X/**/name: 58#define TRAP(a) pushl $(a) ; jmp _alltraps 59 60/* 61 * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose 62 * control. The sti's give the standard losing behaviour for ddb and kgdb. 63 */ 64#ifdef BDE_DEBUGGER 65#define BDBTRAP(name) \ 66 ss ; \ 67 cmpb $0,_bdb_exists ; \ 68 je 1f ; \ 69 testb $SEL_RPL_MASK,4(%esp) ; \ 70 jne 1f ; \ 71 ss ; \ 72 .globl bdb_/**/name/**/_ljmp ; \ 73bdb_/**/name/**/_ljmp: ; \ 74 ljmp $0,$0 ; \ 751: 76#else 77#define BDBTRAP(name) 78#endif 79 80#ifdef KGDB 81# define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; \ 82 pushl $(a) ; jmp _bpttraps 83#else 84# define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; TRAP(a) 85#endif 86 87MCOUNT_LABEL(user) 88MCOUNT_LABEL(btrap) 89 90IDTVEC(div) 91 pushl $0; TRAP(T_DIVIDE) 92IDTVEC(dbg) 93 BDBTRAP(dbg) 94 pushl $0; BPTTRAP(T_TRCTRAP) 95IDTVEC(nmi) 96 pushl $0; TRAP(T_NMI) 97IDTVEC(bpt) 98 BDBTRAP(bpt) 99 pushl $0; BPTTRAP(T_BPTFLT) 100IDTVEC(ofl) 101 pushl $0; TRAP(T_OFLOW) 102IDTVEC(bnd) 103 pushl $0; TRAP(T_BOUND) 104IDTVEC(ill) 105 pushl $0; TRAP(T_PRIVINFLT) 106IDTVEC(dna) 107 pushl $0; TRAP(T_DNA) 108IDTVEC(dble) 109 TRAP(T_DOUBLEFLT) 110IDTVEC(fpusegm) 111 pushl $0; TRAP(T_FPOPFLT) 112IDTVEC(tss) 113 TRAP(T_TSSFLT) 114IDTVEC(missing) 115 TRAP(T_SEGNPFLT) 116IDTVEC(stk) 117 TRAP(T_STKFLT) 118IDTVEC(prot) 119 TRAP(T_PROTFLT) 120IDTVEC(page) 121 TRAP(T_PAGEFLT) 122IDTVEC(rsvd) 123 pushl $0; TRAP(T_RESERVED) 124IDTVEC(fpu) 125#if NNPX > 0 126 /* 127 * Handle like an interrupt (except for accounting) so that we can 128 * call npxintr to clear the error. It would be better to handle 129 * npx interrupts as traps. This used to be difficult for nested 130 * interrupts, but now it is fairly easy - mask nested ones the 131 * same as SWI_AST's. 132 */ 133 pushl $0 /* dumby error code */ 134 pushl $0 /* dumby trap type */ 135 pushal 136 pushl %ds 137 pushl %es /* now the stack frame is a trap frame */ 138 movl $KDSEL,%eax 139 movl %ax,%ds 140 movl %ax,%es 141 FAKE_MCOUNT(12*4(%esp)) 142 movl _cpl,%eax 143 pushl %eax 144 pushl $0 /* dummy unit to finish building intr frame */ 145 incl _cnt+V_TRAP 146 orl $SWI_AST_MASK,%eax 147 movl %eax,_cpl 148 call _npxintr 149 incb _intr_nesting_level 150 MEXITCOUNT 151 jmp _doreti 152#else /* NNPX > 0 */ 153 pushl $0; TRAP(T_ARITHTRAP) 154#endif /* NNPX > 0 */ 155IDTVEC(align) 156 TRAP(T_ALIGNFLT) 157 158 SUPERALIGN_TEXT 159_alltraps: 160 pushal 161 pushl %ds 162 pushl %es 163alltraps_with_regs_pushed: 164 movl $KDSEL,%eax 165 movl %ax,%ds 166 movl %ax,%es 167 FAKE_MCOUNT(12*4(%esp)) 168calltrap: 169 FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */ 170 incl _cnt+V_TRAP 171 orl $SWI_AST_MASK,_cpl 172 173 /* 174 * Fake a call frame: point %ebp at a 2 element array consisting 175 * of { trappee's %ebp, trappee's %eip }. The stack frame is in 176 * the wrong order for this, but the trappee's %ebp is fortunately 177 * followed by junk which we can overwrite with the trappee's %eip. 178 */ 179 movl TF_EIP(%esp),%eax 180 movl %eax,TF_ISP(%esp) 181 lea TF_EBP(%esp),%ebp 182 183 call _trap 184 185 /* 186 * There was no place to save the cpl so we have to recover it 187 * indirectly. For traps from user mode it was 0, and for traps 188 * from kernel mode Oring SWI_AST_MASK into it didn't change it. 189 */ 190 subl %eax,%eax 191 testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) 192 jne 1f 193 movl _cpl,%eax 1941: 195 /* 196 * Return via _doreti to handle ASTs. Have to change trap frame 197 * to interrupt frame. 198 */ 199 pushl %eax 200 subl $4,%esp 201 incb _intr_nesting_level 202 MEXITCOUNT 203 jmp _doreti 204 205#ifdef KGDB 206/* 207 * This code checks for a kgdb trap, then falls through 208 * to the regular trap code. 209 */ 210 SUPERALIGN_TEXT 211_bpttraps: 212 pushal 213 pushl %ds 214 pushl %es 215 movl $KDSEL,%eax 216 movl %ax,%ds 217 movl %ax,%es 218 FAKE_MCOUNT(12*4(%esp)) 219 testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) /* non-kernel mode? */ 220 jne calltrap /* yes */ 221 call _kgdb_trap_glue 222 MEXITCOUNT 223 jmp calltrap 224#endif 225 226/* 227 * Call gate entry for syscall. 228 * The intersegment call has been set up to specify one dummy parameter. 229 * This leaves a place to put eflags so that the call frame can be 230 * converted to a trap frame. Note that the eflags is (semi-)bogusly 231 * pushed into (what will be) tf_err and then copied later into the 232 * final spot. It has to be done this way because esp can't be just 233 * temporarily altered for the pushfl - an interrupt might come in 234 * and clobber the saved cs/eip. 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 movl $KDSEL,%eax /* switch to kernel segments */ 244 movl %ax,%ds 245 movl %ax,%es 246 movl TF_ERR(%esp),%eax /* copy saved eflags to final spot */ 247 movl %eax,TF_EFLAGS(%esp) 248 FAKE_MCOUNT(12*4(%esp)) 249 incl _cnt+V_SYSCALL 250 movl $SWI_AST_MASK,_cpl 251 call _syscall 252 /* 253 * Return via _doreti to handle ASTs. 254 */ 255 pushl $0 /* cpl to restore */ 256 subl $4,%esp 257 movb $1,_intr_nesting_level 258 MEXITCOUNT 259 jmp _doreti 260 261#if defined(COMPAT_LINUX) || defined(LINUX) 262/* 263 * Call gate entry for Linux syscall (int 0x80) 264 */ 265 SUPERALIGN_TEXT 266IDTVEC(linux_syscall) 267 subl $8,%esp /* skip over tf_trapno and tf_err */ 268 pushal 269 pushl %ds 270 pushl %es 271 movl $KDSEL,%eax /* switch to kernel segments */ 272 movl %ax,%ds 273 movl %ax,%es 274 FAKE_MCOUNT(12*4(%esp)) 275 incl _cnt+V_SYSCALL 276 movl $SWI_AST_MASK,_cpl 277 call _linux_syscall 278 /* 279 * Return via _doreti to handle ASTs. 280 */ 281 pushl $0 /* cpl to restore */ 282 subl $4,%esp 283 movb $1,_intr_nesting_level 284 MEXITCOUNT 285 jmp _doreti 286#endif /* COMPAT_LINUX || LINUX */ 287 288/* 289 * Include what was once config+isa-dependent code. 290 * XXX it should be in a stand-alone file. It's still icu-dependent and 291 * belongs in i386/isa. 292 */ 293#include "i386/isa/vector.s" 294 295/* 296 * Include what was once icu-dependent code. 297 * XXX it should be merged into this file (also move the definition of 298 * imen to vector.s or isa.c). 299 * Before including it, set up a normal asm environment so that vector.s 300 * doesn't have to know that stuff is included after it. 301 */ 302 .data 303 ALIGN_DATA 304 .text 305 SUPERALIGN_TEXT 306#include "i386/isa/icu.s" 307