1 /* $NetBSD: linux_trap.c,v 1.3 2006/03/17 06:31:58 erh Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * 386 Trap and System call handling 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.3 2006/03/17 06:31:58 erh Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/proc.h> 49 #include <sys/sa.h> 50 #include <sys/savar.h> 51 #include <sys/user.h> 52 #include <sys/acct.h> 53 #include <sys/kernel.h> 54 #include <sys/signal.h> 55 #include <sys/signalvar.h> 56 #include <sys/syscall.h> 57 58 #include <uvm/uvm_extern.h> 59 60 #include <machine/cpu.h> 61 #include <machine/cpufunc.h> 62 #include <machine/psl.h> 63 #include <machine/reg.h> 64 #include <machine/trap.h> 65 #include <machine/userret.h> 66 67 #include <compat/linux/common/linux_exec.h> 68 69 #define LINUX_T_DIVIDE 0 70 #define LINUX_T_DEBUG 1 71 #define LINUX_T_NMI 2 72 #define LINUX_T_INT3 3 73 #define LINUX_T_OVERFLOW 4 74 #define LINUX_T_BOUNDS 5 75 #define LINUX_T_INVALID_OP 6 76 #define LINUX_T_DEVICE_NOT_AVAIL 7 77 #define LINUX_T_DOUBLE_FAULT 8 78 #define LINUX_T_COPROC_SEG_OVERRUN 9 79 #define LINUX_T_INVALID_TSS 10 80 #define LINUX_T_SEG_NOT_PRESENT 11 81 #define LINUX_T_STACK_SEG_FAULT 12 82 #define LINUX_T_GENERAL_PROT_FAULT 13 83 #define LINUX_T_PAGE_FAULT 14 84 #define LINUX_T_SPURIOUS_INTERRUPT 15 85 #define LINUX_T_COPROC_ERROR 16 86 #define LINUX_T_ALIGN_CHECK 17 87 #define LINUX_T_MACHINE_CHECK 18 /* XXX */ 88 #define LINUX_T_SIMD_COPROC_ERROR 19 /* XXX */ 89 90 /* Note 255 is bogus */ 91 static const int trapno_to_x86_vec[] = { 92 LINUX_T_INVALID_OP, /* 0 T_PRIVINFLT */ 93 LINUX_T_INT3, /* 1 T_BPTFLT */ 94 LINUX_T_COPROC_ERROR, /* 2 T_ARITHTRAP */ 95 LINUX_T_SPURIOUS_INTERRUPT, /* 3 T_ASTFLT XXX: ??? */ 96 LINUX_T_GENERAL_PROT_FAULT, /* 4 T_PROTFLT */ 97 LINUX_T_DEBUG, /* 5 T_TRCTRAP */ 98 LINUX_T_PAGE_FAULT, /* 6 T_PAGEFLT */ 99 LINUX_T_ALIGN_CHECK, /* 7 T_ALIGNFLT */ 100 LINUX_T_DIVIDE, /* 8 T_DIVIDE */ 101 LINUX_T_NMI, /* 9 T_NMI */ 102 LINUX_T_OVERFLOW, /* 10 T_OFLOW */ 103 LINUX_T_BOUNDS, /* 11 T_BOUND */ 104 LINUX_T_DEVICE_NOT_AVAIL, /* 12 T_DNA */ 105 LINUX_T_DOUBLE_FAULT, /* 13 T_DOUBLEFLT */ 106 LINUX_T_COPROC_SEG_OVERRUN, /* 14 T_FPOPFLT */ 107 LINUX_T_INVALID_TSS, /* 15 T_TSSFLT */ 108 LINUX_T_SEG_NOT_PRESENT, /* 16 T_SEGNPFLT */ 109 LINUX_T_STACK_SEG_FAULT, /* 17 T_STKFLT */ 110 LINUX_T_MACHINE_CHECK /* 18 T_RESERVED XXX: ??? */ 111 }; 112 113 /* For the nmi and reserved below linux does not post a signal. */ 114 static const int linux_x86_vec_to_sig[] = { 115 SIGFPE, /* 0 LINUX_T_DIVIDE */ 116 SIGTRAP, /* 1 LINUX_T_DEBUG */ 117 /*nmi*/ SIGSEGV, /* 2 LINUX_T_NMI */ 118 SIGTRAP, /* 3 LINUX_T_INT3 */ 119 SIGSEGV, /* 4 LINUX_T_OVERFLOW */ 120 SIGSEGV, /* 5 LINUX_T_BOUNDS */ 121 SIGILL, /* 6 LINUX_T_INVALIDOP */ 122 SIGSEGV, /* 7 LINUX_T_DEVICE_NOT_AVAIL */ 123 SIGSEGV, /* 8 LINUX_T_DOUBLE_FAULT */ 124 SIGFPE, /* 9 LINUX_T_COPROC_SEG_OVERRUN */ 125 SIGSEGV, /* 10 LINUX_T_INVALID_TSS */ 126 SIGBUS, /* 11 LINUX_T_SEG_NOT_PRESENT */ 127 SIGBUS, /* 12 LINUX_T_STACK_SEG_FAULT */ 128 SIGSEGV, /* 13 LINUX_T_GENERAL_PROT_FAULT */ 129 SIGSEGV, /* 14 LINUX_T_PAGE_FAULT */ 130 /*resv*/SIGSEGV, /* 15 LINUX_T_SPURIOUS_INTERRUPT */ 131 SIGFPE, /* 16 LINUX_T_COPROC_ERROR */ 132 SIGSEGV, /* 17 LINUX_T_ALIGN_CHECK */ 133 SIGSEGV /* 18 LINUX_T_MACHINE_CHECK */ 134 }; 135 136 #define ASIZE(a) (sizeof(a) / sizeof(a[0])) 137 138 void 139 linux_trapsignal(struct lwp *l, const ksiginfo_t *ksi) 140 { 141 142 switch (ksi->ksi_signo) { 143 case SIGILL: 144 case SIGTRAP: 145 case SIGIOT: 146 case SIGBUS: 147 case SIGFPE: 148 case SIGSEGV: 149 KASSERT(KSI_TRAP_P(ksi)); 150 if (ksi->ksi_trap < ASIZE(trapno_to_x86_vec)) { 151 ksiginfo_t nksi = *ksi; 152 nksi.ksi_trap = trapno_to_x86_vec[ksi->ksi_trap]; 153 if (nksi.ksi_trap < ASIZE(linux_x86_vec_to_sig)) { 154 nksi.ksi_signo 155 = linux_x86_vec_to_sig[nksi.ksi_trap]; 156 } else { 157 uprintf("Unhandled sig type %d\n", 158 ksi->ksi_trap); 159 } 160 ksi = &nksi; 161 } else { 162 uprintf("Unhandled trap type %d\n", ksi->ksi_trap); 163 } 164 /*FALLTHROUGH*/ 165 default: 166 trapsignal(l, ksi); 167 return; 168 } 169 } 170