Commit 526216880d5c4cb2507bdb22d6a5d33016f38104
1 parent
40d0591e
SVM VINTR fix, by Alexander Graf.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3248 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
13 additions
and
6 deletions
cpu-exec.c
@@ -409,7 +409,7 @@ int cpu_exec(CPUState *env1) | @@ -409,7 +409,7 @@ int cpu_exec(CPUState *env1) | ||
409 | !(env->hflags & HF_INHIBIT_IRQ_MASK)) { | 409 | !(env->hflags & HF_INHIBIT_IRQ_MASK)) { |
410 | int intno; | 410 | int intno; |
411 | svm_check_intercept(SVM_EXIT_INTR); | 411 | svm_check_intercept(SVM_EXIT_INTR); |
412 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | 412 | + env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); |
413 | intno = cpu_get_pic_interrupt(env); | 413 | intno = cpu_get_pic_interrupt(env); |
414 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 414 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
415 | fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); | 415 | fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); |
@@ -428,12 +428,13 @@ int cpu_exec(CPUState *env1) | @@ -428,12 +428,13 @@ int cpu_exec(CPUState *env1) | ||
428 | int intno; | 428 | int intno; |
429 | /* FIXME: this should respect TPR */ | 429 | /* FIXME: this should respect TPR */ |
430 | env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; | 430 | env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; |
431 | - stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), | ||
432 | - ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK); | 431 | + svm_check_intercept(SVM_EXIT_VINTR); |
433 | intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); | 432 | intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); |
434 | if (loglevel & CPU_LOG_TB_IN_ASM) | 433 | if (loglevel & CPU_LOG_TB_IN_ASM) |
435 | fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); | 434 | fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); |
436 | do_interrupt(intno, 0, 0, -1, 1); | 435 | do_interrupt(intno, 0, 0, -1, 1); |
436 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), | ||
437 | + ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK); | ||
437 | #if defined(__sparc__) && !defined(HOST_SOLARIS) | 438 | #if defined(__sparc__) && !defined(HOST_SOLARIS) |
438 | tmp_T0 = 0; | 439 | tmp_T0 = 0; |
439 | #else | 440 | #else |
target-i386/helper.c
@@ -4120,8 +4120,9 @@ void helper_vmrun(target_ulong addr) | @@ -4120,8 +4120,9 @@ void helper_vmrun(target_ulong addr) | ||
4120 | if (loglevel & CPU_LOG_TB_IN_ASM) | 4120 | if (loglevel & CPU_LOG_TB_IN_ASM) |
4121 | fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); | 4121 | fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); |
4122 | } | 4122 | } |
4123 | - if (int_ctl & V_IRQ_MASK) | 4123 | + if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) { |
4124 | env->interrupt_request |= CPU_INTERRUPT_VIRQ; | 4124 | env->interrupt_request |= CPU_INTERRUPT_VIRQ; |
4125 | + } | ||
4125 | 4126 | ||
4126 | cpu_loop_exit(); | 4127 | cpu_loop_exit(); |
4127 | } | 4128 | } |
@@ -4283,6 +4284,13 @@ void vmexit(uint64_t exit_code, uint64_t exit_info_1) | @@ -4283,6 +4284,13 @@ void vmexit(uint64_t exit_code, uint64_t exit_info_1) | ||
4283 | ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)), | 4284 | ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)), |
4284 | EIP); | 4285 | EIP); |
4285 | 4286 | ||
4287 | + if(env->hflags & HF_INHIBIT_IRQ_MASK) { | ||
4288 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK); | ||
4289 | + env->hflags &= ~HF_INHIBIT_IRQ_MASK; | ||
4290 | + } else { | ||
4291 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0); | ||
4292 | + } | ||
4293 | + | ||
4286 | /* Save the VM state in the vmcb */ | 4294 | /* Save the VM state in the vmcb */ |
4287 | SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es); | 4295 | SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es); |
4288 | SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs); | 4296 | SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs); |
target-i386/translate.c
@@ -5551,8 +5551,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5551,8 +5551,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
5551 | gen_op_set_inhibit_irq(); | 5551 | gen_op_set_inhibit_irq(); |
5552 | /* give a chance to handle pending irqs */ | 5552 | /* give a chance to handle pending irqs */ |
5553 | gen_jmp_im(s->pc - s->cs_base); | 5553 | gen_jmp_im(s->pc - s->cs_base); |
5554 | - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VINTR)) | ||
5555 | - break; | ||
5556 | gen_eob(s); | 5554 | gen_eob(s); |
5557 | } else { | 5555 | } else { |
5558 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 5556 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |