* [PATCH] Report IRQ injection status to userspace.
@ 2009-02-04 11:36 Gleb Natapov
0 siblings, 0 replies; 5+ messages in thread
From: Gleb Natapov @ 2009-02-04 11:36 UTC (permalink / raw)
To: avi; +Cc: kvm
Signed-off-by: Gleb Natapov <gleb@redhat.com>
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 9c77e39..076b00d 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -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;
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 55fd4c5..f0faf58 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -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);
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 179dcb0..712b962 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -76,12 +76,14 @@ 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 = KVM_IRQ_INJECTED;
mask = 1 << irq;
if (s->elcr & mask) /* level triggered */
if (level) {
+ if (s->irr & mask)
+ ret = KVM_IRQ_COALESCED;
s->irr |= mask;
s->last_irr |= mask;
} else {
@@ -90,11 +92,19 @@ 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) {
+ if (s->irr & mask)
+ ret = KVM_IRQ_COALESCED;
s->irr |= mask;
+ }
s->last_irr |= mask;
} else
s->last_irr &= ~mask;
+
+ if (s->imr & mask)
+ ret = KVM_IRQ_IGNORED;
+
+ return ret;
}
/*
@@ -171,16 +181,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 = KVM_IRQ_IGNORED;
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;
}
/*
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index d8adc50..4d44b34 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -201,9 +201,9 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
else
apic_clear_vector(vec, apic->regs + APIC_TMR);
kvm_vcpu_kick(apic->vcpu);
- return 1;
+ return KVM_IRQ_INJECTED;
}
- return 0;
+ return KVM_IRQ_COALESCED;
}
static inline int apic_find_highest_isr(struct kvm_lapic *apic)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e96edda..5754c37 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -995,6 +995,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:
@@ -1852,6 +1853,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;
@@ -1859,10 +1861,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,
- irq_event.irq, irq_event.level);
+ 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;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 869462c..7a6638c 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -40,6 +40,9 @@ struct kvm_userspace_memory_region {
/* for kvm_memory_region::flags */
#define KVM_MEM_LOG_DIRTY_PAGES 1UL
+#define KVM_IRQ_IGNORED -1
+#define KVM_IRQ_COALESCED 0
+#define KVM_IRQ_INJECTED 1
/* for KVM_IRQ_LINE */
struct kvm_irq_level {
@@ -48,7 +51,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..
*/
- __u32 irq;
+ union {
+ __u32 irq;
+ __s32 status;
+ };
__u32 level;
};
@@ -402,6 +408,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
@@ -456,6 +463,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 \
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ce285e0..a8f91bb 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -109,7 +109,7 @@ struct kvm_memory_slot {
struct kvm_kernel_irq_routing_entry {
u32 gsi;
- void (*set)(struct kvm_kernel_irq_routing_entry *e,
+ int (*set)(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level);
union {
struct {
@@ -351,7 +351,7 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
struct kvm_irq_mask_notifier *kimn);
void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
struct kvm_irq_ack_notifier *kian);
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index e85a2bc..fc6c8f6 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -83,19 +83,22 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
return result;
}
-static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
+static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
{
union ioapic_redir_entry *pent;
+ int injected = KVM_IRQ_IGNORED;
pent = &ioapic->redirtbl[idx];
if (!pent->fields.mask) {
- int injected = ioapic_deliver(ioapic, idx);
+ injected = ioapic_deliver(ioapic, idx);
if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
pent->fields.remote_irr = 1;
}
if (!pent->fields.trig_mode)
ioapic->irr &= ~(1 << idx);
+
+ return injected;
}
static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
@@ -207,7 +210,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
u32 deliver_bitmask;
struct kvm_vcpu *vcpu;
- int vcpu_id, r = 0;
+ int vcpu_id, r = KVM_IRQ_IGNORED;
ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
"vector=%x trig_mode=%x\n",
@@ -247,8 +250,10 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
deliver_bitmask &= ~(1 << vcpu_id);
vcpu = ioapic->kvm->vcpus[vcpu_id];
if (vcpu) {
- r = ioapic_inj_irq(ioapic, vcpu, vector,
+ int s;
+ s = ioapic_inj_irq(ioapic, vcpu, vector,
trig_mode, delivery_mode);
+ r = max(r, s);
}
}
break;
@@ -258,8 +263,10 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
continue;
deliver_bitmask &= ~(1 << vcpu_id);
vcpu = ioapic->kvm->vcpus[vcpu_id];
- if (vcpu)
+ if (vcpu) {
ioapic_inj_nmi(vcpu);
+ r = KVM_IRQ_INJECTED;
+ }
else
ioapic_debug("NMI to vcpu %d failed\n",
vcpu->vcpu_id);
@@ -273,11 +280,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
return r;
}
-void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
+int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
{
u32 old_irr = ioapic->irr;
u32 mask = 1 << irq;
union ioapic_redir_entry entry;
+ int ret = 1;
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
entry = ioapic->redirtbl[irq];
@@ -288,9 +296,10 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
ioapic->irr |= mask;
if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
|| !entry.fields.remote_irr)
- ioapic_service(ioapic, irq);
+ ret = ioapic_service(ioapic, irq);
}
}
+ return ret;
}
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 49c9581..a34bd5e 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -83,7 +83,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
unsigned long bitmap);
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
-void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
+int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
u8 dest_mode);
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index a797fa5..00bb29f 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -24,25 +24,28 @@
#include "ioapic.h"
-static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
+static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level)
{
#ifdef CONFIG_X86
- kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level);
+ return kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level);
+#else
+ return -1;
#endif
}
-static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
+static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level)
{
- kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
+ return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
}
/* This should be called with the kvm->lock mutex held */
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
{
struct kvm_kernel_irq_routing_entry *e;
unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
+ int ret = -1;
/* Logical OR for level trig interrupt */
if (level)
@@ -55,8 +58,11 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
* writes to the unused one.
*/
list_for_each_entry(e, &kvm->irq_routing, link)
- if (e->gsi == irq)
- e->set(e, kvm, !!(*irq_state));
+ if (e->gsi == irq) {
+ int r = e->set(e, kvm, !!(*irq_state));
+ ret = max(ret, r);
+ }
+ return ret;
}
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi)
@@ -165,7 +171,7 @@ int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
e->set = kvm_set_pic_irq;
break;
case KVM_IRQCHIP_PIC_SLAVE:
- e->set = kvm_set_pic_irq;
+ e->set = kvm_set_pic_irq;
delta = 8;
break;
case KVM_IRQCHIP_IOAPIC:
--
Gleb.
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH] report IRQ injection status to userspace.
@ 2009-01-20 13:46 Gleb Natapov
2009-01-20 16:53 ` Marcelo Tosatti
0 siblings, 1 reply; 5+ messages in thread
From: Gleb Natapov @ 2009-01-20 13:46 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity
Signed-off-by: Gleb Natapov <gleb@redhat.com>
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 55fd4c5..f0faf58 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -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);
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 179dcb0..bd3f1a5 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -76,9 +76,9 @@ 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) {
@@ -90,11 +90,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;
}
/*
@@ -171,16 +175,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;
}
/*
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e96edda..58cc347 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1860,9 +1860,12 @@ long kvm_arch_vm_ioctl(struct file *filp,
goto out;
if (irqchip_in_kernel(kvm)) {
mutex_lock(&kvm->lock);
- kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
- irq_event.irq, irq_event.level);
+ irq_event.status =
+ kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
+ irq_event.irq, irq_event.level);
mutex_unlock(&kvm->lock);
+ if (copy_to_user(argp, &irq_event, sizeof irq_event))
+ goto out;
r = 0;
}
break;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 869462c..b2c6b93 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -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..
*/
- __u32 irq;
+ union {
+ __u32 irq;
+ __s32 status;
+ };
__u32 level;
};
@@ -450,7 +453,7 @@ struct kvm_irq_routing {
#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
/* Device model IOC */
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
-#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
+#define KVM_IRQ_LINE _IOWR(KVMIO, 0x61, struct kvm_irq_level)
#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ce285e0..a8f91bb 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -109,7 +109,7 @@ struct kvm_memory_slot {
struct kvm_kernel_irq_routing_entry {
u32 gsi;
- void (*set)(struct kvm_kernel_irq_routing_entry *e,
+ int (*set)(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level);
union {
struct {
@@ -351,7 +351,7 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
struct kvm_irq_mask_notifier *kimn);
void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
struct kvm_irq_ack_notifier *kian);
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index e85a2bc..8920a60 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -83,19 +83,22 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
return result;
}
-static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
+static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
{
union ioapic_redir_entry *pent;
+ int injected = -1;
pent = &ioapic->redirtbl[idx];
if (!pent->fields.mask) {
- int injected = ioapic_deliver(ioapic, idx);
+ injected = ioapic_deliver(ioapic, idx);
if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
pent->fields.remote_irr = 1;
}
if (!pent->fields.trig_mode)
ioapic->irr &= ~(1 << idx);
+
+ return injected;
}
static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
@@ -273,11 +276,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
return r;
}
-void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
+int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
{
u32 old_irr = ioapic->irr;
u32 mask = 1 << irq;
union ioapic_redir_entry entry;
+ int ret = 1;
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
entry = ioapic->redirtbl[irq];
@@ -288,9 +292,10 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
ioapic->irr |= mask;
if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
|| !entry.fields.remote_irr)
- ioapic_service(ioapic, irq);
+ ret = ioapic_service(ioapic, irq);
}
}
+ return ret;
}
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 49c9581..a34bd5e 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -83,7 +83,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
unsigned long bitmap);
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
-void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
+int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
u8 dest_mode);
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index a797fa5..00bb29f 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -24,25 +24,28 @@
#include "ioapic.h"
-static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
+static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level)
{
#ifdef CONFIG_X86
- kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level);
+ return kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level);
+#else
+ return -1;
#endif
}
-static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
+static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level)
{
- kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
+ return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
}
/* This should be called with the kvm->lock mutex held */
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
{
struct kvm_kernel_irq_routing_entry *e;
unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
+ int ret = -1;
/* Logical OR for level trig interrupt */
if (level)
@@ -55,8 +58,11 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
* writes to the unused one.
*/
list_for_each_entry(e, &kvm->irq_routing, link)
- if (e->gsi == irq)
- e->set(e, kvm, !!(*irq_state));
+ if (e->gsi == irq) {
+ int r = e->set(e, kvm, !!(*irq_state));
+ ret = max(ret, r);
+ }
+ return ret;
}
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi)
@@ -165,7 +171,7 @@ int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
e->set = kvm_set_pic_irq;
break;
case KVM_IRQCHIP_PIC_SLAVE:
- e->set = kvm_set_pic_irq;
+ e->set = kvm_set_pic_irq;
delta = 8;
break;
case KVM_IRQCHIP_IOAPIC:
--
Gleb.
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] report IRQ injection status to userspace.
2009-01-20 13:46 [PATCH] report " Gleb Natapov
@ 2009-01-20 16:53 ` Marcelo Tosatti
2009-01-20 17:15 ` Gleb Natapov
2009-01-21 10:03 ` Gleb Natapov
0 siblings, 2 replies; 5+ messages in thread
From: Marcelo Tosatti @ 2009-01-20 16:53 UTC (permalink / raw)
To: Gleb Natapov; +Cc: kvm, Avi Kivity
Gleb,
Don't you want IRQ ack notification instead to control reinjection?
Because I think you'll always see a successful injection if using PIC.
On Tue, Jan 20, 2009 at 03:46:53PM +0200, Gleb Natapov wrote:
> diff --git a/include/linux/kvm.h b/include/linux/kvm.h
> index 869462c..b2c6b93 100644
> --- a/include/linux/kvm.h
> +++ b/include/linux/kvm.h
> @@ -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..
> */
> - __u32 irq;
> + union {
> + __u32 irq;
> + __s32 status;
> + };
> __u32 level;
> };
And won't this break older userspace?
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] report IRQ injection status to userspace.
2009-01-20 16:53 ` Marcelo Tosatti
@ 2009-01-20 17:15 ` Gleb Natapov
2009-01-21 10:03 ` Gleb Natapov
1 sibling, 0 replies; 5+ messages in thread
From: Gleb Natapov @ 2009-01-20 17:15 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: kvm, Avi Kivity
On Tue, Jan 20, 2009 at 02:53:40PM -0200, Marcelo Tosatti wrote:
> Gleb,
>
> Don't you want IRQ ack notification instead to control reinjection?
>
I don't see the easy way to do it. There are couple of ways to do what I
need with IRQ ack notifications:
1) expose them to userspace. Each IRQ ack will generate VM exit.
2) make kernel to alway track particular IRQs (userspace will need to
tell kernel which ones it wants to be tracked) and return status
using this info instead of the way my patch does it.
3) Like above but re-inject interrupt from inside the kernel instead of
reporting delivery status to userspace.
First one will generate more VM exist -> not good. The third one has
problem with RTC frequency changes. So the only sane option is second
one, but why us it if we can know if interrupt injection failed during
injection itself?
> Because I think you'll always see a successful injection if using PIC.
>
Then my patch has a bug. I'll recheck. It works for APIC.
> On Tue, Jan 20, 2009 at 03:46:53PM +0200, Gleb Natapov wrote:
>
> > diff --git a/include/linux/kvm.h b/include/linux/kvm.h
> > index 869462c..b2c6b93 100644
> > --- a/include/linux/kvm.h
> > +++ b/include/linux/kvm.h
> > @@ -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..
> > */
> > - __u32 irq;
> > + union {
> > + __u32 irq;
> > + __s32 status;
> > + };
> > __u32 level;
> > };
>
> And won't this break older userspace?
This should not since sizeof should remain the same. But my patch also
changes ioctl definition and it will break old userspace for sure. To
maintain backward compatibility I'll need to introduce new ioctl.
--
Gleb.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] report IRQ injection status to userspace.
2009-01-20 16:53 ` Marcelo Tosatti
2009-01-20 17:15 ` Gleb Natapov
@ 2009-01-21 10:03 ` Gleb Natapov
1 sibling, 0 replies; 5+ messages in thread
From: Gleb Natapov @ 2009-01-21 10:03 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: kvm, Avi Kivity
On Tue, Jan 20, 2009 at 02:53:40PM -0200, Marcelo Tosatti wrote:
> Because I think you'll always see a successful injection if using PIC.
>
I've looked at the code one more time and I think that return value is
correct for edge triggered interrupt. Injection of level triggered
interrupt will always succeed as you say but this is more or less
intentional. Device that uses level triggered interrupt can track
interrupt status by itself since it controls IRQ line level. But I'll
fix PIC code to return proper status anyway.
--
Gleb.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-02-04 11:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-04 11:36 [PATCH] Report IRQ injection status to userspace Gleb Natapov
-- strict thread matches above, loose matches on Subject: below --
2009-01-20 13:46 [PATCH] report " Gleb Natapov
2009-01-20 16:53 ` Marcelo Tosatti
2009-01-20 17:15 ` Gleb Natapov
2009-01-21 10:03 ` Gleb Natapov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox