Commit 2436b61a6b386d712a1813b036921443bd1c5c39
1 parent
e737b32a
SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
On Intel CPUs, sysenter and sysexit are valid in 64-bit mode. This patch makes both 64-bit aware and enables them for Intel CPUs. Add cpu save/load for 64-bit wide sysenter variables. Signed-off-by: Alexander Graf <agraf@suse.de> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5318 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
64 additions
and
29 deletions
target-i386/cpu.h
... | ... | @@ -549,8 +549,8 @@ typedef struct CPUX86State { |
549 | 549 | |
550 | 550 | /* sysenter registers */ |
551 | 551 | uint32_t sysenter_cs; |
552 | - uint32_t sysenter_esp; | |
553 | - uint32_t sysenter_eip; | |
552 | + target_ulong sysenter_esp; | |
553 | + target_ulong sysenter_eip; | |
554 | 554 | uint64_t efer; |
555 | 555 | uint64_t star; |
556 | 556 | |
... | ... | @@ -737,7 +737,7 @@ static inline int cpu_get_time_fast(void) |
737 | 737 | #define cpu_signal_handler cpu_x86_signal_handler |
738 | 738 | #define cpu_list x86_cpu_list |
739 | 739 | |
740 | -#define CPU_SAVE_VERSION 6 | |
740 | +#define CPU_SAVE_VERSION 7 | |
741 | 741 | |
742 | 742 | /* MMU modes definitions */ |
743 | 743 | #define MMU_MODE0_SUFFIX _kernel | ... | ... |
target-i386/helper.h
... | ... | @@ -55,7 +55,7 @@ DEF_HELPER(void, helper_enter_level, (int level, int data32, target_ulong t1)) |
55 | 55 | DEF_HELPER(void, helper_enter64_level, (int level, int data64, target_ulong t1)) |
56 | 56 | #endif |
57 | 57 | DEF_HELPER(void, helper_sysenter, (void)) |
58 | -DEF_HELPER(void, helper_sysexit, (void)) | |
58 | +DEF_HELPER(void, helper_sysexit, (int dflag)) | |
59 | 59 | #ifdef TARGET_X86_64 |
60 | 60 | DEF_HELPER(void, helper_syscall, (int next_eip_addend)) |
61 | 61 | DEF_HELPER(void, helper_sysret, (int dflag)) | ... | ... |
target-i386/machine.c
... | ... | @@ -88,9 +88,9 @@ void cpu_save(QEMUFile *f, void *opaque) |
88 | 88 | cpu_put_seg(f, &env->gdt); |
89 | 89 | cpu_put_seg(f, &env->idt); |
90 | 90 | |
91 | - qemu_put_be32s(f, &env->sysenter_cs); | |
92 | - qemu_put_be32s(f, &env->sysenter_esp); | |
93 | - qemu_put_be32s(f, &env->sysenter_eip); | |
91 | + qemu_put_betls(f, &env->sysenter_cs); | |
92 | + qemu_put_betls(f, &env->sysenter_esp); | |
93 | + qemu_put_betls(f, &env->sysenter_eip); | |
94 | 94 | |
95 | 95 | qemu_put_betls(f, &env->cr[0]); |
96 | 96 | qemu_put_betls(f, &env->cr[2]); |
... | ... | @@ -169,7 +169,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) |
169 | 169 | int32_t a20_mask; |
170 | 170 | |
171 | 171 | if (version_id != 3 && version_id != 4 && version_id != 5 |
172 | - && version_id != 6) | |
172 | + && version_id != 6 && version_id != 7) | |
173 | 173 | return -EINVAL; |
174 | 174 | for(i = 0; i < CPU_NB_REGS; i++) |
175 | 175 | qemu_get_betls(f, &env->regs[i]); |
... | ... | @@ -244,8 +244,13 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) |
244 | 244 | cpu_get_seg(f, &env->idt); |
245 | 245 | |
246 | 246 | qemu_get_be32s(f, &env->sysenter_cs); |
247 | - qemu_get_be32s(f, &env->sysenter_esp); | |
248 | - qemu_get_be32s(f, &env->sysenter_eip); | |
247 | + if (version_id >= 7) { | |
248 | + qemu_get_betls(f, &env->sysenter_esp); | |
249 | + qemu_get_betls(f, &env->sysenter_eip); | |
250 | + } else { | |
251 | + qemu_get_be32s(f, &env->sysenter_esp); | |
252 | + qemu_get_be32s(f, &env->sysenter_eip); | |
253 | + } | |
249 | 254 | |
250 | 255 | qemu_get_betls(f, &env->cr[0]); |
251 | 256 | qemu_get_betls(f, &env->cr[2]); | ... | ... |
target-i386/op_helper.c
... | ... | @@ -2919,11 +2919,23 @@ void helper_sysenter(void) |
2919 | 2919 | } |
2920 | 2920 | env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK); |
2921 | 2921 | cpu_x86_set_cpl(env, 0); |
2922 | - cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, | |
2923 | - 0, 0xffffffff, | |
2924 | - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2925 | - DESC_S_MASK | | |
2926 | - DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
2922 | + | |
2923 | +#ifdef TARGET_X86_64 | |
2924 | + if (env->hflags & HF_LMA_MASK) { | |
2925 | + cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, | |
2926 | + 0, 0xffffffff, | |
2927 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2928 | + DESC_S_MASK | | |
2929 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK); | |
2930 | + } else | |
2931 | +#endif | |
2932 | + { | |
2933 | + cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, | |
2934 | + 0, 0xffffffff, | |
2935 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2936 | + DESC_S_MASK | | |
2937 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
2938 | + } | |
2927 | 2939 | cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, |
2928 | 2940 | 0, 0xffffffff, |
2929 | 2941 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
... | ... | @@ -2933,7 +2945,7 @@ void helper_sysenter(void) |
2933 | 2945 | EIP = env->sysenter_eip; |
2934 | 2946 | } |
2935 | 2947 | |
2936 | -void helper_sysexit(void) | |
2948 | +void helper_sysexit(int dflag) | |
2937 | 2949 | { |
2938 | 2950 | int cpl; |
2939 | 2951 | |
... | ... | @@ -2942,16 +2954,32 @@ void helper_sysexit(void) |
2942 | 2954 | raise_exception_err(EXCP0D_GPF, 0); |
2943 | 2955 | } |
2944 | 2956 | cpu_x86_set_cpl(env, 3); |
2945 | - cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, | |
2946 | - 0, 0xffffffff, | |
2947 | - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2948 | - DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
2949 | - DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
2950 | - cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, | |
2951 | - 0, 0xffffffff, | |
2952 | - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2953 | - DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
2954 | - DESC_W_MASK | DESC_A_MASK); | |
2957 | +#ifdef TARGET_X86_64 | |
2958 | + if (dflag == 2) { | |
2959 | + cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3, | |
2960 | + 0, 0xffffffff, | |
2961 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2962 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
2963 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK); | |
2964 | + cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3, | |
2965 | + 0, 0xffffffff, | |
2966 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2967 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
2968 | + DESC_W_MASK | DESC_A_MASK); | |
2969 | + } else | |
2970 | +#endif | |
2971 | + { | |
2972 | + cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, | |
2973 | + 0, 0xffffffff, | |
2974 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2975 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
2976 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
2977 | + cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, | |
2978 | + 0, 0xffffffff, | |
2979 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
2980 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
2981 | + DESC_W_MASK | DESC_A_MASK); | |
2982 | + } | |
2955 | 2983 | ESP = ECX; |
2956 | 2984 | EIP = EDX; |
2957 | 2985 | #ifdef USE_KQEMU | ... | ... |
target-i386/translate.c
... | ... | @@ -6505,7 +6505,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6505 | 6505 | tcg_gen_helper_0_0(helper_rdpmc); |
6506 | 6506 | break; |
6507 | 6507 | case 0x134: /* sysenter */ |
6508 | - if (CODE64(s)) | |
6508 | + /* For Intel SYSENTER is valid on 64-bit */ | |
6509 | + if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) | |
6509 | 6510 | goto illegal_op; |
6510 | 6511 | if (!s->pe) { |
6511 | 6512 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
... | ... | @@ -6520,7 +6521,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6520 | 6521 | } |
6521 | 6522 | break; |
6522 | 6523 | case 0x135: /* sysexit */ |
6523 | - if (CODE64(s)) | |
6524 | + /* For Intel SYSEXIT is valid on 64-bit */ | |
6525 | + if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) | |
6524 | 6526 | goto illegal_op; |
6525 | 6527 | if (!s->pe) { |
6526 | 6528 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
... | ... | @@ -6530,7 +6532,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6530 | 6532 | s->cc_op = CC_OP_DYNAMIC; |
6531 | 6533 | } |
6532 | 6534 | gen_jmp_im(pc_start - s->cs_base); |
6533 | - tcg_gen_helper_0_0(helper_sysexit); | |
6535 | + tcg_gen_helper_0_1(helper_sysexit, tcg_const_i32(dflag)); | |
6534 | 6536 | gen_eob(s); |
6535 | 6537 | } |
6536 | 6538 | break; | ... | ... |