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) | ... | ... |