diff options
Diffstat (limited to 'virt/kvm/ioapic.c')
| -rw-r--r-- | virt/kvm/ioapic.c | 61 |
1 files changed, 32 insertions, 29 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index d4a7948b010c..b71c0442cecf 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
| @@ -142,54 +142,57 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | |||
| 142 | } | 142 | } |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | 145 | int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e) |
| 146 | { | 146 | { |
| 147 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; | ||
| 148 | DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS); | 147 | DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS); |
| 149 | struct kvm_vcpu *vcpu; | 148 | int i, r = -1; |
| 150 | int vcpu_id, r = -1; | ||
| 151 | 149 | ||
| 152 | ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " | 150 | kvm_get_intr_delivery_bitmask(kvm, e, deliver_bitmask); |
| 153 | "vector=%x trig_mode=%x\n", | ||
| 154 | entry.fields.dest, entry.fields.dest_mode, | ||
| 155 | entry.fields.delivery_mode, entry.fields.vector, | ||
| 156 | entry.fields.trig_mode); | ||
| 157 | |||
| 158 | /* Always delivery PIT interrupt to vcpu 0 */ | ||
| 159 | #ifdef CONFIG_X86 | ||
| 160 | if (irq == 0) { | ||
| 161 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); | ||
| 162 | __set_bit(0, deliver_bitmask); | ||
| 163 | } else | ||
| 164 | #endif | ||
| 165 | kvm_get_intr_delivery_bitmask(ioapic, &entry, deliver_bitmask); | ||
| 166 | 151 | ||
| 167 | if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) { | 152 | if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) { |
| 168 | ioapic_debug("no target on destination\n"); | 153 | ioapic_debug("no target on destination\n"); |
| 169 | return 0; | 154 | return r; |
| 170 | } | 155 | } |
| 171 | 156 | ||
| 172 | while ((vcpu_id = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS)) | 157 | while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS)) |
| 173 | < KVM_MAX_VCPUS) { | 158 | < KVM_MAX_VCPUS) { |
| 174 | __clear_bit(vcpu_id, deliver_bitmask); | 159 | struct kvm_vcpu *vcpu = kvm->vcpus[i]; |
| 175 | vcpu = ioapic->kvm->vcpus[vcpu_id]; | 160 | __clear_bit(i, deliver_bitmask); |
| 176 | if (vcpu) { | 161 | if (vcpu) { |
| 177 | if (r < 0) | 162 | if (r < 0) |
| 178 | r = 0; | 163 | r = 0; |
| 179 | r += kvm_apic_set_irq(vcpu, | 164 | r += kvm_apic_set_irq(vcpu, e->fields.vector, |
| 180 | entry.fields.vector, | 165 | e->fields.delivery_mode, |
| 181 | entry.fields.trig_mode, | 166 | e->fields.trig_mode); |
| 182 | entry.fields.delivery_mode); | ||
| 183 | } else | 167 | } else |
| 184 | ioapic_debug("null destination vcpu: " | 168 | ioapic_debug("null destination vcpu: " |
| 185 | "mask=%x vector=%x delivery_mode=%x\n", | 169 | "mask=%x vector=%x delivery_mode=%x\n", |
| 186 | entry.fields.deliver_bitmask, | 170 | e->fields.deliver_bitmask, |
| 187 | entry.fields.vector, | 171 | e->fields.vector, e->fields.delivery_mode); |
| 188 | entry.fields.delivery_mode); | ||
| 189 | } | 172 | } |
| 190 | return r; | 173 | return r; |
| 191 | } | 174 | } |
| 192 | 175 | ||
| 176 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | ||
| 177 | { | ||
| 178 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; | ||
| 179 | |||
| 180 | ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " | ||
| 181 | "vector=%x trig_mode=%x\n", | ||
| 182 | entry.fields.dest, entry.fields.dest_mode, | ||
| 183 | entry.fields.delivery_mode, entry.fields.vector, | ||
| 184 | entry.fields.trig_mode); | ||
| 185 | |||
| 186 | #ifdef CONFIG_X86 | ||
| 187 | /* Always delivery PIT interrupt to vcpu 0 */ | ||
| 188 | if (irq == 0) { | ||
| 189 | entry.fields.dest_mode = 0; /* Physical mode. */ | ||
| 190 | entry.fields.dest_id = ioapic->kvm->vcpus[0]->vcpu_id; | ||
| 191 | } | ||
| 192 | #endif | ||
| 193 | return ioapic_deliver_entry(ioapic->kvm, &entry); | ||
| 194 | } | ||
| 195 | |||
| 193 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) | 196 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) |
| 194 | { | 197 | { |
| 195 | u32 old_irr = ioapic->irr; | 198 | u32 old_irr = ioapic->irr; |
