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 | 171 | #if defined(TARGET_I386) |
| 172 | 172 | flags = env->hflags; |
| 173 | 173 | flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); |
| 174 | - flags |= env->intercept; | |
| 175 | 174 | cs_base = env->segs[R_CS].base; |
| 176 | 175 | pc = cs_base + env->eip; |
| 177 | 176 | #elif defined(TARGET_ARM) | ... | ... |
target-i386/TODO
| 1 | 1 | Correctness issues: |
| 2 | 2 | |
| 3 | 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 | 5 | - x86_64: lcall/ljmp intel/amd differences ? |
| 8 | 6 | - better code fetch (different exception handling + CS.limit support) |
| 9 | 7 | - user/kernel PUSHL/POPL in helper.c | ... | ... |
target-i386/cpu.h
| ... | ... | @@ -149,6 +149,8 @@ |
| 149 | 149 | #define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ |
| 150 | 150 | #define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ |
| 151 | 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 | 155 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) |
| 154 | 156 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) |
| ... | ... | @@ -169,6 +171,8 @@ |
| 169 | 171 | #define HF_GIF_MASK (1 << HF_GIF_SHIFT) |
| 170 | 172 | #define HF_HIF_MASK (1 << HF_HIF_SHIFT) |
| 171 | 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 | 177 | #define CR0_PE_MASK (1 << 0) |
| 174 | 178 | #define CR0_MP_MASK (1 << 1) |
| ... | ... | @@ -242,6 +246,7 @@ |
| 242 | 246 | #define MSR_EFER_LME (1 << 8) |
| 243 | 247 | #define MSR_EFER_LMA (1 << 10) |
| 244 | 248 | #define MSR_EFER_NXE (1 << 11) |
| 249 | +#define MSR_EFER_SVME (1 << 12) | |
| 245 | 250 | #define MSR_EFER_FFXSR (1 << 14) |
| 246 | 251 | |
| 247 | 252 | #define MSR_STAR 0xc0000081 |
| ... | ... | @@ -322,6 +327,7 @@ |
| 322 | 327 | #define CPUID_EXT3_3DNOWPREFETCH (1 << 8) |
| 323 | 328 | #define CPUID_EXT3_OSVW (1 << 9) |
| 324 | 329 | #define CPUID_EXT3_IBS (1 << 10) |
| 330 | +#define CPUID_EXT3_SKINIT (1 << 12) | |
| 325 | 331 | |
| 326 | 332 | #define EXCP00_DIVZ 0 |
| 327 | 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 | 1096 | (env->efer & MSR_EFER_NXE) && |
| 1097 | 1097 | (env->cr[4] & CR4_PAE_MASK)) |
| 1098 | 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 | 1103 | } else { |
| 1102 | 1104 | env->cr[2] = addr; |
| 1103 | 1105 | } |
| 1104 | 1106 | env->error_code = error_code; |
| 1105 | 1107 | env->exception_index = EXCP0E_PAGE; |
| 1106 | - /* the VMM will handle this */ | |
| 1107 | - if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) | |
| 1108 | - return 2; | |
| 1109 | 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 | 43 | DEF_HELPER(void, helper_iret_real, (int shift)) |
| 44 | 44 | DEF_HELPER(void, helper_iret_protected, (int shift, int next_eip)) |
| 45 | 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 | 48 | DEF_HELPER(void, helper_lmsw, (target_ulong t0)) |
| 48 | 49 | DEF_HELPER(void, helper_clts, (void)) |
| 49 | 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 | 625 | int has_error_code, new_stack, shift; |
| 626 | 626 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
| 627 | 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 | 629 | has_error_code = 0; |
| 641 | 630 | if (!is_int && !is_hw) { |
| 642 | 631 | switch(intno) { |
| ... | ... | @@ -872,17 +861,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, |
| 872 | 861 | int has_error_code, new_stack; |
| 873 | 862 | uint32_t e1, e2, e3, ss; |
| 874 | 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 | 865 | has_error_code = 0; |
| 887 | 866 | if (!is_int && !is_hw) { |
| 888 | 867 | switch(intno) { |
| ... | ... | @@ -1139,17 +1118,7 @@ static void do_interrupt_real(int intno, int is_int, int error_code, |
| 1139 | 1118 | int selector; |
| 1140 | 1119 | uint32_t offset, esp; |
| 1141 | 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 | 1122 | /* real mode (simpler !) */ |
| 1154 | 1123 | dt = &env->idt; |
| 1155 | 1124 | if (intno * 4 + 3 > dt->limit) |
| ... | ... | @@ -1307,6 +1276,8 @@ void raise_interrupt(int intno, int is_int, int error_code, |
| 1307 | 1276 | if (!is_int) { |
| 1308 | 1277 | helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); |
| 1309 | 1278 | intno = check_exception(intno, &error_code); |
| 1279 | + } else { | |
| 1280 | + helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0); | |
| 1310 | 1281 | } |
| 1311 | 1282 | |
| 1312 | 1283 | env->exception_index = intno; |
| ... | ... | @@ -1316,18 +1287,6 @@ void raise_interrupt(int intno, int is_int, int error_code, |
| 1316 | 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 | 1290 | /* shortcuts to generate exceptions */ |
| 1332 | 1291 | |
| 1333 | 1292 | void (raise_exception_err)(int exception_index, int error_code) |
| ... | ... | @@ -1921,8 +1880,10 @@ void helper_single_step(void) |
| 1921 | 1880 | void helper_cpuid(void) |
| 1922 | 1881 | { |
| 1923 | 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 | 1887 | /* test if maximum index reached */ |
| 1927 | 1888 | if (index & 0x80000000) { |
| 1928 | 1889 | if (index > env->cpuid_xlevel) |
| ... | ... | @@ -2957,9 +2918,35 @@ void helper_sysexit(void) |
| 2957 | 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 | 2950 | switch(reg) { |
| 2964 | 2951 | case 0: |
| 2965 | 2952 | cpu_x86_update_cr0(env, t0); |
| ... | ... | @@ -2978,15 +2965,15 @@ void helper_movl_crN_T0(int reg, target_ulong t0) |
| 2978 | 2965 | env->cr[reg] = t0; |
| 2979 | 2966 | break; |
| 2980 | 2967 | } |
| 2981 | -#endif | |
| 2982 | 2968 | } |
| 2969 | +#endif | |
| 2983 | 2970 | |
| 2984 | 2971 | void helper_lmsw(target_ulong t0) |
| 2985 | 2972 | { |
| 2986 | 2973 | /* only 4 lower bits of CR0 are modified. PE cannot be set to zero |
| 2987 | 2974 | if already set to one. */ |
| 2988 | 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 | 2979 | void helper_clts(void) |
| ... | ... | @@ -3010,6 +2997,7 @@ void helper_movl_drN_T0(int reg, target_ulong t0) |
| 3010 | 2997 | |
| 3011 | 2998 | void helper_invlpg(target_ulong addr) |
| 3012 | 2999 | { |
| 3000 | + helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0); | |
| 3013 | 3001 | cpu_x86_flush_tlb(env, addr); |
| 3014 | 3002 | } |
| 3015 | 3003 | |
| ... | ... | @@ -3020,6 +3008,8 @@ void helper_rdtsc(void) |
| 3020 | 3008 | if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { |
| 3021 | 3009 | raise_exception(EXCP0D_GPF); |
| 3022 | 3010 | } |
| 3011 | + helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0); | |
| 3012 | + | |
| 3023 | 3013 | val = cpu_get_tsc(env); |
| 3024 | 3014 | EAX = (uint32_t)(val); |
| 3025 | 3015 | EDX = (uint32_t)(val >> 32); |
| ... | ... | @@ -3030,7 +3020,6 @@ void helper_rdpmc(void) |
| 3030 | 3020 | if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { |
| 3031 | 3021 | raise_exception(EXCP0D_GPF); |
| 3032 | 3022 | } |
| 3033 | - | |
| 3034 | 3023 | helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0); |
| 3035 | 3024 | |
| 3036 | 3025 | /* currently unimplemented */ |
| ... | ... | @@ -3050,6 +3039,8 @@ void helper_wrmsr(void) |
| 3050 | 3039 | { |
| 3051 | 3040 | uint64_t val; |
| 3052 | 3041 | |
| 3042 | + helper_svm_check_intercept_param(SVM_EXIT_MSR, 1); | |
| 3043 | + | |
| 3053 | 3044 | val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); |
| 3054 | 3045 | |
| 3055 | 3046 | switch((uint32_t)ECX) { |
| ... | ... | @@ -3119,6 +3110,9 @@ void helper_wrmsr(void) |
| 3119 | 3110 | void helper_rdmsr(void) |
| 3120 | 3111 | { |
| 3121 | 3112 | uint64_t val; |
| 3113 | + | |
| 3114 | + helper_svm_check_intercept_param(SVM_EXIT_MSR, 0); | |
| 3115 | + | |
| 3122 | 3116 | switch((uint32_t)ECX) { |
| 3123 | 3117 | case MSR_IA32_SYSENTER_CS: |
| 3124 | 3118 | val = env->sysenter_cs; |
| ... | ... | @@ -4549,6 +4543,8 @@ void helper_idivq_EAX(target_ulong t0) |
| 4549 | 4543 | |
| 4550 | 4544 | void helper_hlt(void) |
| 4551 | 4545 | { |
| 4546 | + helper_svm_check_intercept_param(SVM_EXIT_HLT, 0); | |
| 4547 | + | |
| 4552 | 4548 | env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ |
| 4553 | 4549 | env->hflags |= HF_HALTED_MASK; |
| 4554 | 4550 | env->exception_index = EXCP_HLT; |
| ... | ... | @@ -4560,12 +4556,14 @@ void helper_monitor(target_ulong ptr) |
| 4560 | 4556 | if ((uint32_t)ECX != 0) |
| 4561 | 4557 | raise_exception(EXCP0D_GPF); |
| 4562 | 4558 | /* XXX: store address ? */ |
| 4559 | + helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0); | |
| 4563 | 4560 | } |
| 4564 | 4561 | |
| 4565 | 4562 | void helper_mwait(void) |
| 4566 | 4563 | { |
| 4567 | 4564 | if ((uint32_t)ECX != 0) |
| 4568 | 4565 | raise_exception(EXCP0D_GPF); |
| 4566 | + helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0); | |
| 4569 | 4567 | /* XXX: not complete but not completely erroneous */ |
| 4570 | 4568 | if (env->cpu_index != 0 || env->next_cpu != NULL) { |
| 4571 | 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 | 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 | 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 | 4712 | |
| 4718 | 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 | 4715 | #if defined(CONFIG_USER_ONLY) |
| 4731 | 4716 | |
| 4732 | 4717 | void helper_vmrun(void) |
| ... | ... | @@ -4741,6 +4726,12 @@ void helper_vmload(void) |
| 4741 | 4726 | void helper_vmsave(void) |
| 4742 | 4727 | { |
| 4743 | 4728 | } |
| 4729 | +void helper_stgi(void) | |
| 4730 | +{ | |
| 4731 | +} | |
| 4732 | +void helper_clgi(void) | |
| 4733 | +{ | |
| 4734 | +} | |
| 4744 | 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 | 4751 | } |
| 4761 | 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 | 4787 | void helper_vmrun(void) |
| ... | ... | @@ -4782,6 +4790,8 @@ void helper_vmrun(void) |
| 4782 | 4790 | uint32_t event_inj; |
| 4783 | 4791 | uint32_t int_ctl; |
| 4784 | 4792 | |
| 4793 | + helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0); | |
| 4794 | + | |
| 4785 | 4795 | addr = EAX; |
| 4786 | 4796 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4787 | 4797 | fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr); |
| ... | ... | @@ -4806,10 +4816,14 @@ void helper_vmrun(void) |
| 4806 | 4816 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer); |
| 4807 | 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 | 4828 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP); |
| 4815 | 4829 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP); |
| ... | ... | @@ -4817,15 +4831,16 @@ void helper_vmrun(void) |
| 4817 | 4831 | |
| 4818 | 4832 | /* load the interception bitmaps so we do not need to access the |
| 4819 | 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 | 4835 | env->intercept_cr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read)); |
| 4824 | 4836 | env->intercept_cr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write)); |
| 4825 | 4837 | env->intercept_dr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read)); |
| 4826 | 4838 | env->intercept_dr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write)); |
| 4827 | 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 | 4844 | env->gdt.base = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base)); |
| 4830 | 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 | 4872 | load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)), |
| 4858 | 4873 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
| 4859 | 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 | 4885 | EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip)); |
| 4868 | 4886 | env->eip = EIP; |
| ... | ... | @@ -4933,7 +4951,8 @@ void helper_vmrun(void) |
| 4933 | 4951 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4934 | 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 | 4956 | env->interrupt_request |= CPU_INTERRUPT_VIRQ; |
| 4938 | 4957 | } |
| 4939 | 4958 | |
| ... | ... | @@ -4942,23 +4961,30 @@ void helper_vmrun(void) |
| 4942 | 4961 | |
| 4943 | 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 | 4968 | void helper_vmload(void) |
| 4950 | 4969 | { |
| 4951 | 4970 | target_ulong addr; |
| 4971 | + helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0); | |
| 4972 | + | |
| 4973 | + /* XXX: invalid in 32 bit */ | |
| 4952 | 4974 | addr = EAX; |
| 4953 | 4975 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4954 | 4976 | fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", |
| 4955 | 4977 | addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), |
| 4956 | 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 | 4989 | #ifdef TARGET_X86_64 |
| 4964 | 4990 | env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base)); |
| ... | ... | @@ -4975,16 +5001,21 @@ void helper_vmload(void) |
| 4975 | 5001 | void helper_vmsave(void) |
| 4976 | 5002 | { |
| 4977 | 5003 | target_ulong addr; |
| 5004 | + helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0); | |
| 4978 | 5005 | addr = EAX; |
| 4979 | 5006 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4980 | 5007 | fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", |
| 4981 | 5008 | addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), |
| 4982 | 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 | 5020 | #ifdef TARGET_X86_64 |
| 4990 | 5021 | stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase); |
| ... | ... | @@ -4998,50 +5029,65 @@ void helper_vmsave(void) |
| 4998 | 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 | 5044 | void helper_skinit(void) |
| 5002 | 5045 | { |
| 5046 | + helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0); | |
| 5047 | + /* XXX: not implemented */ | |
| 5003 | 5048 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 5004 | 5049 | fprintf(logfile,"skinit!\n"); |
| 5050 | + raise_exception(EXCP06_ILLOP); | |
| 5005 | 5051 | } |
| 5006 | 5052 | |
| 5007 | 5053 | void helper_invlpga(void) |
| 5008 | 5054 | { |
| 5055 | + helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0); | |
| 5009 | 5056 | tlb_flush(env, 0); |
| 5010 | 5057 | } |
| 5011 | 5058 | |
| 5012 | 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 | 5063 | switch(type) { |
| 5015 | 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 | 5066 | helper_vmexit(type, param); |
| 5018 | 5067 | } |
| 5019 | 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 | 5071 | helper_vmexit(type, param); |
| 5023 | 5072 | } |
| 5024 | 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 | 5076 | helper_vmexit(type, param); |
| 5028 | 5077 | } |
| 5029 | 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 | 5081 | helper_vmexit(type, param); |
| 5033 | 5082 | } |
| 5034 | 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 | 5086 | helper_vmexit(type, param); |
| 5038 | 5087 | } |
| 5039 | 5088 | break; |
| 5040 | - case SVM_EXIT_IOIO: | |
| 5041 | - break; | |
| 5042 | - | |
| 5043 | 5089 | case SVM_EXIT_MSR: |
| 5044 | - if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) { | |
| 5090 | + if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) { | |
| 5045 | 5091 | /* FIXME: this should be read in at vmrun (faster this way?) */ |
| 5046 | 5092 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa)); |
| 5047 | 5093 | uint32_t t0, t1; |
| ... | ... | @@ -5071,7 +5117,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) |
| 5071 | 5117 | } |
| 5072 | 5118 | break; |
| 5073 | 5119 | default: |
| 5074 | - if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) { | |
| 5120 | + if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) { | |
| 5075 | 5121 | helper_vmexit(type, param); |
| 5076 | 5122 | } |
| 5077 | 5123 | break; |
| ... | ... | @@ -5081,7 +5127,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) |
| 5081 | 5127 | void helper_svm_check_io(uint32_t port, uint32_t param, |
| 5082 | 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 | 5131 | /* FIXME: this should be read in at vmrun (faster this way?) */ |
| 5086 | 5132 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); |
| 5087 | 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 | 5159 | } |
| 5114 | 5160 | |
| 5115 | 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 | 5171 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base); |
| 5122 | 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 | 5196 | |
| 5147 | 5197 | /* Reload the host state from vm_hsave */ |
| 5148 | 5198 | env->hflags &= ~HF_HIF_MASK; |
| 5199 | + env->hflags &= ~HF_SVMI_MASK; | |
| 5149 | 5200 | env->intercept = 0; |
| 5150 | 5201 | env->intercept_exceptions = 0; |
| 5151 | 5202 | env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; |
| ... | ... | @@ -5169,6 +5220,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) |
| 5169 | 5220 | env->hflags &= ~HF_LMA_MASK; |
| 5170 | 5221 | if (env->efer & MSR_EFER_LMA) |
| 5171 | 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 | 5231 | #endif |
| 5173 | 5232 | |
| 5174 | 5233 | env->eflags = 0; |
| ... | ... | @@ -5176,10 +5235,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) |
| 5176 | 5235 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
| 5177 | 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 | 5247 | EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip)); |
| 5185 | 5248 | ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp)); | ... | ... |
target-i386/svm.h
| 1 | 1 | #ifndef __SVM_H |
| 2 | 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 | 4 | #define TLB_CONTROL_DO_NOTHING 0 |
| 90 | 5 | #define TLB_CONTROL_FLUSH_ALL_ASID 1 |
| 91 | 6 | |
| ... | ... | @@ -116,104 +31,6 @@ struct __attribute__ ((__packed__)) vmcb_control_area { |
| 116 | 31 | #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) |
| 117 | 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 | 34 | #define SVM_EVTINJ_VEC_MASK 0xff |
| 218 | 35 | |
| 219 | 36 | #define SVM_EVTINJ_TYPE_SHIFT 8 |
| ... | ... | @@ -313,37 +130,95 @@ struct __attribute__ ((__packed__)) vmcb { |
| 313 | 130 | |
| 314 | 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 | 224 | #endif | ... | ... |
target-i386/translate.c
| ... | ... | @@ -733,7 +733,7 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, |
| 733 | 733 | tcg_gen_helper_0_1(gen_check_io_func[ot], |
| 734 | 734 | cpu_tmp2_i32); |
| 735 | 735 | } |
| 736 | - if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) { | |
| 736 | + if(s->flags & HF_SVMI_MASK) { | |
| 737 | 737 | if (!state_saved) { |
| 738 | 738 | if (s->cc_op != CC_OP_DYNAMIC) |
| 739 | 739 | gen_op_set_cc_op(s->cc_op); |
| ... | ... | @@ -2322,59 +2322,24 @@ static inline int svm_is_rep(int prefixes) |
| 2322 | 2322 | return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); |
| 2323 | 2323 | } |
| 2324 | 2324 | |
| 2325 | -static inline int | |
| 2325 | +static inline void | |
| 2326 | 2326 | gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
| 2327 | 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 | 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 | 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 | 5708 | val = 0; |
| 5744 | 5709 | goto do_lret; |
| 5745 | 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 | 5712 | if (!s->pe) { |
| 5749 | 5713 | /* real mode */ |
| 5750 | 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 | 5854 | /************************/ |
| 5891 | 5855 | /* flags */ |
| 5892 | 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 | 5858 | if (s->vm86 && s->iopl != 3) { |
| 5896 | 5859 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 5897 | 5860 | } else { |
| ... | ... | @@ -5902,8 +5865,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 5902 | 5865 | } |
| 5903 | 5866 | break; |
| 5904 | 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 | 5869 | if (s->vm86 && s->iopl != 3) { |
| 5908 | 5870 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 5909 | 5871 | } else { |
| ... | ... | @@ -6187,14 +6149,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6187 | 6149 | } |
| 6188 | 6150 | break; |
| 6189 | 6151 | case 0xcc: /* int3 */ |
| 6190 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) | |
| 6191 | - break; | |
| 6192 | 6152 | gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); |
| 6193 | 6153 | break; |
| 6194 | 6154 | case 0xcd: /* int N */ |
| 6195 | 6155 | val = ldub_code(s->pc++); |
| 6196 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) | |
| 6197 | - break; | |
| 6198 | 6156 | if (s->vm86 && s->iopl != 3) { |
| 6199 | 6157 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6200 | 6158 | } else { |
| ... | ... | @@ -6204,16 +6162,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6204 | 6162 | case 0xce: /* into */ |
| 6205 | 6163 | if (CODE64(s)) |
| 6206 | 6164 | goto illegal_op; |
| 6207 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) | |
| 6208 | - break; | |
| 6209 | 6165 | if (s->cc_op != CC_OP_DYNAMIC) |
| 6210 | 6166 | gen_op_set_cc_op(s->cc_op); |
| 6211 | 6167 | gen_jmp_im(pc_start - s->cs_base); |
| 6212 | 6168 | tcg_gen_helper_0_1(helper_into, tcg_const_i32(s->pc - pc_start)); |
| 6213 | 6169 | break; |
| 6214 | 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 | 6172 | #if 1 |
| 6218 | 6173 | gen_debug(s, pc_start - s->cs_base); |
| 6219 | 6174 | #else |
| ... | ... | @@ -6371,25 +6326,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6371 | 6326 | if (s->cpl != 0) { |
| 6372 | 6327 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6373 | 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 | 6332 | if (b & 2) { |
| 6376 | - retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0); | |
| 6377 | 6333 | tcg_gen_helper_0_0(helper_rdmsr); |
| 6378 | 6334 | } else { |
| 6379 | - retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1); | |
| 6380 | 6335 | tcg_gen_helper_0_0(helper_wrmsr); |
| 6381 | 6336 | } |
| 6382 | - if(retval) | |
| 6383 | - gen_eob(s); | |
| 6384 | 6337 | } |
| 6385 | 6338 | break; |
| 6386 | 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 | 6342 | gen_jmp_im(pc_start - s->cs_base); |
| 6390 | 6343 | tcg_gen_helper_0_0(helper_rdtsc); |
| 6391 | 6344 | break; |
| 6392 | 6345 | case 0x133: /* rdpmc */ |
| 6346 | + if (s->cc_op != CC_OP_DYNAMIC) | |
| 6347 | + gen_op_set_cc_op(s->cc_op); | |
| 6393 | 6348 | gen_jmp_im(pc_start - s->cs_base); |
| 6394 | 6349 | tcg_gen_helper_0_0(helper_rdpmc); |
| 6395 | 6350 | break; |
| ... | ... | @@ -6452,16 +6407,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6452 | 6407 | break; |
| 6453 | 6408 | #endif |
| 6454 | 6409 | case 0x1a2: /* cpuid */ |
| 6455 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID)) | |
| 6456 | - break; | |
| 6457 | 6410 | tcg_gen_helper_0_0(helper_cpuid); |
| 6458 | 6411 | break; |
| 6459 | 6412 | case 0xf4: /* hlt */ |
| 6460 | 6413 | if (s->cpl != 0) { |
| 6461 | 6414 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6462 | 6415 | } else { |
| 6463 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT)) | |
| 6464 | - break; | |
| 6465 | 6416 | if (s->cc_op != CC_OP_DYNAMIC) |
| 6466 | 6417 | gen_op_set_cc_op(s->cc_op); |
| 6467 | 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 | 6428 | case 0: /* sldt */ |
| 6478 | 6429 | if (!s->pe || s->vm86) |
| 6479 | 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 | 6432 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector)); |
| 6483 | 6433 | ot = OT_WORD; |
| 6484 | 6434 | if (mod == 3) |
| ... | ... | @@ -6491,8 +6441,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6491 | 6441 | if (s->cpl != 0) { |
| 6492 | 6442 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6493 | 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 | 6445 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 6497 | 6446 | gen_jmp_im(pc_start - s->cs_base); |
| 6498 | 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 | 6451 | case 1: /* str */ |
| 6503 | 6452 | if (!s->pe || s->vm86) |
| 6504 | 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 | 6455 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector)); |
| 6508 | 6456 | ot = OT_WORD; |
| 6509 | 6457 | if (mod == 3) |
| ... | ... | @@ -6516,8 +6464,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6516 | 6464 | if (s->cpl != 0) { |
| 6517 | 6465 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6518 | 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 | 6468 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 6522 | 6469 | gen_jmp_im(pc_start - s->cs_base); |
| 6523 | 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 | 6497 | case 0: /* sgdt */ |
| 6551 | 6498 | if (mod == 3) |
| 6552 | 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 | 6501 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6556 | 6502 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit)); |
| 6557 | 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 | 6514 | if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || |
| 6569 | 6515 | s->cpl != 0) |
| 6570 | 6516 | goto illegal_op; |
| 6571 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR)) | |
| 6572 | - break; | |
| 6573 | 6517 | gen_jmp_im(pc_start - s->cs_base); |
| 6574 | 6518 | #ifdef TARGET_X86_64 |
| 6575 | 6519 | if (s->aflag == 2) { |
| ... | ... | @@ -6592,8 +6536,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6592 | 6536 | gen_op_set_cc_op(s->cc_op); |
| 6593 | 6537 | s->cc_op = CC_OP_DYNAMIC; |
| 6594 | 6538 | } |
| 6595 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT)) | |
| 6596 | - break; | |
| 6597 | 6539 | gen_jmp_im(s->pc - s->cs_base); |
| 6598 | 6540 | tcg_gen_helper_0_0(helper_mwait); |
| 6599 | 6541 | gen_eob(s); |
| ... | ... | @@ -6602,8 +6544,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6602 | 6544 | goto illegal_op; |
| 6603 | 6545 | } |
| 6604 | 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 | 6548 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6608 | 6549 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit)); |
| 6609 | 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 | 6558 | case 2: /* lgdt */ |
| 6618 | 6559 | case 3: /* lidt */ |
| 6619 | 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 | 6564 | switch(rm) { |
| 6621 | 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 | 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 | 6576 | break; |
| 6631 | 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 | 6580 | tcg_gen_helper_0_0(helper_vmmcall); |
| 6636 | 6581 | break; |
| 6637 | 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 | 6591 | break; |
| 6642 | 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 | 6601 | break; |
| 6647 | 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 | 6613 | break; |
| 6652 | 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 | 6623 | break; |
| 6657 | 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 | 6629 | tcg_gen_helper_0_0(helper_skinit); |
| 6661 | 6630 | break; |
| 6662 | 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 | 6640 | break; |
| 6667 | 6641 | default: |
| 6668 | 6642 | goto illegal_op; |
| ... | ... | @@ -6670,9 +6644,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6670 | 6644 | } else if (s->cpl != 0) { |
| 6671 | 6645 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6672 | 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 | 6649 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6677 | 6650 | gen_op_ld_T1_A0(OT_WORD + s->mem_index); |
| 6678 | 6651 | gen_add_A0_im(s, 2); |
| ... | ... | @@ -6689,8 +6662,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6689 | 6662 | } |
| 6690 | 6663 | break; |
| 6691 | 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 | 6666 | tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); |
| 6695 | 6667 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); |
| 6696 | 6668 | break; |
| ... | ... | @@ -6698,8 +6670,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6698 | 6670 | if (s->cpl != 0) { |
| 6699 | 6671 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6700 | 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 | 6674 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 6704 | 6675 | tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]); |
| 6705 | 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 | 6695 | goto illegal_op; |
| 6725 | 6696 | } |
| 6726 | 6697 | } else { |
| 6727 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG)) | |
| 6728 | - break; | |
| 6729 | 6698 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 6730 | 6699 | tcg_gen_helper_0_1(helper_invlpg, cpu_A0); |
| 6731 | 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 | 6711 | if (s->cpl != 0) { |
| 6743 | 6712 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6744 | 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 | 6715 | /* nothing to do */ |
| 6748 | 6716 | } |
| 6749 | 6717 | break; |
| ... | ... | @@ -6892,21 +6860,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6892 | 6860 | case 3: |
| 6893 | 6861 | case 4: |
| 6894 | 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 | 6866 | if (b & 2) { |
| 6896 | - gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg); | |
| 6897 | 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 | 6869 | tcg_const_i32(reg), cpu_T[0]); |
| 6900 | 6870 | gen_jmp_im(s->pc - s->cs_base); |
| 6901 | 6871 | gen_eob(s); |
| 6902 | 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 | 6875 | gen_op_mov_reg_T0(ot, rm); |
| 6911 | 6876 | } |
| 6912 | 6877 | break; |
| ... | ... | @@ -7054,8 +7019,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 7054 | 7019 | /* ignore for now */ |
| 7055 | 7020 | break; |
| 7056 | 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 | 7023 | if (!(s->flags & HF_SMM_MASK)) |
| 7060 | 7024 | goto illegal_op; |
| 7061 | 7025 | if (s->cc_op != CC_OP_DYNAMIC) { | ... | ... |