Commit 8061823a authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity

KVM: Make kvm_cpu_(has|get)_interrupt() work for userspace irqchip too

At the vector level, kernel and userspace irqchip are fairly similar.
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 34382539
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "irq.h" #include "irq.h"
#include "i8254.h" #include "i8254.h"
#include "x86.h"
/* /*
* check if there are pending timer events * check if there are pending timer events
...@@ -48,6 +49,9 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v) ...@@ -48,6 +49,9 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
{ {
struct kvm_pic *s; struct kvm_pic *s;
if (!irqchip_in_kernel(v->kvm))
return v->arch.irq_summary;
if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */ if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */
if (kvm_apic_accept_pic_intr(v)) { if (kvm_apic_accept_pic_intr(v)) {
s = pic_irqchip(v->kvm); /* PIC */ s = pic_irqchip(v->kvm); /* PIC */
...@@ -67,6 +71,9 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) ...@@ -67,6 +71,9 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
struct kvm_pic *s; struct kvm_pic *s;
int vector; int vector;
if (!irqchip_in_kernel(v->kvm))
return kvm_pop_irq(v);
vector = kvm_get_apic_interrupt(v); /* APIC */ vector = kvm_get_apic_interrupt(v); /* APIC */
if (vector == -1) { if (vector == -1) {
if (kvm_apic_accept_pic_intr(v)) { if (kvm_apic_accept_pic_intr(v)) {
......
...@@ -2091,8 +2091,9 @@ static int interrupt_window_interception(struct vcpu_svm *svm, ...@@ -2091,8 +2091,9 @@ static int interrupt_window_interception(struct vcpu_svm *svm,
* If the user space waits to inject interrupts, exit as soon as * If the user space waits to inject interrupts, exit as soon as
* possible * possible
*/ */
if (kvm_run->request_interrupt_window && if (!irqchip_in_kernel(svm->vcpu.kvm) &&
!svm->vcpu.arch.irq_summary) { kvm_run->request_interrupt_window &&
!kvm_cpu_has_interrupt(&svm->vcpu)) {
++svm->vcpu.stat.irq_window_exits; ++svm->vcpu.stat.irq_window_exits;
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0; return 0;
...@@ -2373,7 +2374,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, ...@@ -2373,7 +2374,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
(svm->vmcb->save.rflags & X86_EFLAGS_IF) && (svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
(svm->vcpu.arch.hflags & HF_GIF_MASK)); (svm->vcpu.arch.hflags & HF_GIF_MASK));
if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary) if (svm->vcpu.arch.interrupt_window_open &&
kvm_cpu_has_interrupt(&svm->vcpu))
/* /*
* If interrupts enabled, and not blocked by sti or mov ss. Good. * If interrupts enabled, and not blocked by sti or mov ss. Good.
*/ */
...@@ -2383,7 +2385,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, ...@@ -2383,7 +2385,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
* Interrupts blocked. Wait for unblock. * Interrupts blocked. Wait for unblock.
*/ */
if (!svm->vcpu.arch.interrupt_window_open && if (!svm->vcpu.arch.interrupt_window_open &&
(svm->vcpu.arch.irq_summary || kvm_run->request_interrupt_window)) (kvm_cpu_has_interrupt(&svm->vcpu) ||
kvm_run->request_interrupt_window))
svm_set_vintr(svm); svm_set_vintr(svm);
else else
svm_clear_vintr(svm); svm_clear_vintr(svm);
......
...@@ -2535,21 +2535,20 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, ...@@ -2535,21 +2535,20 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
vmx_inject_nmi(vcpu); vmx_inject_nmi(vcpu);
if (vcpu->arch.nmi_pending) if (vcpu->arch.nmi_pending)
enable_nmi_window(vcpu); enable_nmi_window(vcpu);
else if (vcpu->arch.irq_summary else if (kvm_cpu_has_interrupt(vcpu) ||
|| kvm_run->request_interrupt_window) kvm_run->request_interrupt_window)
enable_irq_window(vcpu); enable_irq_window(vcpu);
return; return;
} }
if (vcpu->arch.interrupt_window_open) { if (vcpu->arch.interrupt_window_open) {
if (vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending) if (kvm_cpu_has_interrupt(vcpu) && !vcpu->arch.interrupt.pending)
kvm_queue_interrupt(vcpu, kvm_pop_irq(vcpu)); kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
if (vcpu->arch.interrupt.pending) if (vcpu->arch.interrupt.pending)
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr); vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
} } else if(kvm_cpu_has_interrupt(vcpu) ||
if (!vcpu->arch.interrupt_window_open && kvm_run->request_interrupt_window)
(vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
enable_irq_window(vcpu); enable_irq_window(vcpu);
} }
...@@ -2976,8 +2975,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu, ...@@ -2976,8 +2975,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
* If the user space waits to inject interrupts, exit as soon as * If the user space waits to inject interrupts, exit as soon as
* possible * possible
*/ */
if (kvm_run->request_interrupt_window && if (!irqchip_in_kernel(vcpu->kvm) &&
!vcpu->arch.irq_summary) { kvm_run->request_interrupt_window &&
!kvm_cpu_has_interrupt(vcpu)) {
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0; return 0;
} }
......
...@@ -3069,7 +3069,7 @@ EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); ...@@ -3069,7 +3069,7 @@ EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu, static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run) struct kvm_run *kvm_run)
{ {
return (!vcpu->arch.irq_summary && return (!irqchip_in_kernel(vcpu->kvm) && !kvm_cpu_has_interrupt(vcpu) &&
kvm_run->request_interrupt_window && kvm_run->request_interrupt_window &&
vcpu->arch.interrupt_window_open && vcpu->arch.interrupt_window_open &&
(kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF)); (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF));
...@@ -3086,7 +3086,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu, ...@@ -3086,7 +3086,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
else else
kvm_run->ready_for_interrupt_injection = kvm_run->ready_for_interrupt_injection =
(vcpu->arch.interrupt_window_open && (vcpu->arch.interrupt_window_open &&
vcpu->arch.irq_summary == 0); !kvm_cpu_has_interrupt(vcpu));
} }
static void vapic_enter(struct kvm_vcpu *vcpu) static void vapic_enter(struct kvm_vcpu *vcpu)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment