Skip to content

Commit 58c2dde

Browse files
Gleb Natapovavikivity
authored andcommitted
KVM: APIC: get rid of deliver_bitmask
Deliver interrupt during destination matching loop. Signed-off-by: Gleb Natapov <[email protected]> Acked-by: Xiantao Zhang <[email protected]> Signed-off-by: Marcelo Tosatti <[email protected]>
1 parent e103571 commit 58c2dde

File tree

8 files changed

+108
-135
lines changed

8 files changed

+108
-135
lines changed

arch/ia64/kvm/kvm-ia64.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,18 @@ static int handle_sal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
283283

284284
}
285285

286+
static int __apic_accept_irq(struct kvm_vcpu *vcpu, uint64_t vector)
287+
{
288+
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
289+
290+
if (!test_and_set_bit(vector, &vpd->irr[0])) {
291+
vcpu->arch.irq_new_pending = 1;
292+
kvm_vcpu_kick(vcpu);
293+
return 1;
294+
}
295+
return 0;
296+
}
297+
286298
/*
287299
* offset: address offset to IPI space.
288300
* value: deliver value.
@@ -292,20 +304,20 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
292304
{
293305
switch (dm) {
294306
case SAPIC_FIXED:
295-
kvm_apic_set_irq(vcpu, vector, dm, 0);
296307
break;
297308
case SAPIC_NMI:
298-
kvm_apic_set_irq(vcpu, 2, dm, 0);
309+
vector = 2;
299310
break;
300311
case SAPIC_EXTINT:
301-
kvm_apic_set_irq(vcpu, 0, dm, 0);
312+
vector = 0;
302313
break;
303314
case SAPIC_INIT:
304315
case SAPIC_PMI:
305316
default:
306317
printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n");
307-
break;
318+
return;
308319
}
320+
__apic_accept_irq(vcpu, vector);
309321
}
310322

311323
static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
@@ -1813,17 +1825,9 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
18131825
put_cpu();
18141826
}
18151827

1816-
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
1828+
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
18171829
{
1818-
1819-
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
1820-
1821-
if (!test_and_set_bit(vec, &vpd->irr[0])) {
1822-
vcpu->arch.irq_new_pending = 1;
1823-
kvm_vcpu_kick(vcpu);
1824-
return 1;
1825-
}
1826-
return 0;
1830+
return __apic_accept_irq(vcpu, irq->vector);
18271831
}
18281832

18291833
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
@@ -1844,6 +1848,7 @@ int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
18441848
int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
18451849
int short_hand, int dest, int dest_mode)
18461850
{
1851+
struct kvm_lapic *target = vcpu->arch.apic;
18471852
return (dest_mode == 0) ?
18481853
kvm_apic_match_physical_addr(target, dest) :
18491854
kvm_apic_match_logical_addr(target, dest);

arch/ia64/kvm/lapic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
2323
int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
2424
int short_hand, int dest, int dest_mode);
2525
int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
26-
bool kvm_apic_present(struct kvm_vcpu *vcpu);
27-
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, struct kvm_lapic_irq *irq);
27+
#define kvm_apic_present(x) (true)
2828

2929
#endif

arch/x86/kvm/lapic.c

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -199,27 +199,12 @@ EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
199199
static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
200200
int vector, int level, int trig_mode);
201201

202-
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
202+
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
203203
{
204204
struct kvm_lapic *apic = vcpu->arch.apic;
205-
int lapic_dmode;
206205

207-
switch (dmode) {
208-
case IOAPIC_LOWEST_PRIORITY:
209-
lapic_dmode = APIC_DM_LOWEST;
210-
break;
211-
case IOAPIC_FIXED:
212-
lapic_dmode = APIC_DM_FIXED;
213-
break;
214-
case IOAPIC_NMI:
215-
lapic_dmode = APIC_DM_NMI;
216-
break;
217-
default:
218-
printk(KERN_DEBUG"Ignoring delivery mode %d\n", dmode);
219-
return 0;
220-
break;
221-
}
222-
return __apic_accept_irq(apic, lapic_dmode, vec, 1, trig);
206+
return __apic_accept_irq(apic, irq->delivery_mode, irq->vector,
207+
irq->level, irq->trig_mode);
223208
}
224209

225210
static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -447,36 +432,24 @@ static void apic_send_ipi(struct kvm_lapic *apic)
447432
{
448433
u32 icr_low = apic_get_reg(apic, APIC_ICR);
449434
u32 icr_high = apic_get_reg(apic, APIC_ICR2);
435+
struct kvm_lapic_irq irq;
450436

451-
unsigned int dest = GET_APIC_DEST_FIELD(icr_high);
452-
unsigned int short_hand = icr_low & APIC_SHORT_MASK;
453-
unsigned int trig_mode = icr_low & APIC_INT_LEVELTRIG;
454-
unsigned int level = icr_low & APIC_INT_ASSERT;
455-
unsigned int dest_mode = icr_low & APIC_DEST_MASK;
456-
unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
457-
unsigned int vector = icr_low & APIC_VECTOR_MASK;
458-
459-
DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
460-
int i;
437+
irq.vector = icr_low & APIC_VECTOR_MASK;
438+
irq.delivery_mode = icr_low & APIC_MODE_MASK;
439+
irq.dest_mode = icr_low & APIC_DEST_MASK;
440+
irq.level = icr_low & APIC_INT_ASSERT;
441+
irq.trig_mode = icr_low & APIC_INT_LEVELTRIG;
442+
irq.shorthand = icr_low & APIC_SHORT_MASK;
443+
irq.dest_id = GET_APIC_DEST_FIELD(icr_high);
461444

462445
apic_debug("icr_high 0x%x, icr_low 0x%x, "
463446
"short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
464447
"dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n",
465-
icr_high, icr_low, short_hand, dest,
466-
trig_mode, level, dest_mode, delivery_mode, vector);
467-
468-
kvm_get_intr_delivery_bitmask(apic->vcpu->kvm, apic, dest, dest_mode,
469-
delivery_mode == APIC_DM_LOWEST, short_hand,
470-
deliver_bitmask);
471-
472-
while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS))
473-
< KVM_MAX_VCPUS) {
474-
struct kvm_vcpu *vcpu = apic->vcpu->kvm->vcpus[i];
475-
__clear_bit(i, deliver_bitmask);
476-
if (vcpu)
477-
__apic_accept_irq(vcpu->arch.apic, delivery_mode,
478-
vector, level, trig_mode);
479-
}
448+
icr_high, icr_low, irq.shorthand, irq.dest,
449+
irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode,
450+
irq.vector);
451+
452+
kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq);
480453
}
481454

482455
static u32 apic_get_tmcct(struct kvm_lapic *apic)

arch/x86/kvm/lapic.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,13 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
3131

3232
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
3333
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
34-
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
34+
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
3535

3636
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
3737
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
3838
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
3939
int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
4040
bool kvm_apic_present(struct kvm_vcpu *vcpu);
41-
bool kvm_lapic_present(struct kvm_vcpu *vcpu);
4241
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
4342

4443
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);

include/linux/kvm_types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,14 @@ union kvm_ioapic_redirect_entry {
5757
} fields;
5858
};
5959

60+
struct kvm_lapic_irq {
61+
u32 vector;
62+
u32 delivery_mode;
63+
u32 dest_mode;
64+
u32 level;
65+
u32 trig_mode;
66+
u32 shorthand;
67+
u32 dest_id;
68+
};
69+
6070
#endif /* __KVM_TYPES_H__ */

