diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 8 | ||||
-rw-r--r-- | arch/ia64/kvm/lapic.h | 3 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 69 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.h | 2 |
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 | ||
1855 | int 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 | |||
1855 | static int find_highest_bits(int *dat) | 1863 | static 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 | ||
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_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | ||
24 | int short_hand, int dest, int dest_mode); | ||
25 | bool kvm_apic_present(struct kvm_vcpu *vcpu); | ||
23 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig); | 26 | int 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 | ||
261 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest) | 261 | int 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 | ||
266 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) | 266 | int 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 | ||
292 | static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | 292 | int 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 | } |
931 | EXPORT_SYMBOL_GPL(kvm_lapic_reset); | 916 | EXPORT_SYMBOL_GPL(kvm_lapic_reset); |
932 | 917 | ||
933 | int kvm_lapic_enabled(struct kvm_vcpu *vcpu) | 918 | bool 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; | 923 | int kvm_lapic_enabled(struct kvm_vcpu *vcpu) |
924 | { | ||
925 | return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic); | ||
943 | } | 926 | } |
944 | EXPORT_SYMBOL_GPL(kvm_lapic_enabled); | 927 | EXPORT_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); | |||
37 | void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); | 37 | void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); |
38 | void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu); | 38 | void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu); |
39 | int kvm_lapic_enabled(struct kvm_vcpu *vcpu); | 39 | int kvm_lapic_enabled(struct kvm_vcpu *vcpu); |
40 | bool kvm_apic_present(struct kvm_vcpu *vcpu); | ||
41 | bool kvm_lapic_present(struct kvm_vcpu *vcpu); | ||
40 | int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); | 42 | int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); |
41 | 43 | ||
42 | void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); | 44 | void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); |