SVM VINTR fix, by Alexander Graf.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3248 c046a42c-6fe2-441c-8c8c-71466251a162
master
ths 2007-09-27 01:52:00 +00:00
parent 40d0591e2c
commit 526216880d
3 changed files with 13 additions and 6 deletions

View File

@ -409,7 +409,7 @@ int cpu_exec(CPUState *env1)
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
svm_check_intercept(SVM_EXIT_INTR);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
@ -428,12 +428,13 @@ int cpu_exec(CPUState *env1)
int intno;
/* FIXME: this should respect TPR */
env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
svm_check_intercept(SVM_EXIT_VINTR);
intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
if (loglevel & CPU_LOG_TB_IN_ASM)
fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
do_interrupt(intno, 0, 0, -1, 1);
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else

View File

@ -4120,8 +4120,9 @@ void helper_vmrun(target_ulong addr)
if (loglevel & CPU_LOG_TB_IN_ASM)
fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
}
if (int_ctl & V_IRQ_MASK)
if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
env->interrupt_request |= CPU_INTERRUPT_VIRQ;
}
cpu_loop_exit();
}
@ -4283,6 +4284,13 @@ void vmexit(uint64_t exit_code, uint64_t exit_info_1)
ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
EIP);
if(env->hflags & HF_INHIBIT_IRQ_MASK) {
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
env->hflags &= ~HF_INHIBIT_IRQ_MASK;
} else {
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
}
/* Save the VM state in the vmcb */
SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);

View File

@ -5551,8 +5551,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
gen_op_set_inhibit_irq();
/* give a chance to handle pending irqs */
gen_jmp_im(s->pc - s->cs_base);
if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VINTR))
break;
gen_eob(s);
} else {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);