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 | 1494 | target_ulong ptr; |
1495 | 1495 | |
1496 | 1496 | selector &= 0xffff; |
1497 | + cpl = env->hflags & HF_CPL_MASK; | |
1497 | 1498 | if ((selector & 0xfffc) == 0) { |
1498 | 1499 | /* null selector case */ |
1499 | 1500 | if (seg_reg == R_SS |
1500 | 1501 | #ifdef TARGET_X86_64 |
1501 | - && !(env->hflags & HF_CS64_MASK) | |
1502 | + && (!(env->hflags & HF_CS64_MASK) || cpl == 3) | |
1502 | 1503 | #endif |
1503 | 1504 | ) |
1504 | 1505 | raise_exception_err(EXCP0D_GPF, 0); |
... | ... | @@ -1520,7 +1521,6 @@ void load_seg(int seg_reg, int selector) |
1520 | 1521 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1521 | 1522 | rpl = selector & 3; |
1522 | 1523 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
1523 | - cpl = env->hflags & HF_CPL_MASK; | |
1524 | 1524 | if (seg_reg == R_SS) { |
1525 | 1525 | /* must be writable segment */ |
1526 | 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 | 2054 | new_ss, new_esp); |
2055 | 2055 | } |
2056 | 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 | 2071 | } else { |
2065 | 2072 | if ((new_ss & 3) != rpl) |
2066 | 2073 | raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | ... | ... |