Message ID | 20090323101211.25798.89641.stgit@dhcp-1-237.tlv.redhat.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Gleb Natapov wrote: > kvm_vcpu_block() unhalts vpu on an interrupt/timer without checking > if interrupt window is actually opened. > > > +static int svm_interrupt_allowed(struct kvm_vcpu *vcpu) > +{ > + struct vcpu_svm *svm = to_svm(vcpu); > + struct vmcb *vmcb = svm->vmcb; > + return (vmcb->save.rflags & X86_EFLAGS_IF) && > + !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) && > + (svm->vcpu.arch.hflags & HF_GIF_MASK); > +} > + > > +static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) > +{ > + vmx_update_window_states(vcpu); > + return vcpu->arch.interrupt_window_open; > +} > + > static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) > } > + > +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) > +{ > + return kvm_x86_ops->interrupt_allowed(vcpu); > +} > If the guest enables interrupts but sets tpr/cr8 to block interrupts, we'll spin (like we do now). So I think this should be called kvm_arch_can_accept_interrupt() and take tpr into account.
Avi Kivity wrote: > Gleb Natapov wrote: >> kvm_vcpu_block() unhalts vpu on an interrupt/timer without checking >> if interrupt window is actually opened. >> >> >> +static int svm_interrupt_allowed(struct kvm_vcpu *vcpu) >> +{ >> + struct vcpu_svm *svm = to_svm(vcpu); >> + struct vmcb *vmcb = svm->vmcb; >> + return (vmcb->save.rflags & X86_EFLAGS_IF) && + >> !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) && >> + (svm->vcpu.arch.hflags & HF_GIF_MASK); >> +} >> + >> >> +static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) >> +{ >> + vmx_update_window_states(vcpu); >> + return vcpu->arch.interrupt_window_open; >> +} >> + >> static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) >> } >> + >> +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) >> +{ >> + return kvm_x86_ops->interrupt_allowed(vcpu); >> +} >> > > If the guest enables interrupts but sets tpr/cr8 to block interrupts, > we'll spin (like we do now). > > So I think this should be called kvm_arch_can_accept_interrupt() and > take tpr into account. > kvm_cpu_has_interrupt() takes the tpr into account, so we're okay here. Marcelo, Sheng?
On Monday 23 March 2009 23:17:42 Avi Kivity wrote: > Avi Kivity wrote: > > Gleb Natapov wrote: > >> kvm_vcpu_block() unhalts vpu on an interrupt/timer without checking > >> if interrupt window is actually opened. > >> > >> > >> +static int svm_interrupt_allowed(struct kvm_vcpu *vcpu) > >> +{ > >> + struct vcpu_svm *svm = to_svm(vcpu); > >> + struct vmcb *vmcb = svm->vmcb; > >> + return (vmcb->save.rflags & X86_EFLAGS_IF) && + > >> !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) && > >> + (svm->vcpu.arch.hflags & HF_GIF_MASK); > >> +} > >> + > >> > >> +static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) > >> +{ > >> + vmx_update_window_states(vcpu); > >> + return vcpu->arch.interrupt_window_open; > >> +} > >> + > >> static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) > >> } > >> + > >> +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) > >> +{ > >> + return kvm_x86_ops->interrupt_allowed(vcpu); > >> +} > > > > If the guest enables interrupts but sets tpr/cr8 to block interrupts, > > we'll spin (like we do now). > > > > So I think this should be called kvm_arch_can_accept_interrupt() and > > take tpr into account. > > kvm_cpu_has_interrupt() takes the tpr into account, so we're okay here. > > Marcelo, Sheng? Yes, looks good to me.
Gleb Natapov wrote: > kvm_vcpu_block() unhalts vpu on an interrupt/timer without checking > if interrupt window is actually opened. > > Applied both, thanks.
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index db0b2a5..fdda799 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -1960,6 +1960,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) return 0; } +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) +{ + /* do real check here */ + return 1; +} + int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) { return vcpu->arch.timer_fired; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 9057335..2cf915e 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -41,6 +41,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v) return !!(v->arch.pending_exceptions); } +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) +{ + /* do real check here */ + return 1; +} + int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) { return !(v->arch.msr & MSR_WE); diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 0189356..4ed4c3a 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -318,6 +318,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) return rc; } +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) +{ + /* do real check here */ + return 1; +} + int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) { return 0; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4627627..8351c4d 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -521,7 +521,7 @@ struct kvm_x86_ops { void (*inject_pending_irq)(struct kvm_vcpu *vcpu); void (*inject_pending_vectors)(struct kvm_vcpu *vcpu, struct kvm_run *run); - + int (*interrupt_allowed)(struct kvm_vcpu *vcpu); int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); int (*get_tdp_level)(void); int (*get_mt_mask_shift)(void); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index da23fd3..70c9dd3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2285,6 +2285,15 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu) vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK; } +static int svm_interrupt_allowed(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm = to_svm(vcpu); + struct vmcb *vmcb = svm->vmcb; + return (vmcb->save.rflags & X86_EFLAGS_IF) && + !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) && + (svm->vcpu.arch.hflags & HF_GIF_MASK); +} + static void svm_intr_assist(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -2664,6 +2673,7 @@ static struct kvm_x86_ops svm_x86_ops = { .exception_injected = svm_exception_injected, .inject_pending_irq = svm_intr_assist, .inject_pending_vectors = do_interrupt_requests, + .interrupt_allowed = svm_interrupt_allowed, .set_tss_addr = svm_set_tss_addr, .get_tdp_level = get_npt_level, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5cf28df..dcc1036 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2489,6 +2489,12 @@ static void vmx_update_window_states(struct kvm_vcpu *vcpu) GUEST_INTR_STATE_MOV_SS))); } +static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) +{ + vmx_update_window_states(vcpu); + return vcpu->arch.interrupt_window_open; +} + static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) { int word_index = __ffs(vcpu->arch.irq_summary); @@ -3703,7 +3709,7 @@ static struct kvm_x86_ops vmx_x86_ops = { .exception_injected = vmx_exception_injected, .inject_pending_irq = vmx_intr_assist, .inject_pending_vectors = do_interrupt_requests, - + .interrupt_allowed = vmx_interrupt_allowed, .set_tss_addr = vmx_set_tss_addr, .get_tdp_level = get_ept_level, .get_mt_mask_shift = vmx_get_mt_mask_shift, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index cfe8213..83822c0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4465,3 +4465,8 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu) smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0); put_cpu(); } + +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) +{ + return kvm_x86_ops->interrupt_allowed(vcpu); +} diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 11eb702..095ebb6 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -298,6 +298,7 @@ int kvm_arch_hardware_setup(void); void kvm_arch_hardware_unsetup(void); void kvm_arch_check_processor_compat(void *rtn); int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu); +int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu); void kvm_free_physmem(struct kvm *kvm); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 273490f..8aa3b95 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1612,7 +1612,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) for (;;) { prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); - if (kvm_cpu_has_interrupt(vcpu) || + if ((kvm_arch_interrupt_allowed(vcpu) && + kvm_cpu_has_interrupt(vcpu)) || kvm_arch_vcpu_runnable(vcpu)) { set_bit(KVM_REQ_UNHALT, &vcpu->requests); break;
kvm_vcpu_block() unhalts vpu on an interrupt/timer without checking if interrupt window is actually opened. Signed-off-by: Gleb Natapov <gleb@redhat.com> --- arch/ia64/kvm/kvm-ia64.c | 6 ++++++ arch/powerpc/kvm/powerpc.c | 6 ++++++ arch/s390/kvm/interrupt.c | 6 ++++++ arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/svm.c | 10 ++++++++++ arch/x86/kvm/vmx.c | 8 +++++++- arch/x86/kvm/x86.c | 5 +++++ include/linux/kvm_host.h | 1 + virt/kvm/kvm_main.c | 3 ++- 9 files changed, 44 insertions(+), 3 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html