diff options
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/irq.h | 1 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 2 | ||||
-rw-r--r-- | virt/kvm/ioapic.h | 1 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 59 |
5 files changed, 39 insertions, 25 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0b113f2b58cf..35d3236c9de4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -410,7 +410,6 @@ struct kvm_arch{ | |||
410 | gpa_t ept_identity_map_addr; | 410 | gpa_t ept_identity_map_addr; |
411 | 411 | ||
412 | unsigned long irq_sources_bitmap; | 412 | unsigned long irq_sources_bitmap; |
413 | unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; | ||
414 | u64 vm_init_tsc; | 413 | u64 vm_init_tsc; |
415 | }; | 414 | }; |
416 | 415 | ||
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index 7d6058a2fd38..c025a2362aae 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h | |||
@@ -71,6 +71,7 @@ struct kvm_pic { | |||
71 | int output; /* intr from master PIC */ | 71 | int output; /* intr from master PIC */ |
72 | struct kvm_io_device dev; | 72 | struct kvm_io_device dev; |
73 | void (*ack_notifier)(void *opaque, int irq); | 73 | void (*ack_notifier)(void *opaque, int irq); |
74 | unsigned long irq_states[16]; | ||
74 | }; | 75 | }; |
75 | 76 | ||
76 | struct kvm_pic *kvm_create_pic(struct kvm *kvm); | 77 | struct kvm_pic *kvm_create_pic(struct kvm *kvm); |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index b7bbb5ddd7ae..1c7f8c49e4e8 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -120,7 +120,7 @@ struct kvm_kernel_irq_routing_entry { | |||
120 | u32 gsi; | 120 | u32 gsi; |
121 | u32 type; | 121 | u32 type; |
122 | int (*set)(struct kvm_kernel_irq_routing_entry *e, | 122 | int (*set)(struct kvm_kernel_irq_routing_entry *e, |
123 | struct kvm *kvm, int level); | 123 | struct kvm *kvm, int irq_source_id, int level); |
124 | union { | 124 | union { |
125 | struct { | 125 | struct { |
126 | unsigned irqchip; | 126 | unsigned irqchip; |
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 7080b713c160..6e461ade6365 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h | |||
@@ -41,6 +41,7 @@ struct kvm_ioapic { | |||
41 | u32 irr; | 41 | u32 irr; |
42 | u32 pad; | 42 | u32 pad; |
43 | union kvm_ioapic_redirect_entry redirtbl[IOAPIC_NUM_PINS]; | 43 | union kvm_ioapic_redirect_entry redirtbl[IOAPIC_NUM_PINS]; |
44 | unsigned long irq_states[IOAPIC_NUM_PINS]; | ||
44 | struct kvm_io_device dev; | 45 | struct kvm_io_device dev; |
45 | struct kvm *kvm; | 46 | struct kvm *kvm; |
46 | void (*ack_notifier)(void *opaque, int irq); | 47 | void (*ack_notifier)(void *opaque, int irq); |
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 001663ff401a..9783f5c43dae 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -31,20 +31,39 @@ | |||
31 | 31 | ||
32 | #include "ioapic.h" | 32 | #include "ioapic.h" |
33 | 33 | ||
34 | static inline int kvm_irq_line_state(unsigned long *irq_state, | ||
35 | int irq_source_id, int level) | ||
36 | { | ||
37 | /* Logical OR for level trig interrupt */ | ||
38 | if (level) | ||
39 | set_bit(irq_source_id, irq_state); | ||
40 | else | ||
41 | clear_bit(irq_source_id, irq_state); | ||
42 | |||
43 | return !!(*irq_state); | ||
44 | } | ||
45 | |||
34 | static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, | 46 | static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, |
35 | struct kvm *kvm, int level) | 47 | struct kvm *kvm, int irq_source_id, int level) |
36 | { | 48 | { |
37 | #ifdef CONFIG_X86 | 49 | #ifdef CONFIG_X86 |
38 | return kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); | 50 | struct kvm_pic *pic = pic_irqchip(kvm); |
51 | level = kvm_irq_line_state(&pic->irq_states[e->irqchip.pin], | ||
52 | irq_source_id, level); | ||
53 | return kvm_pic_set_irq(pic, e->irqchip.pin, level); | ||
39 | #else | 54 | #else |
40 | return -1; | 55 | return -1; |
41 | #endif | 56 | #endif |
42 | } | 57 | } |
43 | 58 | ||
44 | static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, | 59 | static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, |
45 | struct kvm *kvm, int level) | 60 | struct kvm *kvm, int irq_source_id, int level) |
46 | { | 61 | { |
47 | return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); | 62 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; |
63 | level = kvm_irq_line_state(&ioapic->irq_states[e->irqchip.pin], | ||
64 | irq_source_id, level); | ||
65 | |||
66 | return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, level); | ||
48 | } | 67 | } |
49 | 68 | ||
50 | inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq) | 69 | inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq) |
@@ -96,10 +115,13 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, | |||
96 | } | 115 | } |
97 | 116 | ||
98 | static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | 117 | static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, |
99 | struct kvm *kvm, int level) | 118 | struct kvm *kvm, int irq_source_id, int level) |
100 | { | 119 | { |
101 | struct kvm_lapic_irq irq; | 120 | struct kvm_lapic_irq irq; |
102 | 121 | ||
122 | if (!level) | ||
123 | return -1; | ||
124 | |||
103 | trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data); | 125 | trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data); |
104 | 126 | ||
105 | irq.dest_id = (e->msi.address_lo & | 127 | irq.dest_id = (e->msi.address_lo & |
@@ -125,34 +147,19 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | |||
125 | int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) | 147 | int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) |
126 | { | 148 | { |
127 | struct kvm_kernel_irq_routing_entry *e; | 149 | struct kvm_kernel_irq_routing_entry *e; |
128 | unsigned long *irq_state, sig_level; | ||
129 | int ret = -1; | 150 | int ret = -1; |
130 | 151 | ||
131 | trace_kvm_set_irq(irq, level, irq_source_id); | 152 | trace_kvm_set_irq(irq, level, irq_source_id); |
132 | 153 | ||
133 | WARN_ON(!mutex_is_locked(&kvm->irq_lock)); | 154 | WARN_ON(!mutex_is_locked(&kvm->irq_lock)); |
134 | 155 | ||
135 | if (irq < KVM_IOAPIC_NUM_PINS) { | ||
136 | irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; | ||
137 | |||
138 | /* Logical OR for level trig interrupt */ | ||
139 | if (level) | ||
140 | set_bit(irq_source_id, irq_state); | ||
141 | else | ||
142 | clear_bit(irq_source_id, irq_state); | ||
143 | sig_level = !!(*irq_state); | ||
144 | } else if (!level) | ||
145 | return ret; | ||
146 | else /* Deal with MSI/MSI-X */ | ||
147 | sig_level = 1; | ||
148 | |||
149 | /* Not possible to detect if the guest uses the PIC or the | 156 | /* Not possible to detect if the guest uses the PIC or the |
150 | * IOAPIC. So set the bit in both. The guest will ignore | 157 | * IOAPIC. So set the bit in both. The guest will ignore |
151 | * writes to the unused one. | 158 | * writes to the unused one. |
152 | */ | 159 | */ |
153 | list_for_each_entry(e, &kvm->irq_routing, link) | 160 | list_for_each_entry(e, &kvm->irq_routing, link) |
154 | if (e->gsi == irq) { | 161 | if (e->gsi == irq) { |
155 | int r = e->set(e, kvm, sig_level); | 162 | int r = e->set(e, kvm, irq_source_id, level); |
156 | if (r < 0) | 163 | if (r < 0) |
157 | continue; | 164 | continue; |
158 | 165 | ||
@@ -232,8 +239,14 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) | |||
232 | printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); | 239 | printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); |
233 | return; | 240 | return; |
234 | } | 241 | } |
235 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) | 242 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) { |
236 | clear_bit(irq_source_id, &kvm->arch.irq_states[i]); | 243 | clear_bit(irq_source_id, &kvm->arch.vioapic->irq_states[i]); |
244 | if (i >= 16) | ||
245 | continue; | ||
246 | #ifdef CONFIG_X86 | ||
247 | clear_bit(irq_source_id, &pic_irqchip(kvm)->irq_states[i]); | ||
248 | #endif | ||
249 | } | ||
237 | clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); | 250 | clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); |
238 | mutex_unlock(&kvm->irq_lock); | 251 | mutex_unlock(&kvm->irq_lock); |
239 | } | 252 | } |