Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6d579d7 authored by Paolo Bonzini's avatar Paolo Bonzini Committed by Greg Kroah-Hartman
Browse files

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



commit 72c3bcdcda494cbd600712a32e67702cdee60c07 upstream.

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>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 53ee75b8
Loading
Loading
Loading
Loading
+33 −50
Original line number Diff line number Diff line
@@ -54,15 +54,27 @@ static int pending_userspace_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))
		return pending_userspace_extint(v);
	else
		return v->kvm->arch.vpic->output;
	} else
		return 0;
}

/*
@@ -73,20 +85,6 @@ static int kvm_cpu_has_extint(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))
		return 1;

@@ -102,20 +100,6 @@ int kvm_cpu_has_injectable_intr(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))
		return 1;

@@ -129,7 +113,14 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
 */
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)) {
		int vector = v->arch.pending_external_vector;

@@ -137,8 +128,6 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v)
		return vector;
	} else
		return kvm_pic_read_irq(v->kvm); /* PIC */
	} else
		return -1;
}

/*
@@ -146,13 +135,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 */

+1 −1
Original line number Diff line number Diff line
@@ -2284,7 +2284,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);