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
...@@ -42,15 +42,27 @@ static int pending_userspace_extint(struct kvm_vcpu *v) ...@@ -42,15 +42,27 @@ static int pending_userspace_extint(struct kvm_vcpu *v)
*/ */
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); /*
* FIXME: interrupt.injected represents an interrupt whose
* 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_apic_accept_pic_intr(v))
return 0;
if (accept) {
if (irqchip_split(v->kvm)) if (irqchip_split(v->kvm))
return pending_userspace_extint(v); return pending_userspace_extint(v);
else else
return v->kvm->arch.vpic->output; return v->kvm->arch.vpic->output;
} else
return 0;
} }
/* /*
...@@ -61,20 +73,6 @@ static int kvm_cpu_has_extint(struct kvm_vcpu *v) ...@@ -61,20 +73,6 @@ static int kvm_cpu_has_extint(struct kvm_vcpu *v)
*/ */
int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) int kvm_cpu_has_injectable_intr(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;
...@@ -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,7 +102,14 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); ...@@ -118,7 +102,14 @@ 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)) {
WARN_ON(!lapic_in_kernel(v));
return -1;
}
if (!lapic_in_kernel(v))
return v->arch.interrupt.nr;
if (irqchip_split(v->kvm)) { if (irqchip_split(v->kvm)) {
int vector = v->arch.pending_external_vector; int vector = v->arch.pending_external_vector;
...@@ -126,8 +117,6 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v) ...@@ -126,8 +117,6 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v)
return vector; return vector;
} else } else
return kvm_pic_read_irq(v->kvm); /* PIC */ return kvm_pic_read_irq(v->kvm); /* PIC */
} else
return -1;
} }
/* /*
...@@ -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