virt/kvm/ioapic.c

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -142,58 +142,33 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
142142
}
143143
}
144144

145-
int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e)
146-
{
147-
DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
148-
int i, r = -1;
149-
150-
kvm_get_intr_delivery_bitmask(kvm, NULL, e->fields.dest_id,
151-
e->fields.dest_mode,
152-
e->fields.delivery_mode == IOAPIC_LOWEST_PRIORITY,
153-
0, deliver_bitmask);
154-
155-
if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) {
156-
ioapic_debug("no target on destination\n");
157-
return r;
158-
}
159-
160-
while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS))
161-
< KVM_MAX_VCPUS) {
162-
struct kvm_vcpu *vcpu = kvm->vcpus[i];
163-
__clear_bit(i, deliver_bitmask);
164-
if (vcpu) {
165-
if (r < 0)
166-
r = 0;
167-
r += kvm_apic_set_irq(vcpu, e->fields.vector,
168-
e->fields.delivery_mode,
169-
e->fields.trig_mode);
170-
} else
171-
ioapic_debug("null destination vcpu: "
172-
"mask=%x vector=%x delivery_mode=%x\n",
173-
e->fields.deliver_bitmask,
174-
e->fields.vector, e->fields.delivery_mode);
175-
}
176-
return r;
177-
}
178-
179145
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
180146
{
181-
union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
147+
union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
148+
struct kvm_lapic_irq irqe;
182149

183150
ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
184151
"vector=%x trig_mode=%x\n",
185-
entry.fields.dest, entry.fields.dest_mode,
186-
entry.fields.delivery_mode, entry.fields.vector,
187-
entry.fields.trig_mode);
152+
entry->fields.dest, entry->fields.dest_mode,
153+
entry->fields.delivery_mode, entry->fields.vector,
154+
entry->fields.trig_mode);
155+
156+
irqe.dest_id = entry->fields.dest_id;
157+
irqe.vector = entry->fields.vector;
158+
irqe.dest_mode = entry->fields.dest_mode;
159+
irqe.trig_mode = entry->fields.trig_mode;
160+
irqe.delivery_mode = entry->fields.delivery_mode << 8;
161+
irqe.level = 1;
162+
irqe.shorthand = 0;
188163

