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