ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sigsegv.cpp (file contents):
Revision 1.1 by gbeauche, 2001-05-20T20:31:50Z vs.
Revision 1.8 by cebix, 2002-02-01T19:25:49Z

# Line 4 | Line 4
4   *  Derived from Bruno Haible's work on his SIGSEGV library for clisp
5   *  <http://clisp.sourceforge.net/>
6   *
7 < *  Basilisk II (C) 1997-2001 Christian Bauer
7 > *  Basilisk II (C) 1997-2002 Christian Bauer
8   *
9   *  This program is free software; you can redistribute it and/or modify
10   *  it under the terms of the GNU General Public License as published by
# Line 53 | Line 53 | static bool sigsegv_do_install_handler(i
53  
54   #if HAVE_SIGINFO_T
55   // Generic extended signal handler
56 + #if defined(__NetBSD__) || defined(__FreeBSD__)
57 + #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
58 + #else
59   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV)
60 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, siginfo_t *sip, void *
60 > #endif
61 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, siginfo_t *sip, void *scp
62   #define SIGSEGV_FAULT_ADDRESS                   sip->si_addr
63 + #if defined(__linux__)
64 + #if (defined(i386) || defined(__i386__))
65 + #include <sys/ucontext.h>
66 + #define SIGSEGV_FAULT_INSTRUCTION               (((ucontext_t *)scp)->uc_mcontext.gregs[14]) /* should use REG_EIP instead */
67 + #endif
68 + #if (defined(ia64) || defined(__ia64__))
69 + #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
70 + #endif
71 + #endif
72   #endif
73  
74   #if HAVE_SIGCONTEXT_SUBTERFUGE
# Line 70 | Line 83 | static bool sigsegv_do_install_handler(i
83   #endif
84   #if (defined(sparc) || defined(__sparc__))
85   #include <asm/sigcontext.h>
86 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext* scp, char* addr
86 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext *scp, char *addr
87   #define SIGSEGV_FAULT_ADDRESS                   addr
88   #endif
89   #if (defined(powerpc) || defined(__powerpc__))
90   #include <asm/sigcontext.h>
91 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, struct sigcontext* scp
91 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, struct sigcontext *scp
92   #define SIGSEGV_FAULT_ADDRESS                   scp->regs->dar
93   #define SIGSEGV_FAULT_INSTRUCTION               scp->regs->nip
94   #endif
95 + #if (defined(alpha) || defined(__alpha__))
96 + #include <asm/sigcontext.h>
97 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext *scp
98 + #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
99 + #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_pc
100 +
101 + // From Boehm's GC 6.0alpha8
102 + static sigsegv_address_t get_fault_address(struct sigcontext *scp)
103 + {
104 +        unsigned int instruction = *((unsigned int *)(scp->sc_pc));
105 +        unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f];
106 +        fault_address += (signed long)(signed short)(instruction & 0xffff);
107 +        return (sigsegv_address_t)fault_address;
108 + }
109 + #endif
110   #endif
111  
112   // Irix 5 or 6 on MIPS
# Line 132 | Line 160 | static bool sigsegv_do_install_handler(i
160   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
161   #endif
162   #endif
163 +
164 + // MacOS X
165 + #if defined(__APPLE__) && defined(__MACH__)
166 + #if (defined(ppc) || defined(__ppc__))
167 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext *scp
168 + #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
169 + #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_ir
170 + #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
171 +
172 + // From Boehm's GC 6.0alpha8
173 + #define EXTRACT_OP1(iw)     (((iw) & 0xFC000000) >> 26)
174 + #define EXTRACT_OP2(iw)     (((iw) & 0x000007FE) >> 1)
175 + #define EXTRACT_REGA(iw)    (((iw) & 0x001F0000) >> 16)
176 + #define EXTRACT_REGB(iw)    (((iw) & 0x03E00000) >> 21)
177 + #define EXTRACT_REGC(iw)    (((iw) & 0x0000F800) >> 11)
178 + #define EXTRACT_DISP(iw)    ((short *) &(iw))[1]
179 +
180 + static sigsegv_address_t get_fault_address(struct sigcontext *scp)
181 + {
182 +        unsigned int   instr = *((unsigned int *) scp->sc_ir);
183 +        unsigned int * regs = &((unsigned int *) scp->sc_regs)[2];
184 +        int            disp = 0, tmp;
185 +        unsigned int   baseA = 0, baseB = 0;
186 +        unsigned int   addr, alignmask = 0xFFFFFFFF;
187 +
188 +        switch(EXTRACT_OP1(instr)) {
189 +        case 38:   /* stb */
190 +        case 39:   /* stbu */
191 +        case 54:   /* stfd */
192 +        case 55:   /* stfdu */
193 +        case 52:   /* stfs */
194 +        case 53:   /* stfsu */
195 +        case 44:   /* sth */
196 +        case 45:   /* sthu */
197 +        case 47:   /* stmw */
198 +        case 36:   /* stw */
199 +        case 37:   /* stwu */
200 +                tmp = EXTRACT_REGA(instr);
201 +                if(tmp > 0)
202 +                        baseA = regs[tmp];
203 +                disp = EXTRACT_DISP(instr);
204 +                break;
205 +        case 31:
206 +                switch(EXTRACT_OP2(instr)) {
207 +                case 86:    /* dcbf */
208 +                case 54:    /* dcbst */
209 +                case 1014:  /* dcbz */
210 +                case 247:   /* stbux */
211 +                case 215:   /* stbx */
212 +                case 759:   /* stfdux */
213 +                case 727:   /* stfdx */
214 +                case 983:   /* stfiwx */
215 +                case 695:   /* stfsux */
216 +                case 663:   /* stfsx */
217 +                case 918:   /* sthbrx */
218 +                case 439:   /* sthux */
219 +                case 407:   /* sthx */
220 +                case 661:   /* stswx */
221 +                case 662:   /* stwbrx */
222 +                case 150:   /* stwcx. */
223 +                case 183:   /* stwux */
224 +                case 151:   /* stwx */
225 +                case 135:   /* stvebx */
226 +                case 167:   /* stvehx */
227 +                case 199:   /* stvewx */
228 +                case 231:   /* stvx */
229 +                case 487:   /* stvxl */
230 +                        tmp = EXTRACT_REGA(instr);
231 +                        if(tmp > 0)
232 +                                baseA = regs[tmp];
233 +                        baseB = regs[EXTRACT_REGC(instr)];
234 +                        /* determine Altivec alignment mask */
235 +                        switch(EXTRACT_OP2(instr)) {
236 +                        case 167:   /* stvehx */
237 +                                alignmask = 0xFFFFFFFE;
238 +                                break;
239 +                        case 199:   /* stvewx */
240 +                                alignmask = 0xFFFFFFFC;
241 +                                break;
242 +                        case 231:   /* stvx */
243 +                                alignmask = 0xFFFFFFF0;
244 +                                break;
245 +                        case 487:  /* stvxl */
246 +                                alignmask = 0xFFFFFFF0;
247 +                                break;
248 +                        }
249 +                        break;
250 +                case 725:   /* stswi */
251 +                        tmp = EXTRACT_REGA(instr);
252 +                        if(tmp > 0)
253 +                                baseA = regs[tmp];
254 +                        break;
255 +                default:   /* ignore instruction */
256 +                        return 0;
257 +                        break;
258 +                }
259 +                break;
260 +        default:   /* ignore instruction */
261 +                return 0;
262 +                break;
263 +        }
264 +        
265 +        addr = (baseA + baseB) + disp;
266 +        addr &= alignmask;
267 +        return (sigsegv_address_t)addr;
268 + }
269 + #endif
270 + #endif
271   #endif
272  
273   // Fallbacks
# Line 139 | Line 275 | static bool sigsegv_do_install_handler(i
275   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
276   #endif
277  
278 + // SIGSEGV recovery supported ?
279 + #if defined(SIGSEGV_ALL_SIGNALS) && defined(SIGSEGV_FAULT_HANDLER_ARGLIST) && defined(SIGSEGV_FAULT_ADDRESS)
280 + #define HAVE_SIGSEGV_RECOVERY
281 + #endif
282 +
283  
284   /*
285   *  SIGSEGV global handler
286   */
287  
288 + #ifdef HAVE_SIGSEGV_RECOVERY
289   static void sigsegv_handler(SIGSEGV_FAULT_HANDLER_ARGLIST)
290   {
291          // Call user's handler and reinstall the global handler, if required
# Line 159 | Line 301 | static void sigsegv_handler(SIGSEGV_FAUL
301   #undef FAULT_HANDLER
302          }
303   }
304 + #endif
305  
306  
307   /*
# Line 179 | Line 322 | static bool sigsegv_do_install_handler(i
322          return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
323   #endif
324   }
325 < #elif defined(HAVE_SIGCONTEXT_SUBTERFUGE)
325 > #endif
326 >
327 > #if defined(HAVE_SIGCONTEXT_SUBTERFUGE)
328   static bool sigsegv_do_install_handler(int sig)
329   {
330          // Setup SIGSEGV handler to process writes to frame buffer
# Line 202 | Line 347 | static bool sigsegv_do_install_handler(i
347  
348   bool sigsegv_install_handler(sigsegv_handler_t handler)
349   {
350 < #if defined(HAVE_SIGINFO_T) || defined(HAVE_SIGCONTEXT_SUBTERFUGE)
350 > #ifdef HAVE_SIGSEGV_RECOVERY
351          sigsegv_user_handler = handler;
352          bool success = true;
353   #define FAULT_HANDLER(sig) success = success && sigsegv_do_install_handler(sig);
# Line 222 | Line 367 | bool sigsegv_install_handler(sigsegv_han
367  
368   void sigsegv_deinstall_handler(void)
369   {
370 + #ifdef HAVE_SIGSEGV_RECOVERY
371          sigsegv_user_handler = 0;
372   #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
373          SIGSEGV_ALL_SIGNALS
374   #undef FAULT_HANDLER
375 + #endif
376   }
377  
378   /*
379   *  Test program used for configure/test
380   */
381  
382 < #ifdef CONFIGURE_TEST
382 > #ifdef CONFIGURE_TEST_SIGSEGV_RECOVERY
383   #include <stdio.h>
384   #include <stdlib.h>
238 #include <unistd.h>
385   #include <fcntl.h>
386   #include <sys/mman.h>
387 + #include "vm_alloc.h"
388  
242 static caddr_t page = 0;
389   static int page_size;
390 < static int handler_called = 0;
390 > static volatile char * page = 0;
391 > static volatile int handler_called = 0;
392  
393   static bool sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
394   {
395          handler_called++;
396          if ((fault_address - 123) != page)
397                  exit(1);
398 <        if (mprotect((caddr_t)((unsigned long)fault_address & -page_size), page_size, PROT_READ | PROT_WRITE) != 0)
398 >        if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
399                  exit(1);
400          return true;
401   }
402  
403   int main(void)
404   {
405 <        int zero_fd = open("/dev/zero", O_RDWR);
259 <        if (zero_fd < 0)
405 >        if (vm_init() < 0)
406                  return 1;
407  
408          page_size = getpagesize();
409 <        page = (caddr_t)mmap(0, page_size, PROT_READ, MAP_PRIVATE, zero_fd, 0);
410 <        if (page == MAP_FAILED)
409 >        if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
410 >                return 1;
411 >        
412 >        if (vm_protect((char *)page, page_size, VM_PAGE_READ) < 0)
413                  return 1;
414          
415          if (!sigsegv_install_handler(sigsegv_test_handler))
# Line 273 | Line 421 | int main(void)
421          if (handler_called != 1)
422                  return 1;
423  
424 +        vm_exit();
425          return 0;
426   }
427   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines