Commit 72c3bcdc authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint

Centralize handling of interrupts from the userspace APIC
in kvm_cpu_has_extint and kvm_cpu_get_extint, since
userspace APIC interrupts are handled more or less the
same as ExtINTs are with split irqchip.  This removes
duplicated code from kvm_cpu_has_injectable_intr and
kvm_cpu_has_interrupt, and makes the code more similar
between kvm_cpu_has_{extint,interrupt} on one side
and kvm_cpu_get_{extint,interrupt} on the other.

Cc: stable@vger.kernel.org
Reviewed-by: default avatarFilippo Sironi <sironi@amazon.de>
Reviewed-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Tested-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 545f6394
...@@ -41,28 +41,9 @@ static int pending_userspace_extint(struct kvm_vcpu *v) ...@@ -41,28 +41,9 @@ static int pending_userspace_extint(struct kvm_vcpu *v)
* non-APIC source without intack. * non-APIC source without intack.
*/ */
static int kvm_cpu_has_extint(struct kvm_vcpu *v) static int kvm_cpu_has_extint(struct kvm_vcpu *v)
{
u8 accept = kvm_apic_accept_pic_intr(v);
if (accept) {
if (irqchip_split(v->kvm))
return pending_userspace_extint(v);
else
return v->kvm->arch.vpic->output;
} else
return 0;
}
/*
* check if there is injectable interrupt:
* when virtual interrupt delivery enabled,
* interrupt from apic will handled by hardware,
* we don't need to check it here.
*/
int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
{ {
/* /*
* FIXME: interrupt.injected represents an interrupt that it's * FIXME: interrupt.injected represents an interrupt whose
* side-effects have already been applied (e.g. bit from IRR * side-effects have already been applied (e.g. bit from IRR
* already moved to ISR). Therefore, it is incorrect to rely * already moved to ISR). Therefore, it is incorrect to rely
* on interrupt.injected to know if there is a pending * on interrupt.injected to know if there is a pending
...@@ -75,6 +56,23 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) ...@@ -75,6 +56,23 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
if (!lapic_in_kernel(v)) if (!lapic_in_kernel(v))
return v->arch.interrupt.injected; return v->arch.interrupt.injected;
if (!kvm_apic_accept_pic_intr(v))
return 0;
if (irqchip_split(v->kvm))
return pending_userspace_extint(v);
else
return v->kvm->arch.vpic->output;
}
/*
* check if there is injectable interrupt:
* when virtual interrupt delivery enabled,
* interrupt from apic will handled by hardware,
* we don't need to check it here.
*/
int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
{
if (kvm_cpu_has_extint(v)) if (kvm_cpu_has_extint(v))
return 1; return 1;
...@@ -91,20 +89,6 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr); ...@@ -91,20 +89,6 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr);
*/ */
int kvm_cpu_has_interrupt(struct kvm_vcpu *v) int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
{ {
/*
* FIXME: interrupt.injected represents an interrupt that it's
* side-effects have already been applied (e.g. bit from IRR
* already moved to ISR). Therefore, it is incorrect to rely
* on interrupt.injected to know if there is a pending
* interrupt in the user-mode LAPIC.
* This leads to nVMX/nSVM not be able to distinguish
* if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on
* pending interrupt or should re-inject an injected
* interrupt.
*/
if (!lapic_in_kernel(v))
return v->arch.interrupt.injected;
if (kvm_cpu_has_extint(v)) if (kvm_cpu_has_extint(v))
return 1; return 1;
...@@ -118,16 +102,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); ...@@ -118,16 +102,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
*/ */
static int kvm_cpu_get_extint(struct kvm_vcpu *v) static int kvm_cpu_get_extint(struct kvm_vcpu *v)
{ {
if (kvm_cpu_has_extint(v)) { if (!kvm_cpu_has_extint(v)) {
if (irqchip_split(v->kvm)) { WARN_ON(!lapic_in_kernel(v));
int vector = v->arch.pending_external_vector;
v->arch.pending_external_vector = -1;
return vector;
} else
return kvm_pic_read_irq(v->kvm); /* PIC */
} else
return -1; return -1;
}
if (!lapic_in_kernel(v))
return v->arch.interrupt.nr;
if (irqchip_split(v->kvm)) {
int vector = v->arch.pending_external_vector;
v->arch.pending_external_vector = -1;
return vector;
} else
return kvm_pic_read_irq(v->kvm); /* PIC */
} }
/* /*
...@@ -135,13 +124,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v) ...@@ -135,13 +124,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v)
*/ */
int kvm_cpu_get_interrupt(struct kvm_vcpu *v) int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
{ {
int vector; int vector = kvm_cpu_get_extint(v);
if (!lapic_in_kernel(v))
return v->arch.interrupt.nr;
vector = kvm_cpu_get_extint(v);
if (vector != -1) if (vector != -1)
return vector; /* PIC */ return vector; /* PIC */
......
...@@ -2465,7 +2465,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu) ...@@ -2465,7 +2465,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_lapic *apic = vcpu->arch.apic;
u32 ppr; u32 ppr;
if (!kvm_apic_hw_enabled(apic)) if (!kvm_apic_present(vcpu))
return -1; return -1;
__apic_update_ppr(apic, &ppr); __apic_update_ppr(apic, &ppr);
......
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