diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-03-05 09:34:44 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-06-10 04:48:26 -0400 |
commit | 6da7e3f643cf7099965d75fda8606b9d3a8650b9 (patch) | |
tree | af1ae2e8e3cca59c127d252b3f84efda1dfadc5d | |
parent | f5a1e9f89504f57b2b45645a7239dc8a8ddb0f4c (diff) |
KVM: APIC: kvm_apic_set_irq deliver all kinds of interrupts
Get rid of ioapic_inj_irq() and ioapic_inj_nmi() functions.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/ia64/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 8 | ||||
-rw-r--r-- | arch/ia64/kvm/lapic.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 47 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.h | 2 | ||||
-rw-r--r-- | virt/kvm/ioapic.c | 40 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 1 |
7 files changed, 42 insertions, 59 deletions
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index 4542651e6acb..5608488dc2da 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h | |||
@@ -585,7 +585,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu); | |||
585 | int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); | 585 | int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); |
586 | void kvm_sal_emul(struct kvm_vcpu *vcpu); | 586 | void kvm_sal_emul(struct kvm_vcpu *vcpu); |
587 | 587 | ||
588 | static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {} | ||
589 | #endif /* __ASSEMBLY__*/ | 588 | #endif /* __ASSEMBLY__*/ |
590 | 589 | ||
591 | #endif | 590 | #endif |
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 774f0d78a581..99d6d174d932 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -292,13 +292,13 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm, | |||
292 | { | 292 | { |
293 | switch (dm) { | 293 | switch (dm) { |
294 | case SAPIC_FIXED: | 294 | case SAPIC_FIXED: |
295 | kvm_apic_set_irq(vcpu, vector, 0); | 295 | kvm_apic_set_irq(vcpu, vector, dm, 0); |
296 | break; | 296 | break; |
297 | case SAPIC_NMI: | 297 | case SAPIC_NMI: |
298 | kvm_apic_set_irq(vcpu, 2, 0); | 298 | kvm_apic_set_irq(vcpu, 2, dm, 0); |
299 | break; | 299 | break; |
300 | case SAPIC_EXTINT: | 300 | case SAPIC_EXTINT: |
301 | kvm_apic_set_irq(vcpu, 0, 0); | 301 | kvm_apic_set_irq(vcpu, 0, dm, 0); |
302 | break; | 302 | break; |
303 | case SAPIC_INIT: | 303 | case SAPIC_INIT: |
304 | case SAPIC_PMI: | 304 | case SAPIC_PMI: |
@@ -1813,7 +1813,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu) | |||
1813 | put_cpu(); | 1813 | put_cpu(); |
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) | 1816 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig) |
1817 | { | 1817 | { |
1818 | 1818 | ||
1819 | struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); | 1819 | struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); |
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h index 6d6cbcb14893..cbcfaa6195c7 100644 --- a/arch/ia64/kvm/lapic.h +++ b/arch/ia64/kvm/lapic.h | |||
@@ -20,6 +20,6 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu); | |||
20 | 20 | ||
21 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); | 21 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); |
22 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); | 22 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); |
23 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig); | 23 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig); |
24 | 24 | ||
25 | #endif | 25 | #endif |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 27ca43e4e440..a42f968a23e1 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu) | |||
196 | } | 196 | } |
197 | EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr); | 197 | EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr); |
198 | 198 | ||
199 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) | 199 | static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, |
200 | int vector, int level, int trig_mode); | ||
201 | |||
202 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig) | ||
200 | { | 203 | { |
201 | struct kvm_lapic *apic = vcpu->arch.apic; | 204 | struct kvm_lapic *apic = vcpu->arch.apic; |
205 | int lapic_dmode; | ||
202 | 206 | ||
203 | if (!apic_test_and_set_irr(vec, apic)) { | 207 | switch (dmode) { |
204 | /* a new pending irq is set in IRR */ | 208 | case IOAPIC_LOWEST_PRIORITY: |
205 | if (trig) | 209 | lapic_dmode = APIC_DM_LOWEST; |
206 | apic_set_vector(vec, apic->regs + APIC_TMR); | 210 | break; |
207 | else | 211 | case IOAPIC_FIXED: |
208 | apic_clear_vector(vec, apic->regs + APIC_TMR); | 212 | lapic_dmode = APIC_DM_FIXED; |
209 | kvm_vcpu_kick(apic->vcpu); | 213 | break; |
210 | return 1; | 214 | case IOAPIC_NMI: |
215 | lapic_dmode = APIC_DM_NMI; | ||
216 | break; | ||
217 | default: | ||
218 | printk(KERN_DEBUG"Ignoring delivery mode %d\n", dmode); | ||
219 | return 0; | ||
220 | break; | ||
211 | } | 221 | } |
212 | return 0; | 222 | return __apic_accept_irq(apic, lapic_dmode, vec, 1, trig); |
213 | } | 223 | } |
214 | 224 | ||
215 | static inline int apic_find_highest_isr(struct kvm_lapic *apic) | 225 | static inline int apic_find_highest_isr(struct kvm_lapic *apic) |
@@ -327,7 +337,7 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | |||
327 | static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | 337 | static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, |
328 | int vector, int level, int trig_mode) | 338 | int vector, int level, int trig_mode) |
329 | { | 339 | { |
330 | int orig_irr, result = 0; | 340 | int result = 0; |
331 | struct kvm_vcpu *vcpu = apic->vcpu; | 341 | struct kvm_vcpu *vcpu = apic->vcpu; |
332 | 342 | ||
333 | switch (delivery_mode) { | 343 | switch (delivery_mode) { |
@@ -337,10 +347,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
337 | if (unlikely(!apic_enabled(apic))) | 347 | if (unlikely(!apic_enabled(apic))) |
338 | break; | 348 | break; |
339 | 349 | ||
340 | orig_irr = apic_test_and_set_irr(vector, apic); | 350 | result = !apic_test_and_set_irr(vector, apic); |
341 | if (orig_irr && trig_mode) { | 351 | if (!result) { |
342 | apic_debug("level trig mode repeatedly for vector %d", | 352 | if (trig_mode) |
343 | vector); | 353 | apic_debug("level trig mode repeatedly for " |
354 | "vector %d", vector); | ||
344 | break; | 355 | break; |
345 | } | 356 | } |
346 | 357 | ||
@@ -349,10 +360,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
349 | apic_set_vector(vector, apic->regs + APIC_TMR); | 360 | apic_set_vector(vector, apic->regs + APIC_TMR); |
350 | } else | 361 | } else |
351 | apic_clear_vector(vector, apic->regs + APIC_TMR); | 362 | apic_clear_vector(vector, apic->regs + APIC_TMR); |
352 | |||
353 | kvm_vcpu_kick(vcpu); | 363 | kvm_vcpu_kick(vcpu); |
354 | |||
355 | result = (orig_irr == 0); | ||
356 | break; | 364 | break; |
357 | 365 | ||
358 | case APIC_DM_REMRD: | 366 | case APIC_DM_REMRD: |
@@ -364,12 +372,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
364 | break; | 372 | break; |
365 | 373 | ||
366 | case APIC_DM_NMI: | 374 | case APIC_DM_NMI: |
375 | result = 1; | ||
367 | kvm_inject_nmi(vcpu); | 376 | kvm_inject_nmi(vcpu); |
368 | kvm_vcpu_kick(vcpu); | 377 | kvm_vcpu_kick(vcpu); |
369 | break; | 378 | break; |
370 | 379 | ||
371 | case APIC_DM_INIT: | 380 | case APIC_DM_INIT: |
372 | if (level) { | 381 | if (level) { |
382 | result = 1; | ||
373 | if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) | 383 | if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) |
374 | printk(KERN_DEBUG | 384 | printk(KERN_DEBUG |
375 | "INIT on a runnable vcpu %d\n", | 385 | "INIT on a runnable vcpu %d\n", |
@@ -386,6 +396,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
386 | apic_debug("SIPI to vcpu %d vector 0x%02x\n", | 396 | apic_debug("SIPI to vcpu %d vector 0x%02x\n", |
387 | vcpu->vcpu_id, vector); | 397 | vcpu->vcpu_id, vector); |
388 | if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { | 398 | if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { |
399 | result = 1; | ||
389 | vcpu->arch.sipi_vector = vector; | 400 | vcpu->arch.sipi_vector = vector; |
390 | vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; | 401 | vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; |
391 | kvm_vcpu_kick(vcpu); | 402 | kvm_vcpu_kick(vcpu); |
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 2fc0d3c1b194..1b0e3c03cb34 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h | |||
@@ -31,7 +31,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); | |||
31 | 31 | ||
32 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); | 32 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); |
33 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); | 33 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); |
34 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig); | 34 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig); |
35 | 35 | ||
36 | u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); | 36 | u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); |
37 | void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); | 37 | void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); |
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index ea268a8c37da..d4a7948b010c 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -142,25 +142,6 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | |||
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | static int ioapic_inj_irq(struct kvm_ioapic *ioapic, | ||
146 | struct kvm_vcpu *vcpu, | ||
147 | u8 vector, u8 trig_mode, u8 delivery_mode) | ||
148 | { | ||
149 | ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode, | ||
150 | delivery_mode); | ||
151 | |||
152 | ASSERT((delivery_mode == IOAPIC_FIXED) || | ||
153 | (delivery_mode == IOAPIC_LOWEST_PRIORITY)); | ||
154 | |||
155 | return kvm_apic_set_irq(vcpu, vector, trig_mode); | ||
156 | } | ||
157 | |||
158 | static void ioapic_inj_nmi(struct kvm_vcpu *vcpu) | ||
159 | { | ||
160 | kvm_inject_nmi(vcpu); | ||
161 | kvm_vcpu_kick(vcpu); | ||
162 | } | ||
163 | |||
164 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | 145 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) |
165 | { | 146 | { |
166 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; | 147 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; |
@@ -193,21 +174,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | |||
193 | __clear_bit(vcpu_id, deliver_bitmask); | 174 | __clear_bit(vcpu_id, deliver_bitmask); |
194 | vcpu = ioapic->kvm->vcpus[vcpu_id]; | 175 | vcpu = ioapic->kvm->vcpus[vcpu_id]; |
195 | if (vcpu) { | 176 | if (vcpu) { |
196 | if (entry.fields.delivery_mode == | 177 | if (r < 0) |
197 | IOAPIC_LOWEST_PRIORITY || | 178 | r = 0; |
198 | entry.fields.delivery_mode == IOAPIC_FIXED) { | 179 | r += kvm_apic_set_irq(vcpu, |
199 | if (r < 0) | 180 | entry.fields.vector, |
200 | r = 0; | 181 | entry.fields.trig_mode, |
201 | r += ioapic_inj_irq(ioapic, vcpu, | 182 | entry.fields.delivery_mode); |
202 | entry.fields.vector, | ||
203 | entry.fields.trig_mode, | ||
204 | entry.fields.delivery_mode); | ||
205 | } else if (entry.fields.delivery_mode == IOAPIC_NMI) { | ||
206 | r = 1; | ||
207 | ioapic_inj_nmi(vcpu); | ||
208 | } else | ||
209 | ioapic_debug("unsupported delivery mode %x!\n", | ||
210 | entry.fields.delivery_mode); | ||
211 | } else | 183 | } else |
212 | ioapic_debug("null destination vcpu: " | 184 | ioapic_debug("null destination vcpu: " |
213 | "mask=%x vector=%x delivery_mode=%x\n", | 185 | "mask=%x vector=%x delivery_mode=%x\n", |
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 1c6ff6d1b842..325c6685f206 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -148,6 +148,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | |||
148 | if (r < 0) | 148 | if (r < 0) |
149 | r = 0; | 149 | r = 0; |
150 | r += kvm_apic_set_irq(vcpu, entry.fields.vector, | 150 | r += kvm_apic_set_irq(vcpu, entry.fields.vector, |
151 | entry.fields.dest_mode, | ||
151 | entry.fields.trig_mode); | 152 | entry.fields.trig_mode); |
152 | } | 153 | } |
153 | } | 154 | } |