From 74a3a8f152053394a016518cc2f2fee216897fa4 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 4 Mar 2009 13:33:02 +0800 Subject: KVM: Merge kvm_ioapic_get_delivery_bitmask into kvm_get_intr_delivery_bitmask Gleb fixed bitmap ops usage in kvm_ioapic_get_delivery_bitmask. Sheng merged two functions, as well as fixed several issues in kvm_get_intr_delivery_bitmask 1. deliver_bitmask is a bitmap rather than a unsigned long intereger. 2. Lowest priority target bitmap wrong calculated by mistake. 3. Prevent potential NULL reference. 4. Declaration in include/kvm_host.h caused powerpc compilation warning. 5. Add warning for guest broadcast interrupt with lowest priority delivery mode. 6. Removed duplicate bitmap clean up in caller of kvm_get_intr_delivery_bitmask. Signed-off-by: Gleb Natapov Signed-off-by: Sheng Yang Signed-off-by: Marcelo Tosatti --- virt/kvm/irq_comm.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) (limited to 'virt/kvm/irq_comm.c') diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index d165e056f79b..1c6ff6d1b842 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -47,15 +47,54 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, union kvm_ioapic_redirect_entry *entry, unsigned long *deliver_bitmask) { + int i; + struct kvm *kvm = ioapic->kvm; struct kvm_vcpu *vcpu; - kvm_ioapic_get_delivery_bitmask(ioapic, entry->fields.dest_id, - entry->fields.dest_mode, - deliver_bitmask); + bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); + + if (entry->fields.dest_mode == 0) { /* Physical mode. */ + if (entry->fields.dest_id == 0xFF) { /* Broadcast. */ + for (i = 0; i < KVM_MAX_VCPUS; ++i) + if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic) + __set_bit(i, deliver_bitmask); + /* Lowest priority shouldn't combine with broadcast */ + if (entry->fields.delivery_mode == + IOAPIC_LOWEST_PRIORITY && printk_ratelimit()) + printk(KERN_INFO "kvm: apic: phys broadcast " + "and lowest prio\n"); + return; + } + for (i = 0; i < KVM_MAX_VCPUS; ++i) { + vcpu = kvm->vcpus[i]; + if (!vcpu) + continue; + if (kvm_apic_match_physical_addr(vcpu->arch.apic, + entry->fields.dest_id)) { + if (vcpu->arch.apic) + __set_bit(i, deliver_bitmask); + break; + } + } + } else if (entry->fields.dest_id != 0) /* Logical mode, MDA non-zero. */ + for (i = 0; i < KVM_MAX_VCPUS; ++i) { + vcpu = kvm->vcpus[i]; + if (!vcpu) + continue; + if (vcpu->arch.apic && + kvm_apic_match_logical_addr(vcpu->arch.apic, + entry->fields.dest_id)) + __set_bit(i, deliver_bitmask); + } + switch (entry->fields.delivery_mode) { case IOAPIC_LOWEST_PRIORITY: + /* Select one in deliver_bitmask */ vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, entry->fields.vector, deliver_bitmask); + bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); + if (!vcpu) + return; __set_bit(vcpu->vcpu_id, deliver_bitmask); break; case IOAPIC_FIXED: @@ -65,7 +104,7 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, if (printk_ratelimit()) printk(KERN_INFO "kvm: unsupported delivery mode %d\n", entry->fields.delivery_mode); - *deliver_bitmask = 0; + bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); } } @@ -80,8 +119,6 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, BUG_ON(!ioapic); - bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); - entry.bits = 0; entry.fields.dest_id = (e->msi.address_lo & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; -- cgit v1.2.3