Commit 66f1cdbde44b82e53b5337981f38ca9e837cd5f7
1 parent
d07bde88
Partial fix to Sparc32 Linux host global register mangling problem
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3806 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
55 additions
and
23 deletions
Makefile.target
| ... | ... | @@ -161,7 +161,7 @@ ifeq ($(ARCH),sparc) |
| 161 | 161 | OP_CFLAGS+=-fno-omit-frame-pointer |
| 162 | 162 | else |
| 163 | 163 | BASE_CFLAGS+=-ffixed-g1 -ffixed-g6 |
| 164 | - HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat | |
| 164 | + HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 | |
| 165 | 165 | # -static is used to avoid g1/g3 usage by the dynamic linker |
| 166 | 166 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static |
| 167 | 167 | endif | ... | ... |
cpu-exec.c
| ... | ... | @@ -40,6 +40,52 @@ int tb_invalidated_flag; |
| 40 | 40 | //#define DEBUG_EXEC |
| 41 | 41 | //#define DEBUG_SIGNAL |
| 42 | 42 | |
| 43 | +#define SAVE_GLOBALS() | |
| 44 | +#define RESTORE_GLOBALS() | |
| 45 | + | |
| 46 | +#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 47 | +#include <features.h> | |
| 48 | +#if defined(__GLIBC__) && ((__GLIBC__ < 2) || \ | |
| 49 | + ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90))) | |
| 50 | +// Work around ugly bugs in glibc that mangle global register contents | |
| 51 | + | |
| 52 | +static volatile void *saved_env; | |
| 53 | +static volatile unsigned long saved_t0, saved_i7; | |
| 54 | +#undef SAVE_GLOBALS | |
| 55 | +#define SAVE_GLOBALS() do { \ | |
| 56 | + saved_env = env; \ | |
| 57 | + saved_t0 = T0; \ | |
| 58 | + asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7)); \ | |
| 59 | + } while(0) | |
| 60 | + | |
| 61 | +#undef RESTORE_GLOBALS | |
| 62 | +#define RESTORE_GLOBALS() do { \ | |
| 63 | + env = (void *)saved_env; \ | |
| 64 | + T0 = saved_t0; \ | |
| 65 | + asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7)); \ | |
| 66 | + } while(0) | |
| 67 | + | |
| 68 | +static int sparc_setjmp(jmp_buf buf) | |
| 69 | +{ | |
| 70 | + int ret; | |
| 71 | + | |
| 72 | + SAVE_GLOBALS(); | |
| 73 | + ret = setjmp(buf); | |
| 74 | + RESTORE_GLOBALS(); | |
| 75 | + return ret; | |
| 76 | +} | |
| 77 | +#undef setjmp | |
| 78 | +#define setjmp(jmp_buf) sparc_setjmp(jmp_buf) | |
| 79 | + | |
| 80 | +static void sparc_longjmp(jmp_buf buf, int val) | |
| 81 | +{ | |
| 82 | + SAVE_GLOBALS(); | |
| 83 | + longjmp(buf, val); | |
| 84 | +} | |
| 85 | +#define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val) | |
| 86 | +#endif | |
| 87 | +#endif | |
| 88 | + | |
| 43 | 89 | void cpu_loop_exit(void) |
| 44 | 90 | { |
| 45 | 91 | /* NOTE: the register at this point must be saved by hand because |
| ... | ... | @@ -133,7 +179,9 @@ static TranslationBlock *tb_find_slow(target_ulong pc, |
| 133 | 179 | tb->tc_ptr = tc_ptr; |
| 134 | 180 | tb->cs_base = cs_base; |
| 135 | 181 | tb->flags = flags; |
| 182 | + SAVE_GLOBALS(); | |
| 136 | 183 | cpu_gen_code(env, tb, &code_gen_size); |
| 184 | + RESTORE_GLOBALS(); | |
| 137 | 185 | code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); |
| 138 | 186 | |
| 139 | 187 | /* check next page if needed */ |
| ... | ... | @@ -232,11 +280,7 @@ static inline TranslationBlock *tb_find_fast(void) |
| 232 | 280 | return tb; |
| 233 | 281 | } |
| 234 | 282 | |
| 235 | -#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 236 | -#define BREAK_CHAIN tmp_T0 = 0 | |
| 237 | -#else | |
| 238 | 283 | #define BREAK_CHAIN T0 = 0 |
| 239 | -#endif | |
| 240 | 284 | |
| 241 | 285 | /* main execution loop */ |
| 242 | 286 | |
| ... | ... | @@ -249,10 +293,6 @@ int cpu_exec(CPUState *env1) |
| 249 | 293 | uint32_t *saved_regwptr; |
| 250 | 294 | #endif |
| 251 | 295 | #endif |
| 252 | -#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 253 | - int saved_i7; | |
| 254 | - target_ulong tmp_T0; | |
| 255 | -#endif | |
| 256 | 296 | int ret, interrupt_request; |
| 257 | 297 | void (*gen_func)(void); |
| 258 | 298 | TranslationBlock *tb; |
| ... | ... | @@ -267,10 +307,7 @@ int cpu_exec(CPUState *env1) |
| 267 | 307 | #define SAVE_HOST_REGS 1 |
| 268 | 308 | #include "hostregs_helper.h" |
| 269 | 309 | env = env1; |
| 270 | -#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 271 | - /* we also save i7 because longjmp may not restore it */ | |
| 272 | - asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); | |
| 273 | -#endif | |
| 310 | + SAVE_GLOBALS(); | |
| 274 | 311 | |
| 275 | 312 | env_to_regs(); |
| 276 | 313 | #if defined(TARGET_I386) |
| ... | ... | @@ -380,10 +417,7 @@ int cpu_exec(CPUState *env1) |
| 380 | 417 | |
| 381 | 418 | T0 = 0; /* force lookup of first TB */ |
| 382 | 419 | for(;;) { |
| 383 | -#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 384 | - /* g1 can be modified by some libc? functions */ | |
| 385 | - tmp_T0 = T0; | |
| 386 | -#endif | |
| 420 | + SAVE_GLOBALS(); | |
| 387 | 421 | interrupt_request = env->interrupt_request; |
| 388 | 422 | if (__builtin_expect(interrupt_request, 0) |
| 389 | 423 | #if defined(TARGET_I386) |
| ... | ... | @@ -597,9 +631,7 @@ int cpu_exec(CPUState *env1) |
| 597 | 631 | lookup_symbol(tb->pc)); |
| 598 | 632 | } |
| 599 | 633 | #endif |
| 600 | -#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 601 | - T0 = tmp_T0; | |
| 602 | -#endif | |
| 634 | + RESTORE_GLOBALS(); | |
| 603 | 635 | /* see if we can patch the calling TB. When the TB |
| 604 | 636 | spans two pages, we cannot safely do a direct |
| 605 | 637 | jump. */ |
| ... | ... | @@ -695,9 +727,7 @@ int cpu_exec(CPUState *env1) |
| 695 | 727 | #endif |
| 696 | 728 | |
| 697 | 729 | /* restore global registers */ |
| 698 | -#if defined(__sparc__) && !defined(HOST_SOLARIS) | |
| 699 | - asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); | |
| 700 | -#endif | |
| 730 | + RESTORE_GLOBALS(); | |
| 701 | 731 | #include "hostregs_helper.h" |
| 702 | 732 | |
| 703 | 733 | /* fail safe : never use cpu_single_env outside cpu_exec() */ | ... | ... |
target-sparc/op.c
| ... | ... | @@ -1244,12 +1244,14 @@ void OPPROTO op_exception(void) |
| 1244 | 1244 | { |
| 1245 | 1245 | env->exception_index = PARAM1; |
| 1246 | 1246 | cpu_loop_exit(); |
| 1247 | + FORCE_RET(); | |
| 1247 | 1248 | } |
| 1248 | 1249 | |
| 1249 | 1250 | void OPPROTO op_trap_T0(void) |
| 1250 | 1251 | { |
| 1251 | 1252 | env->exception_index = TT_TRAP + (T0 & 0x7f); |
| 1252 | 1253 | cpu_loop_exit(); |
| 1254 | + FORCE_RET(); | |
| 1253 | 1255 | } |
| 1254 | 1256 | |
| 1255 | 1257 | void OPPROTO op_trapcc_T0(void) | ... | ... |