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 Free Software Foundation, 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
18 // eCos is distributed in the hope that it will be useful, but WITHOUT
19 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License
24 // along with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 // As a special exception, if other files instantiate templates or use
28 // macros or inline functions from this file, or you compile this file
29 // and link it with other works to produce a work based on this file,
30 // this file does not by itself cause the resulting work to be covered by
31 // the GNU General Public License. However the source code for this file
32 // must still be made available in accordance with section (3) of the GNU
33 // General Public License v2.
35 // This exception does not invalidate any other reasons why a work based
36 // on this file might be covered by the GNU General Public License.
37 // -------------------------------------------
38 // ####ECOSGPLCOPYRIGHTEND####
39 //==========================================================================
40 //#####DESCRIPTIONBEGIN####
43 // Contributors: nickg
45 // Purpose: POSIX exception translation
46 // Description: This file contains code to translate eCos hardware
47 // exceptions into POSIX signals.
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 #include <pkgconf/hal.h>
56 #include <pkgconf/kernel.h>
57 #include <pkgconf/posix.h>
59 #include <cyg/kernel/ktypes.h> // base kernel types
60 #include <cyg/infra/cyg_trac.h> // tracing macros
61 #include <cyg/infra/cyg_ass.h> // assertion macros
63 #include <cyg/infra/diag.h>
65 #include "pprivate.h" // POSIX private header
67 #include <signal.h> // our header
69 #include <cyg/kernel/thread.inl>
71 //==========================================================================
72 // Translation table from eCos exceptions to POSIX signals.
78 } exception_signal_mapping
[] =
80 #ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
81 {CYGNUM_HAL_EXCEPTION_DATA_ACCESS
, SIGBUS
},
83 #ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE
84 {CYGNUM_HAL_EXCEPTION_DATA_WRITE
, SIGBUS
},
86 #ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS
87 {CYGNUM_HAL_EXCEPTION_CODE_ACCESS
, SIGBUS
},
89 #ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE
90 {CYGNUM_HAL_EXCEPTION_CODE_WRITE
, SIGBUS
},
92 #ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
93 {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
, SIGBUS
},
95 #ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS
96 {CYGNUM_HAL_EXCEPTION_IO_ACCESS
, SIGBUS
},
98 #ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE
99 {CYGNUM_HAL_EXCEPTION_IO_ACCESS
, SIGBUS
},
101 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
102 {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
, SIGSEGV
},
104 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
105 {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
, SIGSEGV
},
107 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
108 {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
, SIGSEGV
},
110 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
111 {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
, SIGSEGV
},
113 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
114 {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
, SIGSEGV
},
116 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
117 {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
, SIGSEGV
},
119 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
120 {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
, SIGSEGV
},
122 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
123 {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
, SIGSEGV
},
125 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
126 {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
, SIGBUS
},
128 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
129 {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
, SIGBUS
},
131 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
132 {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
, SIGBUS
},
134 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
135 {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
, SIGBUS
},
137 #ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
138 {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
, SIGILL
},
140 #ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT
141 {CYGNUM_HAL_EXCEPTION_INTERRUPT
, SIGINT
},
143 #ifdef CYGNUM_HAL_EXCEPTION_TRAP
144 {CYGNUM_HAL_EXCEPTION_TRAP
, SIGTRAP
},
146 #ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
147 {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
, SIGFPE
},
149 #ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW
150 {CYGNUM_HAL_EXCEPTION_OVERFLOW
, SIGFPE
},
152 #ifdef CYGNUM_HAL_EXCEPTION_BOUNDS
153 {CYGNUM_HAL_EXCEPTION_BOUNDS
, SIGSEGV
},
155 #ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP
156 {CYGNUM_HAL_EXCEPTION_SINGLE_STEP
, SIGTRAP
},
158 #ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
159 {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
, SIGTRAP
},
161 #ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
162 {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
, SIGTRAP
},
164 #ifdef CYGNUM_HAL_EXCEPTION_DATA_BP
165 {CYGNUM_HAL_EXCEPTION_DATA_BP
, SIGTRAP
},
167 #ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
168 {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
, SIGTRAP
},
170 #ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
171 {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
, SIGSEGV
},
173 #ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT
174 {CYGNUM_HAL_EXCEPTION_STACK_FAULT
, SIGSEGV
},
176 #ifdef CYGNUM_HAL_EXCEPTION_PARITY
177 {CYGNUM_HAL_EXCEPTION_PARITY
, SIGBUS
},
179 #ifdef CYGNUM_HAL_EXCEPTION_FPU
180 {CYGNUM_HAL_EXCEPTION_FPU
, SIGFPE
},
182 #ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
183 {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
, SIGFPE
},
185 #ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
186 {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
, SIGFPE
},
188 #ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
189 {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
, SIGFPE
},
191 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
192 {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
, SIGFPE
},
194 #ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
195 {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
, SIGSYS
},
197 {0, 0} // dummy value to ensure compiler is happy
200 //==========================================================================
201 // POSIX exception handler
203 static void cyg_posix_exception_handler(
204 CYG_ADDRWORD data
, // user supplied data == signal number
205 cyg_code exception_number
, // exception being raised
206 CYG_ADDRWORD exception_info
// any exception specific info
211 pthread_info
*self
= pthread_self_info();
215 // Not a POSIX thread, just return
219 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
225 for( int i
= 0; exception_signal_mapping
[i
].signal
!= 0; i
++ )
227 if( exception_signal_mapping
[i
].exception
== exception_number
)
229 signo
= exception_signal_mapping
[i
].signal
;
236 if( sigismember( &self
->sigmask
, signo
) )
238 // The signal is masked in the current thread. POSIX says that
239 // the behaviour is undefined here. We choose to ignore it.
244 // The kernel exception handler may have disabled interrupts, so
245 // we (re-)enable them here. From this point on we are running in
246 // a context that is effectively just pushed onto the stack of the
247 // current thread. If we return we will unwind and resume
248 // execution from the excepting code. We can also, in theory,
249 // longjump out of the signal handler, and although that is
250 // deprecated, we make sure in cyg_deliver_signals() that it is
251 // possible to do it.
253 HAL_ENABLE_INTERRUPTS();
257 sev
.sigev_notify
= SIGEV_SIGNAL
;
258 sev
.sigev_signo
= signo
;
259 sev
.sigev_value
.sival_ptr
= (void *)exception_info
;
261 // Generate the signal
262 cyg_sigqueue( &sev
, SI_EXCEPT
);
264 // And try to deliver it
265 cyg_deliver_signals();
268 //==========================================================================
269 // Install all the exception handlers
271 static void install_handlers( Cyg_Thread
*thread
)
273 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
275 // With decoded exceptions, we must install a separate exception
276 // handler for each supported exception.
278 for( int i
= 0; exception_signal_mapping
[i
].signal
!= 0; i
++ )
280 thread
->register_exception( exception_signal_mapping
[i
].exception
,
281 cyg_posix_exception_handler
,
282 exception_signal_mapping
[i
].signal
,
289 // Otherwise there is just one exception handler for all exceptions.
291 thread
->register_exception( CYGNUM_HAL_EXCEPTION_MIN
,
292 cyg_posix_exception_handler
,
301 //==========================================================================
304 externC
void cyg_posix_exception_start()
306 #ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
308 // With global exceptions, we only need to install a single static
309 // set of exception handlers. Note that by this point in system
310 // initialization the idle thread should be installed as the
311 // current thread, so we pass a pointer to that to
312 // install_handlers(). The identity of the thread passed is
313 // actually irrelevant in this case and is just used as a handle
314 // into the thread class.
316 install_handlers( Cyg_Thread::self() );
321 //==========================================================================
322 // Per thread exception initialization and destruction
324 externC
void cyg_pthread_exception_init(pthread_info
*thread
)
326 #ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
328 // With non-global exceptions we must install a new set of handlers
331 install_handlers( thread
->thread
);
336 externC
void cyg_pthread_exception_destroy(pthread_info
*thread
)
338 // Nothing to do at present.
341 // -------------------------------------------------------------------------