1 //==========================================================================
5 // POSIX exception translation
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: nickg
46 // Purpose: POSIX exception translation
47 // Description: This file contains code to translate eCos hardware
48 // exceptions into POSIX signals.
52 //####DESCRIPTIONEND####
54 //==========================================================================
56 #include <pkgconf/hal.h>
57 #include <pkgconf/kernel.h>
58 #include <pkgconf/posix.h>
60 #include <cyg/kernel/ktypes.h> // base kernel types
61 #include <cyg/infra/cyg_trac.h> // tracing macros
62 #include <cyg/infra/cyg_ass.h> // assertion macros
64 #include <cyg/infra/diag.h>
66 #include "pprivate.h" // POSIX private header
68 #include <signal.h> // our header
70 #include <cyg/kernel/thread.inl>
72 //==========================================================================
73 // Translation table from eCos exceptions to POSIX signals.
79 } exception_signal_mapping[] =
81 #ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
82 {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS},
84 #ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE
85 {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS},
87 #ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS
88 {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS},
90 #ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE
91 {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS},
93 #ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
94 {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS},
96 #ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS
97 {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
99 #ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE
100 {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
102 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
103 {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV},
105 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
106 {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV},
108 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
109 {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV},
111 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
112 {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV},
114 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
115 {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV},
117 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
118 {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV},
120 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
121 {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV},
123 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
124 {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV},
126 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
127 {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS},
129 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
130 {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS},
132 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
133 {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS},
135 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
136 {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS},
138 #ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
139 {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL},
141 #ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT
142 {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT},
144 #ifdef CYGNUM_HAL_EXCEPTION_TRAP
145 {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP},
147 #ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
148 {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE},
150 #ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW
151 {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE},
153 #ifdef CYGNUM_HAL_EXCEPTION_BOUNDS
154 {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV},
156 #ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP
157 {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP},
159 #ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
160 {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP},
162 #ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
163 {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP},
165 #ifdef CYGNUM_HAL_EXCEPTION_DATA_BP
166 {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP},
168 #ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
169 {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP},
171 #ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
172 {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV},
174 #ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT
175 {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV},
177 #ifdef CYGNUM_HAL_EXCEPTION_PARITY
178 {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS},
180 #ifdef CYGNUM_HAL_EXCEPTION_FPU
181 {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE},
183 #ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
184 {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE},
186 #ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
187 {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE},
189 #ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
190 {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE},
192 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
193 {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE},
195 #ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
196 {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS},
198 {0, 0} // dummy value to ensure compiler is happy
201 //==========================================================================
202 // POSIX exception handler
204 static void cyg_posix_exception_handler(
205 CYG_ADDRWORD data, // user supplied data == signal number
206 cyg_code exception_number, // exception being raised
207 CYG_ADDRWORD exception_info // any exception specific info
212 pthread_info *self = pthread_self_info();
216 // Not a POSIX thread, just return
220 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
226 for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )
228 if( exception_signal_mapping[i].exception == exception_number )
230 signo = exception_signal_mapping[i].signal;
237 if( sigismember( &self->sigmask, signo ) )
239 // The signal is masked in the current thread. POSIX says that
240 // the behaviour is undefined here. We choose to ignore it.
245 // The kernel exception handler may have disabled interrupts, so
246 // we (re-)enable them here. From this point on we are running in
247 // a context that is effectively just pushed onto the stack of the
248 // current thread. If we return we will unwind and resume
249 // execution from the excepting code. We can also, in theory,
250 // longjump out of the signal handler, and although that is
251 // deprecated, we make sure in cyg_deliver_signals() that it is
252 // possible to do it.
254 HAL_ENABLE_INTERRUPTS();
258 sev.sigev_notify = SIGEV_SIGNAL;
259 sev.sigev_signo = signo;
260 sev.sigev_value.sival_ptr = (void *)exception_info;
262 // Generate the signal
263 cyg_sigqueue( &sev, SI_EXCEPT );
265 // And try to deliver it
266 cyg_deliver_signals();
269 //==========================================================================
270 // Install all the exception handlers
272 static void install_handlers( Cyg_Thread *thread)
274 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
276 // With decoded exceptions, we must install a separate exception
277 // handler for each supported exception.
279 for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )
281 thread->register_exception( exception_signal_mapping[i].exception,
282 cyg_posix_exception_handler,
283 exception_signal_mapping[i].signal,
290 // Otherwise there is just one exception handler for all exceptions.
292 thread->register_exception( CYGNUM_HAL_EXCEPTION_MIN,
293 cyg_posix_exception_handler,
302 //==========================================================================
305 externC void cyg_posix_exception_start()
307 #ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
309 // With global exceptions, we only need to install a single static
310 // set of exception handlers. Note that by this point in system
311 // initialization the idle thread should be installed as the
312 // current thread, so we pass a pointer to that to
313 // install_handlers(). The identity of the thread passed is
314 // actually irrelevant in this case and is just used as a handle
315 // into the thread class.
317 install_handlers( Cyg_Thread::self() );
322 //==========================================================================
323 // Per thread exception initialization and destruction
325 externC void cyg_pthread_exception_init(pthread_info *thread)
327 #ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
329 // With non-global exceptions we must install a new set of handlers
332 install_handlers( thread->thread );
337 externC void cyg_pthread_exception_destroy(pthread_info *thread)
339 // Nothing to do at present.
342 // -------------------------------------------------------------------------