diff options
Diffstat (limited to 'virt/kvm/irq_comm.c')
-rw-r--r-- | virt/kvm/irq_comm.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index d0169f5e6047..55ad76ee2d09 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -25,15 +25,23 @@ | |||
25 | #include "ioapic.h" | 25 | #include "ioapic.h" |
26 | 26 | ||
27 | /* This should be called with the kvm->lock mutex held */ | 27 | /* This should be called with the kvm->lock mutex held */ |
28 | void kvm_set_irq(struct kvm *kvm, int irq, int level) | 28 | void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) |
29 | { | 29 | { |
30 | unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; | ||
31 | |||
32 | /* Logical OR for level trig interrupt */ | ||
33 | if (level) | ||
34 | set_bit(irq_source_id, irq_state); | ||
35 | else | ||
36 | clear_bit(irq_source_id, irq_state); | ||
37 | |||
30 | /* Not possible to detect if the guest uses the PIC or the | 38 | /* Not possible to detect if the guest uses the PIC or the |
31 | * IOAPIC. So set the bit in both. The guest will ignore | 39 | * IOAPIC. So set the bit in both. The guest will ignore |
32 | * writes to the unused one. | 40 | * writes to the unused one. |
33 | */ | 41 | */ |
34 | kvm_ioapic_set_irq(kvm->arch.vioapic, irq, level); | 42 | kvm_ioapic_set_irq(kvm->arch.vioapic, irq, !!(*irq_state)); |
35 | #ifdef CONFIG_X86 | 43 | #ifdef CONFIG_X86 |
36 | kvm_pic_set_irq(pic_irqchip(kvm), irq, level); | 44 | kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state)); |
37 | #endif | 45 | #endif |
38 | } | 46 | } |
39 | 47 | ||
@@ -58,3 +66,31 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm, | |||
58 | { | 66 | { |
59 | hlist_del(&kian->link); | 67 | hlist_del(&kian->link); |
60 | } | 68 | } |
69 | |||
70 | /* The caller must hold kvm->lock mutex */ | ||
71 | int kvm_request_irq_source_id(struct kvm *kvm) | ||
72 | { | ||
73 | unsigned long *bitmap = &kvm->arch.irq_sources_bitmap; | ||
74 | int irq_source_id = find_first_zero_bit(bitmap, | ||
75 | sizeof(kvm->arch.irq_sources_bitmap)); | ||
76 | if (irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { | ||
77 | printk(KERN_WARNING "kvm: exhaust allocatable IRQ sources!\n"); | ||
78 | irq_source_id = -EFAULT; | ||
79 | } else | ||
80 | set_bit(irq_source_id, bitmap); | ||
81 | return irq_source_id; | ||
82 | } | ||
83 | |||
84 | void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) | ||
85 | { | ||
86 | int i; | ||
87 | |||
88 | if (irq_source_id <= 0 || | ||
89 | irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { | ||
90 | printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); | ||
91 | return; | ||
92 | } | ||
93 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) | ||
94 | clear_bit(irq_source_id, &kvm->arch.irq_states[i]); | ||
95 | clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); | ||
96 | } | ||