| Commit | Line | Data |
|---|---|---|
| eb44537a | 1 | /* |
| 2 | * Darwin-os.c. | |
| 3 | * From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc Exp | |
| 4 | * | |
| 5 | * OS-dependent routines. This file (along with os.h) exports an | |
| 6 | * OS-independent interface to the operating system VM facilities. | |
| 7 | * Suprisingly, this interface looks a lot like the Mach interface | |
| 8 | * (but simpler in some places). For some operating systems, a subset | |
| 9 | * of these functions will have to be emulated. | |
| 10 | * | |
| 11 | * This is the OSF1 version. By Sean Hallgren. | |
| 12 | * Much hacked by Paul Werkowski | |
| 13 | * GENCGC support by Douglas Crosher, 1996, 1997. | |
| 14 | * Frobbed for OpenBSD by Pierre R. Mai, 2001. | |
| 15 | * Frobbed for Darwin by Pierre R. Mai, 2003. | |
| 16 | * | |
| eb44537a | 17 | */ |
| 18 | ||
| 19 | #include <stdio.h> | |
| 20 | #include <sys/param.h> | |
| 21 | #include <sys/file.h> | |
| 22 | #include <errno.h> | |
| 555746e0 | 23 | #include <dlfcn.h> |
| 9495c516 | 24 | #include <string.h> |
| eb44537a | 25 | #include "os.h" |
| 26 | #include "arch.h" | |
| 27 | #include "globals.h" | |
| 28 | #include "interrupt.h" | |
| 29 | #include "lispregs.h" | |
| 30 | #include "internals.h" | |
| 46a4f482 | 31 | #ifdef GENCGC |
| 32 | #include "gencgc.h" | |
| 33 | #endif | |
| eb44537a | 34 | |
| 35 | #include <sys/types.h> | |
| 36 | #include <signal.h> | |
| 37 | /* #include <sys/sysinfo.h> */ | |
| 38 | /* #include <sys/proc.h> */ | |
| e7d07412 | 39 | /* For timebase info */ |
| e7d07412 | 40 | #include <sys/sysctl.h> |
| 41 | ||
| a3806e20 | 42 | |
| 43 | /* Need this to define ppc_saved_state_t (for 10.4) */ | |
| 44 | #include <mach/thread_status.h> | |
| 45 | ||
| eb44537a | 46 | #include "validate.h" |
| 47 | vm_size_t os_vm_page_size; | |
| 48 | ||
| eb44537a | 49 | \f |
| 9a8c1c2f | 50 | |
| e7d07412 | 51 | /* |
| 52 | * This is accessed by Lisp! Make this a static symbol? | |
| 53 | */ | |
| 54 | int cycles_per_tick = 1; | |
| 55 | ||
| 56 | /* | |
| 57 | * Compute the conversion factor from the numbef of time base ticks to | |
| 58 | * clock frequency. The timebase counter on PPC is not a cycle | |
| 59 | * counter; we have to derive the relationship ourselves. | |
| 60 | */ | |
| 61 | ||
| 555746e0 | 62 | #ifdef __ppc__ |
| 9a8c1c2f | 63 | void |
| b8d0dfaf | 64 | timebase_init(void) |
| e7d07412 | 65 | { |
| 9a8c1c2f | 66 | int mib[2]; |
| 67 | int tbfrequency; | |
| 68 | int cpufrequency; | |
| 69 | unsigned int miblen; | |
| 70 | size_t len; | |
| e7d07412 | 71 | |
| 9a8c1c2f | 72 | mib[0] = CTL_HW; |
| e7d07412 | 73 | #ifndef HW_TB_FREQ |
| 9a8c1c2f | 74 | /* |
| 75 | * Mac OS X 10.2.8 doesn't have this, so we take it from 10.3.8, | |
| 76 | * which does. | |
| 77 | */ | |
| e7d07412 | 78 | #define HW_TB_FREQ 23 |
| 9a8c1c2f | 79 | #endif |
| 80 | mib[1] = HW_TB_FREQ; | |
| 81 | miblen = 2; | |
| 82 | len = sizeof(tbfrequency); | |
| 83 | ||
| 84 | if (sysctl(mib, miblen, &tbfrequency, &len, NULL, 0) == -1) { | |
| 85 | perror("Error getting HW_TB_FREQ from sysctl: "); | |
| 86 | } | |
| e7d07412 | 87 | |
| 9a8c1c2f | 88 | mib[0] = CTL_HW; |
| 89 | mib[1] = HW_CPU_FREQ; | |
| 90 | miblen = 2; | |
| 91 | len = sizeof(cpufrequency); | |
| 92 | if (sysctl(mib, miblen, &cpufrequency, &len, NULL, 0) == -1) { | |
| 93 | perror("Error getting HW_CPU_FREQ from sysctl: "); | |
| 94 | } | |
| 95 | ||
| 96 | cycles_per_tick = cpufrequency / tbfrequency; | |
| 97 | } | |
| 555746e0 | 98 | #endif |
| e7d07412 | 99 | \f |
| 9a8c1c2f | 100 | |
| 101 | void | |
| e7997cb6 RT |
102 | os_init0(const char *argv[], const char *envp[]) |
| 103 | {} | |
| 104 | ||
| 105 | void | |
| 0f0aed07 | 106 | os_init(const char *argv[], const char *envp[]) |
| eb44537a | 107 | { |
| 9a8c1c2f | 108 | os_vm_page_size = OS_VM_DEFAULT_PAGESIZE; |
| 555746e0 | 109 | #ifdef __ppc__ |
| 9a8c1c2f | 110 | timebase_init(); |
| 555746e0 | 111 | #endif |
| eb44537a | 112 | } |
| 113 | ||
| 838ff560 | 114 | |
| 555746e0 | 115 | #if defined(__ppc__) |
| 838ff560 RT |
116 | #if __DARWIN_UNIX03 |
| 117 | /* Nothing needed for 10.5 */ | |
| 118 | #else | |
| 119 | /* For 10.4 */ | |
| 120 | #define __ss ss | |
| 121 | #define __r0 r0 | |
| 122 | #define __r1 r1 | |
| 123 | #define __r2 r2 | |
| 124 | #define __r3 r3 | |
| 125 | #define __r4 r4 | |
| 126 | #define __r5 r5 | |
| 127 | #define __r6 r6 | |
| 128 | #define __r7 r7 | |
| 129 | #define __r8 r8 | |
| 130 | #define __r9 r9 | |
| 131 | #define __r10 r10 | |
| 132 | #define __r11 r11 | |
| 133 | #define __r12 r12 | |
| 134 | #define __r13 r13 | |
| 135 | #define __r14 r14 | |
| 136 | #define __r15 r15 | |
| 137 | #define __r16 r16 | |
| 138 | #define __r17 r17 | |
| 139 | #define __r18 r18 | |
| 140 | #define __r19 r19 | |
| 141 | #define __r20 r20 | |
| 142 | #define __r21 r21 | |
| 143 | #define __r22 r22 | |
| 144 | #define __r23 r23 | |
| 145 | #define __r24 r24 | |
| 146 | #define __r25 r25 | |
| 147 | #define __r26 r26 | |
| 148 | #define __r27 r27 | |
| 149 | #define __r28 r28 | |
| 150 | #define __r29 r29 | |
| 151 | #define __r30 r30 | |
| 152 | #define __r31 r31 | |
| 153 | #define __lr lr | |
| 154 | #define __ctr ctr | |
| 155 | #define __es es | |
| 156 | #define __dar dar | |
| 157 | #define __dsisr dsisr | |
| 158 | #endif | |
| 159 | ||
| e3fa809d | 160 | unsigned int * |
| 9a8c1c2f | 161 | sc_reg(os_context_t * context, int offset) |
| eb44537a | 162 | { |
| 9dcff02e | 163 | _STRUCT_PPC_THREAD_STATE *state = &context->uc_mcontext->__ss; |
| 9a8c1c2f | 164 | |
| 165 | switch (offset) { | |
| 166 | case 0: | |
| 9dcff02e | 167 | return &state->__r0; |
| 9a8c1c2f | 168 | case 1: |
| 9dcff02e | 169 | return &state->__r1; |
| 9a8c1c2f | 170 | case 2: |
| 9dcff02e | 171 | return &state->__r2; |
| 9a8c1c2f | 172 | case 3: |
| 9dcff02e | 173 | return &state->__r3; |
| 9a8c1c2f | 174 | case 4: |
| 9dcff02e | 175 | return &state->__r4; |
| 9a8c1c2f | 176 | case 5: |
| 9dcff02e | 177 | return &state->__r5; |
| 9a8c1c2f | 178 | case 6: |
| 9dcff02e | 179 | return &state->__r6; |
| 9a8c1c2f | 180 | case 7: |
| 9dcff02e | 181 | return &state->__r7; |
| 9a8c1c2f | 182 | case 8: |
| 9dcff02e | 183 | return &state->__r8; |
| 9a8c1c2f | 184 | case 9: |
| 9dcff02e | 185 | return &state->__r9; |
| 9a8c1c2f | 186 | case 10: |
| 9dcff02e | 187 | return &state->__r10; |
| 9a8c1c2f | 188 | case 11: |
| 9dcff02e | 189 | return &state->__r11; |
| 9a8c1c2f | 190 | case 12: |
| 9dcff02e | 191 | return &state->__r12; |
| 9a8c1c2f | 192 | case 13: |
| 9dcff02e | 193 | return &state->__r13; |
| 9a8c1c2f | 194 | case 14: |
| 9dcff02e | 195 | return &state->__r14; |
| 9a8c1c2f | 196 | case 15: |
| 9dcff02e | 197 | return &state->__r15; |
| 9a8c1c2f | 198 | case 16: |
| 9dcff02e | 199 | return &state->__r16; |
| 9a8c1c2f | 200 | case 17: |
| 9dcff02e | 201 | return &state->__r17; |
| 9a8c1c2f | 202 | case 18: |
| 9dcff02e | 203 | return &state->__r18; |
| 9a8c1c2f | 204 | case 19: |
| 9dcff02e | 205 | return &state->__r19; |
| 9a8c1c2f | 206 | case 20: |
| 9dcff02e | 207 | return &state->__r20; |
| 9a8c1c2f | 208 | case 21: |
| 9dcff02e | 209 | return &state->__r21; |
| 9a8c1c2f | 210 | case 22: |
| 9dcff02e | 211 | return &state->__r22; |
| 9a8c1c2f | 212 | case 23: |
| 9dcff02e | 213 | return &state->__r23; |
| 9a8c1c2f | 214 | case 24: |
| 9dcff02e | 215 | return &state->__r24; |
| 9a8c1c2f | 216 | case 25: |
| 9dcff02e | 217 | return &state->__r25; |
| 9a8c1c2f | 218 | case 26: |
| 9dcff02e | 219 | return &state->__r26; |
| 9a8c1c2f | 220 | case 27: |
| 9dcff02e | 221 | return &state->__r27; |
| 9a8c1c2f | 222 | case 28: |
| 9dcff02e | 223 | return &state->__r28; |
| 9a8c1c2f | 224 | case 29: |
| 9dcff02e | 225 | return &state->__r29; |
| 9a8c1c2f | 226 | case 30: |
| 9dcff02e | 227 | return &state->__r30; |
| 9a8c1c2f | 228 | case 31: |
| 9dcff02e | 229 | return &state->__r31; |
| 87e1c793 | 230 | case 34: |
| 231 | /* | |
| 232 | * Not sure if this is really defined anywhere, but after | |
| 233 | * r31 is cr, xer, lr, and ctr. So we let 34 be lr. | |
| 234 | */ | |
| 9dcff02e | 235 | return &state->__lr; |
| 87e1c793 | 236 | case 35: |
| 9dcff02e | 237 | return &state->__ctr; |
| 9a8c1c2f | 238 | case 41: |
| 9dcff02e | 239 | return &context->uc_mcontext->__es.__dar; |
| 9a8c1c2f | 240 | case 42: |
| 9dcff02e | 241 | return &context->uc_mcontext->__es.__dsisr; |
| 9a8c1c2f | 242 | } |
| 243 | ||
| e3fa809d | 244 | return (unsigned int *) 0; |
| eb44537a | 245 | } |
| 555746e0 | 246 | #elif defined(__i386__) |
| c2e1d8a6 | 247 | #if __DARWIN_UNIX03 |
| 248 | /* Nothing needed for 10.5 */ | |
| 249 | #else | |
| 250 | /* This is for 10.4 */ | |
| 251 | #define __ss ss | |
| 252 | #define __eax eax | |
| 253 | #define __ecx ecx | |
| 254 | #define __edx edx | |
| 255 | #define __ebx ebx | |
| 256 | #define __esp esp | |
| 257 | #define __ebp ebp | |
| 258 | #define __esi esi | |
| 259 | #define __edi edi | |
| 260 | #define __eip eip | |
| 261 | #define __fs fs | |
| 262 | #define __fpu_stmm0 fpu_stmm0 | |
| 263 | #define __fpu_stmm1 fpu_stmm1 | |
| 264 | #define __fpu_stmm2 fpu_stmm2 | |
| 265 | #define __fpu_stmm3 fpu_stmm3 | |
| 266 | #define __fpu_stmm4 fpu_stmm4 | |
| 267 | #define __fpu_stmm5 fpu_stmm5 | |
| 268 | #define __fpu_stmm6 fpu_stmm6 | |
| 269 | #define __fpu_stmm7 fpu_stmm7 | |
| 270 | #define __fpu_fcw fpu_fcw | |
| 271 | #define __fpu_fsw fpu_fsw | |
| 272 | #define __fpu_mxcsr fpu_mxcsr | |
| e7997cb6 RT |
273 | #ifdef FEATURE_SSE2 |
| 274 | #define __fpu_xmm0 fpu_xmm0 | |
| 275 | #define __fpu_xmm1 fpu_xmm1 | |
| 276 | #define __fpu_xmm2 fpu_xmm2 | |
| 277 | #define __fpu_xmm3 fpu_xmm3 | |
| 278 | #define __fpu_xmm4 fpu_xmm4 | |
| 279 | #define __fpu_xmm5 fpu_xmm5 | |
| 280 | #define __fpu_xmm6 fpu_xmm6 | |
| 281 | #define __fpu_xmm7 fpu_xmm7 | |
| 282 | #endif | |
| c2e1d8a6 | 283 | #endif |
| 4040cc75 | 284 | |
| 285 | unsigned long * | |
| 286 | os_sigcontext_reg(ucontext_t *scp, int index) | |
| 287 | { | |
| 9495c516 | 288 | switch (index) { |
| 289 | case 0: | |
| 290 | return (unsigned long *) &scp->uc_mcontext->__ss.__eax; | |
| 291 | case 2: | |
| 292 | return (unsigned long *) &scp->uc_mcontext->__ss.__ecx; | |
| 293 | case 4: | |
| 294 | return (unsigned long *) &scp->uc_mcontext->__ss.__edx; | |
| 295 | case 6: | |
| 296 | return (unsigned long *) &scp->uc_mcontext->__ss.__ebx; | |
| 297 | case 8: | |
| 298 | return (unsigned long *) &scp->uc_mcontext->__ss.__esp; | |
| 299 | case 10: | |
| 300 | return (unsigned long *) &scp->uc_mcontext->__ss.__ebp; | |
| 301 | case 12: | |
| 302 | return (unsigned long *) &scp->uc_mcontext->__ss.__esi; | |
| 303 | case 14: | |
| 304 | return (unsigned long *) &scp->uc_mcontext->__ss.__edi; | |
| 555746e0 | 305 | } |
| 9495c516 | 306 | return NULL; |
| 307 | } | |
| 555746e0 | 308 | |
| 9495c516 | 309 | unsigned long * |
| 310 | os_sigcontext_pc(ucontext_t *scp) | |
| 311 | { | |
| 312 | return (unsigned long *) &scp->uc_mcontext->__ss.__eip; | |
| 313 | } | |
| 314 | ||
| 315 | unsigned char * | |
| 316 | os_sigcontext_fpu_reg(ucontext_t *scp, int index) | |
| 317 | { | |
| 318 | switch (index) { | |
| 319 | case 0: | |
| 320 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm0; | |
| 321 | case 1: | |
| 322 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm1; | |
| 323 | case 2: | |
| 324 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm2; | |
| 325 | case 3: | |
| 326 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm3; | |
| 327 | case 4: | |
| 328 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm4; | |
| 329 | case 5: | |
| 330 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm5; | |
| 331 | case 6: | |
| 332 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm6; | |
| 333 | case 7: | |
| 334 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7; | |
| e7997cb6 RT |
335 | #ifdef FEATURE_SSE2 |
| 336 | case 8: | |
| 337 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0; | |
| 338 | case 9: | |
| 339 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1; | |
| 340 | case 10: | |
| 341 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2; | |
| 342 | case 11: | |
| 343 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3; | |
| 344 | case 12: | |
| 345 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4; | |
| 346 | case 13: | |
| 347 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5; | |
| 348 | case 14: | |
| 349 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6; | |
| 350 | case 15: | |
| 351 | return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7; | |
| 352 | #endif | |
| 2b3d7fb0 | 353 | } |
| 354 | return NULL; | |
| 355 | } | |
| 2b3d7fb0 | 356 | |
| b17a70c7 | 357 | unsigned int |
| 9495c516 | 358 | os_sigcontext_fpu_modes(ucontext_t *scp) |
| 359 | { | |
| b17a70c7 | 360 | unsigned int modes; |
| 361 | unsigned int mxcsr; | |
| 9495c516 | 362 | unsigned short cw, sw; |
| cb786538 | 363 | |
| 364 | /* | |
| 365 | * Get the status word and the control word. | |
| 366 | */ | |
| 9495c516 | 367 | memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw)); |
| 368 | memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw)); | |
| cb786538 | 369 | |
| 370 | /* | |
| 371 | * Put the cw in the upper bits and the status word in the lower 6 | |
| 372 | * bits, ignoring everything except the exception masks and the | |
| 373 | * exception flags. | |
| 374 | */ | |
| 375 | modes = ((cw & 0x3f) << 7) | (sw & 0x3f); | |
| 376 | ||
| 377 | DPRINTF(0, (stderr, "FPU modes = %08x (sw = %4x, cw = %4x)\n", | |
| 378 | modes, (unsigned int) sw, (unsigned int) cw)); | |
| 379 | ||
| 4040cc75 | 380 | if (fpu_mode == SSE2) { |
| 381 | mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr; | |
| 382 | DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr)); | |
| cb786538 | 383 | |
| 4040cc75 | 384 | modes |= mxcsr; |
| 385 | } | |
| 386 | ||
| cb786538 | 387 | DPRINTF(0, (stderr, "modes pre mask = %08x\n", modes)); |
| 388 | ||
| 389 | /* Convert exception mask to exception enable */ | |
| 390 | modes ^= (0x3f << 7); | |
| 391 | DPRINTF(0, (stderr, "Finale = %08x\n", modes)); | |
| 9495c516 | 392 | return modes; |
| 393 | } | |
| 394 | ||
| 395 | void | |
| 396 | restore_fpu(ucontext_t *scp) | |
| 397 | { | |
| 398 | unsigned short cw; | |
| cb786538 | 399 | unsigned int mxcsr; |
| 400 | ||
| 9495c516 | 401 | memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw)); |
| cb786538 | 402 | DPRINTF(0, (stderr, "restore_fpu: FPU cw = 0x%x\n", cw)); |
| 346910c6 | 403 | __asm__ __volatile__ ("fclex"); |
| 9495c516 | 404 | __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)); |
| cb786538 | 405 | |
| 406 | mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr; | |
| 407 | DPRINTF(0, (stderr, "restore_fpu: mxcsr (raw) = %04x\n", mxcsr)); | |
| 408 | __asm__ __volatile__ ("ldmxcsr %0" :: "m" (*&mxcsr)); | |
| 555746e0 | 409 | } |
| 410 | #endif | |
| eb44537a | 411 | |
| 9a8c1c2f | 412 | os_vm_address_t |
| 413 | os_validate(os_vm_address_t addr, os_vm_size_t len) | |
| eb44537a | 414 | { |
| 1e078503 | 415 | int flags = MAP_PRIVATE | MAP_ANON; |
| eb44537a | 416 | |
| 9a8c1c2f | 417 | if (addr) |
| 418 | flags |= MAP_FIXED; | |
| eb44537a | 419 | |
| 555746e0 | 420 | DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len)); |
| eb44537a | 421 | |
| 9a8c1c2f | 422 | addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0); |
| eb44537a | 423 | |
| 9a8c1c2f | 424 | if (addr == (os_vm_address_t) - 1) { |
| 425 | perror("mmap"); | |
| 426 | return NULL; | |
| eb44537a | 427 | } |
| 428 | ||
| 555746e0 | 429 | DPRINTF(0, (stderr, "%p\n", addr)); |
| eb44537a | 430 | |
| 9a8c1c2f | 431 | return addr; |
| eb44537a | 432 | } |
| 433 | ||
| 9a8c1c2f | 434 | void |
| 435 | os_invalidate(os_vm_address_t addr, os_vm_size_t len) | |
| eb44537a | 436 | { |
| 555746e0 | 437 | DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len)); |
| eb44537a | 438 | |
| 9a8c1c2f | 439 | if (munmap(addr, len) == -1) |
| 440 | perror("munmap"); | |
| eb44537a | 441 | } |
| 442 | ||
| 9a8c1c2f | 443 | os_vm_address_t |
| 444 | os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len) | |
| eb44537a | 445 | { |
| 9a8c1c2f | 446 | addr = mmap(addr, len, |
| 447 | OS_VM_PROT_ALL, | |
| 448 | MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset); | |
| eb44537a | 449 | |
| 9a8c1c2f | 450 | if (addr == (os_vm_address_t) - 1) |
| 451 | perror("mmap"); | |
| eb44537a | 452 | |
| 9a8c1c2f | 453 | return addr; |
| eb44537a | 454 | } |
| 455 | ||
| 9a8c1c2f | 456 | void |
| 457 | os_flush_icache(os_vm_address_t address, os_vm_size_t length) | |
| eb44537a | 458 | { |
| 555746e0 | 459 | #ifdef __ppc__ |
| eb44537a | 460 | /* see ppc-arch.c */ |
| 9a8c1c2f | 461 | ppc_flush_icache(address, length); |
| 555746e0 | 462 | #endif |
| eb44537a | 463 | } |
| 464 | ||
| 9a8c1c2f | 465 | void |
| 466 | os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot) | |
| eb44537a | 467 | { |
| 9a8c1c2f | 468 | if (mprotect(address, length, prot) == -1) |
| 469 | perror("mprotect"); | |
| eb44537a | 470 | } |
| eb44537a | 471 | \f |
| 472 | ||
| 9a8c1c2f | 473 | |
| 474 | static boolean | |
| 475 | in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen) | |
| eb44537a | 476 | { |
| 9a8c1c2f | 477 | char *beg = (char *) sbeg; |
| 478 | char *end = (char *) sbeg + slen; | |
| 479 | char *adr = (char *) a; | |
| 480 | ||
| 481 | return (adr >= beg && adr < end); | |
| eb44537a | 482 | } |
| 483 | ||
| 9a8c1c2f | 484 | boolean |
| 485 | valid_addr(os_vm_address_t addr) | |
| eb44537a | 486 | { |
| 9a8c1c2f | 487 | os_vm_address_t newaddr; |
| 488 | ||
| 489 | newaddr = os_trunc_to_page(addr); | |
| 490 | ||
| e7997cb6 RT |
491 | if (in_range_p(addr, READ_ONLY_SPACE_START, read_only_space_size) |
| 492 | || in_range_p(addr, STATIC_SPACE_START, static_space_size) | |
| 9a8c1c2f | 493 | || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size) |
| 46a4f482 | 494 | #ifndef GENCGC |
| 9a8c1c2f | 495 | || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size) |
| 46a4f482 | 496 | #endif |
| e7997cb6 RT |
497 | || in_range_p(addr, CONTROL_STACK_START, control_stack_size) |
| 498 | || in_range_p(addr, BINDING_STACK_START, binding_stack_size)) | |
| 9a8c1c2f | 499 | return TRUE; |
| 500 | return FALSE; | |
| eb44537a | 501 | } |
| eb44537a | 502 | \f |
| e7997cb6 RT |
503 | static void |
| 504 | sigbus_handle_now(HANDLER_ARGS) | |
| 505 | { | |
| 506 | interrupt_handle_now(signal, code, context); | |
| 507 | } | |
| 4970f6a7 | 508 | |
| 9a8c1c2f | 509 | static void |
| 46a4f482 | 510 | sigbus_handler(HANDLER_ARGS) |
| eb44537a | 511 | { |
| 838ff560 | 512 | os_context_t *os_context = (os_context_t *) context; |
| 46a4f482 | 513 | #if defined(GENCGC) |
| 9a8c1c2f | 514 | caddr_t fault_addr = code->si_addr; |
| 46a4f482 | 515 | #endif |
| 516 | ||
| e7997cb6 | 517 | #ifdef RED_ZONE_HIT |
| 838ff560 | 518 | if (os_control_stack_overflow((void *) fault_addr, os_context)) |
| e7997cb6 RT |
519 | return; |
| 520 | #endif | |
| 521 | ||
| 53ec2e7d | 522 | #ifdef __ppc__ |
| 46a4f482 | 523 | DPRINTF(0, (stderr, "sigbus:\n")); |
| 838ff560 RT |
524 | DPRINTF(0, (stderr, " PC = %p\n", SC_PC(os_context))); |
| 525 | DPRINTF(0, (stderr, " ALLOC-TN = %p\n", SC_REG(os_context, reg_ALLOC))); | |
| 526 | DPRINTF(0, (stderr, " CODE-TN = %p\n", SC_REG(os_context, reg_CODE))); | |
| 527 | DPRINTF(0, (stderr, " LRA-TN = %p\n", SC_REG(os_context, reg_LRA))); | |
| 528 | DPRINTF(0, (stderr, " CFP-TN = %p\n", SC_REG(os_context, reg_CFP))); | |
| 529 | DPRINTF(0, (stderr, " FDEFN-TN = %p\n", SC_REG(os_context, reg_FDEFN))); | |
| 46a4f482 | 530 | DPRINTF(0, (stderr, " foreign_function_call = %d\n", foreign_function_call_active)); |
| 53ec2e7d | 531 | #endif |
| 46a4f482 | 532 | |
| b7b2103a | 533 | #if defined(GENCGC) |
| 534 | #if defined(SIGSEGV_VERBOSE) | |
| 9dcff02e RT |
535 | fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n", |
| 536 | signal, fault_addr, page_index); | |
| b7b2103a | 537 | #endif |
| 538 | if (gc_write_barrier(code->si_addr)) | |
| 539 | return; | |
| 540 | #else | |
| 838ff560 | 541 | if (interrupt_maybe_gc(signal, code, os_context)) |
| b7b2103a | 542 | return; |
| 543 | #endif | |
| 1df6ba74 | 544 | /* a *real* protection fault */ |
| e7997cb6 | 545 | fprintf(stderr, "sigbus_handler: Real protection violation at %p, PC = %p\n", |
| 838ff560 RT |
546 | fault_addr, (void *) SC_PC(os_context)); |
| 547 | sigbus_handle_now(signal, code, os_context); | |
| 53ec2e7d | 548 | #ifdef __ppc__ |
| 9a8c1c2f | 549 | /* Work around G5 bug; fix courtesy gbyers via chandler */ |
| 838ff560 | 550 | sigreturn(os_context); |
| 555746e0 | 551 | #endif |
| 53ec2e7d | 552 | } |
| eb44537a | 553 | |
| 9a8c1c2f | 554 | void |
| 555 | os_install_interrupt_handlers(void) | |
| eb44537a | 556 | { |
| 9a8c1c2f | 557 | interrupt_install_low_level_handler(SIGBUS, sigbus_handler); |
| eb44537a | 558 | } |
| 559 | ||
| 9a8c1c2f | 560 | void * |
| 561 | os_dlsym(const char *sym_name, lispobj lib_list) | |
| 6a4fd3c3 | 562 | { |
| 563 | static void *program_handle; | |
| 564 | void *sym_addr = 0; | |
| 565 | ||
| 566 | if (!program_handle) | |
| 9a8c1c2f | 567 | program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL); |
| 6a4fd3c3 | 568 | if (lib_list != NIL) { |
| 569 | lispobj lib_list_head; | |
| 570 | ||
| 571 | for (lib_list_head = lib_list; | |
| 9a8c1c2f | 572 | lib_list_head != NIL; lib_list_head = (CONS(lib_list_head))->cdr) { |
| 6a4fd3c3 | 573 | struct cons *lib_cons = CONS(CONS(lib_list_head)->car); |
| 9a8c1c2f | 574 | struct sap *dlhandle = (struct sap *) PTR(lib_cons->car); |
| 6a4fd3c3 | 575 | |
| 9a8c1c2f | 576 | sym_addr = dlsym((void *) dlhandle->pointer, sym_name); |
| 6a4fd3c3 | 577 | if (sym_addr) |
| 578 | return sym_addr; | |
| 579 | } | |
| 580 | } | |
| 581 | sym_addr = dlsym(program_handle, sym_name); | |
| 582 | ||
| 583 | return sym_addr; | |
| 584 | } | |
| e7997cb6 RT |
585 | |
| 586 | #ifdef i386 | |
| 587 | boolean | |
| 588 | os_support_sse2() | |
| 589 | { | |
| 590 | return TRUE; | |
| 591 | } | |
| 592 | #endif |