aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-03-05 09:34:54 -0500
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:27 -0400
commit343f94fe4d16ec898da77720c03da9e09f8523d2 (patch)
treefa0180a8446a90000086593b9fa8d4d81708ddd8 /arch
parenta53c17d21c46a752f5ac6695376481bc27865b04 (diff)
KVM: consolidate ioapic/ipi interrupt delivery logic
Use kvm_apic_match_dest() in kvm_get_intr_delivery_bitmask() instead of duplicating the same code. Use kvm_get_intr_delivery_bitmask() in apic_send_ipi() to figure out ipi destination instead of reimplementing the logic. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/kvm/kvm-ia64.c8
-rw-r--r--arch/ia64/kvm/lapic.h3
-rw-r--r--arch/x86/kvm/lapic.c69
-rw-r--r--arch/x86/kvm/lapic.h2
4 files changed, 39 insertions, 43 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 99d6d174d932..8eea9cba7b7c 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1852,6 +1852,14 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
1852 return lvcpu; 1852 return lvcpu;
1853} 1853}
1854 1854
1855int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
1856 int short_hand, int dest, int dest_mode)
1857{
1858 return (dest_mode == 0) ?
1859 kvm_apic_match_physical_addr(target, dest) :
1860 kvm_apic_match_logical_addr(target, dest);
1861}
1862
1855static int find_highest_bits(int *dat) 1863static int find_highest_bits(int *dat)
1856{ 1864{
1857 u32 bits, bitnum; 1865 u32 bits, bitnum;
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
index cbcfaa6195c7..31602e7338d7 100644
--- a/arch/ia64/kvm/lapic.h
+++ b/arch/ia64/kvm/lapic.h
@@ -20,6 +20,9 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
20 20
21int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); 21int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
22int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); 22int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
23int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
24 int short_hand, int dest, int dest_mode);
25bool kvm_apic_present(struct kvm_vcpu *vcpu);
23int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig); 26int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
24 27
25#endif 28#endif
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index a42f968a23e1..998862a3c267 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -260,7 +260,7 @@ static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
260 260
261int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest) 261int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
262{ 262{
263 return kvm_apic_id(apic) == dest; 263 return dest == 0xff || kvm_apic_id(apic) == dest;
264} 264}
265 265
266int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) 266int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
@@ -289,37 +289,34 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
289 return result; 289 return result;
290} 290}
291 291
292static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, 292int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
293 int short_hand, int dest, int dest_mode) 293 int short_hand, int dest, int dest_mode)
294{ 294{
295 int result = 0; 295 int result = 0;
296 struct kvm_lapic *target = vcpu->arch.apic; 296 struct kvm_lapic *target = vcpu->arch.apic;
297 297
298 apic_debug("target %p, source %p, dest 0x%x, " 298 apic_debug("target %p, source %p, dest 0x%x, "
299 "dest_mode 0x%x, short_hand 0x%x", 299 "dest_mode 0x%x, short_hand 0x%x\n",
300 target, source, dest, dest_mode, short_hand); 300 target, source, dest, dest_mode, short_hand);
301 301
302 ASSERT(!target); 302 ASSERT(!target);
303 switch (short_hand) { 303 switch (short_hand) {
304 case APIC_DEST_NOSHORT: 304 case APIC_DEST_NOSHORT:
305 if (dest_mode == 0) { 305 if (dest_mode == 0)
306 /* Physical mode. */ 306 /* Physical mode. */
307 if ((dest == 0xFF) || (dest == kvm_apic_id(target))) 307 result = kvm_apic_match_physical_addr(target, dest);
308 result = 1; 308 else
309 } else
310 /* Logical mode. */ 309 /* Logical mode. */
311 result = kvm_apic_match_logical_addr(target, dest); 310 result = kvm_apic_match_logical_addr(target, dest);
312 break; 311 break;
313 case APIC_DEST_SELF: 312 case APIC_DEST_SELF:
314 if (target == source) 313 result = (target == source);
315 result = 1;
316 break; 314 break;
317 case APIC_DEST_ALLINC: 315 case APIC_DEST_ALLINC:
318 result = 1; 316 result = 1;
319 break; 317 break;
320 case APIC_DEST_ALLBUT: 318 case APIC_DEST_ALLBUT:
321 if (target != source) 319 result = (target != source);
322 result = 1;
323 break; 320 break;
324 default: 321 default:
325 printk(KERN_WARNING "Bad dest shorthand value %x\n", 322 printk(KERN_WARNING "Bad dest shorthand value %x\n",
@@ -492,38 +489,26 @@ static void apic_send_ipi(struct kvm_lapic *apic)
492 unsigned int delivery_mode = icr_low & APIC_MODE_MASK; 489 unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
493 unsigned int vector = icr_low & APIC_VECTOR_MASK; 490 unsigned int vector = icr_low & APIC_VECTOR_MASK;
494 491
495 struct kvm_vcpu *target; 492 DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
496 struct kvm_vcpu *vcpu;
497 DECLARE_BITMAP(lpr_map, KVM_MAX_VCPUS);
498 int i; 493 int i;
499 494
500 bitmap_zero(lpr_map, KVM_MAX_VCPUS);
501 apic_debug("icr_high 0x%x, icr_low 0x%x, " 495 apic_debug("icr_high 0x%x, icr_low 0x%x, "
502 "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, " 496 "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
503 "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n", 497 "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n",
504 icr_high, icr_low, short_hand, dest, 498 icr_high, icr_low, short_hand, dest,
505 trig_mode, level, dest_mode, delivery_mode, vector); 499 trig_mode, level, dest_mode, delivery_mode, vector);
506 500
507 for (i = 0; i < KVM_MAX_VCPUS; i++) { 501 kvm_get_intr_delivery_bitmask(apic->vcpu->kvm, apic, dest, dest_mode,
508 vcpu = apic->vcpu->kvm->vcpus[i]; 502 delivery_mode == APIC_DM_LOWEST, short_hand,
509 if (!vcpu) 503 deliver_bitmask);
510 continue; 504
511 505 while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS))
512 if (vcpu->arch.apic && 506 < KVM_MAX_VCPUS) {
513 apic_match_dest(vcpu, apic, short_hand, dest, dest_mode)) { 507 struct kvm_vcpu *vcpu = apic->vcpu->kvm->vcpus[i];
514 if (delivery_mode == APIC_DM_LOWEST) 508 __clear_bit(i, deliver_bitmask);
515 __set_bit(vcpu->vcpu_id, lpr_map); 509 if (vcpu)
516 else 510 __apic_accept_irq(vcpu->arch.apic, delivery_mode,
517 __apic_accept_irq(vcpu->arch.apic, delivery_mode, 511 vector, level, trig_mode);
518 vector, level, trig_mode);
519 }
520 }
521
522 if (delivery_mode == APIC_DM_LOWEST) {
523 target = kvm_get_lowest_prio_vcpu(vcpu->kvm, vector, lpr_map);
524 if (target != NULL)
525 __apic_accept_irq(target->arch.apic, delivery_mode,
526 vector, level, trig_mode);
527 } 512 }
528} 513}
529 514
@@ -930,16 +915,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
930} 915}
931EXPORT_SYMBOL_GPL(kvm_lapic_reset); 916EXPORT_SYMBOL_GPL(kvm_lapic_reset);
932 917
933int kvm_lapic_enabled(struct kvm_vcpu *vcpu) 918bool kvm_apic_present(struct kvm_vcpu *vcpu)
934{ 919{
935 struct kvm_lapic *apic = vcpu->arch.apic; 920 return vcpu->arch.apic && apic_hw_enabled(vcpu->arch.apic);
936 int ret = 0; 921}
937
938 if (!apic)
939 return 0;
940 ret = apic_enabled(apic);
941 922
942 return ret; 923int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
924{
925 return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic);
943} 926}
944EXPORT_SYMBOL_GPL(kvm_lapic_enabled); 927EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
945 928
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 1b0e3c03cb34..b66dc14a9698 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -37,6 +37,8 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
37void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); 37void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
38void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu); 38void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
39int kvm_lapic_enabled(struct kvm_vcpu *vcpu); 39int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
40bool kvm_apic_present(struct kvm_vcpu *vcpu);
41bool kvm_lapic_present(struct kvm_vcpu *vcpu);
40int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); 42int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
41 43
42void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); 44void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);