diff options
| -rw-r--r-- | arch/x86/include/asm/kvm_host.h | 15 | ||||
| -rw-r--r-- | arch/x86/kvm/i8259.c | 17 | ||||
| -rw-r--r-- | virt/kvm/ioapic.c | 19 | ||||
| -rw-r--r-- | virt/kvm/ioapic.h | 4 | ||||
| -rw-r--r-- | virt/kvm/irq_comm.c | 31 |
5 files changed, 51 insertions, 35 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index a3e9409e90b6..2c75b400e40c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
| @@ -816,7 +816,20 @@ int kvm_read_guest_page_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, | |||
| 816 | void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault); | 816 | void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault); |
| 817 | bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl); | 817 | bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl); |
| 818 | 818 | ||
| 819 | int kvm_pic_set_irq(void *opaque, int irq, int level); | 819 | static inline int __kvm_irq_line_state(unsigned long *irq_state, |
| 820 | int irq_source_id, int level) | ||
| 821 | { | ||
| 822 | /* Logical OR for level trig interrupt */ | ||
| 823 | if (level) | ||
| 824 | __set_bit(irq_source_id, irq_state); | ||
| 825 | else | ||
| 826 | __clear_bit(irq_source_id, irq_state); | ||
| 827 | |||
| 828 | return !!(*irq_state); | ||
| 829 | } | ||
| 830 | |||
| 831 | int kvm_pic_set_irq(struct kvm_pic *pic, int irq, int irq_source_id, int level); | ||
| 832 | void kvm_pic_clear_all(struct kvm_pic *pic, int irq_source_id); | ||
| 820 | 833 | ||
| 821 | void kvm_inject_nmi(struct kvm_vcpu *vcpu); | 834 | void kvm_inject_nmi(struct kvm_vcpu *vcpu); |
| 822 | 835 | ||
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 81cf4fa4a2be..1df8fb9e1d5d 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
| @@ -188,14 +188,15 @@ void kvm_pic_update_irq(struct kvm_pic *s) | |||
| 188 | pic_unlock(s); | 188 | pic_unlock(s); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | int kvm_pic_set_irq(void *opaque, int irq, int level) | 191 | int kvm_pic_set_irq(struct kvm_pic *s, int irq, int irq_source_id, int level) |
| 192 | { | 192 | { |
| 193 | struct kvm_pic *s = opaque; | ||
| 194 | int ret = -1; | 193 | int ret = -1; |
| 195 | 194 | ||
| 196 | pic_lock(s); | 195 | pic_lock(s); |
| 197 | if (irq >= 0 && irq < PIC_NUM_PINS) { | 196 | if (irq >= 0 && irq < PIC_NUM_PINS) { |
| 198 | ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); | 197 | int irq_level = __kvm_irq_line_state(&s->irq_states[irq], |
| 198 | irq_source_id, level); | ||
| 199 | ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, irq_level); | ||
| 199 | pic_update_irq(s); | 200 | pic_update_irq(s); |
| 200 | trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr, | 201 | trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr, |
| 201 | s->pics[irq >> 3].imr, ret == 0); | 202 | s->pics[irq >> 3].imr, ret == 0); |
| @@ -205,6 +206,16 @@ int kvm_pic_set_irq(void *opaque, int irq, int level) | |||
| 205 | return ret; | 206 | return ret; |
| 206 | } | 207 | } |
| 207 | 208 | ||
| 209 | void kvm_pic_clear_all(struct kvm_pic *s, int irq_source_id) | ||
| 210 | { | ||
| 211 | int i; | ||
| 212 | |||
| 213 | pic_lock(s); | ||
| 214 | for (i = 0; i < PIC_NUM_PINS; i++) | ||
| 215 | __clear_bit(irq_source_id, &s->irq_states[i]); | ||
| 216 | pic_unlock(s); | ||
| 217 | } | ||
| 218 | |||
| 208 | /* | 219 | /* |
| 209 | * acknowledge interrupt 'irq' | 220 | * acknowledge interrupt 'irq' |
| 210 | */ | 221 | */ |
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 26fd54dc459e..ef61d529a6c4 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
| @@ -191,7 +191,8 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | |||
| 191 | return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); | 191 | return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) | 194 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, |
| 195 | int level) | ||
| 195 | { | 196 | { |
| 196 | u32 old_irr; | 197 | u32 old_irr; |
| 197 | u32 mask = 1 << irq; | 198 | u32 mask = 1 << irq; |
| @@ -201,9 +202,11 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) | |||
| 201 | spin_lock(&ioapic->lock); | 202 | spin_lock(&ioapic->lock); |
| 202 | old_irr = ioapic->irr; | 203 | old_irr = ioapic->irr; |
| 203 | if (irq >= 0 && irq < IOAPIC_NUM_PINS) { | 204 | if (irq >= 0 && irq < IOAPIC_NUM_PINS) { |
| 205 | int irq_level = __kvm_irq_line_state(&ioapic->irq_states[irq], | ||
| 206 | irq_source_id, level); | ||
| 204 | entry = ioapic->redirtbl[irq]; | 207 | entry = ioapic->redirtbl[irq]; |
| 205 | level ^= entry.fields.polarity; | 208 | irq_level ^= entry.fields.polarity; |
| 206 | if (!level) | 209 | if (!irq_level) |
| 207 | ioapic->irr &= ~mask; | 210 | ioapic->irr &= ~mask; |
| 208 | else { | 211 | else { |
| 209 | int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG); | 212 | int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG); |
| @@ -221,6 +224,16 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) | |||
| 221 | return ret; | 224 | return ret; |
| 222 | } | 225 | } |
| 223 | 226 | ||
| 227 | void kvm_ioapic_clear_all(struct kvm_ioapic *ioapic, int irq_source_id) | ||
| 228 | { | ||
| 229 | int i; | ||
| 230 | |||
| 231 | spin_lock(&ioapic->lock); | ||
| 232 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) | ||
| 233 | __clear_bit(irq_source_id, &ioapic->irq_states[i]); | ||
| 234 | spin_unlock(&ioapic->lock); | ||
| 235 | } | ||
| 236 | |||
| 224 | static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, | 237 | static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, |
| 225 | int trigger_mode) | 238 | int trigger_mode) |
| 226 | { | 239 | { |
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 32872a09b63f..a30abfe6ed16 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h | |||
| @@ -74,7 +74,9 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); | |||
| 74 | bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector); | 74 | bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector); |
| 75 | int kvm_ioapic_init(struct kvm *kvm); | 75 | int kvm_ioapic_init(struct kvm *kvm); |
| 76 | void kvm_ioapic_destroy(struct kvm *kvm); | 76 | void kvm_ioapic_destroy(struct kvm *kvm); |
| 77 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); | 77 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, |
| 78 | int level); | ||
| 79 | void kvm_ioapic_clear_all(struct kvm_ioapic *ioapic, int irq_source_id); | ||
| 78 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); | 80 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); |
| 79 | int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, | 81 | int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, |
| 80 | struct kvm_lapic_irq *irq); | 82 | struct kvm_lapic_irq *irq); |
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index a6a0365475ed..cc59c68da032 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
| @@ -33,26 +33,12 @@ | |||
| 33 | 33 | ||
| 34 | #include "ioapic.h" | 34 | #include "ioapic.h" |
| 35 | 35 | ||
| 36 | static inline int kvm_irq_line_state(unsigned long *irq_state, | ||
| 37 | int irq_source_id, int level) | ||
| 38 | { | ||
| 39 | /* Logical OR for level trig interrupt */ | ||
| 40 | if (level) | ||
| 41 | set_bit(irq_source_id, irq_state); | ||
| 42 | else | ||
| 43 | clear_bit(irq_source_id, irq_state); | ||
| 44 | |||
| 45 | return !!(*irq_state); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, | 36 | static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, |
| 49 | struct kvm *kvm, int irq_source_id, int level) | 37 | struct kvm *kvm, int irq_source_id, int level) |
| 50 | { | 38 | { |
| 51 | #ifdef CONFIG_X86 | 39 | #ifdef CONFIG_X86 |
| 52 | struct kvm_pic *pic = pic_irqchip(kvm); | 40 | struct kvm_pic *pic = pic_irqchip(kvm); |
| 53 | level = kvm_irq_line_state(&pic->irq_states[e->irqchip.pin], | 41 | return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level); |
| 54 | irq_source_id, level); | ||
| 55 | return kvm_pic_set_irq(pic, e->irqchip.pin, level); | ||
| 56 | #else | 42 | #else |
| 57 | return -1; | 43 | return -1; |
| 58 | #endif | 44 | #endif |
| @@ -62,10 +48,7 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, | |||
| 62 | struct kvm *kvm, int irq_source_id, int level) | 48 | struct kvm *kvm, int irq_source_id, int level) |
| 63 | { | 49 | { |
| 64 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; | 50 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; |
| 65 | level = kvm_irq_line_state(&ioapic->irq_states[e->irqchip.pin], | 51 | return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level); |
| 66 | irq_source_id, level); | ||
| 67 | |||
| 68 | return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, level); | ||
| 69 | } | 52 | } |
| 70 | 53 | ||
| 71 | inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq) | 54 | inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq) |
| @@ -249,8 +232,6 @@ unlock: | |||
| 249 | 232 | ||
| 250 | void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) | 233 | void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) |
| 251 | { | 234 | { |
| 252 | int i; | ||
| 253 | |||
| 254 | ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); | 235 | ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); |
| 255 | 236 | ||
| 256 | mutex_lock(&kvm->irq_lock); | 237 | mutex_lock(&kvm->irq_lock); |
| @@ -263,14 +244,10 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) | |||
| 263 | if (!irqchip_in_kernel(kvm)) | 244 | if (!irqchip_in_kernel(kvm)) |
| 264 | goto unlock; | 245 | goto unlock; |
| 265 | 246 | ||
| 266 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) { | 247 | kvm_ioapic_clear_all(kvm->arch.vioapic, irq_source_id); |
| 267 | clear_bit(irq_source_id, &kvm->arch.vioapic->irq_states[i]); | ||
| 268 | if (i >= 16) | ||
| 269 | continue; | ||
| 270 | #ifdef CONFIG_X86 | 248 | #ifdef CONFIG_X86 |
| 271 | clear_bit(irq_source_id, &pic_irqchip(kvm)->irq_states[i]); | 249 | kvm_pic_clear_all(pic_irqchip(kvm), irq_source_id); |
| 272 | #endif | 250 | #endif |
| 273 | } | ||
| 274 | unlock: | 251 | unlock: |
| 275 | mutex_unlock(&kvm->irq_lock); | 252 | mutex_unlock(&kvm->irq_lock); |
| 276 | } | 253 | } |
