diff options
Diffstat (limited to 'arch/x86/kvm/irq.c')
| -rw-r--r-- | arch/x86/kvm/irq.c | 73 | 
1 files changed, 53 insertions, 20 deletions
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c index 7e06ba1618b..bd0da433e6d 100644 --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -38,47 +38,80 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)  EXPORT_SYMBOL(kvm_cpu_has_pending_timer);  /* + * check if there is pending interrupt from + * non-APIC source without intack. + */ +static int kvm_cpu_has_extint(struct kvm_vcpu *v) +{ +	if (kvm_apic_accept_pic_intr(v)) +		return pic_irqchip(v->kvm)->output;	/* PIC */ +	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) +{ +	if (!irqchip_in_kernel(v->kvm)) +		return v->arch.interrupt.pending; + +	if (kvm_cpu_has_extint(v)) +		return 1; + +	if (kvm_apic_vid_enabled(v->kvm)) +		return 0; + +	return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ +} + +/*   * check if there is pending interrupt without   * intack.   */  int kvm_cpu_has_interrupt(struct kvm_vcpu *v)  { -	struct kvm_pic *s; -  	if (!irqchip_in_kernel(v->kvm))  		return v->arch.interrupt.pending; -	if (kvm_apic_has_interrupt(v) == -1) {	/* LAPIC */ -		if (kvm_apic_accept_pic_intr(v)) { -			s = pic_irqchip(v->kvm);	/* PIC */ -			return s->output; -		} else -			return 0; -	} -	return 1; +	if (kvm_cpu_has_extint(v)) +		return 1; + +	return kvm_apic_has_interrupt(v) != -1;	/* LAPIC */  }  EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);  /* + * Read pending interrupt(from non-APIC source) + * vector and intack. + */ +static int kvm_cpu_get_extint(struct kvm_vcpu *v) +{ +	if (kvm_cpu_has_extint(v)) +		return kvm_pic_read_irq(v->kvm); /* PIC */ +	return -1; +} + +/*   * Read pending interrupt vector and intack.   */  int kvm_cpu_get_interrupt(struct kvm_vcpu *v)  { -	struct kvm_pic *s;  	int vector;  	if (!irqchip_in_kernel(v->kvm))  		return v->arch.interrupt.nr; -	vector = kvm_get_apic_interrupt(v);	/* APIC */ -	if (vector == -1) { -		if (kvm_apic_accept_pic_intr(v)) { -			s = pic_irqchip(v->kvm); -			s->output = 0;		/* PIC */ -			vector = kvm_pic_read_irq(v->kvm); -		} -	} -	return vector; +	vector = kvm_cpu_get_extint(v); + +	if (kvm_apic_vid_enabled(v->kvm) || vector != -1) +		return vector;			/* PIC */ + +	return kvm_get_apic_interrupt(v);	/* APIC */  }  EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);  | 
