Commit b359d4e7e44d643d25e3ead1dba31e6559f4eb72
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); |