Skip to content

Commit 8feb4a0

Browse files
Feng Wubonzini
authored andcommitted
KVM: Define a new interface kvm_intr_is_single_vcpu()
This patch defines a new interface kvm_intr_is_single_vcpu(), which can returns whether the interrupt is for single-CPU or not. It is used by VT-d PI, since now we only support single-CPU interrupts, For lowest-priority interrupts, if user configures it via /proc/irq or uses irqbalance to make it single-CPU, we can use PI to deliver the interrupts to it. Full functionality of lowest-priority support will be added later. Signed-off-by: Feng Wu <[email protected]> Reviewed-by: Alex Williamson <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent ebbfc76 commit 8feb4a0

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,4 +1241,7 @@ int x86_set_memory_region(struct kvm *kvm,
12411241
bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
12421242
bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
12431243

1244+
bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
1245+
struct kvm_vcpu **dest_vcpu);
1246+
12441247
#endif /* _ASM_X86_KVM_HOST_H */

arch/x86/kvm/irq_comm.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,33 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
297297
return r;
298298
}
299299

300+
bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
301+
struct kvm_vcpu **dest_vcpu)
302+
{
303+
int i, r = 0;
304+
struct kvm_vcpu *vcpu;
305+
306+
if (kvm_intr_is_single_vcpu_fast(kvm, irq, dest_vcpu))
307+
return true;
308+
309+
kvm_for_each_vcpu(i, vcpu, kvm) {
310+
if (!kvm_apic_present(vcpu))
311+
continue;
312+
313+
if (!kvm_apic_match_dest(vcpu, NULL, irq->shorthand,
314+
irq->dest_id, irq->dest_mode))
315+
continue;
316+
317+
if (++r == 2)
318+
return false;
319+
320+
*dest_vcpu = vcpu;
321+
}
322+
323+
return r == 1;
324+
}
325+
EXPORT_SYMBOL_GPL(kvm_intr_is_single_vcpu);
326+
300327
#define IOAPIC_ROUTING_ENTRY(irq) \
301328
{ .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \
302329
.u.irqchip = { .irqchip = KVM_IRQCHIP_IOAPIC, .pin = (irq) } }

arch/x86/kvm/lapic.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,65 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
755755
return ret;
756756
}
757757

758+
bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
759+
struct kvm_vcpu **dest_vcpu)
760+
{
761+
struct kvm_apic_map *map;
762+
bool ret = false;
763+
struct kvm_lapic *dst = NULL;
764+
765+
if (irq->shorthand)
766+
return false;
767+
768+
rcu_read_lock();
769+
map = rcu_dereference(kvm->arch.apic_map);
770+
771+
if (!map)
772+
goto out;
773+
774+
if (irq->dest_mode == APIC_DEST_PHYSICAL) {
775+
if (irq->dest_id == 0xFF)
776+
goto out;
777+
778+
if (irq->dest_id >= ARRAY_SIZE(map->phys_map))
779+
goto out;
780+
781+
dst = map->phys_map[irq->dest_id];
782+
if (dst && kvm_apic_present(dst->vcpu))
783+
*dest_vcpu = dst->vcpu;
784+
else
785+
goto out;
786+
} else {
787+
u16 cid;
788+
unsigned long bitmap = 1;
789+
int i, r = 0;
790+
791+
if (!kvm_apic_logical_map_valid(map))
792+
goto out;
793+
794+
apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap);
795+
796+
if (cid >= ARRAY_SIZE(map->logical_map))
797+
goto out;
798+
799+
for_each_set_bit(i, &bitmap, 16) {
800+
dst = map->logical_map[cid][i];
801+
if (++r == 2)
802+
goto out;
803+
}
804+
805+
if (dst && kvm_apic_present(dst->vcpu))
806+
*dest_vcpu = dst->vcpu;
807+
else
808+
goto out;
809+
}
810+
811+
ret = true;
812+
out:
813+
rcu_read_unlock();
814+
return ret;
815+
}
816+
758817
/*
759818
* Add a pending IRQ into lapic.
760819
* Return 1 if successfully added and 0 if discarded.

arch/x86/kvm/lapic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,6 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
168168

169169
void wait_lapic_expire(struct kvm_vcpu *vcpu);
170170

171+
bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
172+
struct kvm_vcpu **dest_vcpu);
171173
#endif

0 commit comments

Comments
 (0)