diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/kvm.h | 1 | ||||
-rw-r--r-- | drivers/kvm/lapic.c | 33 |
2 files changed, 29 insertions, 5 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index f8fe87d3ddb..dbb929d8a31 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -413,6 +413,7 @@ struct kvm { struct kvm_io_bus pio_bus; struct kvm_pic *vpic; struct kvm_ioapic *vioapic; + int round_robin_prev_vcpu; }; static inline struct kvm_pic *pic_irqchip(struct kvm *kvm) diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c index 01e769672dc..ca1db3852ac 100644 --- a/drivers/kvm/lapic.c +++ b/drivers/kvm/lapic.c @@ -371,12 +371,35 @@ struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector, unsigned long bitmap) { int vcpu_id; + int last; + int next; + struct kvm_lapic *apic; + + last = kvm->round_robin_prev_vcpu; + next = last; + + do { + if (++next == KVM_MAX_VCPUS) + next = 0; + if (kvm->vcpus[next] == NULL || !test_bit(next, &bitmap)) + continue; + apic = kvm->vcpus[next]->apic; + if (apic && apic_enabled(apic)) + break; + apic = NULL; + } while (next != last); + kvm->round_robin_prev_vcpu = next; + + if (!apic) { + vcpu_id = ffs(bitmap) - 1; + if (vcpu_id < 0) { + vcpu_id = 0; + printk(KERN_DEBUG "vcpu not ready for apic_round_robin\n"); + } + apic = kvm->vcpus[vcpu_id]->apic; + } - /* TODO for real round robin */ - vcpu_id = fls(bitmap) - 1; - if (vcpu_id < 0) - printk(KERN_DEBUG "vcpu not ready for apic_round_robin\n"); - return kvm->vcpus[vcpu_id]->apic; + return apic; } static void apic_set_eoi(struct kvm_lapic *apic) |