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

Commit 4925663a authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity
Browse files

KVM: Report IRQ injection status to userspace.



IRQ injection status is either -1 (if there was no CPU found
that should except the interrupt because IRQ was masked or
ioapic was misconfigured or ...) or >= 0 in that case the
number indicates to how many CPUs interrupt was injected.
If the value is 0 it means that the interrupt was coalesced
and probably should be reinjected.

Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 452425db
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ int kvm_dev_ioctl_check_extension(long ext)
	switch (ext) {
	case KVM_CAP_IRQCHIP:
	case KVM_CAP_MP_STATE:

	case KVM_CAP_IRQ_INJECT_STATUS:
		r = 1;
		break;
	case KVM_CAP_COALESCED_MMIO:
@@ -927,6 +927,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
			goto out;
		}
		break;
	case KVM_IRQ_LINE_STATUS:
	case KVM_IRQ_LINE: {
		struct kvm_irq_level irq_event;

@@ -934,10 +935,17 @@ long kvm_arch_vm_ioctl(struct file *filp,
		if (copy_from_user(&irq_event, argp, sizeof irq_event))
			goto out;
		if (irqchip_in_kernel(kvm)) {
			__s32 status;
			mutex_lock(&kvm->lock);
			kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
			status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
				    irq_event.irq, irq_event.level);
			mutex_unlock(&kvm->lock);
			if (ioctl == KVM_IRQ_LINE_STATUS) {
				irq_event.status = status;
				if (copy_to_user(argp, &irq_event,
							sizeof irq_event))
					goto out;
			}
			r = 0;
		}
		break;
+1 −1
Original line number Diff line number Diff line
@@ -616,7 +616,7 @@ void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2,
			   u32 error_code);

void kvm_pic_set_irq(void *opaque, int irq, int level);
int kvm_pic_set_irq(void *opaque, int irq, int level);

void kvm_inject_nmi(struct kvm_vcpu *vcpu);

+13 −5
Original line number Diff line number Diff line
@@ -77,12 +77,13 @@ void kvm_pic_clear_isr_ack(struct kvm *kvm)
/*
 * set irq level. If an edge is detected, then the IRR is set to 1
 */
static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level)
static inline int pic_set_irq1(struct kvm_kpic_state *s, int irq, int level)
{
	int mask;
	int mask, ret = 1;
	mask = 1 << irq;
	if (s->elcr & mask)	/* level triggered */
		if (level) {
			ret = !(s->irr & mask);
			s->irr |= mask;
			s->last_irr |= mask;
		} else {
@@ -91,11 +92,15 @@ static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level)
		}
	else	/* edge triggered */
		if (level) {
			if ((s->last_irr & mask) == 0)
			if ((s->last_irr & mask) == 0) {
				ret = !(s->irr & mask);
				s->irr |= mask;
			}
			s->last_irr |= mask;
		} else
			s->last_irr &= ~mask;

	return (s->imr & mask) ? -1 : ret;
}

/*
@@ -172,16 +177,19 @@ void kvm_pic_update_irq(struct kvm_pic *s)
	pic_unlock(s);
}

void kvm_pic_set_irq(void *opaque, int irq, int level)
int kvm_pic_set_irq(void *opaque, int irq, int level)
{
	struct kvm_pic *s = opaque;
	int ret = -1;

	pic_lock(s);
	if (irq >= 0 && irq < PIC_NUM_PINS) {
		pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
		ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
		pic_update_irq(s);
	}
	pic_unlock(s);

	return ret;
}

/*
+11 −2
Original line number Diff line number Diff line
@@ -1019,6 +1019,7 @@ int kvm_dev_ioctl_check_extension(long ext)
	case KVM_CAP_MP_STATE:
	case KVM_CAP_SYNC_MMU:
	case KVM_CAP_REINJECT_CONTROL:
	case KVM_CAP_IRQ_INJECT_STATUS:
		r = 1;
		break;
	case KVM_CAP_COALESCED_MMIO:
@@ -1877,6 +1878,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
	create_pit_unlock:
		mutex_unlock(&kvm->lock);
		break;
	case KVM_IRQ_LINE_STATUS:
	case KVM_IRQ_LINE: {
		struct kvm_irq_level irq_event;

@@ -1884,10 +1886,17 @@ long kvm_arch_vm_ioctl(struct file *filp,
		if (copy_from_user(&irq_event, argp, sizeof irq_event))
			goto out;
		if (irqchip_in_kernel(kvm)) {
			__s32 status;
			mutex_lock(&kvm->lock);
			kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
			status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
					irq_event.irq, irq_event.level);
			mutex_unlock(&kvm->lock);
			if (ioctl == KVM_IRQ_LINE_STATUS) {
				irq_event.status = status;
				if (copy_to_user(argp, &irq_event,
							sizeof irq_event))
					goto out;
			}
			r = 0;
		}
		break;
+6 −1
Original line number Diff line number Diff line
@@ -48,7 +48,10 @@ struct kvm_irq_level {
	 * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
	 * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
	 */
	union {
		__u32 irq;
		__s32 status;
	};
	__u32 level;
};

@@ -402,6 +405,7 @@ struct kvm_trace_rec {
#ifdef __KVM_HAVE_IOAPIC
#define KVM_CAP_IRQ_ROUTING 25
#endif
#define KVM_CAP_IRQ_INJECT_STATUS 26

#ifdef KVM_CAP_IRQ_ROUTING

@@ -465,6 +469,7 @@ struct kvm_irq_routing {
#define KVM_CREATE_PIT		  _IO(KVMIO,  0x64)
#define KVM_GET_PIT		  _IOWR(KVMIO, 0x65, struct kvm_pit_state)
#define KVM_SET_PIT		  _IOR(KVMIO,  0x66, struct kvm_pit_state)
#define KVM_IRQ_LINE_STATUS	  _IOWR(KVMIO, 0x67, struct kvm_irq_level)
#define KVM_REGISTER_COALESCED_MMIO \
			_IOW(KVMIO,  0x67, struct kvm_coalesced_mmio_zone)
#define KVM_UNREGISTER_COALESCED_MMIO \
Loading