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: Filippo Sironi <sironi@amazon.de> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> Tested-by: David Woodhouse <dwmw@amazon.co.uk> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
545f63948d
commit
72c3bcdcda
@ -41,28 +41,9 @@ static int pending_userspace_extint(struct kvm_vcpu *v)
|
||||
* non-APIC source without intack.
|
||||
*/
|
||||
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
|
||||
* already moved to ISR). Therefore, it is incorrect to rely
|
||||
* on interrupt.injected to know if there is a pending
|
||||
@ -75,6 +56,23 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
|
||||
if (!lapic_in_kernel(v))
|
||||
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))
|
||||
return 1;
|
||||
|
||||
@ -91,20 +89,6 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr);
|
||||
*/
|
||||
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))
|
||||
return 1;
|
||||
|
||||
@ -118,16 +102,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
|
||||
*/
|
||||
static int kvm_cpu_get_extint(struct kvm_vcpu *v)
|
||||
{
|
||||
if (kvm_cpu_has_extint(v)) {
|
||||
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 */
|
||||
} else
|
||||
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)) {
|
||||
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)
|
||||
*/
|
||||
int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
|
||||
{
|
||||
int vector;
|
||||
|
||||
if (!lapic_in_kernel(v))
|
||||
return v->arch.interrupt.nr;
|
||||
|
||||
vector = kvm_cpu_get_extint(v);
|
||||
|
||||
int vector = kvm_cpu_get_extint(v);
|
||||
if (vector != -1)
|
||||
return vector; /* PIC */
|
||||
|
||||
|
@ -2465,7 +2465,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
u32 ppr;
|
||||
|
||||
if (!kvm_apic_hw_enabled(apic))
|
||||
if (!kvm_apic_present(vcpu))
|
||||
return -1;
|
||||
|
||||
__apic_update_ppr(apic, &ppr);
|
||||
|
Loading…
Reference in New Issue
Block a user