Commit b359d4e7e44d643d25e3ead1dba31e6559f4eb72

Authored by bellard
1 parent c45b3c0e

fixed zero ss selector case in x86_64 emulation


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1394 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 16 additions and 9 deletions
target-i386/helper.c
@@ -1494,11 +1494,12 @@ void load_seg(int seg_reg, int selector) @@ -1494,11 +1494,12 @@ void load_seg(int seg_reg, int selector)
1494 target_ulong ptr; 1494 target_ulong ptr;
1495 1495
1496 selector &= 0xffff; 1496 selector &= 0xffff;
  1497 + cpl = env->hflags & HF_CPL_MASK;
1497 if ((selector & 0xfffc) == 0) { 1498 if ((selector & 0xfffc) == 0) {
1498 /* null selector case */ 1499 /* null selector case */
1499 if (seg_reg == R_SS 1500 if (seg_reg == R_SS
1500 #ifdef TARGET_X86_64 1501 #ifdef TARGET_X86_64
1501 - && !(env->hflags & HF_CS64_MASK) 1502 + && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
1502 #endif 1503 #endif
1503 ) 1504 )
1504 raise_exception_err(EXCP0D_GPF, 0); 1505 raise_exception_err(EXCP0D_GPF, 0);
@@ -1520,7 +1521,6 @@ void load_seg(int seg_reg, int selector) @@ -1520,7 +1521,6 @@ void load_seg(int seg_reg, int selector)
1520 raise_exception_err(EXCP0D_GPF, selector & 0xfffc); 1521 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1521 rpl = selector & 3; 1522 rpl = selector & 3;
1522 dpl = (e2 >> DESC_DPL_SHIFT) & 3; 1523 dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1523 - cpl = env->hflags & HF_CPL_MASK;  
1524 if (seg_reg == R_SS) { 1524 if (seg_reg == R_SS) {
1525 /* must be writable segment */ 1525 /* must be writable segment */
1526 if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) 1526 if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
@@ -2054,13 +2054,20 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) @@ -2054,13 +2054,20 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
2054 new_ss, new_esp); 2054 new_ss, new_esp);
2055 } 2055 }
2056 #endif 2056 #endif
2057 - if ((env->hflags & HF_LMA_MASK) && (new_ss & 0xfffc) == 0) {  
2058 - /* NULL ss is allowed in long mode */  
2059 - cpu_x86_load_seg_cache(env, R_SS, new_ss,  
2060 - 0, 0xffffffff,  
2061 - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |  
2062 - DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |  
2063 - DESC_W_MASK | DESC_A_MASK); 2057 + if ((new_ss & 0xfffc) == 0) {
  2058 +#ifdef TARGET_X86_64
  2059 + /* NULL ss is allowed in long mode if cpl != 3*/
  2060 + if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
  2061 + cpu_x86_load_seg_cache(env, R_SS, new_ss,
  2062 + 0, 0xffffffff,
  2063 + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
  2064 + DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
  2065 + DESC_W_MASK | DESC_A_MASK);
  2066 + } else
  2067 +#endif
  2068 + {
  2069 + raise_exception_err(EXCP0D_GPF, 0);
  2070 + }
2064 } else { 2071 } else {
2065 if ((new_ss & 3) != rpl) 2072 if ((new_ss & 3) != rpl)
2066 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); 2073 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);