interrupt unhalts vcpu when it shouldn't
PATCH 1/1 interrupt unhalts vcpu when it shouldn't
kvm_vcpu_block() unhalts vcpu on an interrupt/timer without checking if interrupt window is actually opened. Solve this by checking interrupt windows in kvm_vcpu_block().
Signed-off-by Gleb Natapov <[email protected]>
arch/ia64/kvm/kvm-ia64.c +9 -3
@@ -488,10 +488,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)hrtimer_cancel (p_ht); vcpu->arch.ht_active =0 ; -if (test_and_clear_bit (KVM_REQ_UNHALT , &vcpu->requests)) +if (test_and_clear_bit (KVM_REQ_UNHALT , &vcpu->requests) || +kvm_cpu_has_pending_timer (vcpu))if (vcpu->arch.mp_state ==KVM_MP_STATE_HALTED ) - vcpu->arch.mp_state = -KVM_MP_STATE_RUNNABLE ; + vcpu->arch.mp_state =KVM_MP_STATE_RUNNABLE ;if (vcpu->arch.mp_state !=KVM_MP_STATE_RUNNABLE )return -EINTR ;
@@ -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;
arch/powerpc/kvm/powerpc.c +6 -0
@@ -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 );
arch/s390/kvm/interrupt.c +6 -0
@@ -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 ;
arch/x86/include/asm/kvm_host.h +1 -1
@@ -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 );
arch/x86/kvm/svm.c +10 -0
@@ -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);
@@ -2672,6 +2681,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,
arch/x86/kvm/vmx.c +7 -1
@@ -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,
arch/x86/kvm/x86.c +36 -23
83 lines not on this page · raw message
include/linux/kvm_host.h +1 -0
@@ -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);
virt/kvm/kvm_main.c +5 -3
@@ -1612,12 +1612,14 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)for (;;) {prepare_to_wait (&vcpu->wq, &wait,TASK_INTERRUPTIBLE ); -if (kvm_cpu_has_interrupt (vcpu) || -kvm_cpu_has_pending_timer (vcpu) || -kvm_arch_vcpu_runnable (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 ; } +if (kvm_cpu_has_pending_timer (vcpu)) +break ;if (signal_pending (current))break ;
--
Gleb.