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.6 by gbeauche, 2002-01-07T16:30:39Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines