提交 8d7b0fbb 编写于 作者: B bellard

32 bit RSP update fix (aka Open Solaris x86_64 bug)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2186 c046a42c-6fe2-441c-8c8c-71466251a162
上级 5e966ce6
...@@ -553,6 +553,20 @@ static inline unsigned int get_sp_mask(unsigned int e2) ...@@ -553,6 +553,20 @@ static inline unsigned int get_sp_mask(unsigned int e2)
return 0xffff; return 0xffff;
} }
#ifdef TARGET_X86_64
#define SET_ESP(val, sp_mask)\
do {\
if ((sp_mask) == 0xffff)\
ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
else if ((sp_mask) == 0xffffffffLL)\
ESP = (uint32_t)(val);\
else\
ESP = (val);\
} while (0)
#else
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
#endif
/* XXX: add a is_user flag to have proper security support */ /* XXX: add a is_user flag to have proper security support */
#define PUSHW(ssp, sp, sp_mask, val)\ #define PUSHW(ssp, sp, sp_mask, val)\
{\ {\
...@@ -584,10 +598,10 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, ...@@ -584,10 +598,10 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
{ {
SegmentCache *dt; SegmentCache *dt;
target_ulong ptr, ssp; target_ulong ptr, ssp;
int type, dpl, selector, ss_dpl, cpl, sp_mask; int type, dpl, selector, ss_dpl, cpl;
int has_error_code, new_stack, shift; int has_error_code, new_stack, shift;
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
uint32_t old_eip; uint32_t old_eip, sp_mask;
has_error_code = 0; has_error_code = 0;
if (!is_int && !is_hw) { if (!is_int && !is_hw) {
...@@ -623,7 +637,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, ...@@ -623,7 +637,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip); switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
if (has_error_code) { if (has_error_code) {
int mask, type; int type;
uint32_t mask;
/* push the error code */ /* push the error code */
type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf; type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
shift = type >> 3; shift = type >> 3;
...@@ -637,7 +652,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, ...@@ -637,7 +652,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
stl_kernel(ssp, error_code); stl_kernel(ssp, error_code);
else else
stw_kernel(ssp, error_code); stw_kernel(ssp, error_code);
ESP = (esp & mask) | (ESP & ~mask); SET_ESP(esp, mask);
} }
return; return;
case 6: /* 286 interrupt gate */ case 6: /* 286 interrupt gate */
...@@ -765,7 +780,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, ...@@ -765,7 +780,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
cpu_x86_load_seg_cache(env, R_SS, ss, cpu_x86_load_seg_cache(env, R_SS, ss,
ssp, get_seg_limit(ss_e1, ss_e2), ss_e2); ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
} }
ESP = (ESP & ~sp_mask) | (esp & sp_mask); SET_ESP(esp, sp_mask);
selector = (selector & ~3) | dpl; selector = (selector & ~3) | dpl;
cpu_x86_load_seg_cache(env, R_CS, selector, cpu_x86_load_seg_cache(env, R_CS, selector,
...@@ -2015,7 +2030,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) ...@@ -2015,7 +2030,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip)
PUSHW(ssp, esp, esp_mask, next_eip); PUSHW(ssp, esp, esp_mask, next_eip);
} }
ESP = (ESP & ~esp_mask) | (esp & esp_mask); SET_ESP(esp, esp_mask);
env->eip = new_eip; env->eip = new_eip;
env->segs[R_CS].selector = new_cs; env->segs[R_CS].selector = new_cs;
env->segs[R_CS].base = (new_cs << 4); env->segs[R_CS].base = (new_cs << 4);
...@@ -2101,7 +2116,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip_addend) ...@@ -2101,7 +2116,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
if (new_eip > limit) if (new_eip > limit)
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
/* from this point, not restartable */ /* from this point, not restartable */
ESP = (ESP & ~sp_mask) | (sp & sp_mask); SET_ESP(sp, sp_mask);
cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
get_seg_base(e1, e2), limit, e2); get_seg_base(e1, e2), limit, e2);
EIP = new_eip; EIP = new_eip;
...@@ -2230,7 +2245,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip_addend) ...@@ -2230,7 +2245,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
get_seg_limit(e1, e2), get_seg_limit(e1, e2),
e2); e2);
cpu_x86_set_cpl(env, dpl); cpu_x86_set_cpl(env, dpl);
ESP = (ESP & ~sp_mask) | (sp & sp_mask); SET_ESP(sp, sp_mask);
EIP = offset; EIP = offset;
} }
#ifdef USE_KQEMU #ifdef USE_KQEMU
...@@ -2459,7 +2474,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) ...@@ -2459,7 +2474,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
sp += addend; sp += addend;
} }
ESP = (ESP & ~sp_mask) | (sp & sp_mask); SET_ESP(sp, sp_mask);
env->eip = new_eip; env->eip = new_eip;
if (is_iret) { if (is_iret) {
/* NOTE: 'cpl' is the _old_ CPL */ /* NOTE: 'cpl' is the _old_ CPL */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册