Commit db620f46a8c8b168831812eabd7428a952964334
1 parent
3cd9acb4
reworked SVM interrupt handling logic - fixed vmrun EIP saved value - reworked c…
…r8 handling - added CPUState.hflags2 git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4662 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
110 additions
and
109 deletions
cpu-exec.c
| @@ -368,11 +368,8 @@ int cpu_exec(CPUState *env1) | @@ -368,11 +368,8 @@ int cpu_exec(CPUState *env1) | ||
| 368 | next_tb = 0; /* force lookup of first TB */ | 368 | next_tb = 0; /* force lookup of first TB */ |
| 369 | for(;;) { | 369 | for(;;) { |
| 370 | interrupt_request = env->interrupt_request; | 370 | interrupt_request = env->interrupt_request; |
| 371 | - if (__builtin_expect(interrupt_request, 0) | ||
| 372 | -#if defined(TARGET_I386) | ||
| 373 | - && env->hflags & HF_GIF_MASK | ||
| 374 | -#endif | ||
| 375 | - && likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) { | 371 | + if (__builtin_expect(interrupt_request, 0) && |
| 372 | + likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) { | ||
| 376 | if (interrupt_request & CPU_INTERRUPT_DEBUG) { | 373 | if (interrupt_request & CPU_INTERRUPT_DEBUG) { |
| 377 | env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; | 374 | env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; |
| 378 | env->exception_index = EXCP_DEBUG; | 375 | env->exception_index = EXCP_DEBUG; |
| @@ -388,47 +385,51 @@ int cpu_exec(CPUState *env1) | @@ -388,47 +385,51 @@ int cpu_exec(CPUState *env1) | ||
| 388 | } | 385 | } |
| 389 | #endif | 386 | #endif |
| 390 | #if defined(TARGET_I386) | 387 | #if defined(TARGET_I386) |
| 391 | - if ((interrupt_request & CPU_INTERRUPT_SMI) && | ||
| 392 | - !(env->hflags & HF_SMM_MASK)) { | ||
| 393 | - svm_check_intercept(SVM_EXIT_SMI); | ||
| 394 | - env->interrupt_request &= ~CPU_INTERRUPT_SMI; | ||
| 395 | - do_smm_enter(); | ||
| 396 | - next_tb = 0; | ||
| 397 | - } else if ((interrupt_request & CPU_INTERRUPT_NMI) && | ||
| 398 | - !(env->hflags & HF_NMI_MASK)) { | ||
| 399 | - env->interrupt_request &= ~CPU_INTERRUPT_NMI; | ||
| 400 | - env->hflags |= HF_NMI_MASK; | ||
| 401 | - do_interrupt(EXCP02_NMI, 0, 0, 0, 1); | ||
| 402 | - next_tb = 0; | ||
| 403 | - } else if ((interrupt_request & CPU_INTERRUPT_HARD) && | ||
| 404 | - (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) && | ||
| 405 | - !(env->hflags & HF_INHIBIT_IRQ_MASK)) { | ||
| 406 | - int intno; | ||
| 407 | - svm_check_intercept(SVM_EXIT_INTR); | ||
| 408 | - env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); | ||
| 409 | - intno = cpu_get_pic_interrupt(env); | ||
| 410 | - if (loglevel & CPU_LOG_TB_IN_ASM) { | ||
| 411 | - fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); | ||
| 412 | - } | ||
| 413 | - do_interrupt(intno, 0, 0, 0, 1); | ||
| 414 | - /* ensure that no TB jump will be modified as | ||
| 415 | - the program flow was changed */ | ||
| 416 | - next_tb = 0; | 388 | + if (env->hflags2 & HF2_GIF_MASK) { |
| 389 | + if ((interrupt_request & CPU_INTERRUPT_SMI) && | ||
| 390 | + !(env->hflags & HF_SMM_MASK)) { | ||
| 391 | + svm_check_intercept(SVM_EXIT_SMI); | ||
| 392 | + env->interrupt_request &= ~CPU_INTERRUPT_SMI; | ||
| 393 | + do_smm_enter(); | ||
| 394 | + next_tb = 0; | ||
| 395 | + } else if ((interrupt_request & CPU_INTERRUPT_NMI) && | ||
| 396 | + !(env->hflags2 & HF2_NMI_MASK)) { | ||
| 397 | + env->interrupt_request &= ~CPU_INTERRUPT_NMI; | ||
| 398 | + env->hflags2 |= HF2_NMI_MASK; | ||
| 399 | + do_interrupt(EXCP02_NMI, 0, 0, 0, 1); | ||
| 400 | + next_tb = 0; | ||
| 401 | + } else if ((interrupt_request & CPU_INTERRUPT_HARD) && | ||
| 402 | + (((env->hflags2 & HF2_VINTR_MASK) && | ||
| 403 | + (env->hflags2 & HF2_HIF_MASK)) || | ||
| 404 | + (!(env->hflags2 & HF2_VINTR_MASK) && | ||
| 405 | + (env->eflags & IF_MASK && | ||
| 406 | + !(env->hflags & HF_INHIBIT_IRQ_MASK))))) { | ||
| 407 | + int intno; | ||
| 408 | + svm_check_intercept(SVM_EXIT_INTR); | ||
| 409 | + env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); | ||
| 410 | + intno = cpu_get_pic_interrupt(env); | ||
| 411 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | ||
| 412 | + fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); | ||
| 413 | + } | ||
| 414 | + do_interrupt(intno, 0, 0, 0, 1); | ||
| 415 | + /* ensure that no TB jump will be modified as | ||
| 416 | + the program flow was changed */ | ||
| 417 | + next_tb = 0; | ||
| 417 | #if !defined(CONFIG_USER_ONLY) | 418 | #if !defined(CONFIG_USER_ONLY) |
| 418 | - } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && | ||
| 419 | - (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) { | ||
| 420 | - int intno; | ||
| 421 | - /* FIXME: this should respect TPR */ | ||
| 422 | - env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; | ||
| 423 | - svm_check_intercept(SVM_EXIT_VINTR); | ||
| 424 | - intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); | ||
| 425 | - if (loglevel & CPU_LOG_TB_IN_ASM) | ||
| 426 | - fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); | ||
| 427 | - do_interrupt(intno, 0, 0, -1, 1); | ||
| 428 | - stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), | ||
| 429 | - ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK); | ||
| 430 | - next_tb = 0; | 419 | + } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && |
| 420 | + (env->eflags & IF_MASK) && | ||
| 421 | + !(env->hflags & HF_INHIBIT_IRQ_MASK)) { | ||
| 422 | + int intno; | ||
| 423 | + /* FIXME: this should respect TPR */ | ||
| 424 | + svm_check_intercept(SVM_EXIT_VINTR); | ||
| 425 | + env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; | ||
| 426 | + intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); | ||
| 427 | + if (loglevel & CPU_LOG_TB_IN_ASM) | ||
| 428 | + fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); | ||
| 429 | + do_interrupt(intno, 0, 0, 0, 1); | ||
| 430 | + next_tb = 0; | ||
| 431 | #endif | 431 | #endif |
| 432 | + } | ||
| 432 | } | 433 | } |
| 433 | #elif defined(TARGET_PPC) | 434 | #elif defined(TARGET_PPC) |
| 434 | #if 0 | 435 | #if 0 |
target-i386/cpu.h
| @@ -145,11 +145,8 @@ | @@ -145,11 +145,8 @@ | ||
| 145 | #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */ | 145 | #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */ |
| 146 | #define HF_VM_SHIFT 17 /* must be same as eflags */ | 146 | #define HF_VM_SHIFT 17 /* must be same as eflags */ |
| 147 | #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ | 147 | #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ |
| 148 | -#define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ | ||
| 149 | -#define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ | ||
| 150 | -#define HF_NMI_SHIFT 22 /* CPU serving NMI */ | ||
| 151 | -#define HF_SVME_SHIFT 23 /* SVME enabled (copy of EFER.SVME) */ | ||
| 152 | -#define HF_SVMI_SHIFT 24 /* SVM intercepts are active */ | 148 | +#define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ |
| 149 | +#define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ | ||
| 153 | 150 | ||
| 154 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) | 151 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) |
| 155 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) | 152 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) |
| @@ -166,12 +163,21 @@ | @@ -166,12 +163,21 @@ | ||
| 166 | #define HF_CS64_MASK (1 << HF_CS64_SHIFT) | 163 | #define HF_CS64_MASK (1 << HF_CS64_SHIFT) |
| 167 | #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) | 164 | #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) |
| 168 | #define HF_SMM_MASK (1 << HF_SMM_SHIFT) | 165 | #define HF_SMM_MASK (1 << HF_SMM_SHIFT) |
| 169 | -#define HF_GIF_MASK (1 << HF_GIF_SHIFT) | ||
| 170 | -#define HF_HIF_MASK (1 << HF_HIF_SHIFT) | ||
| 171 | -#define HF_NMI_MASK (1 << HF_NMI_SHIFT) | ||
| 172 | #define HF_SVME_MASK (1 << HF_SVME_SHIFT) | 166 | #define HF_SVME_MASK (1 << HF_SVME_SHIFT) |
| 173 | #define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) | 167 | #define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) |
| 174 | 168 | ||
| 169 | +/* hflags2 */ | ||
| 170 | + | ||
| 171 | +#define HF2_GIF_SHIFT 0 /* if set CPU takes interrupts */ | ||
| 172 | +#define HF2_HIF_SHIFT 1 /* value of IF_MASK when entering SVM */ | ||
| 173 | +#define HF2_NMI_SHIFT 2 /* CPU serving NMI */ | ||
| 174 | +#define HF2_VINTR_SHIFT 3 /* value of V_INTR_MASKING bit */ | ||
| 175 | + | ||
| 176 | +#define HF2_GIF_MASK (1 << HF2_GIF_SHIFT) | ||
| 177 | +#define HF2_HIF_MASK (1 << HF2_HIF_SHIFT) | ||
| 178 | +#define HF2_NMI_MASK (1 << HF2_NMI_SHIFT) | ||
| 179 | +#define HF2_VINTR_MASK (1 << HF2_VINTR_SHIFT) | ||
| 180 | + | ||
| 175 | #define CR0_PE_MASK (1 << 0) | 181 | #define CR0_PE_MASK (1 << 0) |
| 176 | #define CR0_MP_MASK (1 << 1) | 182 | #define CR0_MP_MASK (1 << 1) |
| 177 | #define CR0_EM_MASK (1 << 2) | 183 | #define CR0_EM_MASK (1 << 2) |
| @@ -488,7 +494,9 @@ typedef struct CPUX86State { | @@ -488,7 +494,9 @@ typedef struct CPUX86State { | ||
| 488 | target_ulong cc_dst; | 494 | target_ulong cc_dst; |
| 489 | uint32_t cc_op; | 495 | uint32_t cc_op; |
| 490 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ | 496 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ |
| 491 | - uint32_t hflags; /* hidden flags, see HF_xxx constants */ | 497 | + uint32_t hflags; /* TB flags, see HF_xxx constants. These flags |
| 498 | + are known at translation time. */ | ||
| 499 | + uint32_t hflags2; /* various other flags, see HF2_xxx constants. */ | ||
| 492 | 500 | ||
| 493 | /* segments */ | 501 | /* segments */ |
| 494 | SegmentCache segs[6]; /* selector values */ | 502 | SegmentCache segs[6]; /* selector values */ |
| @@ -497,7 +505,7 @@ typedef struct CPUX86State { | @@ -497,7 +505,7 @@ typedef struct CPUX86State { | ||
| 497 | SegmentCache gdt; /* only base and limit are used */ | 505 | SegmentCache gdt; /* only base and limit are used */ |
| 498 | SegmentCache idt; /* only base and limit are used */ | 506 | SegmentCache idt; /* only base and limit are used */ |
| 499 | 507 | ||
| 500 | - target_ulong cr[9]; /* NOTE: cr1, cr5-7 are unused */ | 508 | + target_ulong cr[5]; /* NOTE: cr1 is unused */ |
| 501 | uint64_t a20_mask; | 509 | uint64_t a20_mask; |
| 502 | 510 | ||
| 503 | /* FPU state */ | 511 | /* FPU state */ |
| @@ -541,6 +549,7 @@ typedef struct CPUX86State { | @@ -541,6 +549,7 @@ typedef struct CPUX86State { | ||
| 541 | uint16_t intercept_dr_read; | 549 | uint16_t intercept_dr_read; |
| 542 | uint16_t intercept_dr_write; | 550 | uint16_t intercept_dr_write; |
| 543 | uint32_t intercept_exceptions; | 551 | uint32_t intercept_exceptions; |
| 552 | + uint8_t v_tpr; | ||
| 544 | 553 | ||
| 545 | #ifdef TARGET_X86_64 | 554 | #ifdef TARGET_X86_64 |
| 546 | target_ulong lstar; | 555 | target_ulong lstar; |
target-i386/helper.c
| @@ -374,7 +374,7 @@ void cpu_reset(CPUX86State *env) | @@ -374,7 +374,7 @@ void cpu_reset(CPUX86State *env) | ||
| 374 | #ifdef CONFIG_SOFTMMU | 374 | #ifdef CONFIG_SOFTMMU |
| 375 | env->hflags |= HF_SOFTMMU_MASK; | 375 | env->hflags |= HF_SOFTMMU_MASK; |
| 376 | #endif | 376 | #endif |
| 377 | - env->hflags |= HF_GIF_MASK; | 377 | + env->hflags2 |= HF2_GIF_MASK; |
| 378 | 378 | ||
| 379 | cpu_x86_update_cr0(env, 0x60000010); | 379 | cpu_x86_update_cr0(env, 0x60000010); |
| 380 | env->a20_mask = ~0x0; | 380 | env->a20_mask = ~0x0; |
target-i386/helper.h
| @@ -47,9 +47,6 @@ DEF_HELPER(target_ulong, helper_read_crN, (int reg)) | @@ -47,9 +47,6 @@ DEF_HELPER(target_ulong, helper_read_crN, (int reg)) | ||
| 47 | DEF_HELPER(void, helper_write_crN, (int reg, target_ulong t0)) | 47 | DEF_HELPER(void, helper_write_crN, (int reg, target_ulong t0)) |
| 48 | DEF_HELPER(void, helper_lmsw, (target_ulong t0)) | 48 | DEF_HELPER(void, helper_lmsw, (target_ulong t0)) |
| 49 | DEF_HELPER(void, helper_clts, (void)) | 49 | DEF_HELPER(void, helper_clts, (void)) |
| 50 | -#if !defined(CONFIG_USER_ONLY) | ||
| 51 | -DEF_HELPER(target_ulong, helper_movtl_T0_cr8, (void)) | ||
| 52 | -#endif | ||
| 53 | DEF_HELPER(void, helper_movl_drN_T0, (int reg, target_ulong t0)) | 50 | DEF_HELPER(void, helper_movl_drN_T0, (int reg, target_ulong t0)) |
| 54 | DEF_HELPER(void, helper_invlpg, (target_ulong addr)) | 51 | DEF_HELPER(void, helper_invlpg, (target_ulong addr)) |
| 55 | 52 | ||
| @@ -102,7 +99,7 @@ DEF_HELPER(void, helper_svm_check_intercept_param, (uint32_t type, uint64_t para | @@ -102,7 +99,7 @@ DEF_HELPER(void, helper_svm_check_intercept_param, (uint32_t type, uint64_t para | ||
| 102 | DEF_HELPER(void, helper_vmexit, (uint32_t exit_code, uint64_t exit_info_1)) | 99 | DEF_HELPER(void, helper_vmexit, (uint32_t exit_code, uint64_t exit_info_1)) |
| 103 | DEF_HELPER(void, helper_svm_check_io, (uint32_t port, uint32_t param, | 100 | DEF_HELPER(void, helper_svm_check_io, (uint32_t port, uint32_t param, |
| 104 | uint32_t next_eip_addend)) | 101 | uint32_t next_eip_addend)) |
| 105 | -DEF_HELPER(void, helper_vmrun, (int aflag)) | 102 | +DEF_HELPER(void, helper_vmrun, (int aflag, int next_eip_addend)) |
| 106 | DEF_HELPER(void, helper_vmmcall, (void)) | 103 | DEF_HELPER(void, helper_vmmcall, (void)) |
| 107 | DEF_HELPER(void, helper_vmload, (int aflag)) | 104 | DEF_HELPER(void, helper_vmload, (int aflag)) |
| 108 | DEF_HELPER(void, helper_vmsave, (int aflag)) | 105 | DEF_HELPER(void, helper_vmsave, (int aflag)) |
target-i386/op_helper.c
| @@ -2591,7 +2591,7 @@ void helper_iret_real(int shift) | @@ -2591,7 +2591,7 @@ void helper_iret_real(int shift) | ||
| 2591 | if (shift == 0) | 2591 | if (shift == 0) |
| 2592 | eflags_mask &= 0xffff; | 2592 | eflags_mask &= 0xffff; |
| 2593 | load_eflags(new_eflags, eflags_mask); | 2593 | load_eflags(new_eflags, eflags_mask); |
| 2594 | - env->hflags &= ~HF_NMI_MASK; | 2594 | + env->hflags2 &= ~HF2_NMI_MASK; |
| 2595 | } | 2595 | } |
| 2596 | 2596 | ||
| 2597 | static inline void validate_seg(int seg_reg, int cpl) | 2597 | static inline void validate_seg(int seg_reg, int cpl) |
| @@ -2843,7 +2843,7 @@ void helper_iret_protected(int shift, int next_eip) | @@ -2843,7 +2843,7 @@ void helper_iret_protected(int shift, int next_eip) | ||
| 2843 | } else { | 2843 | } else { |
| 2844 | helper_ret_protected(shift, 1, 0); | 2844 | helper_ret_protected(shift, 1, 0); |
| 2845 | } | 2845 | } |
| 2846 | - env->hflags &= ~HF_NMI_MASK; | 2846 | + env->hflags2 &= ~HF2_NMI_MASK; |
| 2847 | #ifdef USE_KQEMU | 2847 | #ifdef USE_KQEMU |
| 2848 | if (kqemu_is_ok(env)) { | 2848 | if (kqemu_is_ok(env)) { |
| 2849 | CC_OP = CC_OP_EFLAGS; | 2849 | CC_OP = CC_OP_EFLAGS; |
| @@ -2934,7 +2934,11 @@ target_ulong helper_read_crN(int reg) | @@ -2934,7 +2934,11 @@ target_ulong helper_read_crN(int reg) | ||
| 2934 | val = env->cr[reg]; | 2934 | val = env->cr[reg]; |
| 2935 | break; | 2935 | break; |
| 2936 | case 8: | 2936 | case 8: |
| 2937 | - val = cpu_get_apic_tpr(env); | 2937 | + if (!(env->hflags2 & HF2_VINTR_MASK)) { |
| 2938 | + val = cpu_get_apic_tpr(env); | ||
| 2939 | + } else { | ||
| 2940 | + val = env->v_tpr; | ||
| 2941 | + } | ||
| 2938 | break; | 2942 | break; |
| 2939 | } | 2943 | } |
| 2940 | return val; | 2944 | return val; |
| @@ -2954,8 +2958,10 @@ void helper_write_crN(int reg, target_ulong t0) | @@ -2954,8 +2958,10 @@ void helper_write_crN(int reg, target_ulong t0) | ||
| 2954 | cpu_x86_update_cr4(env, t0); | 2958 | cpu_x86_update_cr4(env, t0); |
| 2955 | break; | 2959 | break; |
| 2956 | case 8: | 2960 | case 8: |
| 2957 | - cpu_set_apic_tpr(env, t0); | ||
| 2958 | - env->cr[8] = t0; | 2961 | + if (!(env->hflags2 & HF2_VINTR_MASK)) { |
| 2962 | + cpu_set_apic_tpr(env, t0); | ||
| 2963 | + } | ||
| 2964 | + env->v_tpr = t0 & 0x0f; | ||
| 2959 | break; | 2965 | break; |
| 2960 | default: | 2966 | default: |
| 2961 | env->cr[reg] = t0; | 2967 | env->cr[reg] = t0; |
| @@ -2978,13 +2984,6 @@ void helper_clts(void) | @@ -2978,13 +2984,6 @@ void helper_clts(void) | ||
| 2978 | env->hflags &= ~HF_TS_MASK; | 2984 | env->hflags &= ~HF_TS_MASK; |
| 2979 | } | 2985 | } |
| 2980 | 2986 | ||
| 2981 | -#if !defined(CONFIG_USER_ONLY) | ||
| 2982 | -target_ulong helper_movtl_T0_cr8(void) | ||
| 2983 | -{ | ||
| 2984 | - return cpu_get_apic_tpr(env); | ||
| 2985 | -} | ||
| 2986 | -#endif | ||
| 2987 | - | ||
| 2988 | /* XXX: do more */ | 2987 | /* XXX: do more */ |
| 2989 | void helper_movl_drN_T0(int reg, target_ulong t0) | 2988 | void helper_movl_drN_T0(int reg, target_ulong t0) |
| 2990 | { | 2989 | { |
| @@ -4721,7 +4720,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) | @@ -4721,7 +4720,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) | ||
| 4721 | 4720 | ||
| 4722 | #if defined(CONFIG_USER_ONLY) | 4721 | #if defined(CONFIG_USER_ONLY) |
| 4723 | 4722 | ||
| 4724 | -void helper_vmrun(int aflag) | 4723 | +void helper_vmrun(int aflag, int next_eip_addend) |
| 4725 | { | 4724 | { |
| 4726 | } | 4725 | } |
| 4727 | void helper_vmmcall(void) | 4726 | void helper_vmmcall(void) |
| @@ -4791,7 +4790,7 @@ static inline void svm_load_seg_cache(target_phys_addr_t addr, | @@ -4791,7 +4790,7 @@ static inline void svm_load_seg_cache(target_phys_addr_t addr, | ||
| 4791 | sc->base, sc->limit, sc->flags); | 4790 | sc->base, sc->limit, sc->flags); |
| 4792 | } | 4791 | } |
| 4793 | 4792 | ||
| 4794 | -void helper_vmrun(int aflag) | 4793 | +void helper_vmrun(int aflag, int next_eip_addend) |
| 4795 | { | 4794 | { |
| 4796 | target_ulong addr; | 4795 | target_ulong addr; |
| 4797 | uint32_t event_inj; | 4796 | uint32_t event_inj; |
| @@ -4820,7 +4819,6 @@ void helper_vmrun(int aflag) | @@ -4820,7 +4819,6 @@ void helper_vmrun(int aflag) | ||
| 4820 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]); | 4819 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]); |
| 4821 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]); | 4820 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]); |
| 4822 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]); | 4821 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]); |
| 4823 | - stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]); | ||
| 4824 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]); | 4822 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]); |
| 4825 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]); | 4823 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]); |
| 4826 | 4824 | ||
| @@ -4836,7 +4834,8 @@ void helper_vmrun(int aflag) | @@ -4836,7 +4834,8 @@ void helper_vmrun(int aflag) | ||
| 4836 | svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), | 4834 | svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), |
| 4837 | &env->segs[R_DS]); | 4835 | &env->segs[R_DS]); |
| 4838 | 4836 | ||
| 4839 | - stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP); | 4837 | + stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), |
| 4838 | + EIP + next_eip_addend); | ||
| 4840 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP); | 4839 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP); |
| 4841 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX); | 4840 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX); |
| 4842 | 4841 | ||
| @@ -4866,17 +4865,16 @@ void helper_vmrun(int aflag) | @@ -4866,17 +4865,16 @@ void helper_vmrun(int aflag) | ||
| 4866 | cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3))); | 4865 | cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3))); |
| 4867 | env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2)); | 4866 | env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2)); |
| 4868 | int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)); | 4867 | int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)); |
| 4868 | + env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); | ||
| 4869 | if (int_ctl & V_INTR_MASKING_MASK) { | 4869 | if (int_ctl & V_INTR_MASKING_MASK) { |
| 4870 | - env->cr[8] = int_ctl & V_TPR_MASK; | ||
| 4871 | - cpu_set_apic_tpr(env, env->cr[8]); | 4870 | + env->v_tpr = int_ctl & V_TPR_MASK; |
| 4871 | + env->hflags2 |= HF2_VINTR_MASK; | ||
| 4872 | if (env->eflags & IF_MASK) | 4872 | if (env->eflags & IF_MASK) |
| 4873 | - env->hflags |= HF_HIF_MASK; | 4873 | + env->hflags2 |= HF2_HIF_MASK; |
| 4874 | } | 4874 | } |
| 4875 | 4875 | ||
| 4876 | -#ifdef TARGET_X86_64 | ||
| 4877 | cpu_load_efer(env, | 4876 | cpu_load_efer(env, |
| 4878 | ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer))); | 4877 | ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer))); |
| 4879 | -#endif | ||
| 4880 | env->eflags = 0; | 4878 | env->eflags = 0; |
| 4881 | load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)), | 4879 | load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)), |
| 4882 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); | 4880 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
| @@ -4912,6 +4910,10 @@ void helper_vmrun(int aflag) | @@ -4912,6 +4910,10 @@ void helper_vmrun(int aflag) | ||
| 4912 | 4910 | ||
| 4913 | helper_stgi(); | 4911 | helper_stgi(); |
| 4914 | 4912 | ||
| 4913 | + if (int_ctl & V_IRQ_MASK) { | ||
| 4914 | + env->interrupt_request |= CPU_INTERRUPT_VIRQ; | ||
| 4915 | + } | ||
| 4916 | + | ||
| 4915 | /* maybe we need to inject an event */ | 4917 | /* maybe we need to inject an event */ |
| 4916 | event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); | 4918 | event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); |
| 4917 | if (event_inj & SVM_EVTINJ_VALID) { | 4919 | if (event_inj & SVM_EVTINJ_VALID) { |
| @@ -4931,14 +4933,17 @@ void helper_vmrun(int aflag) | @@ -4931,14 +4933,17 @@ void helper_vmrun(int aflag) | ||
| 4931 | env->exception_next_eip = -1; | 4933 | env->exception_next_eip = -1; |
| 4932 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4934 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4933 | fprintf(logfile, "INTR"); | 4935 | fprintf(logfile, "INTR"); |
| 4936 | + /* XXX: is it always correct ? */ | ||
| 4937 | + do_interrupt(vector, 0, 0, 0, 1); | ||
| 4934 | break; | 4938 | break; |
| 4935 | case SVM_EVTINJ_TYPE_NMI: | 4939 | case SVM_EVTINJ_TYPE_NMI: |
| 4936 | - env->exception_index = vector; | 4940 | + env->exception_index = EXCP02_NMI; |
| 4937 | env->error_code = event_inj_err; | 4941 | env->error_code = event_inj_err; |
| 4938 | env->exception_is_int = 0; | 4942 | env->exception_is_int = 0; |
| 4939 | env->exception_next_eip = EIP; | 4943 | env->exception_next_eip = EIP; |
| 4940 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4944 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4941 | fprintf(logfile, "NMI"); | 4945 | fprintf(logfile, "NMI"); |
| 4946 | + cpu_loop_exit(); | ||
| 4942 | break; | 4947 | break; |
| 4943 | case SVM_EVTINJ_TYPE_EXEPT: | 4948 | case SVM_EVTINJ_TYPE_EXEPT: |
| 4944 | env->exception_index = vector; | 4949 | env->exception_index = vector; |
| @@ -4947,6 +4952,7 @@ void helper_vmrun(int aflag) | @@ -4947,6 +4952,7 @@ void helper_vmrun(int aflag) | ||
| 4947 | env->exception_next_eip = -1; | 4952 | env->exception_next_eip = -1; |
| 4948 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4953 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4949 | fprintf(logfile, "EXEPT"); | 4954 | fprintf(logfile, "EXEPT"); |
| 4955 | + cpu_loop_exit(); | ||
| 4950 | break; | 4956 | break; |
| 4951 | case SVM_EVTINJ_TYPE_SOFT: | 4957 | case SVM_EVTINJ_TYPE_SOFT: |
| 4952 | env->exception_index = vector; | 4958 | env->exception_index = vector; |
| @@ -4955,17 +4961,12 @@ void helper_vmrun(int aflag) | @@ -4955,17 +4961,12 @@ void helper_vmrun(int aflag) | ||
| 4955 | env->exception_next_eip = EIP; | 4961 | env->exception_next_eip = EIP; |
| 4956 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4962 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4957 | fprintf(logfile, "SOFT"); | 4963 | fprintf(logfile, "SOFT"); |
| 4964 | + cpu_loop_exit(); | ||
| 4958 | break; | 4965 | break; |
| 4959 | } | 4966 | } |
| 4960 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4967 | if (loglevel & CPU_LOG_TB_IN_ASM) |
| 4961 | fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); | 4968 | fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); |
| 4962 | } | 4969 | } |
| 4963 | - if ((int_ctl & V_IRQ_MASK) || | ||
| 4964 | - (env->intercept & (1ULL << (SVM_EXIT_INTR - SVM_EXIT_INTR)))) { | ||
| 4965 | - env->interrupt_request |= CPU_INTERRUPT_VIRQ; | ||
| 4966 | - } | ||
| 4967 | - | ||
| 4968 | - cpu_loop_exit(); | ||
| 4969 | } | 4970 | } |
| 4970 | 4971 | ||
| 4971 | void helper_vmmcall(void) | 4972 | void helper_vmmcall(void) |
| @@ -5049,13 +5050,13 @@ void helper_vmsave(int aflag) | @@ -5049,13 +5050,13 @@ void helper_vmsave(int aflag) | ||
| 5049 | void helper_stgi(void) | 5050 | void helper_stgi(void) |
| 5050 | { | 5051 | { |
| 5051 | helper_svm_check_intercept_param(SVM_EXIT_STGI, 0); | 5052 | helper_svm_check_intercept_param(SVM_EXIT_STGI, 0); |
| 5052 | - env->hflags |= HF_GIF_MASK; | 5053 | + env->hflags2 |= HF2_GIF_MASK; |
| 5053 | } | 5054 | } |
| 5054 | 5055 | ||
| 5055 | void helper_clgi(void) | 5056 | void helper_clgi(void) |
| 5056 | { | 5057 | { |
| 5057 | helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0); | 5058 | helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0); |
| 5058 | - env->hflags &= ~HF_GIF_MASK; | 5059 | + env->hflags2 &= ~HF2_GIF_MASK; |
| 5059 | } | 5060 | } |
| 5060 | 5061 | ||
| 5061 | void helper_skinit(void) | 5062 | void helper_skinit(void) |
| @@ -5204,11 +5205,12 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5204,11 +5205,12 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5204 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]); | 5205 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]); |
| 5205 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]); | 5206 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]); |
| 5206 | 5207 | ||
| 5207 | - if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) { | ||
| 5208 | - int_ctl &= ~V_TPR_MASK; | ||
| 5209 | - int_ctl |= env->cr[8] & V_TPR_MASK; | ||
| 5210 | - stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl); | ||
| 5211 | - } | 5208 | + int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)); |
| 5209 | + int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK); | ||
| 5210 | + int_ctl |= env->v_tpr & V_TPR_MASK; | ||
| 5211 | + if (env->interrupt_request & CPU_INTERRUPT_VIRQ) | ||
| 5212 | + int_ctl |= V_IRQ_MASK; | ||
| 5213 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl); | ||
| 5212 | 5214 | ||
| 5213 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags()); | 5215 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags()); |
| 5214 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip); | 5216 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip); |
| @@ -5219,7 +5221,7 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5219,7 +5221,7 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5219 | stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK); | 5221 | stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK); |
| 5220 | 5222 | ||
| 5221 | /* Reload the host state from vm_hsave */ | 5223 | /* Reload the host state from vm_hsave */ |
| 5222 | - env->hflags &= ~HF_HIF_MASK; | 5224 | + env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); |
| 5223 | env->hflags &= ~HF_SVMI_MASK; | 5225 | env->hflags &= ~HF_SVMI_MASK; |
| 5224 | env->intercept = 0; | 5226 | env->intercept = 0; |
| 5225 | env->intercept_exceptions = 0; | 5227 | env->intercept_exceptions = 0; |
| @@ -5234,17 +5236,10 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | @@ -5234,17 +5236,10 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5234 | cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK); | 5236 | cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK); |
| 5235 | cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4))); | 5237 | cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4))); |
| 5236 | cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3))); | 5238 | cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3))); |
| 5237 | - if (int_ctl & V_INTR_MASKING_MASK) { | ||
| 5238 | - env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8)); | ||
| 5239 | - cpu_set_apic_tpr(env, env->cr[8]); | ||
| 5240 | - } | ||
| 5241 | /* we need to set the efer after the crs so the hidden flags get | 5239 | /* we need to set the efer after the crs so the hidden flags get |
| 5242 | set properly */ | 5240 | set properly */ |
| 5243 | -#ifdef TARGET_X86_64 | ||
| 5244 | cpu_load_efer(env, | 5241 | cpu_load_efer(env, |
| 5245 | ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer))); | 5242 | ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer))); |
| 5246 | -#endif | ||
| 5247 | - | ||
| 5248 | env->eflags = 0; | 5243 | env->eflags = 0; |
| 5249 | load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)), | 5244 | load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)), |
| 5250 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); | 5245 | ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
target-i386/svm.h
| @@ -205,9 +205,7 @@ struct __attribute__ ((__packed__)) vmcb_save_area { | @@ -205,9 +205,7 @@ struct __attribute__ ((__packed__)) vmcb_save_area { | ||
| 205 | uint64_t sysenter_esp; | 205 | uint64_t sysenter_esp; |
| 206 | uint64_t sysenter_eip; | 206 | uint64_t sysenter_eip; |
| 207 | uint64_t cr2; | 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 */ | 208 | + uint8_t reserved_6[32]; |
| 211 | uint64_t g_pat; | 209 | uint64_t g_pat; |
| 212 | uint64_t dbgctl; | 210 | uint64_t dbgctl; |
| 213 | uint64_t br_from; | 211 | uint64_t br_from; |
target-i386/translate.c
| @@ -6569,10 +6569,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6569,10 +6569,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6569 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 6569 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 6570 | break; | 6570 | break; |
| 6571 | } else { | 6571 | } else { |
| 6572 | - tcg_gen_helper_0_1(helper_vmrun, | ||
| 6573 | - tcg_const_i32(s->aflag)); | ||
| 6574 | - s->cc_op = CC_OP_EFLAGS; | ||
| 6575 | - gen_eob(s); | 6572 | + tcg_gen_helper_0_2(helper_vmrun, |
| 6573 | + tcg_const_i32(s->aflag), | ||
| 6574 | + tcg_const_i32(s->pc - pc_start)); | ||
| 6575 | + tcg_gen_exit_tb(0); | ||
| 6576 | + s->is_jmp = 3; | ||
| 6576 | } | 6577 | } |
| 6577 | break; | 6578 | break; |
| 6578 | case 1: /* VMMCALL */ | 6579 | case 1: /* VMMCALL */ |