]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/compat/posix/v2_0/src/except.cxx
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / compat / posix / v2_0 / src / except.cxx
1 //==========================================================================
2 //
3 //      except.cxx
4 //
5 //      POSIX exception translation
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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####
42 //
43 // Author(s):           nickg
44 // Contributors:        nickg
45 // Date:                2000-03-27
46 // Purpose:             POSIX exception translation
47 // Description:         This file contains code to translate eCos hardware
48 //                      exceptions into POSIX signals.
49 //              
50 //              
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <pkgconf/hal.h>
57 #include <pkgconf/kernel.h>
58 #include <pkgconf/posix.h>
59
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
63
64 #include <cyg/infra/diag.h>
65
66 #include "pprivate.h"                   // POSIX private header
67
68 #include <signal.h>                     // our header
69
70 #include <cyg/kernel/thread.inl>
71
72 //==========================================================================
73 // Translation table from eCos exceptions to POSIX signals.
74
75 static const struct
76 {
77     cyg_code    exception;
78     int         signal;
79 } exception_signal_mapping[] =
80 {
81 #ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
82     {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS},
83 #endif
84 #ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE
85     {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS},
86 #endif
87 #ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS
88     {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS},
89 #endif    
90 #ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE
91     {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS},
92 #endif    
93 #ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
94     {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS},
95 #endif    
96 #ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS
97     {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
98 #endif    
99 #ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE
100     {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
101 #endif    
102 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
103     {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV},
104 #endif    
105 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
106     {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV},
107 #endif    
108 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
109     {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV},
110 #endif    
111 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
112     {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV},
113 #endif    
114 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
115     {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV},
116 #endif    
117 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
118     {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV},
119 #endif    
120 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
121     {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV},
122 #endif    
123 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
124     {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV},
125 #endif    
126 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
127     {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS},
128 #endif    
129 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
130     {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS},
131 #endif    
132 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
133     {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS},
134 #endif    
135 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
136     {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS},
137 #endif    
138 #ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
139     {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL},
140 #endif    
141 #ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT
142     {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT},
143 #endif    
144 #ifdef CYGNUM_HAL_EXCEPTION_TRAP
145     {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP},
146 #endif    
147 #ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
148     {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE},
149 #endif    
150 #ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW
151     {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE},
152 #endif    
153 #ifdef CYGNUM_HAL_EXCEPTION_BOUNDS
154     {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV},
155 #endif
156 #ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP
157     {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP},
158 #endif
159 #ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
160     {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP},
161 #endif
162 #ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
163     {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP},
164 #endif
165 #ifdef CYGNUM_HAL_EXCEPTION_DATA_BP
166     {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP},
167 #endif
168 #ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
169     {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP},
170 #endif
171 #ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
172     {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV},
173 #endif
174 #ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT
175     {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV},
176 #endif
177 #ifdef CYGNUM_HAL_EXCEPTION_PARITY
178     {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS},
179 #endif
180 #ifdef CYGNUM_HAL_EXCEPTION_FPU
181     {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE},
182 #endif
183 #ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
184     {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE},
185 #endif
186 #ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
187     {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE},
188 #endif
189 #ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
190     {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE},
191 #endif
192 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
193     {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE},
194 #endif
195 #ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
196     {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS},
197 #endif
198     {0, 0} // dummy value to ensure compiler is happy
199 };
200
201 //==========================================================================
202 // POSIX exception handler
203
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
208     )
209 {
210     int signo = 0;
211
212     pthread_info *self = pthread_self_info();
213
214     if( self == NULL )
215     {
216         // Not a POSIX thread, just return
217         return;
218     }
219     
220 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
221
222     signo = data;
223
224 #else
225
226     for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )    
227     {
228         if( exception_signal_mapping[i].exception == exception_number )
229         {
230             signo = exception_signal_mapping[i].signal;
231             break;
232         }
233     }
234
235 #endif
236
237     if( sigismember( &self->sigmask, signo ) )
238     {
239         // The signal is masked in the current thread. POSIX says that
240         // the behaviour is undefined here. We choose to ignore it.
241
242         return;
243     }
244
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.
253     
254     HAL_ENABLE_INTERRUPTS();
255     
256     struct sigevent sev;
257
258     sev.sigev_notify           = SIGEV_SIGNAL;
259     sev.sigev_signo            = signo;
260     sev.sigev_value.sival_ptr  = (void *)exception_info;
261
262     // Generate the signal
263     cyg_sigqueue( &sev, SI_EXCEPT );
264
265     // And try to deliver it
266     cyg_deliver_signals();
267 }
268
269 //==========================================================================
270 // Install all the exception handlers
271
272 static void install_handlers( Cyg_Thread *thread)
273 {
274 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
275
276     // With decoded exceptions, we must install a separate exception
277     // handler for each supported exception.
278
279     for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )
280     {
281         thread->register_exception( exception_signal_mapping[i].exception,
282                                     cyg_posix_exception_handler,
283                                     exception_signal_mapping[i].signal,
284                                     NULL,
285                                     NULL);
286     }
287     
288 #else
289
290     // Otherwise there is just one exception handler for all exceptions.
291     
292     thread->register_exception( CYGNUM_HAL_EXCEPTION_MIN,
293                                 cyg_posix_exception_handler,
294                                 0,
295                                 NULL,
296                                 NULL);
297     
298 #endif    
299     
300 }
301
302 //==========================================================================
303 // Initialization
304
305 externC void cyg_posix_exception_start()
306 {
307 #ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
308
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.
316
317     install_handlers( Cyg_Thread::self() );
318     
319 #endif    
320 }
321
322 //==========================================================================
323 // Per thread exception initialization and destruction
324
325 externC void cyg_pthread_exception_init(pthread_info *thread)
326 {
327 #ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
328
329     // With non-global exceptions we must install a new set of handlers
330     // for each thread.
331
332     install_handlers( thread->thread );
333     
334 #endif
335 }
336
337 externC void cyg_pthread_exception_destroy(pthread_info *thread)
338 {
339     // Nothing to do at present.
340 }
341
342 // -------------------------------------------------------------------------
343 // EOF except.cxx