Commit 872929aa59cba19fd83b98f87929ccda12a2cbbb
1 parent
893f9865
SVM rework
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4605 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
383 additions
and
478 deletions
cpu-exec.c
| @@ -171,7 +171,6 @@ static inline TranslationBlock *tb_find_fast(void) | @@ -171,7 +171,6 @@ static inline TranslationBlock *tb_find_fast(void) | ||
| 171 | #if defined(TARGET_I386) | 171 | #if defined(TARGET_I386) |
| 172 | flags = env->hflags; | 172 | flags = env->hflags; |
| 173 | flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); | 173 | flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); |
| 174 | - flags |= env->intercept; | ||
| 175 | cs_base = env->segs[R_CS].base; | 174 | cs_base = env->segs[R_CS].base; |
| 176 | pc = cs_base + env->eip; | 175 | pc = cs_base + env->eip; |
| 177 | #elif defined(TARGET_ARM) | 176 | #elif defined(TARGET_ARM) |
target-i386/TODO
| 1 | Correctness issues: | 1 | Correctness issues: |
| 2 | 2 | ||
| 3 | - some eflags manipulation incorrectly reset the bit 0x2. | 3 | - some eflags manipulation incorrectly reset the bit 0x2. |
| 4 | -- SVM: rework the implementation: simplify code, move most intercept | ||
| 5 | - tests as dynamic, correct segment access, verify exception safety, | ||
| 6 | - cpu save/restore, SMM save/restore. | 4 | +- SVM: test, cpu save/restore, SMM save/restore. |
| 7 | - x86_64: lcall/ljmp intel/amd differences ? | 5 | - x86_64: lcall/ljmp intel/amd differences ? |
| 8 | - better code fetch (different exception handling + CS.limit support) | 6 | - better code fetch (different exception handling + CS.limit support) |
| 9 | - user/kernel PUSHL/POPL in helper.c | 7 | - user/kernel PUSHL/POPL in helper.c |
target-i386/cpu.h
| @@ -149,6 +149,8 @@ | @@ -149,6 +149,8 @@ | ||
| 149 | #define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ | 149 | #define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ |
| 150 | #define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ | 150 | #define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ |
| 151 | #define HF_NMI_SHIFT 22 /* CPU serving NMI */ | 151 | #define HF_NMI_SHIFT 22 /* CPU serving NMI */ |
| 152 | +#define HF_SVME_SHIFT 23 /* SVME enabled (copy of EFER.SVME */ | ||
| 153 | +#define HF_SVMI_SHIFT 24 /* SVM intercepts are active */ | ||
| 152 | 154 | ||
| 153 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) | 155 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) |
| 154 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) | 156 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) |
| @@ -169,6 +171,8 @@ | @@ -169,6 +171,8 @@ | ||
| 169 | #define HF_GIF_MASK (1 << HF_GIF_SHIFT) | 171 | #define HF_GIF_MASK (1 << HF_GIF_SHIFT) |
| 170 | #define HF_HIF_MASK (1 << HF_HIF_SHIFT) | 172 | #define HF_HIF_MASK (1 << HF_HIF_SHIFT) |
| 171 | #define HF_NMI_MASK (1 << HF_NMI_SHIFT) | 173 | #define HF_NMI_MASK (1 << HF_NMI_SHIFT) |
| 174 | +#define HF_SVME_MASK (1 << HF_SVME_SHIFT) | ||
| 175 | +#define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) | ||
| 172 | 176 | ||
| 173 | #define CR0_PE_MASK (1 << 0) | 177 | #define CR0_PE_MASK (1 << 0) |
| 174 | #define CR0_MP_MASK (1 << 1) | 178 | #define CR0_MP_MASK (1 << 1) |
| @@ -242,6 +246,7 @@ | @@ -242,6 +246,7 @@ | ||
| 242 | #define MSR_EFER_LME (1 << 8) | 246 | #define MSR_EFER_LME (1 << 8) |
| 243 | #define MSR_EFER_LMA (1 << 10) | 247 | #define MSR_EFER_LMA (1 << 10) |
| 244 | #define MSR_EFER_NXE (1 << 11) | 248 | #define MSR_EFER_NXE (1 << 11) |
| 249 | +#define MSR_EFER_SVME (1 << 12) | ||
| 245 | #define MSR_EFER_FFXSR (1 << 14) | 250 | #define MSR_EFER_FFXSR (1 << 14) |
| 246 | 251 | ||
| 247 | #define MSR_STAR 0xc0000081 | 252 | #define MSR_STAR 0xc0000081 |
| @@ -322,6 +327,7 @@ | @@ -322,6 +327,7 @@ | ||
| 322 | #define CPUID_EXT3_3DNOWPREFETCH (1 << 8) | 327 | #define CPUID_EXT3_3DNOWPREFETCH (1 << 8) |
| 323 | #define CPUID_EXT3_OSVW (1 << 9) | 328 | #define CPUID_EXT3_OSVW (1 << 9) |
| 324 | #define CPUID_EXT3_IBS (1 << 10) | 329 | #define CPUID_EXT3_IBS (1 << 10) |
| 330 | +#define CPUID_EXT3_SKINIT (1 << 12) | ||
| 325 | 331 | ||
| 326 | #define EXCP00_DIVZ 0 | 332 | #define EXCP00_DIVZ 0 |
| 327 | #define EXCP01_SSTP 1 | 333 | #define EXCP01_SSTP 1 |
target-i386/helper.c
| @@ -1096,16 +1096,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, | @@ -1096,16 +1096,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, | ||
| 1096 | (env->efer & MSR_EFER_NXE) && | 1096 | (env->efer & MSR_EFER_NXE) && |
| 1097 | (env->cr[4] & CR4_PAE_MASK)) | 1097 | (env->cr[4] & CR4_PAE_MASK)) |
| 1098 | error_code |= PG_ERROR_I_D_MASK; | 1098 | error_code |= PG_ERROR_I_D_MASK; |
| 1099 | - if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) { | ||
| 1100 | - stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr); | 1099 | + if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) { |
| 1100 | + /* cr2 is not modified in case of exceptions */ | ||
| 1101 | + stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), | ||
| 1102 | + addr); | ||
| 1101 | } else { | 1103 | } else { |
| 1102 | env->cr[2] = addr; | 1104 | env->cr[2] = addr; |
| 1103 | } | 1105 | } |
| 1104 | env->error_code = error_code; | 1106 | env->error_code = error_code; |
| 1105 | env->exception_index = EXCP0E_PAGE; | 1107 | env->exception_index = EXCP0E_PAGE; |
| 1106 | - /* the VMM will handle this */ | ||
| 1107 | - if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) | ||
| 1108 | - return 2; | ||
| 1109 | return 1; | 1108 | return 1; |
| 1110 | } | 1109 | } |
| 1111 | 1110 |
target-i386/helper.h
| @@ -43,7 +43,8 @@ DEF_HELPER(void, helper_lcall_protected, (int new_cs, target_ulong new_eip, | @@ -43,7 +43,8 @@ DEF_HELPER(void, helper_lcall_protected, (int new_cs, target_ulong new_eip, | ||
| 43 | DEF_HELPER(void, helper_iret_real, (int shift)) | 43 | DEF_HELPER(void, helper_iret_real, (int shift)) |
| 44 | DEF_HELPER(void, helper_iret_protected, (int shift, int next_eip)) | 44 | DEF_HELPER(void, helper_iret_protected, (int shift, int next_eip)) |
| 45 | DEF_HELPER(void, helper_lret_protected, (int shift, int addend)) | 45 | DEF_HELPER(void, helper_lret_protected, (int shift, int addend)) |
| 46 | -DEF_HELPER(void, helper_movl_crN_T0, (int reg, target_ulong t0)) | 46 | +DEF_HELPER(target_ulong, helper_read_crN, (int reg)) |
| 47 | +DEF_HELPER(void, helper_write_crN, (int reg, target_ulong t0)) | ||
| 47 | DEF_HELPER(void, helper_lmsw, (target_ulong t0)) | 48 | DEF_HELPER(void, helper_lmsw, (target_ulong t0)) |
| 48 | DEF_HELPER(void, helper_clts, (void)) | 49 | DEF_HELPER(void, helper_clts, (void)) |
| 49 | #if !defined(CONFIG_USER_ONLY) | 50 | #if !defined(CONFIG_USER_ONLY) |
target-i386/op_helper.c
| @@ -625,18 +625,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -625,18 +625,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 625 | int has_error_code, new_stack, shift; | 625 | int has_error_code, new_stack, shift; |
| 626 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; | 626 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
| 627 | uint32_t old_eip, sp_mask; | 627 | uint32_t old_eip, sp_mask; |
| 628 | - int svm_should_check = 1; | ||
| 629 | 628 | ||
| 630 | - if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) { | ||
| 631 | - next_eip = EIP; | ||
| 632 | - svm_should_check = 0; | ||
| 633 | - } | ||
| 634 | - | ||
| 635 | - if (svm_should_check | ||
| 636 | - && (INTERCEPTEDl(_exceptions, 1 << intno) | ||
| 637 | - && !is_int)) { | ||
| 638 | - raise_interrupt(intno, is_int, error_code, 0); | ||
| 639 | - } | ||
| 640 | has_error_code = 0; | 629 | has_error_code = 0; |
| 641 | if (!is_int && !is_hw) { | 630 | if (!is_int && !is_hw) { |
| 642 | switch(intno) { | 631 | switch(intno) { |
| @@ -872,17 +861,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, | @@ -872,17 +861,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, | ||
| 872 | int has_error_code, new_stack; | 861 | int has_error_code, new_stack; |
| 873 | uint32_t e1, e2, e3, ss; | 862 | uint32_t e1, e2, e3, ss; |
| 874 | target_ulong old_eip, esp, offset; | 863 | target_ulong old_eip, esp, offset; |
| 875 | - int svm_should_check = 1; | ||
| 876 | 864 | ||
| 877 | - if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) { | ||
| 878 | - next_eip = EIP; | ||
| 879 | - svm_should_check = 0; | ||
| 880 | - } | ||
| 881 | - if (svm_should_check | ||
| 882 | - && INTERCEPTEDl(_exceptions, 1 << intno) | ||
| 883 | - && !is_int) { | ||
| 884 | - raise_interrupt(intno, is_int, error_code, 0); | ||
| 885 | - } | ||
| 886 | has_error_code = 0; | 865 | has_error_code = 0; |
| 887 | if (!is_int && !is_hw) { | 866 | if (!is_int && !is_hw) { |
| 888 | switch(intno) { | 867 | switch(intno) { |
| @@ -1139,17 +1118,7 @@ static void do_interrupt_real(int intno, int is_int, int error_code, | @@ -1139,17 +1118,7 @@ static void do_interrupt_real(int intno, int is_int, int error_code, | ||
| 1139 | int selector; | 1118 | int selector; |
| 1140 | uint32_t offset, esp; | 1119 | uint32_t offset, esp; |
| 1141 | uint32_t old_cs, old_eip; | 1120 | uint32_t old_cs, old_eip; |
| 1142 | - int svm_should_check = 1; | ||
| 1143 | 1121 | ||
| 1144 | - if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) { | ||
| 1145 | - next_eip = EIP; | ||
| 1146 | - svm_should_check = 0; | ||
| 1147 | - } | ||
| 1148 | - if (svm_should_check | ||
| 1149 | - && INTERCEPTEDl(_exceptions, 1 << intno) | ||
| 1150 | - && !is_int) { | ||
| 1151 | - raise_interrupt(intno, is_int, error_code, 0); | ||
| 1152 | - } | ||
| 1153 | /* real mode (simpler !) */ | 1122 | /* real mode (simpler !) */ |
| 1154 | dt = &env->idt; | 1123 | dt = &env->idt; |
| 1155 | if (intno * 4 + 3 > dt->limit) | 1124 | if (intno * 4 + 3 > dt->limit) |
| @@ -1307,6 +1276,8 @@ void raise_interrupt(int intno, int is_int, int error_code, | @@ -1307,6 +1276,8 @@ void raise_interrupt(int intno, int is_int, int error_code, | ||
| 1307 | if (!is_int) { | 1276 | if (!is_int) { |
| 1308 | helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); | 1277 | helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); |
| 1309 | intno = check_exception(intno, &error_code); | 1278 | intno = check_exception(intno, &error_code); |
| 1279 | + } else { | ||
| 1280 | + helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0); | ||
| 1310 | } | 1281 | } |
| 1311 | 1282 | ||
| 1312 | env->exception_index = intno; | 1283 | env->exception_index = intno; |
| @@ -1316,18 +1287,6 @@ void raise_interrupt(int intno, int is_int, int error_code, | @@ -1316,18 +1287,6 @@ void raise_interrupt(int intno, int is_int, int error_code, | ||
| 1316 | cpu_loop_exit(); | 1287 | cpu_loop_exit(); |
| 1317 | } | 1288 | } |
| 1318 | 1289 | ||
| 1319 | -/* same as raise_exception_err, but do not restore global registers */ | ||
| 1320 | -static void raise_exception_err_norestore(int exception_index, int error_code) | ||
| 1321 | -{ | ||
| 1322 | - exception_index = check_exception(exception_index, &error_code); | ||
| 1323 | - | ||
| 1324 | - env->exception_index = exception_index; | ||
| 1325 | - env->error_code = error_code; | ||
| 1326 | - env->exception_is_int = 0; | ||
| 1327 | - env->exception_next_eip = 0; | ||
| 1328 | - longjmp(env->jmp_env, 1); | ||
| 1329 | -} | ||
| 1330 | - | ||
| 1331 | /* shortcuts to generate exceptions */ | 1290 | /* shortcuts to generate exceptions */ |
| 1332 | 1291 | ||
| 1333 | void (raise_exception_err)(int exception_index, int error_code) | 1292 | void (raise_exception_err)(int exception_index, int error_code) |
| @@ -1921,8 +1880,10 @@ void helper_single_step(void) | @@ -1921,8 +1880,10 @@ void helper_single_step(void) | ||
| 1921 | void helper_cpuid(void) | 1880 | void helper_cpuid(void) |
| 1922 | { | 1881 | { |
| 1923 | uint32_t index; | 1882 | uint32_t index; |
| 1924 | - index = (uint32_t)EAX; | ||
| 1925 | 1883 | ||
| 1884 | + helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0); | ||
| 1885 | + | ||
| 1886 | + index = (uint32_t)EAX; | ||
| 1926 | /* test if maximum index reached */ | 1887 | /* test if maximum index reached */ |
| 1927 | if (index & 0x80000000) { | 1888 | if (index & 0x80000000) { |
| 1928 | if (index > env->cpuid_xlevel) | 1889 | if (index > env->cpuid_xlevel) |
| @@ -2957,9 +2918,35 @@ void helper_sysexit(void) | @@ -2957,9 +2918,35 @@ void helper_sysexit(void) | ||
| 2957 | #endif | 2918 | #endif |
| 2958 | } | 2919 | } |
| 2959 | 2920 | ||
| 2960 | -void helper_movl_crN_T0(int reg, target_ulong t0) | 2921 | +#if defined(CONFIG_USER_ONLY) |
| 2922 | +target_ulong helper_read_crN(int reg) | ||
| 2961 | { | 2923 | { |
| 2962 | -#if !defined(CONFIG_USER_ONLY) | 2924 | + return 0; |
| 2925 | +} | ||
| 2926 | + | ||
| 2927 | +void helper_write_crN(int reg, target_ulong t0) | ||
| 2928 | +{ | ||
| 2929 | +} | ||
| 2930 | +#else | ||
| 2931 | +target_ulong helper_read_crN(int reg) | ||
| 2932 | +{ | ||
| 2933 | + target_ulong val; | ||
| 2934 | + | ||
| 2935 | + helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0); | ||
| 2936 | + switch(reg) { | ||
| 2937 | + default: | ||
| 2938 | + val = env->cr[reg]; | ||
| 2939 | + break; | ||
| 2940 | + case 8: | ||
| 2941 | + val = cpu_get_apic_tpr(env); | ||
| 2942 | + break; | ||
| 2943 | + } | ||
| 2944 | + return val; | ||
| 2945 | +} | ||
| 2946 | + | ||
| 2947 | +void helper_write_crN(int reg, target_ulong t0) | ||
| 2948 | +{ | ||
| 2949 | + helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0); | ||
| 2963 | switch(reg) { | 2950 | switch(reg) { |
| 2964 | case 0: | 2951 | case 0: |
| 2965 | cpu_x86_update_cr0(env, t0); | 2952 | cpu_x86_update_cr0(env, t0); |
| @@ -2978,15 +2965,15 @@ void helper_movl_crN_T0(int reg, target_ulong t0) | @@ -2978,15 +2965,15 @@ void helper_movl_crN_T0(int reg, target_ulong t0) | ||
| 2978 | env->cr[reg] = t0; | 2965 | env->cr[reg] = t0; |
| 2979 | break; | 2966 | break; |
| 2980 | } | 2967 | } |
| 2981 | -#endif | ||
| 2982 | } | 2968 | } |
| 2969 | +#endif | ||
| 2983 | 2970 | ||
| 2984 | void helper_lmsw(target_ulong t0) | 2971 | void helper_lmsw(target_ulong t0) |
| 2985 | { | 2972 | { |
| 2986 | /* only 4 lower bits of CR0 are modified. PE cannot be set to zero | 2973 | /* only 4 lower bits of CR0 are modified. PE cannot be set to zero |
| 2987 | if already set to one. */ | 2974 | if already set to one. */ |
| 2988 | t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); | 2975 | t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); |
| 2989 | - helper_movl_crN_T0(0, t0); | 2976 | + helper_write_crN(0, t0); |
| 2990 | } | 2977 | } |
| 2991 | 2978 | ||
| 2992 | void helper_clts(void) | 2979 | void helper_clts(void) |
| @@ -3010,6 +2997,7 @@ void helper_movl_drN_T0(int reg, target_ulong t0) | @@ -3010,6 +2997,7 @@ void helper_movl_drN_T0(int reg, target_ulong t0) | ||
| 3010 | 2997 | ||
| 3011 | void helper_invlpg(target_ulong addr) | 2998 | void helper_invlpg(target_ulong addr) |
| 3012 | { | 2999 | { |
| 3000 | + helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0); | ||
| 3013 | cpu_x86_flush_tlb(env, addr); | 3001 | cpu_x86_flush_tlb(env, addr); |
| 3014 | } | 3002 | } |
| 3015 | 3003 | ||
| @@ -3020,6 +3008,8 @@ void helper_rdtsc(void) | @@ -3020,6 +3008,8 @@ void helper_rdtsc(void) | ||
| 3020 | if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { | 3008 | if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { |
| 3021 | raise_exception(EXCP0D_GPF); | 3009 | raise_exception(EXCP0D_GPF); |
| 3022 | } | 3010 | } |
| 3011 | + helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0); | ||
| 3012 | + | ||
| 3023 | val = cpu_get_tsc(env); | 3013 | val = cpu_get_tsc(env); |
| 3024 | EAX = (uint32_t)(val); | 3014 | EAX = (uint32_t)(val); |
| 3025 | EDX = (uint32_t)(val >> 32); | 3015 | EDX = (uint32_t)(val >> 32); |
| @@ -3030,7 +3020,6 @@ void helper_rdpmc(void) | @@ -3030,7 +3020,6 @@ void helper_rdpmc(void) | ||
| 3030 | if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { | 3020 | if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { |
| 3031 | raise_exception(EXCP0D_GPF); | 3021 | raise_exception(EXCP0D_GPF); |
| 3032 | } | 3022 | } |
| 3033 | - | ||
| 3034 | helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0); | 3023 | helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0); |
| 3035 | 3024 | ||
| 3036 | /* currently unimplemented */ | 3025 | /* currently unimplemented */ |
| @@ -3050,6 +3039,8 @@ void helper_wrmsr(void) | @@ -3050,6 +3039,8 @@ void helper_wrmsr(void) | ||
| 3050 | { | 3039 | { |
| 3051 | uint64_t val; | 3040 | uint64_t val; |
| 3052 | 3041 | ||
| 3042 | + helper_svm_check_intercept_param(SVM_EXIT_MSR, 1); | ||
| 3043 | + | ||
| 3053 | val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); | 3044 | val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); |
| 3054 | 3045 | ||
| 3055 | switch((uint32_t)ECX) { | 3046 | switch((uint32_t)ECX) { |
| @@ -3119,6 +3110,9 @@ void helper_wrmsr(void) | @@ -3119,6 +3110,9 @@ void helper_wrmsr(void) | ||
| 3119 | void helper_rdmsr(void) | 3110 | void helper_rdmsr(void) |
| 3120 | { | 3111 | { |
| 3121 | uint64_t val; | 3112 | uint64_t val; |
| 3113 | + | ||
| 3114 | + helper_svm_check_intercept_param(SVM_EXIT_MSR, 0); | ||
| 3115 | + | ||
| 3122 | switch((uint32_t)ECX) { | 3116 | switch((uint32_t)ECX) { |
| 3123 | case MSR_IA32_SYSENTER_CS: | 3117 | case MSR_IA32_SYSENTER_CS: |
| 3124 | val = env->sysenter_cs; | 3118 | val = env->sysenter_cs; |
| @@ -4549,6 +4543,8 @@ void helper_idivq_EAX(target_ulong t0) | @@ -4549,6 +4543,8 @@ void helper_idivq_EAX(target_ulong t0) | ||
| 4549 | 4543 | ||
| 4550 | void helper_hlt(void) | 4544 | void helper_hlt(void) |
| 4551 | { | 4545 | { |
| 4546 | + helper_svm_check_intercept_param(SVM_EXIT_HLT, 0); | ||
| 4547 | + | ||
| 4552 | env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ | 4548 | env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ |
| 4553 | env->hflags |= HF_HALTED_MASK; | 4549 | env->hflags |= HF_HALTED_MASK; |
| 4554 | env->exception_index = EXCP_HLT; | 4550 | env->exception_index = EXCP_HLT; |
| @@ -4560,12 +4556,14 @@ void helper_monitor(target_ulong ptr) | @@ -4560,12 +4556,14 @@ void helper_monitor(target_ulong ptr) | ||
| 4560 | if ((uint32_t)ECX != 0) | 4556 | if ((uint32_t)ECX != 0) |
| 4561 | raise_exception(EXCP0D_GPF); | 4557 | raise_exception(EXCP0D_GPF); |
| 4562 | /* XXX: store address ? */ | 4558 | /* XXX: store address ? */ |
| 4559 | + helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0); | ||
| 4563 | } | 4560 | } |
| 4564 | 4561 | ||
| 4565 | void helper_mwait(void) | 4562 | void helper_mwait(void) |
| 4566 | { | 4563 | { |
| 4567 | if ((uint32_t)ECX != 0) | 4564 | if ((uint32_t)ECX != 0) |
| 4568 | raise_exception(EXCP0D_GPF); | 4565 | raise_exception(EXCP0D_GPF); |
| 4566 | + helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0); | ||
| 4569 | /* XXX: not complete but not completely erroneous */ | 4567 | /* XXX: not complete but not completely erroneous */ |
| 4570 | if (env->cpu_index != 0 || env->next_cpu != NULL) { | 4568 | if (env->cpu_index != 0 || env->next_cpu != NULL) { |
| 4571 | /* more than one CPU: do not sleep because another CPU may | 4569 | /* more than one CPU: do not sleep because another CPU may |
| @@ -4706,10 +4704,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) | @@ -4706,10 +4704,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) | ||
| 4706 | cpu_restore_state(tb, env, pc, NULL); | 4704 | cpu_restore_state(tb, env, pc, NULL); |
| 4707 | } | 4705 | } |
| 4708 | } | 4706 | } |
| 4709 | - if (retaddr) | ||
| 4710 | - raise_exception_err(env->exception_index, env->error_code); | ||
| 4711 | - else | ||
| 4712 | - raise_exception_err_norestore(env->exception_index, env->error_code); | 4707 | + raise_exception_err(env->exception_index, env->error_code); |
| 4713 | } | 4708 | } |
| 4714 | env = saved_env; | 4709 | env = saved_env; |
| 4715 | } | 4710 | } |
| @@ -4717,16 +4712,6 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) | @@ -4717,16 +4712,6 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) | ||
| 4717 | 4712 | ||
| 4718 | /* Secure Virtual Machine helpers */ | 4713 | /* Secure Virtual Machine helpers */ |
| 4719 | 4714 | ||
| 4720 | -void helper_stgi(void) | ||
| 4721 | -{ | ||
| 4722 | - env->hflags |= HF_GIF_MASK; | ||
| 4723 | -} | ||
| 4724 | - | ||
| 4725 | -void helper_clgi(void) | ||
| 4726 | -{ | ||
| 4727 | - env->hflags &= ~HF_GIF_MASK; | ||
| 4728 | -} | ||
| 4729 | - | ||
| 4730 | #if defined(CONFIG_USER_ONLY) | 4715 | #if defined(CONFIG_USER_ONLY) |
| 4731 | 4716 | ||
| 4732 | void helper_vmrun(void) | 4717 | void helper_vmrun(void) |
| @@ -4741,6 +4726,12 @@ void helper_vmload(void) | @@ -4741,6 +4726,12 @@ void helper_vmload(void) | ||
| 4741 | void helper_vmsave(void) | 4726 | void helper_vmsave(void) |
| 4742 | { | 4727 | { |
| 4743 | } | 4728 | } |
| 4729 | +void helper_stgi(void) | ||
| 4730 | +{ | ||
| 4731 | +} | ||
| 4732 | +void helper_clgi(void) | ||
| 4733 | +{ | ||
| 4734 | +} | ||
| 4744 | void helper_skinit(void) | 4735 | void helper_skinit(void) |
| 4745 | { | 4736 | { |
| 4746 | } | 4737 | } |
| @@ -4760,20 +4751,37 @@ void helper_svm_check_io(uint32_t port, uint32_t param, | @@ -4760,20 +4751,37 @@ void helper_svm_check_io(uint32_t port, uint32_t param, | ||
| 4760 | } | 4751 | } |
| 4761 | #else | 4752 | #else |
| 4762 | 4753 | ||
| 4763 | -static inline uint32_t | ||
| 4764 | -vmcb2cpu_attrib(uint16_t vmcb_attrib, uint32_t vmcb_base, uint32_t vmcb_limit) | 4754 | +static inline void svm_save_seg(target_phys_addr_t addr, |
| 4755 | + const SegmentCache *sc) | ||
| 4765 | { | 4756 | { |
| 4766 | - return ((vmcb_attrib & 0x00ff) << 8) /* Type, S, DPL, P */ | ||
| 4767 | - | ((vmcb_attrib & 0x0f00) << 12) /* AVL, L, DB, G */ | ||
| 4768 | - | ((vmcb_base >> 16) & 0xff) /* Base 23-16 */ | ||
| 4769 | - | (vmcb_base & 0xff000000) /* Base 31-24 */ | ||
| 4770 | - | (vmcb_limit & 0xf0000); /* Limit 19-16 */ | 4757 | + stw_phys(addr + offsetof(struct vmcb_seg, selector), |
| 4758 | + sc->selector); | ||
| 4759 | + stq_phys(addr + offsetof(struct vmcb_seg, base), | ||
| 4760 | + sc->base); | ||
| 4761 | + stl_phys(addr + offsetof(struct vmcb_seg, limit), | ||
| 4762 | + sc->limit); | ||
| 4763 | + stw_phys(addr + offsetof(struct vmcb_seg, attrib), | ||
| 4764 | + (sc->flags >> 8) | ((sc->flags >> 12) & 0x0f00)); | ||
| 4765 | +} | ||
| 4766 | + | ||
| 4767 | +static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc) | ||
| 4768 | +{ | ||
| 4769 | + unsigned int flags; | ||
| 4770 | + | ||
| 4771 | + sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector)); | ||
| 4772 | + sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base)); | ||
| 4773 | + sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit)); | ||
| 4774 | + flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib)); | ||
| 4775 | + sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12); | ||
| 4771 | } | 4776 | } |
| 4772 | 4777 | ||
| 4773 | -static inline uint16_t cpu2vmcb_attrib(uint32_t cpu_attrib) | 4778 | +static inline void svm_load_seg_cache(target_phys_addr_t addr, |
| 4779 | + CPUState *env, int seg_reg) | ||
| 4774 | { | 4780 | { |
| 4775 | - return ((cpu_attrib >> 8) & 0xff) /* Type, S, DPL, P */ | ||
| 4776 | - | ((cpu_attrib & 0xf00000) >> 12); /* AVL, L, DB, G */ | 4781 | + SegmentCache sc1, *sc = &sc1; |
| 4782 | + svm_load_seg(addr, sc); | ||
| 4783 | + cpu_x86_load_seg_cache(env, seg_reg, sc->selector, | ||
| 4784 | + sc->base, sc->limit, sc->flags); | ||
| 4777 | } | 4785 | } |
| 4778 | 4786 | ||
| 4779 | void helper_vmrun(void) | 4787 | void helper_vmrun(void) |
| @@ -4782,6 +4790,8 @@ void helper_vmrun(void) | @@ -4782,6 +4790,8 @@ void helper_vmrun(void) | ||
| 4782 | uint32_t event_inj; | 4790 | uint32_t event_inj; |
| 4783 | uint32_t int_ctl; | 4791 | uint32_t int_ctl; |
| 4784 | 4792 | ||
| 4793 | + helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0); | ||
| 4794 | + | ||
| 4785 | addr = EAX; | 4795 | addr = EAX; |
| 4786 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4796 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4787 | fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr); | 4797 | fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr); |
| @@ -4806,10 +4816,14 @@ void helper_vmrun(void) | @@ -4806,10 +4816,14 @@ void helper_vmrun(void) | ||
| 4806 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer); | 4816 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer); |
| 4807 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags()); | 4817 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags()); |
| 4808 | 4818 | ||
| 4809 | - SVM_SAVE_SEG(env->vm_hsave, segs[R_ES], es); | ||
| 4810 | - SVM_SAVE_SEG(env->vm_hsave, segs[R_CS], cs); | ||
| 4811 | - SVM_SAVE_SEG(env->vm_hsave, segs[R_SS], ss); | ||
| 4812 | - SVM_SAVE_SEG(env->vm_hsave, segs[R_DS], ds); | 4819 | + svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), |
| 4820 | + &env->segs[R_ES]); | ||
| 4821 | + svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), | ||
| 4822 | + &env->segs[R_CS]); | ||
| 4823 | + svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), | ||
| 4824 | + &env->segs[R_SS]); | ||
| 4825 | + svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), | ||
| 4826 | + &env->segs[R_DS]); | ||
| 4813 | 4827 | ||
| 4814 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP); | 4828 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP); |
| 4815 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP); | 4829 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP); |
| @@ -4817,15 +4831,16 @@ void helper_vmrun(void) | @@ -4817,15 +4831,16 @@ void helper_vmrun(void) | ||
| 4817 | 4831 | ||
| 4818 | /* load the interception bitmaps so we do not need to access the | 4832 | /* load the interception bitmaps so we do not need to access the |
| 4819 | vmcb in svm mode */ | 4833 | vmcb in svm mode */ |
| 4820 | - /* We shift all the intercept bits so we can OR them with the TB | ||
| 4821 | - flags later on */ | ||
| 4822 | - env->intercept = (ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)) << INTERCEPT_INTR) | INTERCEPT_SVM_MASK; | 4834 | + env->intercept = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)); |
| 4823 | env->intercept_cr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read)); | 4835 | env->intercept_cr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read)); |
| 4824 | env->intercept_cr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write)); | 4836 | env->intercept_cr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write)); |
| 4825 | env->intercept_dr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read)); | 4837 | env->intercept_dr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read)); |
| 4826 | env->intercept_dr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write)); | 4838 | env->intercept_dr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write)); |
| 4827 | env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions)); | 4839 | env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions)); |
| 4828 | 4840 | ||
| 4841 | + /* enable intercepts */ | ||
| 4842 | + env->hflags |= HF_SVMI_MASK; | ||
| 4843 | + | ||
| 4829 | env->gdt.base = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base)); | 4844 | env->gdt.base = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base)); |
| 4830 | env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit)); | 4845 | env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit)); |
| 4831 | 4846 | ||
| @@ -4857,12 +4872,15 @@ void helper_vmrun(void) | @@ -4857,12 +4872,15 @@ void helper_vmrun(void) | ||
| 4857 | load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)), | 4872 | load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)), |
| 4858 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); | 4873 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
| 4859 | CC_OP = CC_OP_EFLAGS; | 4874 | CC_OP = CC_OP_EFLAGS; |
| 4860 | - CC_DST = 0xffffffff; | ||
| 4861 | 4875 | ||
| 4862 | - SVM_LOAD_SEG(env->vm_vmcb, ES, es); | ||
| 4863 | - SVM_LOAD_SEG(env->vm_vmcb, CS, cs); | ||
| 4864 | - SVM_LOAD_SEG(env->vm_vmcb, SS, ss); | ||
| 4865 | - SVM_LOAD_SEG(env->vm_vmcb, DS, ds); | 4876 | + svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es), |
| 4877 | + env, R_ES); | ||
| 4878 | + svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs), | ||
| 4879 | + env, R_CS); | ||
| 4880 | + svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss), | ||
| 4881 | + env, R_SS); | ||
| 4882 | + svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds), | ||
| 4883 | + env, R_DS); | ||
| 4866 | 4884 | ||
| 4867 | EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip)); | 4885 | EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip)); |
| 4868 | env->eip = EIP; | 4886 | env->eip = EIP; |
| @@ -4933,7 +4951,8 @@ void helper_vmrun(void) | @@ -4933,7 +4951,8 @@ void helper_vmrun(void) | ||
| 4933 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4951 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4934 | fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); | 4952 | fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); |
| 4935 | } | 4953 | } |
| 4936 | - if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) { | 4954 | + if ((int_ctl & V_IRQ_MASK) || |
| 4955 | + (env->intercept & (1ULL << (SVM_EXIT_INTR - SVM_EXIT_INTR)))) { | ||
| 4937 | env->interrupt_request |= CPU_INTERRUPT_VIRQ; | 4956 | env->interrupt_request |= CPU_INTERRUPT_VIRQ; |
| 4938 | } | 4957 | } |
| 4939 | 4958 | ||
| @@ -4942,23 +4961,30 @@ void helper_vmrun(void) | @@ -4942,23 +4961,30 @@ void helper_vmrun(void) | ||
| 4942 | 4961 | ||
| 4943 | void helper_vmmcall(void) | 4962 | void helper_vmmcall(void) |
| 4944 | { | 4963 | { |
| 4945 | - if (loglevel & CPU_LOG_TB_IN_ASM) | ||
| 4946 | - fprintf(logfile,"vmmcall!\n"); | 4964 | + helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0); |
| 4965 | + raise_exception(EXCP06_ILLOP); | ||
| 4947 | } | 4966 | } |
| 4948 | 4967 | ||
| 4949 | void helper_vmload(void) | 4968 | void helper_vmload(void) |
| 4950 | { | 4969 | { |
| 4951 | target_ulong addr; | 4970 | target_ulong addr; |
| 4971 | + helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0); | ||
| 4972 | + | ||
| 4973 | + /* XXX: invalid in 32 bit */ | ||
| 4952 | addr = EAX; | 4974 | addr = EAX; |
| 4953 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4975 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4954 | fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", | 4976 | fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", |
| 4955 | addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), | 4977 | addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), |
| 4956 | env->segs[R_FS].base); | 4978 | env->segs[R_FS].base); |
| 4957 | 4979 | ||
| 4958 | - SVM_LOAD_SEG2(addr, segs[R_FS], fs); | ||
| 4959 | - SVM_LOAD_SEG2(addr, segs[R_GS], gs); | ||
| 4960 | - SVM_LOAD_SEG2(addr, tr, tr); | ||
| 4961 | - SVM_LOAD_SEG2(addr, ldt, ldtr); | 4980 | + svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs), |
| 4981 | + env, R_FS); | ||
| 4982 | + svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs), | ||
| 4983 | + env, R_GS); | ||
| 4984 | + svm_load_seg(addr + offsetof(struct vmcb, save.tr), | ||
| 4985 | + &env->tr); | ||
| 4986 | + svm_load_seg(addr + offsetof(struct vmcb, save.ldtr), | ||
| 4987 | + &env->ldt); | ||
| 4962 | 4988 | ||
| 4963 | #ifdef TARGET_X86_64 | 4989 | #ifdef TARGET_X86_64 |
| 4964 | env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base)); | 4990 | env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base)); |
| @@ -4975,16 +5001,21 @@ void helper_vmload(void) | @@ -4975,16 +5001,21 @@ void helper_vmload(void) | ||
| 4975 | void helper_vmsave(void) | 5001 | void helper_vmsave(void) |
| 4976 | { | 5002 | { |
| 4977 | target_ulong addr; | 5003 | target_ulong addr; |
| 5004 | + helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0); | ||
| 4978 | addr = EAX; | 5005 | addr = EAX; |
| 4979 | if (loglevel & CPU_LOG_TB_IN_ASM) | 5006 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4980 | fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", | 5007 | fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", |
| 4981 | addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), | 5008 | addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), |
| 4982 | env->segs[R_FS].base); | 5009 | env->segs[R_FS].base); |
| 4983 | 5010 | ||
| 4984 | - SVM_SAVE_SEG(addr, segs[R_FS], fs); | ||
| 4985 | - SVM_SAVE_SEG(addr, segs[R_GS], gs); | ||
| 4986 | - SVM_SAVE_SEG(addr, tr, tr); | ||
| 4987 | - SVM_SAVE_SEG(addr, ldt, ldtr); | 5011 | + svm_save_seg(addr + offsetof(struct vmcb, save.fs), |
| 5012 | + &env->segs[R_FS]); | ||
| 5013 | + svm_save_seg(addr + offsetof(struct vmcb, save.gs), | ||
| 5014 | + &env->segs[R_GS]); | ||
| 5015 | + svm_save_seg(addr + offsetof(struct vmcb, save.tr), | ||
| 5016 | + &env->tr); | ||
| 5017 | + svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), | ||
| 5018 | + &env->ldt); | ||
| 4988 | 5019 | ||
| 4989 | #ifdef TARGET_X86_64 | 5020 | #ifdef TARGET_X86_64 |
| 4990 | stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase); | 5021 | stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase); |
| @@ -4998,50 +5029,65 @@ void helper_vmsave(void) | @@ -4998,50 +5029,65 @@ void helper_vmsave(void) | ||
| 4998 | stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip); | 5029 | stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip); |
| 4999 | } | 5030 | } |
| 5000 | 5031 | ||
| 5032 | +void helper_stgi(void) | ||
| 5033 | +{ | ||
| 5034 | + helper_svm_check_intercept_param(SVM_EXIT_STGI, 0); | ||
| 5035 | + env->hflags |= HF_GIF_MASK; | ||
| 5036 | +} | ||
| 5037 | + | ||
| 5038 | +void helper_clgi(void) | ||
| 5039 | +{ | ||
| 5040 | + helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0); | ||
| 5041 | + env->hflags &= ~HF_GIF_MASK; | ||
| 5042 | +} | ||
| 5043 | + | ||
| 5001 | void helper_skinit(void) | 5044 | void helper_skinit(void) |
| 5002 | { | 5045 | { |
| 5046 | + helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0); | ||
| 5047 | + /* XXX: not implemented */ | ||
| 5003 | if (loglevel & CPU_LOG_TB_IN_ASM) | 5048 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 5004 | fprintf(logfile,"skinit!\n"); | 5049 | fprintf(logfile,"skinit!\n"); |
| 5050 | + raise_exception(EXCP06_ILLOP); | ||
| 5005 | } | 5051 | } |
| 5006 | 5052 | ||
| 5007 | void helper_invlpga(void) | 5053 | void helper_invlpga(void) |
| 5008 | { | 5054 | { |
| 5055 | + helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0); | ||
| 5009 | tlb_flush(env, 0); | 5056 | tlb_flush(env, 0); |
| 5010 | } | 5057 | } |
| 5011 | 5058 | ||
| 5012 | void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | 5059 | void helper_svm_check_intercept_param(uint32_t type, uint64_t param) |
| 5013 | { | 5060 | { |
| 5061 | + if (likely(!(env->hflags & HF_SVMI_MASK))) | ||
| 5062 | + return; | ||
| 5014 | switch(type) { | 5063 | switch(type) { |
| 5015 | case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8: | 5064 | case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8: |
| 5016 | - if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) { | 5065 | + if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) { |
| 5017 | helper_vmexit(type, param); | 5066 | helper_vmexit(type, param); |
| 5018 | } | 5067 | } |
| 5019 | break; | 5068 | break; |
| 5020 | - case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8: | ||
| 5021 | - if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) { | 5069 | + case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8: |
| 5070 | + if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) { | ||
| 5022 | helper_vmexit(type, param); | 5071 | helper_vmexit(type, param); |
| 5023 | } | 5072 | } |
| 5024 | break; | 5073 | break; |
| 5025 | - case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8: | ||
| 5026 | - if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) { | 5074 | + case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7: |
| 5075 | + if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) { | ||
| 5027 | helper_vmexit(type, param); | 5076 | helper_vmexit(type, param); |
| 5028 | } | 5077 | } |
| 5029 | break; | 5078 | break; |
| 5030 | - case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8: | ||
| 5031 | - if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) { | 5079 | + case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7: |
| 5080 | + if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) { | ||
| 5032 | helper_vmexit(type, param); | 5081 | helper_vmexit(type, param); |
| 5033 | } | 5082 | } |
| 5034 | break; | 5083 | break; |
| 5035 | - case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16: | ||
| 5036 | - if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) { | 5084 | + case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31: |
| 5085 | + if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) { | ||
| 5037 | helper_vmexit(type, param); | 5086 | helper_vmexit(type, param); |
| 5038 | } | 5087 | } |
| 5039 | break; | 5088 | break; |
| 5040 | - case SVM_EXIT_IOIO: | ||
| 5041 | - break; | ||
| 5042 | - | ||
| 5043 | case SVM_EXIT_MSR: | 5089 | case SVM_EXIT_MSR: |
| 5044 | - if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) { | 5090 | + if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) { |
| 5045 | /* FIXME: this should be read in at vmrun (faster this way?) */ | 5091 | /* FIXME: this should be read in at vmrun (faster this way?) */ |
| 5046 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa)); | 5092 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa)); |
| 5047 | uint32_t t0, t1; | 5093 | uint32_t t0, t1; |
| @@ -5071,7 +5117,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | @@ -5071,7 +5117,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | ||
| 5071 | } | 5117 | } |
| 5072 | break; | 5118 | break; |
| 5073 | default: | 5119 | default: |
| 5074 | - if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) { | 5120 | + if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) { |
| 5075 | helper_vmexit(type, param); | 5121 | helper_vmexit(type, param); |
| 5076 | } | 5122 | } |
| 5077 | break; | 5123 | break; |
| @@ -5081,7 +5127,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | @@ -5081,7 +5127,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | ||
| 5081 | void helper_svm_check_io(uint32_t port, uint32_t param, | 5127 | void helper_svm_check_io(uint32_t port, uint32_t param, |
| 5082 | uint32_t next_eip_addend) | 5128 | uint32_t next_eip_addend) |
| 5083 | { | 5129 | { |
| 5084 | - if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) { | 5130 | + if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) { |
| 5085 | /* FIXME: this should be read in at vmrun (faster this way?) */ | 5131 | /* FIXME: this should be read in at vmrun (faster this way?) */ |
| 5086 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); | 5132 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); |
| 5087 | uint16_t mask = (1 << ((param >> 4) & 7)) - 1; | 5133 | uint16_t mask = (1 << ((param >> 4) & 7)) - 1; |
| @@ -5113,10 +5159,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5113,10 +5159,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5113 | } | 5159 | } |
| 5114 | 5160 | ||
| 5115 | /* Save the VM state in the vmcb */ | 5161 | /* Save the VM state in the vmcb */ |
| 5116 | - SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es); | ||
| 5117 | - SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs); | ||
| 5118 | - SVM_SAVE_SEG(env->vm_vmcb, segs[R_SS], ss); | ||
| 5119 | - SVM_SAVE_SEG(env->vm_vmcb, segs[R_DS], ds); | 5162 | + svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), |
| 5163 | + &env->segs[R_ES]); | ||
| 5164 | + svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), | ||
| 5165 | + &env->segs[R_CS]); | ||
| 5166 | + svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), | ||
| 5167 | + &env->segs[R_SS]); | ||
| 5168 | + svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), | ||
| 5169 | + &env->segs[R_DS]); | ||
| 5120 | 5170 | ||
| 5121 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base); | 5171 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base); |
| 5122 | stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit); | 5172 | stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit); |
| @@ -5146,6 +5196,7 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5146,6 +5196,7 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5146 | 5196 | ||
| 5147 | /* Reload the host state from vm_hsave */ | 5197 | /* Reload the host state from vm_hsave */ |
| 5148 | env->hflags &= ~HF_HIF_MASK; | 5198 | env->hflags &= ~HF_HIF_MASK; |
| 5199 | + env->hflags &= ~HF_SVMI_MASK; | ||
| 5149 | env->intercept = 0; | 5200 | env->intercept = 0; |
| 5150 | env->intercept_exceptions = 0; | 5201 | env->intercept_exceptions = 0; |
| 5151 | env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; | 5202 | env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; |
| @@ -5169,6 +5220,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5169,6 +5220,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5169 | env->hflags &= ~HF_LMA_MASK; | 5220 | env->hflags &= ~HF_LMA_MASK; |
| 5170 | if (env->efer & MSR_EFER_LMA) | 5221 | if (env->efer & MSR_EFER_LMA) |
| 5171 | env->hflags |= HF_LMA_MASK; | 5222 | env->hflags |= HF_LMA_MASK; |
| 5223 | + /* XXX: should also emulate the VM_CR MSR */ | ||
| 5224 | + env->hflags &= ~HF_SVME_MASK; | ||
| 5225 | + if (env->cpuid_ext3_features & CPUID_EXT3_SVM) { | ||
| 5226 | + if (env->efer & MSR_EFER_SVME) | ||
| 5227 | + env->hflags |= HF_SVME_MASK; | ||
| 5228 | + } else { | ||
| 5229 | + env->efer &= ~MSR_EFER_SVME; | ||
| 5230 | + } | ||
| 5172 | #endif | 5231 | #endif |
| 5173 | 5232 | ||
| 5174 | env->eflags = 0; | 5233 | env->eflags = 0; |
| @@ -5176,10 +5235,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5176,10 +5235,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5176 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); | 5235 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
| 5177 | CC_OP = CC_OP_EFLAGS; | 5236 | CC_OP = CC_OP_EFLAGS; |
| 5178 | 5237 | ||
| 5179 | - SVM_LOAD_SEG(env->vm_hsave, ES, es); | ||
| 5180 | - SVM_LOAD_SEG(env->vm_hsave, CS, cs); | ||
| 5181 | - SVM_LOAD_SEG(env->vm_hsave, SS, ss); | ||
| 5182 | - SVM_LOAD_SEG(env->vm_hsave, DS, ds); | 5238 | + svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es), |
| 5239 | + env, R_ES); | ||
| 5240 | + svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs), | ||
| 5241 | + env, R_CS); | ||
| 5242 | + svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss), | ||
| 5243 | + env, R_SS); | ||
| 5244 | + svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds), | ||
| 5245 | + env, R_DS); | ||
| 5183 | 5246 | ||
| 5184 | EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip)); | 5247 | EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip)); |
| 5185 | ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp)); | 5248 | ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp)); |
target-i386/svm.h
| 1 | #ifndef __SVM_H | 1 | #ifndef __SVM_H |
| 2 | #define __SVM_H | 2 | #define __SVM_H |
| 3 | 3 | ||
| 4 | -enum { | ||
| 5 | - /* We shift all the intercept bits so we can OR them with the | ||
| 6 | - TB flags later on */ | ||
| 7 | - INTERCEPT_INTR = HF_HIF_SHIFT, | ||
| 8 | - INTERCEPT_NMI, | ||
| 9 | - INTERCEPT_SMI, | ||
| 10 | - INTERCEPT_INIT, | ||
| 11 | - INTERCEPT_VINTR, | ||
| 12 | - INTERCEPT_SELECTIVE_CR0, | ||
| 13 | - INTERCEPT_STORE_IDTR, | ||
| 14 | - INTERCEPT_STORE_GDTR, | ||
| 15 | - INTERCEPT_STORE_LDTR, | ||
| 16 | - INTERCEPT_STORE_TR, | ||
| 17 | - INTERCEPT_LOAD_IDTR, | ||
| 18 | - INTERCEPT_LOAD_GDTR, | ||
| 19 | - INTERCEPT_LOAD_LDTR, | ||
| 20 | - INTERCEPT_LOAD_TR, | ||
| 21 | - INTERCEPT_RDTSC, | ||
| 22 | - INTERCEPT_RDPMC, | ||
| 23 | - INTERCEPT_PUSHF, | ||
| 24 | - INTERCEPT_POPF, | ||
| 25 | - INTERCEPT_CPUID, | ||
| 26 | - INTERCEPT_RSM, | ||
| 27 | - INTERCEPT_IRET, | ||
| 28 | - INTERCEPT_INTn, | ||
| 29 | - INTERCEPT_INVD, | ||
| 30 | - INTERCEPT_PAUSE, | ||
| 31 | - INTERCEPT_HLT, | ||
| 32 | - INTERCEPT_INVLPG, | ||
| 33 | - INTERCEPT_INVLPGA, | ||
| 34 | - INTERCEPT_IOIO_PROT, | ||
| 35 | - INTERCEPT_MSR_PROT, | ||
| 36 | - INTERCEPT_TASK_SWITCH, | ||
| 37 | - INTERCEPT_FERR_FREEZE, | ||
| 38 | - INTERCEPT_SHUTDOWN, | ||
| 39 | - INTERCEPT_VMRUN, | ||
| 40 | - INTERCEPT_VMMCALL, | ||
| 41 | - INTERCEPT_VMLOAD, | ||
| 42 | - INTERCEPT_VMSAVE, | ||
| 43 | - INTERCEPT_STGI, | ||
| 44 | - INTERCEPT_CLGI, | ||
| 45 | - INTERCEPT_SKINIT, | ||
| 46 | - INTERCEPT_RDTSCP, | ||
| 47 | - INTERCEPT_ICEBP, | ||
| 48 | - INTERCEPT_WBINVD, | ||
| 49 | -}; | ||
| 50 | -/* This is not really an intercept but rather a placeholder to | ||
| 51 | - show that we are in an SVM (just like a hidden flag, but keeps the | ||
| 52 | - TBs clean) */ | ||
| 53 | -#define INTERCEPT_SVM 63 | ||
| 54 | -#define INTERCEPT_SVM_MASK (1ULL << INTERCEPT_SVM) | ||
| 55 | - | ||
| 56 | -struct __attribute__ ((__packed__)) vmcb_control_area { | ||
| 57 | - uint16_t intercept_cr_read; | ||
| 58 | - uint16_t intercept_cr_write; | ||
| 59 | - uint16_t intercept_dr_read; | ||
| 60 | - uint16_t intercept_dr_write; | ||
| 61 | - uint32_t intercept_exceptions; | ||
| 62 | - uint64_t intercept; | ||
| 63 | - uint8_t reserved_1[44]; | ||
| 64 | - uint64_t iopm_base_pa; | ||
| 65 | - uint64_t msrpm_base_pa; | ||
| 66 | - uint64_t tsc_offset; | ||
| 67 | - uint32_t asid; | ||
| 68 | - uint8_t tlb_ctl; | ||
| 69 | - uint8_t reserved_2[3]; | ||
| 70 | - uint32_t int_ctl; | ||
| 71 | - uint32_t int_vector; | ||
| 72 | - uint32_t int_state; | ||
| 73 | - uint8_t reserved_3[4]; | ||
| 74 | - uint64_t exit_code; | ||
| 75 | - uint64_t exit_info_1; | ||
| 76 | - uint64_t exit_info_2; | ||
| 77 | - uint32_t exit_int_info; | ||
| 78 | - uint32_t exit_int_info_err; | ||
| 79 | - uint64_t nested_ctl; | ||
| 80 | - uint8_t reserved_4[16]; | ||
| 81 | - uint32_t event_inj; | ||
| 82 | - uint32_t event_inj_err; | ||
| 83 | - uint64_t nested_cr3; | ||
| 84 | - uint64_t lbr_ctl; | ||
| 85 | - uint8_t reserved_5[832]; | ||
| 86 | -}; | ||
| 87 | - | ||
| 88 | - | ||
| 89 | #define TLB_CONTROL_DO_NOTHING 0 | 4 | #define TLB_CONTROL_DO_NOTHING 0 |
| 90 | #define TLB_CONTROL_FLUSH_ALL_ASID 1 | 5 | #define TLB_CONTROL_FLUSH_ALL_ASID 1 |
| 91 | 6 | ||
| @@ -116,104 +31,6 @@ struct __attribute__ ((__packed__)) vmcb_control_area { | @@ -116,104 +31,6 @@ struct __attribute__ ((__packed__)) vmcb_control_area { | ||
| 116 | #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) | 31 | #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) |
| 117 | #define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT) | 32 | #define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT) |
| 118 | 33 | ||
| 119 | -struct __attribute__ ((__packed__)) vmcb_seg { | ||
| 120 | - uint16_t selector; | ||
| 121 | - uint16_t attrib; | ||
| 122 | - uint32_t limit; | ||
| 123 | - uint64_t base; | ||
| 124 | -}; | ||
| 125 | - | ||
| 126 | -struct __attribute__ ((__packed__)) vmcb_save_area { | ||
| 127 | - struct vmcb_seg es; | ||
| 128 | - struct vmcb_seg cs; | ||
| 129 | - struct vmcb_seg ss; | ||
| 130 | - struct vmcb_seg ds; | ||
| 131 | - struct vmcb_seg fs; | ||
| 132 | - struct vmcb_seg gs; | ||
| 133 | - struct vmcb_seg gdtr; | ||
| 134 | - struct vmcb_seg ldtr; | ||
| 135 | - struct vmcb_seg idtr; | ||
| 136 | - struct vmcb_seg tr; | ||
| 137 | - uint8_t reserved_1[43]; | ||
| 138 | - uint8_t cpl; | ||
| 139 | - uint8_t reserved_2[4]; | ||
| 140 | - uint64_t efer; | ||
| 141 | - uint8_t reserved_3[112]; | ||
| 142 | - uint64_t cr4; | ||
| 143 | - uint64_t cr3; | ||
| 144 | - uint64_t cr0; | ||
| 145 | - uint64_t dr7; | ||
| 146 | - uint64_t dr6; | ||
| 147 | - uint64_t rflags; | ||
| 148 | - uint64_t rip; | ||
| 149 | - uint8_t reserved_4[88]; | ||
| 150 | - uint64_t rsp; | ||
| 151 | - uint8_t reserved_5[24]; | ||
| 152 | - uint64_t rax; | ||
| 153 | - uint64_t star; | ||
| 154 | - uint64_t lstar; | ||
| 155 | - uint64_t cstar; | ||
| 156 | - uint64_t sfmask; | ||
| 157 | - uint64_t kernel_gs_base; | ||
| 158 | - uint64_t sysenter_cs; | ||
| 159 | - uint64_t sysenter_esp; | ||
| 160 | - uint64_t sysenter_eip; | ||
| 161 | - uint64_t cr2; | ||
| 162 | - /* qemu: cr8 added to reuse this as hsave */ | ||
| 163 | - uint64_t cr8; | ||
| 164 | - uint8_t reserved_6[32 - 8]; /* originally 32 */ | ||
| 165 | - uint64_t g_pat; | ||
| 166 | - uint64_t dbgctl; | ||
| 167 | - uint64_t br_from; | ||
| 168 | - uint64_t br_to; | ||
| 169 | - uint64_t last_excp_from; | ||
| 170 | - uint64_t last_excp_to; | ||
| 171 | -}; | ||
| 172 | - | ||
| 173 | -struct __attribute__ ((__packed__)) vmcb { | ||
| 174 | - struct vmcb_control_area control; | ||
| 175 | - struct vmcb_save_area save; | ||
| 176 | -}; | ||
| 177 | - | ||
| 178 | -#define SVM_CPUID_FEATURE_SHIFT 2 | ||
| 179 | -#define SVM_CPUID_FUNC 0x8000000a | ||
| 180 | - | ||
| 181 | -#define MSR_EFER_SVME_MASK (1ULL << 12) | ||
| 182 | - | ||
| 183 | -#define SVM_SELECTOR_S_SHIFT 4 | ||
| 184 | -#define SVM_SELECTOR_DPL_SHIFT 5 | ||
| 185 | -#define SVM_SELECTOR_P_SHIFT 7 | ||
| 186 | -#define SVM_SELECTOR_AVL_SHIFT 8 | ||
| 187 | -#define SVM_SELECTOR_L_SHIFT 9 | ||
| 188 | -#define SVM_SELECTOR_DB_SHIFT 10 | ||
| 189 | -#define SVM_SELECTOR_G_SHIFT 11 | ||
| 190 | - | ||
| 191 | -#define SVM_SELECTOR_TYPE_MASK (0xf) | ||
| 192 | -#define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT) | ||
| 193 | -#define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT) | ||
| 194 | -#define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT) | ||
| 195 | -#define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT) | ||
| 196 | -#define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT) | ||
| 197 | -#define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT) | ||
| 198 | -#define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT) | ||
| 199 | - | ||
| 200 | -#define SVM_SELECTOR_WRITE_MASK (1 << 1) | ||
| 201 | -#define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK | ||
| 202 | -#define SVM_SELECTOR_CODE_MASK (1 << 3) | ||
| 203 | - | ||
| 204 | -#define INTERCEPT_CR0_MASK 1 | ||
| 205 | -#define INTERCEPT_CR3_MASK (1 << 3) | ||
| 206 | -#define INTERCEPT_CR4_MASK (1 << 4) | ||
| 207 | - | ||
| 208 | -#define INTERCEPT_DR0_MASK 1 | ||
| 209 | -#define INTERCEPT_DR1_MASK (1 << 1) | ||
| 210 | -#define INTERCEPT_DR2_MASK (1 << 2) | ||
| 211 | -#define INTERCEPT_DR3_MASK (1 << 3) | ||
| 212 | -#define INTERCEPT_DR4_MASK (1 << 4) | ||
| 213 | -#define INTERCEPT_DR5_MASK (1 << 5) | ||
| 214 | -#define INTERCEPT_DR6_MASK (1 << 6) | ||
| 215 | -#define INTERCEPT_DR7_MASK (1 << 7) | ||
| 216 | - | ||
| 217 | #define SVM_EVTINJ_VEC_MASK 0xff | 34 | #define SVM_EVTINJ_VEC_MASK 0xff |
| 218 | 35 | ||
| 219 | #define SVM_EVTINJ_TYPE_SHIFT 8 | 36 | #define SVM_EVTINJ_TYPE_SHIFT 8 |
| @@ -313,37 +130,95 @@ struct __attribute__ ((__packed__)) vmcb { | @@ -313,37 +130,95 @@ struct __attribute__ ((__packed__)) vmcb { | ||
| 313 | 130 | ||
| 314 | #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */ | 131 | #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */ |
| 315 | 132 | ||
| 316 | -#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" | ||
| 317 | -#define SVM_VMRUN ".byte 0x0f, 0x01, 0xd8" | ||
| 318 | -#define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb" | ||
| 319 | -#define SVM_CLGI ".byte 0x0f, 0x01, 0xdd" | ||
| 320 | -#define SVM_STGI ".byte 0x0f, 0x01, 0xdc" | ||
| 321 | -#define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf" | ||
| 322 | - | ||
| 323 | -/* function references */ | ||
| 324 | - | ||
| 325 | -#define INTERCEPTED(mask) (env->intercept & mask) | ||
| 326 | -#define INTERCEPTEDw(var, mask) (env->intercept ## var & mask) | ||
| 327 | -#define INTERCEPTEDl(var, mask) (env->intercept ## var & mask) | 133 | +struct __attribute__ ((__packed__)) vmcb_control_area { |
| 134 | + uint16_t intercept_cr_read; | ||
| 135 | + uint16_t intercept_cr_write; | ||
| 136 | + uint16_t intercept_dr_read; | ||
| 137 | + uint16_t intercept_dr_write; | ||
| 138 | + uint32_t intercept_exceptions; | ||
| 139 | + uint64_t intercept; | ||
| 140 | + uint8_t reserved_1[44]; | ||
| 141 | + uint64_t iopm_base_pa; | ||
| 142 | + uint64_t msrpm_base_pa; | ||
| 143 | + uint64_t tsc_offset; | ||
| 144 | + uint32_t asid; | ||
| 145 | + uint8_t tlb_ctl; | ||
| 146 | + uint8_t reserved_2[3]; | ||
| 147 | + uint32_t int_ctl; | ||
| 148 | + uint32_t int_vector; | ||
| 149 | + uint32_t int_state; | ||
| 150 | + uint8_t reserved_3[4]; | ||
| 151 | + uint64_t exit_code; | ||
| 152 | + uint64_t exit_info_1; | ||
| 153 | + uint64_t exit_info_2; | ||
| 154 | + uint32_t exit_int_info; | ||
| 155 | + uint32_t exit_int_info_err; | ||
| 156 | + uint64_t nested_ctl; | ||
| 157 | + uint8_t reserved_4[16]; | ||
| 158 | + uint32_t event_inj; | ||
| 159 | + uint32_t event_inj_err; | ||
| 160 | + uint64_t nested_cr3; | ||
| 161 | + uint64_t lbr_ctl; | ||
| 162 | + uint8_t reserved_5[832]; | ||
| 163 | +}; | ||
| 328 | 164 | ||
| 329 | -#define SVM_LOAD_SEG(addr, seg_index, seg) \ | ||
| 330 | - cpu_x86_load_seg_cache(env, \ | ||
| 331 | - R_##seg_index, \ | ||
| 332 | - lduw_phys(addr + offsetof(struct vmcb, save.seg.selector)),\ | ||
| 333 | - ldq_phys(addr + offsetof(struct vmcb, save.seg.base)),\ | ||
| 334 | - ldl_phys(addr + offsetof(struct vmcb, save.seg.limit)),\ | ||
| 335 | - vmcb2cpu_attrib(lduw_phys(addr + offsetof(struct vmcb, save.seg.attrib)), ldq_phys(addr + offsetof(struct vmcb, save.seg.base)), ldl_phys(addr + offsetof(struct vmcb, save.seg.limit)))) | 165 | +struct __attribute__ ((__packed__)) vmcb_seg { |
| 166 | + uint16_t selector; | ||
| 167 | + uint16_t attrib; | ||
| 168 | + uint32_t limit; | ||
| 169 | + uint64_t base; | ||
| 170 | +}; | ||
| 336 | 171 | ||
| 337 | -#define SVM_LOAD_SEG2(addr, seg_qemu, seg_vmcb) \ | ||
| 338 | - env->seg_qemu.selector = lduw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.selector)); \ | ||
| 339 | - env->seg_qemu.base = ldq_phys(addr + offsetof(struct vmcb, save.seg_vmcb.base)); \ | ||
| 340 | - env->seg_qemu.limit = ldl_phys(addr + offsetof(struct vmcb, save.seg_vmcb.limit)); \ | ||
| 341 | - env->seg_qemu.flags = vmcb2cpu_attrib(lduw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.attrib)), env->seg_qemu.base, env->seg_qemu.limit) | 172 | +struct __attribute__ ((__packed__)) vmcb_save_area { |
| 173 | + struct vmcb_seg es; | ||
| 174 | + struct vmcb_seg cs; | ||
| 175 | + struct vmcb_seg ss; | ||
| 176 | + struct vmcb_seg ds; | ||
| 177 | + struct vmcb_seg fs; | ||
| 178 | + struct vmcb_seg gs; | ||
| 179 | + struct vmcb_seg gdtr; | ||
| 180 | + struct vmcb_seg ldtr; | ||
| 181 | + struct vmcb_seg idtr; | ||
| 182 | + struct vmcb_seg tr; | ||
| 183 | + uint8_t reserved_1[43]; | ||
| 184 | + uint8_t cpl; | ||
| 185 | + uint8_t reserved_2[4]; | ||
| 186 | + uint64_t efer; | ||
| 187 | + uint8_t reserved_3[112]; | ||
| 188 | + uint64_t cr4; | ||
| 189 | + uint64_t cr3; | ||
| 190 | + uint64_t cr0; | ||
| 191 | + uint64_t dr7; | ||
| 192 | + uint64_t dr6; | ||
| 193 | + uint64_t rflags; | ||
| 194 | + uint64_t rip; | ||
| 195 | + uint8_t reserved_4[88]; | ||
| 196 | + uint64_t rsp; | ||
| 197 | + uint8_t reserved_5[24]; | ||
| 198 | + uint64_t rax; | ||
| 199 | + uint64_t star; | ||
| 200 | + uint64_t lstar; | ||
| 201 | + uint64_t cstar; | ||
| 202 | + uint64_t sfmask; | ||
| 203 | + uint64_t kernel_gs_base; | ||
| 204 | + uint64_t sysenter_cs; | ||
| 205 | + uint64_t sysenter_esp; | ||
| 206 | + uint64_t sysenter_eip; | ||
| 207 | + uint64_t cr2; | ||
| 208 | + /* qemu: cr8 added to reuse this as hsave */ | ||
| 209 | + uint64_t cr8; | ||
| 210 | + uint8_t reserved_6[32 - 8]; /* originally 32 */ | ||
| 211 | + uint64_t g_pat; | ||
| 212 | + uint64_t dbgctl; | ||
| 213 | + uint64_t br_from; | ||
| 214 | + uint64_t br_to; | ||
| 215 | + uint64_t last_excp_from; | ||
| 216 | + uint64_t last_excp_to; | ||
| 217 | +}; | ||
| 342 | 218 | ||
| 343 | -#define SVM_SAVE_SEG(addr, seg_qemu, seg_vmcb) \ | ||
| 344 | - stw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.selector), env->seg_qemu.selector); \ | ||
| 345 | - stq_phys(addr + offsetof(struct vmcb, save.seg_vmcb.base), env->seg_qemu.base); \ | ||
| 346 | - stl_phys(addr + offsetof(struct vmcb, save.seg_vmcb.limit), env->seg_qemu.limit); \ | ||
| 347 | - stw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.attrib), cpu2vmcb_attrib(env->seg_qemu.flags)) | 219 | +struct __attribute__ ((__packed__)) vmcb { |
| 220 | + struct vmcb_control_area control; | ||
| 221 | + struct vmcb_save_area save; | ||
| 222 | +}; | ||
| 348 | 223 | ||
| 349 | #endif | 224 | #endif |
target-i386/translate.c
| @@ -733,7 +733,7 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, | @@ -733,7 +733,7 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, | ||
| 733 | tcg_gen_helper_0_1(gen_check_io_func[ot], | 733 | tcg_gen_helper_0_1(gen_check_io_func[ot], |
| 734 | cpu_tmp2_i32); | 734 | cpu_tmp2_i32); |
| 735 | } | 735 | } |
| 736 | - if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) { | 736 | + if(s->flags & HF_SVMI_MASK) { |
| 737 | if (!state_saved) { | 737 | if (!state_saved) { |
| 738 | if (s->cc_op != CC_OP_DYNAMIC) | 738 | if (s->cc_op != CC_OP_DYNAMIC) |
| 739 | gen_op_set_cc_op(s->cc_op); | 739 | gen_op_set_cc_op(s->cc_op); |
| @@ -2322,59 +2322,24 @@ static inline int svm_is_rep(int prefixes) | @@ -2322,59 +2322,24 @@ static inline int svm_is_rep(int prefixes) | ||
| 2322 | return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); | 2322 | return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); |
| 2323 | } | 2323 | } |
| 2324 | 2324 | ||
| 2325 | -static inline int | 2325 | +static inline void |
| 2326 | gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, | 2326 | gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
| 2327 | uint32_t type, uint64_t param) | 2327 | uint32_t type, uint64_t param) |
| 2328 | { | 2328 | { |
| 2329 | - if(!(s->flags & (INTERCEPT_SVM_MASK))) | ||
| 2330 | - /* no SVM activated */ | ||
| 2331 | - return 0; | ||
| 2332 | - switch(type) { | ||
| 2333 | - /* CRx and DRx reads/writes */ | ||
| 2334 | - case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1: | ||
| 2335 | - if (s->cc_op != CC_OP_DYNAMIC) { | ||
| 2336 | - gen_op_set_cc_op(s->cc_op); | ||
| 2337 | - } | ||
| 2338 | - gen_jmp_im(pc_start - s->cs_base); | ||
| 2339 | - tcg_gen_helper_0_2(helper_svm_check_intercept_param, | ||
| 2340 | - tcg_const_i32(type), tcg_const_i64(param)); | ||
| 2341 | - /* this is a special case as we do not know if the interception occurs | ||
| 2342 | - so we assume there was none */ | ||
| 2343 | - return 0; | ||
| 2344 | - case SVM_EXIT_MSR: | ||
| 2345 | - if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) { | ||
| 2346 | - if (s->cc_op != CC_OP_DYNAMIC) { | ||
| 2347 | - gen_op_set_cc_op(s->cc_op); | ||
| 2348 | - } | ||
| 2349 | - gen_jmp_im(pc_start - s->cs_base); | ||
| 2350 | - tcg_gen_helper_0_2(helper_svm_check_intercept_param, | ||
| 2351 | - tcg_const_i32(type), tcg_const_i64(param)); | ||
| 2352 | - /* this is a special case as we do not know if the interception occurs | ||
| 2353 | - so we assume there was none */ | ||
| 2354 | - return 0; | ||
| 2355 | - } | ||
| 2356 | - break; | ||
| 2357 | - default: | ||
| 2358 | - if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) { | ||
| 2359 | - if (s->cc_op != CC_OP_DYNAMIC) { | ||
| 2360 | - gen_op_set_cc_op(s->cc_op); | ||
| 2361 | - } | ||
| 2362 | - gen_jmp_im(pc_start - s->cs_base); | ||
| 2363 | - tcg_gen_helper_0_2(helper_vmexit, | ||
| 2364 | - tcg_const_i32(type), tcg_const_i64(param)); | ||
| 2365 | - /* we can optimize this one so TBs don't get longer | ||
| 2366 | - than up to vmexit */ | ||
| 2367 | - gen_eob(s); | ||
| 2368 | - return 1; | ||
| 2369 | - } | ||
| 2370 | - } | ||
| 2371 | - return 0; | 2329 | + /* no SVM activated; fast case */ |
| 2330 | + if (likely(!(s->flags & HF_SVMI_MASK))) | ||
| 2331 | + return; | ||
| 2332 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 2333 | + gen_op_set_cc_op(s->cc_op); | ||
| 2334 | + gen_jmp_im(pc_start - s->cs_base); | ||
| 2335 | + tcg_gen_helper_0_2(helper_svm_check_intercept_param, | ||
| 2336 | + tcg_const_i32(type), tcg_const_i64(param)); | ||
| 2372 | } | 2337 | } |
| 2373 | 2338 | ||
| 2374 | -static inline int | 2339 | +static inline void |
| 2375 | gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type) | 2340 | gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type) |
| 2376 | { | 2341 | { |
| 2377 | - return gen_svm_check_intercept_param(s, pc_start, type, 0); | 2342 | + gen_svm_check_intercept_param(s, pc_start, type, 0); |
| 2378 | } | 2343 | } |
| 2379 | 2344 | ||
| 2380 | static inline void gen_stack_update(DisasContext *s, int addend) | 2345 | static inline void gen_stack_update(DisasContext *s, int addend) |
| @@ -5743,8 +5708,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5743,8 +5708,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5743 | val = 0; | 5708 | val = 0; |
| 5744 | goto do_lret; | 5709 | goto do_lret; |
| 5745 | case 0xcf: /* iret */ | 5710 | case 0xcf: /* iret */ |
| 5746 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET)) | ||
| 5747 | - break; | 5711 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET); |
| 5748 | if (!s->pe) { | 5712 | if (!s->pe) { |
| 5749 | /* real mode */ | 5713 | /* real mode */ |
| 5750 | tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag)); | 5714 | tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag)); |
| @@ -5890,8 +5854,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5890,8 +5854,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5890 | /************************/ | 5854 | /************************/ |
| 5891 | /* flags */ | 5855 | /* flags */ |
| 5892 | case 0x9c: /* pushf */ | 5856 | case 0x9c: /* pushf */ |
| 5893 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF)) | ||
| 5894 | - break; | 5857 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF); |
| 5895 | if (s->vm86 && s->iopl != 3) { | 5858 | if (s->vm86 && s->iopl != 3) { |
| 5896 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 5859 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 5897 | } else { | 5860 | } else { |
| @@ -5902,8 +5865,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5902,8 +5865,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5902 | } | 5865 | } |
| 5903 | break; | 5866 | break; |
| 5904 | case 0x9d: /* popf */ | 5867 | case 0x9d: /* popf */ |
| 5905 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF)) | ||
| 5906 | - break; | 5868 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF); |
| 5907 | if (s->vm86 && s->iopl != 3) { | 5869 | if (s->vm86 && s->iopl != 3) { |
| 5908 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 5870 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 5909 | } else { | 5871 | } else { |
| @@ -6187,14 +6149,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6187,14 +6149,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6187 | } | 6149 | } |
| 6188 | break; | 6150 | break; |
| 6189 | case 0xcc: /* int3 */ | 6151 | case 0xcc: /* int3 */ |
| 6190 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) | ||
| 6191 | - break; | ||
| 6192 | gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); | 6152 | gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); |
| 6193 | break; | 6153 | break; |
| 6194 | case 0xcd: /* int N */ | 6154 | case 0xcd: /* int N */ |
| 6195 | val = ldub_code(s->pc++); | 6155 | val = ldub_code(s->pc++); |
| 6196 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) | ||
| 6197 | - break; | ||
| 6198 | if (s->vm86 && s->iopl != 3) { | 6156 | if (s->vm86 && s->iopl != 3) { |
| 6199 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6157 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6200 | } else { | 6158 | } else { |
| @@ -6204,16 +6162,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6204,16 +6162,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6204 | case 0xce: /* into */ | 6162 | case 0xce: /* into */ |
| 6205 | if (CODE64(s)) | 6163 | if (CODE64(s)) |
| 6206 | goto illegal_op; | 6164 | goto illegal_op; |
| 6207 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) | ||
| 6208 | - break; | ||
| 6209 | if (s->cc_op != CC_OP_DYNAMIC) | 6165 | if (s->cc_op != CC_OP_DYNAMIC) |
| 6210 | gen_op_set_cc_op(s->cc_op); | 6166 | gen_op_set_cc_op(s->cc_op); |
| 6211 | gen_jmp_im(pc_start - s->cs_base); | 6167 | gen_jmp_im(pc_start - s->cs_base); |
| 6212 | tcg_gen_helper_0_1(helper_into, tcg_const_i32(s->pc - pc_start)); | 6168 | tcg_gen_helper_0_1(helper_into, tcg_const_i32(s->pc - pc_start)); |
| 6213 | break; | 6169 | break; |
| 6214 | case 0xf1: /* icebp (undocumented, exits to external debugger) */ | 6170 | case 0xf1: /* icebp (undocumented, exits to external debugger) */ |
| 6215 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP)) | ||
| 6216 | - break; | 6171 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP); |
| 6217 | #if 1 | 6172 | #if 1 |
| 6218 | gen_debug(s, pc_start - s->cs_base); | 6173 | gen_debug(s, pc_start - s->cs_base); |
| 6219 | #else | 6174 | #else |
| @@ -6371,25 +6326,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6371,25 +6326,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6371 | if (s->cpl != 0) { | 6326 | if (s->cpl != 0) { |
| 6372 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6327 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6373 | } else { | 6328 | } else { |
| 6374 | - int retval = 0; | 6329 | + if (s->cc_op != CC_OP_DYNAMIC) |
| 6330 | + gen_op_set_cc_op(s->cc_op); | ||
| 6331 | + gen_jmp_im(pc_start - s->cs_base); | ||
| 6375 | if (b & 2) { | 6332 | if (b & 2) { |
| 6376 | - retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0); | ||
| 6377 | tcg_gen_helper_0_0(helper_rdmsr); | 6333 | tcg_gen_helper_0_0(helper_rdmsr); |
| 6378 | } else { | 6334 | } else { |
| 6379 | - retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1); | ||
| 6380 | tcg_gen_helper_0_0(helper_wrmsr); | 6335 | tcg_gen_helper_0_0(helper_wrmsr); |
| 6381 | } | 6336 | } |
| 6382 | - if(retval) | ||
| 6383 | - gen_eob(s); | ||
| 6384 | } | 6337 | } |
| 6385 | break; | 6338 | break; |
| 6386 | case 0x131: /* rdtsc */ | 6339 | case 0x131: /* rdtsc */ |
| 6387 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC)) | ||
| 6388 | - break; | 6340 | + if (s->cc_op != CC_OP_DYNAMIC) |
| 6341 | + gen_op_set_cc_op(s->cc_op); | ||
| 6389 | gen_jmp_im(pc_start - s->cs_base); | 6342 | gen_jmp_im(pc_start - s->cs_base); |
| 6390 | tcg_gen_helper_0_0(helper_rdtsc); | 6343 | tcg_gen_helper_0_0(helper_rdtsc); |
| 6391 | break; | 6344 | break; |
| 6392 | case 0x133: /* rdpmc */ | 6345 | case 0x133: /* rdpmc */ |
| 6346 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 6347 | + gen_op_set_cc_op(s->cc_op); | ||
| 6393 | gen_jmp_im(pc_start - s->cs_base); | 6348 | gen_jmp_im(pc_start - s->cs_base); |
| 6394 | tcg_gen_helper_0_0(helper_rdpmc); | 6349 | tcg_gen_helper_0_0(helper_rdpmc); |
| 6395 | break; | 6350 | break; |
| @@ -6452,16 +6407,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6452,16 +6407,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6452 | break; | 6407 | break; |
| 6453 | #endif | 6408 | #endif |
| 6454 | case 0x1a2: /* cpuid */ | 6409 | case 0x1a2: /* cpuid */ |
| 6455 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID)) | ||
| 6456 | - break; | ||
| 6457 | tcg_gen_helper_0_0(helper_cpuid); | 6410 | tcg_gen_helper_0_0(helper_cpuid); |
| 6458 | break; | 6411 | break; |
| 6459 | case 0xf4: /* hlt */ | 6412 | case 0xf4: /* hlt */ |
| 6460 | if (s->cpl != 0) { | 6413 | if (s->cpl != 0) { |
| 6461 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6414 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6462 | } else { | 6415 | } else { |
| 6463 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT)) | ||
| 6464 | - break; | ||
| 6465 | if (s->cc_op != CC_OP_DYNAMIC) | 6416 | if (s->cc_op != CC_OP_DYNAMIC) |
| 6466 | gen_op_set_cc_op(s->cc_op); | 6417 | gen_op_set_cc_op(s->cc_op); |
| 6467 | gen_jmp_im(s->pc - s->cs_base); | 6418 | gen_jmp_im(s->pc - s->cs_base); |
| @@ -6477,8 +6428,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6477,8 +6428,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6477 | case 0: /* sldt */ | 6428 | case 0: /* sldt */ |
| 6478 | if (!s->pe || s->vm86) | 6429 | if (!s->pe || s->vm86) |
| 6479 | goto illegal_op; | 6430 | goto illegal_op; |
| 6480 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ)) | ||
| 6481 | - break; | 6431 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ); |
| 6482 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector)); | 6432 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector)); |
| 6483 | ot = OT_WORD; | 6433 | ot = OT_WORD; |
| 6484 | if (mod == 3) | 6434 | if (mod == 3) |
| @@ -6491,8 +6441,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6491,8 +6441,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6491 | if (s->cpl != 0) { | 6441 | if (s->cpl != 0) { |
| 6492 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6442 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6493 | } else { | 6443 | } else { |
| 6494 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE)) | ||
| 6495 | - break; | 6444 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE); |
| 6496 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | 6445 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 6497 | gen_jmp_im(pc_start - s->cs_base); | 6446 | gen_jmp_im(pc_start - s->cs_base); |
| 6498 | tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); | 6447 | tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
| @@ -6502,8 +6451,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6502,8 +6451,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6502 | case 1: /* str */ | 6451 | case 1: /* str */ |
| 6503 | if (!s->pe || s->vm86) | 6452 | if (!s->pe || s->vm86) |
| 6504 | goto illegal_op; | 6453 | goto illegal_op; |
| 6505 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ)) | ||
| 6506 | - break; | 6454 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ); |
| 6507 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector)); | 6455 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector)); |
| 6508 | ot = OT_WORD; | 6456 | ot = OT_WORD; |
| 6509 | if (mod == 3) | 6457 | if (mod == 3) |
| @@ -6516,8 +6464,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6516,8 +6464,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6516 | if (s->cpl != 0) { | 6464 | if (s->cpl != 0) { |
| 6517 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6465 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6518 | } else { | 6466 | } else { |
| 6519 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE)) | ||
| 6520 | - break; | 6467 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE); |
| 6521 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | 6468 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 6522 | gen_jmp_im(pc_start - s->cs_base); | 6469 | gen_jmp_im(pc_start - s->cs_base); |
| 6523 | tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); | 6470 | tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
| @@ -6550,8 +6497,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6550,8 +6497,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6550 | case 0: /* sgdt */ | 6497 | case 0: /* sgdt */ |
| 6551 | if (mod == 3) | 6498 | if (mod == 3) |
| 6552 | goto illegal_op; | 6499 | goto illegal_op; |
| 6553 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ)) | ||
| 6554 | - break; | 6500 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ); |
| 6555 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 6501 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6556 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit)); | 6502 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit)); |
| 6557 | gen_op_st_T0_A0(OT_WORD + s->mem_index); | 6503 | gen_op_st_T0_A0(OT_WORD + s->mem_index); |
| @@ -6568,8 +6514,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6568,8 +6514,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6568 | if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || | 6514 | if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || |
| 6569 | s->cpl != 0) | 6515 | s->cpl != 0) |
| 6570 | goto illegal_op; | 6516 | goto illegal_op; |
| 6571 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR)) | ||
| 6572 | - break; | ||
| 6573 | gen_jmp_im(pc_start - s->cs_base); | 6517 | gen_jmp_im(pc_start - s->cs_base); |
| 6574 | #ifdef TARGET_X86_64 | 6518 | #ifdef TARGET_X86_64 |
| 6575 | if (s->aflag == 2) { | 6519 | if (s->aflag == 2) { |
| @@ -6592,8 +6536,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6592,8 +6536,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6592 | gen_op_set_cc_op(s->cc_op); | 6536 | gen_op_set_cc_op(s->cc_op); |
| 6593 | s->cc_op = CC_OP_DYNAMIC; | 6537 | s->cc_op = CC_OP_DYNAMIC; |
| 6594 | } | 6538 | } |
| 6595 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT)) | ||
| 6596 | - break; | ||
| 6597 | gen_jmp_im(s->pc - s->cs_base); | 6539 | gen_jmp_im(s->pc - s->cs_base); |
| 6598 | tcg_gen_helper_0_0(helper_mwait); | 6540 | tcg_gen_helper_0_0(helper_mwait); |
| 6599 | gen_eob(s); | 6541 | gen_eob(s); |
| @@ -6602,8 +6544,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6602,8 +6544,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6602 | goto illegal_op; | 6544 | goto illegal_op; |
| 6603 | } | 6545 | } |
| 6604 | } else { /* sidt */ | 6546 | } else { /* sidt */ |
| 6605 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ)) | ||
| 6606 | - break; | 6547 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ); |
| 6607 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 6548 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6608 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit)); | 6549 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit)); |
| 6609 | gen_op_st_T0_A0(OT_WORD + s->mem_index); | 6550 | gen_op_st_T0_A0(OT_WORD + s->mem_index); |
| @@ -6617,52 +6558,85 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6617,52 +6558,85 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6617 | case 2: /* lgdt */ | 6558 | case 2: /* lgdt */ |
| 6618 | case 3: /* lidt */ | 6559 | case 3: /* lidt */ |
| 6619 | if (mod == 3) { | 6560 | if (mod == 3) { |
| 6561 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 6562 | + gen_op_set_cc_op(s->cc_op); | ||
| 6563 | + gen_jmp_im(pc_start - s->cs_base); | ||
| 6620 | switch(rm) { | 6564 | switch(rm) { |
| 6621 | case 0: /* VMRUN */ | 6565 | case 0: /* VMRUN */ |
| 6622 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN)) | 6566 | + if (!(s->flags & HF_SVME_MASK) || !s->pe) |
| 6567 | + goto illegal_op; | ||
| 6568 | + if (s->cpl != 0) { | ||
| 6569 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 6623 | break; | 6570 | break; |
| 6624 | - if (s->cc_op != CC_OP_DYNAMIC) | ||
| 6625 | - gen_op_set_cc_op(s->cc_op); | ||
| 6626 | - gen_jmp_im(s->pc - s->cs_base); | ||
| 6627 | - tcg_gen_helper_0_0(helper_vmrun); | ||
| 6628 | - s->cc_op = CC_OP_EFLAGS; | ||
| 6629 | - gen_eob(s); | 6571 | + } else { |
| 6572 | + tcg_gen_helper_0_0(helper_vmrun); | ||
| 6573 | + s->cc_op = CC_OP_EFLAGS; | ||
| 6574 | + gen_eob(s); | ||
| 6575 | + } | ||
| 6630 | break; | 6576 | break; |
| 6631 | case 1: /* VMMCALL */ | 6577 | case 1: /* VMMCALL */ |
| 6632 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL)) | ||
| 6633 | - break; | ||
| 6634 | - /* FIXME: cause #UD if hflags & SVM */ | 6578 | + if (!(s->flags & HF_SVME_MASK)) |
| 6579 | + goto illegal_op; | ||
| 6635 | tcg_gen_helper_0_0(helper_vmmcall); | 6580 | tcg_gen_helper_0_0(helper_vmmcall); |
| 6636 | break; | 6581 | break; |
| 6637 | case 2: /* VMLOAD */ | 6582 | case 2: /* VMLOAD */ |
| 6638 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD)) | ||
| 6639 | - break; | ||
| 6640 | - tcg_gen_helper_0_0(helper_vmload); | 6583 | + if (!(s->flags & HF_SVME_MASK) || !s->pe) |
| 6584 | + goto illegal_op; | ||
| 6585 | + if (s->cpl != 0) { | ||
| 6586 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 6587 | + break; | ||
| 6588 | + } else { | ||
| 6589 | + tcg_gen_helper_0_0(helper_vmload); | ||
| 6590 | + } | ||
| 6641 | break; | 6591 | break; |
| 6642 | case 3: /* VMSAVE */ | 6592 | case 3: /* VMSAVE */ |
| 6643 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE)) | ||
| 6644 | - break; | ||
| 6645 | - tcg_gen_helper_0_0(helper_vmsave); | 6593 | + if (!(s->flags & HF_SVME_MASK) || !s->pe) |
| 6594 | + goto illegal_op; | ||
| 6595 | + if (s->cpl != 0) { | ||
| 6596 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 6597 | + break; | ||
| 6598 | + } else { | ||
| 6599 | + tcg_gen_helper_0_0(helper_vmsave); | ||
| 6600 | + } | ||
| 6646 | break; | 6601 | break; |
| 6647 | case 4: /* STGI */ | 6602 | case 4: /* STGI */ |
| 6648 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI)) | ||
| 6649 | - break; | ||
| 6650 | - tcg_gen_helper_0_0(helper_stgi); | 6603 | + if ((!(s->flags & HF_SVME_MASK) && |
| 6604 | + !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || | ||
| 6605 | + !s->pe) | ||
| 6606 | + goto illegal_op; | ||
| 6607 | + if (s->cpl != 0) { | ||
| 6608 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 6609 | + break; | ||
| 6610 | + } else { | ||
| 6611 | + tcg_gen_helper_0_0(helper_stgi); | ||
| 6612 | + } | ||
| 6651 | break; | 6613 | break; |
| 6652 | case 5: /* CLGI */ | 6614 | case 5: /* CLGI */ |
| 6653 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI)) | ||
| 6654 | - break; | ||
| 6655 | - tcg_gen_helper_0_0(helper_clgi); | 6615 | + if (!(s->flags & HF_SVME_MASK) || !s->pe) |
| 6616 | + goto illegal_op; | ||
| 6617 | + if (s->cpl != 0) { | ||
| 6618 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 6619 | + break; | ||
| 6620 | + } else { | ||
| 6621 | + tcg_gen_helper_0_0(helper_clgi); | ||
| 6622 | + } | ||
| 6656 | break; | 6623 | break; |
| 6657 | case 6: /* SKINIT */ | 6624 | case 6: /* SKINIT */ |
| 6658 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT)) | ||
| 6659 | - break; | 6625 | + if ((!(s->flags & HF_SVME_MASK) && |
| 6626 | + !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || | ||
| 6627 | + !s->pe) | ||
| 6628 | + goto illegal_op; | ||
| 6660 | tcg_gen_helper_0_0(helper_skinit); | 6629 | tcg_gen_helper_0_0(helper_skinit); |
| 6661 | break; | 6630 | break; |
| 6662 | case 7: /* INVLPGA */ | 6631 | case 7: /* INVLPGA */ |
| 6663 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA)) | ||
| 6664 | - break; | ||
| 6665 | - tcg_gen_helper_0_0(helper_invlpga); | 6632 | + if (!(s->flags & HF_SVME_MASK) || !s->pe) |
| 6633 | + goto illegal_op; | ||
| 6634 | + if (s->cpl != 0) { | ||
| 6635 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 6636 | + break; | ||
| 6637 | + } else { | ||
| 6638 | + tcg_gen_helper_0_0(helper_invlpga); | ||
| 6639 | + } | ||
| 6666 | break; | 6640 | break; |
| 6667 | default: | 6641 | default: |
| 6668 | goto illegal_op; | 6642 | goto illegal_op; |
| @@ -6670,9 +6644,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6670,9 +6644,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6670 | } else if (s->cpl != 0) { | 6644 | } else if (s->cpl != 0) { |
| 6671 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6645 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6672 | } else { | 6646 | } else { |
| 6673 | - if (gen_svm_check_intercept(s, pc_start, | ||
| 6674 | - op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE)) | ||
| 6675 | - break; | 6647 | + gen_svm_check_intercept(s, pc_start, |
| 6648 | + op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE); | ||
| 6676 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 6649 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6677 | gen_op_ld_T1_A0(OT_WORD + s->mem_index); | 6650 | gen_op_ld_T1_A0(OT_WORD + s->mem_index); |
| 6678 | gen_add_A0_im(s, 2); | 6651 | gen_add_A0_im(s, 2); |
| @@ -6689,8 +6662,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6689,8 +6662,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6689 | } | 6662 | } |
| 6690 | break; | 6663 | break; |
| 6691 | case 4: /* smsw */ | 6664 | case 4: /* smsw */ |
| 6692 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0)) | ||
| 6693 | - break; | 6665 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); |
| 6694 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); | 6666 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); |
| 6695 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); | 6667 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); |
| 6696 | break; | 6668 | break; |
| @@ -6698,8 +6670,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6698,8 +6670,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6698 | if (s->cpl != 0) { | 6670 | if (s->cpl != 0) { |
| 6699 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6671 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6700 | } else { | 6672 | } else { |
| 6701 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0)) | ||
| 6702 | - break; | 6673 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); |
| 6703 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | 6674 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 6704 | tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]); | 6675 | tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]); |
| 6705 | gen_jmp_im(s->pc - s->cs_base); | 6676 | gen_jmp_im(s->pc - s->cs_base); |
| @@ -6724,8 +6695,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6724,8 +6695,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6724 | goto illegal_op; | 6695 | goto illegal_op; |
| 6725 | } | 6696 | } |
| 6726 | } else { | 6697 | } else { |
| 6727 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG)) | ||
| 6728 | - break; | ||
| 6729 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 6698 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6730 | tcg_gen_helper_0_1(helper_invlpg, cpu_A0); | 6699 | tcg_gen_helper_0_1(helper_invlpg, cpu_A0); |
| 6731 | gen_jmp_im(s->pc - s->cs_base); | 6700 | gen_jmp_im(s->pc - s->cs_base); |
| @@ -6742,8 +6711,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6742,8 +6711,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6742 | if (s->cpl != 0) { | 6711 | if (s->cpl != 0) { |
| 6743 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6712 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6744 | } else { | 6713 | } else { |
| 6745 | - if (gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD)) | ||
| 6746 | - break; | 6714 | + gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD); |
| 6747 | /* nothing to do */ | 6715 | /* nothing to do */ |
| 6748 | } | 6716 | } |
| 6749 | break; | 6717 | break; |
| @@ -6892,21 +6860,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6892,21 +6860,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6892 | case 3: | 6860 | case 3: |
| 6893 | case 4: | 6861 | case 4: |
| 6894 | case 8: | 6862 | case 8: |
| 6863 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 6864 | + gen_op_set_cc_op(s->cc_op); | ||
| 6865 | + gen_jmp_im(pc_start - s->cs_base); | ||
| 6895 | if (b & 2) { | 6866 | if (b & 2) { |
| 6896 | - gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg); | ||
| 6897 | gen_op_mov_TN_reg(ot, 0, rm); | 6867 | gen_op_mov_TN_reg(ot, 0, rm); |
| 6898 | - tcg_gen_helper_0_2(helper_movl_crN_T0, | 6868 | + tcg_gen_helper_0_2(helper_write_crN, |
| 6899 | tcg_const_i32(reg), cpu_T[0]); | 6869 | tcg_const_i32(reg), cpu_T[0]); |
| 6900 | gen_jmp_im(s->pc - s->cs_base); | 6870 | gen_jmp_im(s->pc - s->cs_base); |
| 6901 | gen_eob(s); | 6871 | gen_eob(s); |
| 6902 | } else { | 6872 | } else { |
| 6903 | - gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg); | ||
| 6904 | -#if !defined(CONFIG_USER_ONLY) | ||
| 6905 | - if (reg == 8) | ||
| 6906 | - tcg_gen_helper_1_0(helper_movtl_T0_cr8, cpu_T[0]); | ||
| 6907 | - else | ||
| 6908 | -#endif | ||
| 6909 | - tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[reg])); | 6873 | + tcg_gen_helper_1_1(helper_read_crN, |
| 6874 | + cpu_T[0], tcg_const_i32(reg)); | ||
| 6910 | gen_op_mov_reg_T0(ot, rm); | 6875 | gen_op_mov_reg_T0(ot, rm); |
| 6911 | } | 6876 | } |
| 6912 | break; | 6877 | break; |
| @@ -7054,8 +7019,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -7054,8 +7019,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 7054 | /* ignore for now */ | 7019 | /* ignore for now */ |
| 7055 | break; | 7020 | break; |
| 7056 | case 0x1aa: /* rsm */ | 7021 | case 0x1aa: /* rsm */ |
| 7057 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM)) | ||
| 7058 | - break; | 7022 | + gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM); |
| 7059 | if (!(s->flags & HF_SMM_MASK)) | 7023 | if (!(s->flags & HF_SMM_MASK)) |
| 7060 | goto illegal_op; | 7024 | goto illegal_op; |
| 7061 | if (s->cc_op != CC_OP_DYNAMIC) { | 7025 | if (s->cc_op != CC_OP_DYNAMIC) { |