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 */ |