Commit 872929aa59cba19fd83b98f87929ccda12a2cbbb

Authored by bellard
1 parent 893f9865

SVM rework

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4605 c046a42c-6fe2-441c-8c8c-71466251a162
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, &reg_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, &reg_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, &reg_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, &reg_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) {
... ...