diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-02-04 10:28:14 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:03:11 -0400 |
commit | 4925663a079c77d95d8685228ad6675fc5639c8e (patch) | |
tree | 52e93df78b23a44ed21d015f835688f673dd351a /arch/x86 | |
parent | 452425dbaa1974e9fc489e64a8de46a47b4c2754 (diff) |
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: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/i8259.c | 18 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 13 |
3 files changed, 25 insertions, 8 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 55fd4c5fd388..f0faf58044ff 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); | |||
616 | void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, | 616 | void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, |
617 | u32 error_code); | 617 | u32 error_code); |
618 | 618 | ||
619 | void kvm_pic_set_irq(void *opaque, int irq, int level); | 619 | int kvm_pic_set_irq(void *opaque, int irq, int level); |
620 | 620 | ||
621 | void kvm_inject_nmi(struct kvm_vcpu *vcpu); | 621 | void kvm_inject_nmi(struct kvm_vcpu *vcpu); |
622 | 622 | ||
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 93160375c841..b4e662e94ddc 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
@@ -77,12 +77,13 @@ void kvm_pic_clear_isr_ack(struct kvm *kvm) | |||
77 | /* | 77 | /* |
78 | * set irq level. If an edge is detected, then the IRR is set to 1 | 78 | * set irq level. If an edge is detected, then the IRR is set to 1 |
79 | */ | 79 | */ |
80 | static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) | 80 | static inline int pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) |
81 | { | 81 | { |
82 | int mask; | 82 | int mask, ret = 1; |
83 | mask = 1 << irq; | 83 | mask = 1 << irq; |
84 | if (s->elcr & mask) /* level triggered */ | 84 | if (s->elcr & mask) /* level triggered */ |
85 | if (level) { | 85 | if (level) { |
86 | ret = !(s->irr & mask); | ||
86 | s->irr |= mask; | 87 | s->irr |= mask; |
87 | s->last_irr |= mask; | 88 | s->last_irr |= mask; |
88 | } else { | 89 | } else { |
@@ -91,11 +92,15 @@ static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) | |||
91 | } | 92 | } |
92 | else /* edge triggered */ | 93 | else /* edge triggered */ |
93 | if (level) { | 94 | if (level) { |
94 | if ((s->last_irr & mask) == 0) | 95 | if ((s->last_irr & mask) == 0) { |
96 | ret = !(s->irr & mask); | ||
95 | s->irr |= mask; | 97 | s->irr |= mask; |
98 | } | ||
96 | s->last_irr |= mask; | 99 | s->last_irr |= mask; |
97 | } else | 100 | } else |
98 | s->last_irr &= ~mask; | 101 | s->last_irr &= ~mask; |
102 | |||
103 | return (s->imr & mask) ? -1 : ret; | ||
99 | } | 104 | } |
100 | 105 | ||
101 | /* | 106 | /* |
@@ -172,16 +177,19 @@ void kvm_pic_update_irq(struct kvm_pic *s) | |||
172 | pic_unlock(s); | 177 | pic_unlock(s); |
173 | } | 178 | } |
174 | 179 | ||
175 | void kvm_pic_set_irq(void *opaque, int irq, int level) | 180 | int kvm_pic_set_irq(void *opaque, int irq, int level) |
176 | { | 181 | { |
177 | struct kvm_pic *s = opaque; | 182 | struct kvm_pic *s = opaque; |
183 | int ret = -1; | ||
178 | 184 | ||
179 | pic_lock(s); | 185 | pic_lock(s); |
180 | if (irq >= 0 && irq < PIC_NUM_PINS) { | 186 | if (irq >= 0 && irq < PIC_NUM_PINS) { |
181 | pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); | 187 | ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); |
182 | pic_update_irq(s); | 188 | pic_update_irq(s); |
183 | } | 189 | } |
184 | pic_unlock(s); | 190 | pic_unlock(s); |
191 | |||
192 | return ret; | ||
185 | } | 193 | } |
186 | 194 | ||
187 | /* | 195 | /* |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 05d7be89b5eb..e4db5be7c953 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1019,6 +1019,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
1019 | case KVM_CAP_MP_STATE: | 1019 | case KVM_CAP_MP_STATE: |
1020 | case KVM_CAP_SYNC_MMU: | 1020 | case KVM_CAP_SYNC_MMU: |
1021 | case KVM_CAP_REINJECT_CONTROL: | 1021 | case KVM_CAP_REINJECT_CONTROL: |
1022 | case KVM_CAP_IRQ_INJECT_STATUS: | ||
1022 | r = 1; | 1023 | r = 1; |
1023 | break; | 1024 | break; |
1024 | case KVM_CAP_COALESCED_MMIO: | 1025 | case KVM_CAP_COALESCED_MMIO: |
@@ -1877,6 +1878,7 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
1877 | create_pit_unlock: | 1878 | create_pit_unlock: |
1878 | mutex_unlock(&kvm->lock); | 1879 | mutex_unlock(&kvm->lock); |
1879 | break; | 1880 | break; |
1881 | case KVM_IRQ_LINE_STATUS: | ||
1880 | case KVM_IRQ_LINE: { | 1882 | case KVM_IRQ_LINE: { |
1881 | struct kvm_irq_level irq_event; | 1883 | struct kvm_irq_level irq_event; |
1882 | 1884 | ||
@@ -1884,10 +1886,17 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
1884 | if (copy_from_user(&irq_event, argp, sizeof irq_event)) | 1886 | if (copy_from_user(&irq_event, argp, sizeof irq_event)) |
1885 | goto out; | 1887 | goto out; |
1886 | if (irqchip_in_kernel(kvm)) { | 1888 | if (irqchip_in_kernel(kvm)) { |
1889 | __s32 status; | ||
1887 | mutex_lock(&kvm->lock); | 1890 | mutex_lock(&kvm->lock); |
1888 | kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, | 1891 | status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, |
1889 | irq_event.irq, irq_event.level); | 1892 | irq_event.irq, irq_event.level); |
1890 | mutex_unlock(&kvm->lock); | 1893 | mutex_unlock(&kvm->lock); |
1894 | if (ioctl == KVM_IRQ_LINE_STATUS) { | ||
1895 | irq_event.status = status; | ||
1896 | if (copy_to_user(argp, &irq_event, | ||
1897 | sizeof irq_event)) | ||
1898 | goto out; | ||
1899 | } | ||
1891 | r = 0; | 1900 | r = 0; |
1892 | } | 1901 | } |
1893 | break; | 1902 | break; |