189164
#ifdef CONFIG_X86
190165
/* Always delivery PIT interrupt to vcpu 0 */
191166
if (irq == 0) {
192-
entry.fields.dest_mode = 0; /* Physical mode. */
193-
entry.fields.dest_id = ioapic->kvm->vcpus[0]->vcpu_id;
167+
irqe.dest_mode = 0; /* Physical mode. */
168+
irqe.dest_id = ioapic->kvm->vcpus[0]->vcpu_id;
194169
}
195170
#endif
196-
return ioapic_deliver_entry(ioapic->kvm, &entry);
171+
return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe);
197172
}
198173

199174
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)

virt/kvm/ioapic.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
7171
int kvm_ioapic_init(struct kvm *kvm);
7272
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
7373
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
74-
void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
75-
int dest_id, int dest_mode, bool low_prio, int short_hand,
76-
unsigned long *deliver_bitmask);
77-
int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e);
74+
int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
75+
struct kvm_lapic_irq *irq);
7876
#endif

virt/kvm/irq_comm.c

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <linux/kvm_host.h>
2323

2424
#include <asm/msidef.h>
25+
#ifdef CONFIG_IA64
26+
#include <asm/iosapic.h>
27+
#endif
2528

2629
#include "irq.h"
2730

@@ -43,61 +46,71 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
4346
return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
4447
}
4548

46-
void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
47-
int dest_id, int dest_mode, bool low_prio, int short_hand,
48-
unsigned long *deliver_bitmask)
49+
inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq)
4950
{
50-
int i, lowest = -1;
51-
struct kvm_vcpu *vcpu;
51+
#ifdef CONFIG_IA64
52+
return irq->delivery_mode ==
53+
(IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
54+
#else
55+
return irq->delivery_mode == APIC_DM_LOWEST;
56+
#endif
57+
}
5258

53-
if (dest_mode == 0 && dest_id == 0xff && low_prio)
59+
int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
60+
struct kvm_lapic_irq *irq)
61+
{
62+
int i, r = -1;
63+
struct kvm_vcpu *vcpu, *lowest = NULL;
64+
65+
if (irq->dest_mode == 0 && irq->dest_id == 0xff &&
66+
kvm_is_dm_lowest_prio(irq))
5467
printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n");
5568

56-
bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
5769
for (i = 0; i < KVM_MAX_VCPUS; i++) {
5870
vcpu = kvm->vcpus[i];
5971

6072
if (!vcpu || !kvm_apic_present(vcpu))
6173
continue;
6274

63-
if (!kvm_apic_match_dest(vcpu, src, short_hand, dest_id,
64-
dest_mode))
75+
if (!kvm_apic_match_dest(vcpu, src, irq->shorthand,
76+
irq->dest_id, irq->dest_mode))
6577
continue;
6678

67-
if (!low_prio) {
68-
__set_bit(i, deliver_bitmask);
79+
if (!kvm_is_dm_lowest_prio(irq)) {
80+
if (r < 0)
81+
r = 0;
82+
r += kvm_apic_set_irq(vcpu, irq);
6983
} else {
70-
if (lowest < 0)
71-
lowest = i;
72-
if (kvm_apic_compare_prio(vcpu, kvm->vcpus[lowest]) < 0)
73-
lowest = i;
84+
if (!lowest)
85+
lowest = vcpu;
86+
else if (kvm_apic_compare_prio(vcpu, lowest) < 0)
87+
lowest = vcpu;
7488
}
7589
}
7690

77-
if (lowest != -1)
78-
__set_bit(lowest, deliver_bitmask);
91+
if (lowest)
92+
r = kvm_apic_set_irq(lowest, irq);
93+
94+
return r;
7995
}
8096

8197
static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
8298
struct kvm *kvm, int level)
8399
{
84-
union kvm_ioapic_redirect_entry entry;
100+
struct kvm_lapic_irq irq;
85101

86-
entry.bits = 0;
87-
entry.fields.dest_id = (e->msi.address_lo &
102+
irq.dest_id = (e->msi.address_lo &
88103
MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
89-
entry.fields.vector = (e->msi.data &
104+
irq.vector = (e->msi.data &
90105
MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
91-
entry.fields.dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
92-
(unsigned long *)&e->msi.address_lo);
93-
entry.fields.trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
94-
(unsigned long *)&e->msi.data);
95-
entry.fields.delivery_mode = test_bit(
96-
MSI_DATA_DELIVERY_MODE_SHIFT,
97-
(unsigned long *)&e->msi.data);
106+
irq.dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo;
107+
irq.trig_mode = (1 << MSI_DATA_TRIGGER_SHIFT) & e->msi.data;
108+
irq.delivery_mode = e->msi.data & 0x700;
109+
irq.level = 1;
110+
irq.shorthand = 0;
98111

99112
/* TODO Deal with RH bit of MSI message address */
100-
return ioapic_deliver_entry(kvm, &entry);
113+
return kvm_irq_delivery_to_apic(kvm, NULL, &irq);
101114
}
102115

103116
/* This should be called with the kvm->lock mutex held

0 commit comments

Comments
 (0)