* [PATCH 0/3] ioapic/lapic/msi cleanup
@ 2009-03-04 13:30 Gleb Natapov
2009-03-04 13:30 ` [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts Gleb Natapov
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Gleb Natapov @ 2009-03-04 13:30 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
There are many code/logic duplications throughout ioapic/lapic/msi device
emulation. Try to consolidate as much code as possible.
The patch series is on top of Sheng Yang's patch:
KVM: Merge kvm_ioapic_get_delivery_bitmask into kvm_get_intr_delivery_bitmask
---
Gleb Natapov (3):
Consolidate ioapic/ipi interrupt delivery logic.
ioapic/msi interrupt delivery consolidation.
Make kvm_apic_set_irq() deliver all kinds of interrupts.
arch/ia64/include/asm/kvm_host.h | 1
arch/ia64/kvm/kvm-ia64.c | 33 ++++-----
arch/ia64/kvm/lapic.h | 6 +-
arch/x86/include/asm/kvm_host.h | 2 -
arch/x86/kvm/lapic.c | 147 ++++++++++++++------------------------
arch/x86/kvm/lapic.h | 4 +
virt/kvm/ioapic.c | 89 +++++++++--------------
virt/kvm/ioapic.h | 13 ++-
virt/kvm/irq_comm.c | 109 +++++++---------------------
9 files changed, 151 insertions(+), 253 deletions(-)
--
Gleb.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts.
2009-03-04 13:30 [PATCH 0/3] ioapic/lapic/msi cleanup Gleb Natapov
@ 2009-03-04 13:30 ` Gleb Natapov
2009-03-04 17:48 ` Marcelo Tosatti
2009-03-04 13:30 ` [PATCH 2/3] ioapic/msi interrupt delivery consolidation Gleb Natapov
2009-03-04 13:30 ` [PATCH 3/3] Consolidate ioapic/ipi interrupt delivery logic Gleb Natapov
2 siblings, 1 reply; 6+ messages in thread
From: Gleb Natapov @ 2009-03-04 13:30 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
Get rid of ioapic_inj_irq() and ioapic_inj_nmi() functions.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/ia64/include/asm/kvm_host.h | 1 -
arch/ia64/kvm/kvm-ia64.c | 8 ++++----
arch/ia64/kvm/lapic.h | 2 +-
arch/x86/kvm/lapic.c | 33 ++++++++++++++++++++++---------
arch/x86/kvm/lapic.h | 2 +-
virt/kvm/ioapic.c | 40 ++++++--------------------------------
virt/kvm/irq_comm.c | 1 +
7 files changed, 36 insertions(+), 51 deletions(-)
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h
index 4542651..5608488 100644
--- a/arch/ia64/include/asm/kvm_host.h
+++ b/arch/ia64/include/asm/kvm_host.h
@@ -585,7 +585,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu);
int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
void kvm_sal_emul(struct kvm_vcpu *vcpu);
-static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
#endif /* __ASSEMBLY__*/
#endif
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 076b00d..708b1fc 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -292,13 +292,13 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
{
switch (dm) {
case SAPIC_FIXED:
- kvm_apic_set_irq(vcpu, vector, 0);
+ kvm_apic_set_irq(vcpu, vector, dm, 0);
break;
case SAPIC_NMI:
- kvm_apic_set_irq(vcpu, 2, 0);
+ kvm_apic_set_irq(vcpu, 2, dm, 0);
break;
case SAPIC_EXTINT:
- kvm_apic_set_irq(vcpu, 0, 0);
+ kvm_apic_set_irq(vcpu, 0, dm, 0);
break;
case SAPIC_INIT:
case SAPIC_PMI:
@@ -1811,7 +1811,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
put_cpu();
}
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
{
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
index 6d6cbcb..cbcfaa6 100644
--- a/arch/ia64/kvm/lapic.h
+++ b/arch/ia64/kvm/lapic.h
@@ -20,6 +20,6 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
#endif
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index afc59b2..d58268f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
+ int vector, int level, int trig_mode);
+
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
{
struct kvm_lapic *apic = vcpu->arch.apic;
+ int lapic_dmode;
- if (!apic_test_and_set_irr(vec, apic)) {
- /* a new pending irq is set in IRR */
- if (trig)
- apic_set_vector(vec, apic->regs + APIC_TMR);
- else
- apic_clear_vector(vec, apic->regs + APIC_TMR);
- kvm_vcpu_kick(apic->vcpu);
- return 1;
+ switch(dmode) {
+ case IOAPIC_LOWEST_PRIORITY:
+ lapic_dmode = APIC_DM_LOWEST;
+ break;
+ case IOAPIC_FIXED:
+ lapic_dmode = APIC_DM_FIXED;
+ break;
+ case IOAPIC_NMI:
+ lapic_dmode = APIC_DM_NMI;
+ break;
+ default:
+ printk(KERN_DEBUG"Ignoring delivery mode %d\n", dmode);
+ return 0;
+ break;
}
- return 0;
+ return __apic_accept_irq(apic, lapic_dmode, vec, 1, trig);
}
static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -364,12 +374,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
break;
case APIC_DM_NMI:
+ result = 1;
kvm_inject_nmi(vcpu);
kvm_vcpu_kick(vcpu);
break;
case APIC_DM_INIT:
if (level) {
+ result = 1;
if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
printk(KERN_DEBUG
"INIT on a runnable vcpu %d\n",
@@ -386,6 +398,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic_debug("SIPI to vcpu %d vector 0x%02x\n",
vcpu->vcpu_id, vector);
if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+ result = 1;
vcpu->arch.sipi_vector = vector;
vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
kvm_vcpu_kick(vcpu);
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 45ab6ee..2a07fab 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -34,7 +34,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index cd47575..94f6312 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -142,25 +142,6 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
}
}
-static int ioapic_inj_irq(struct kvm_ioapic *ioapic,
- struct kvm_vcpu *vcpu,
- u8 vector, u8 trig_mode, u8 delivery_mode)
-{
- ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode,
- delivery_mode);
-
- ASSERT((delivery_mode == IOAPIC_FIXED) ||
- (delivery_mode == IOAPIC_LOWEST_PRIORITY));
-
- return kvm_apic_set_irq(vcpu, vector, trig_mode);
-}
-
-static void ioapic_inj_nmi(struct kvm_vcpu *vcpu)
-{
- kvm_inject_nmi(vcpu);
- kvm_vcpu_kick(vcpu);
-}
-
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
{
union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
@@ -192,21 +173,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
__clear_bit(vcpu_id, deliver_bitmask);
vcpu = ioapic->kvm->vcpus[vcpu_id];
if (vcpu) {
- if (entry.fields.delivery_mode ==
- IOAPIC_LOWEST_PRIORITY ||
- entry.fields.delivery_mode == IOAPIC_FIXED) {
- if (r < 0)
- r = 0;
- r += ioapic_inj_irq(ioapic, vcpu,
- entry.fields.vector,
- entry.fields.trig_mode,
- entry.fields.delivery_mode);
- } else if (entry.fields.delivery_mode == IOAPIC_NMI) {
- r = 1;
- ioapic_inj_nmi(vcpu);
- } else
- ioapic_debug("unsupported delivery mode %x!\n",
- entry.fields.delivery_mode);
+ if (r < 0)
+ r = 0;
+ r += kvm_apic_set_irq(vcpu,
+ entry.fields.vector,
+ entry.fields.trig_mode,
+ entry.fields.delivery_mode);
} else
ioapic_debug("null destination vcpu: "
"mask=%x vector=%x delivery_mode=%x\n",
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index b431844..b37126c 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -146,6 +146,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
if (r < 0)
r = 0;
r += kvm_apic_set_irq(vcpu, entry.fields.vector,
+ entry.fields.dest_mode,
entry.fields.trig_mode);
}
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] ioapic/msi interrupt delivery consolidation.
2009-03-04 13:30 [PATCH 0/3] ioapic/lapic/msi cleanup Gleb Natapov
2009-03-04 13:30 ` [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts Gleb Natapov
@ 2009-03-04 13:30 ` Gleb Natapov
2009-03-04 13:30 ` [PATCH 3/3] Consolidate ioapic/ipi interrupt delivery logic Gleb Natapov
2 siblings, 0 replies; 6+ messages in thread
From: Gleb Natapov @ 2009-03-04 13:30 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
ioapic_deliver() and kvm_set_msi() have code duplication. Move
the code into ioapic_deliver_entry() function and call it from
both places.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
virt/kvm/ioapic.c | 60 +++++++++++++++++++++++++++------------------------
virt/kvm/ioapic.h | 4 ++-
virt/kvm/irq_comm.c | 32 +++------------------------
3 files changed, 37 insertions(+), 59 deletions(-)
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 94f6312..b71c044 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -142,53 +142,57 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
}
}
-static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
+int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e)
{
- union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
- struct kvm_vcpu *vcpu;
- int vcpu_id, r = -1;
-
- ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
- "vector=%x trig_mode=%x\n",
- entry.fields.dest, entry.fields.dest_mode,
- entry.fields.delivery_mode, entry.fields.vector,
- entry.fields.trig_mode);
+ int i, r = -1;
- /* Always delivery PIT interrupt to vcpu 0 */
-#ifdef CONFIG_X86
- if (irq == 0)
- __set_bit(0, deliver_bitmask);
- else
-#endif
- kvm_get_intr_delivery_bitmask(ioapic, &entry, deliver_bitmask);
+ kvm_get_intr_delivery_bitmask(kvm, e, deliver_bitmask);
if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) {
ioapic_debug("no target on destination\n");
- return 0;
+ return r;
}
- while ((vcpu_id = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS))
+ while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS))
< KVM_MAX_VCPUS) {
- __clear_bit(vcpu_id, deliver_bitmask);
- vcpu = ioapic->kvm->vcpus[vcpu_id];
+ struct kvm_vcpu *vcpu = kvm->vcpus[i];
+ __clear_bit(i, deliver_bitmask);
if (vcpu) {
if (r < 0)
r = 0;
- r += kvm_apic_set_irq(vcpu,
- entry.fields.vector,
- entry.fields.trig_mode,
- entry.fields.delivery_mode);
+ r += kvm_apic_set_irq(vcpu, e->fields.vector,
+ e->fields.delivery_mode,
+ e->fields.trig_mode);
} else
ioapic_debug("null destination vcpu: "
"mask=%x vector=%x delivery_mode=%x\n",
- entry.fields.deliver_bitmask,
- entry.fields.vector,
- entry.fields.delivery_mode);
+ e->fields.deliver_bitmask,
+ e->fields.vector, e->fields.delivery_mode);
}
return r;
}
+static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
+{
+ union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
+
+ ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
+ "vector=%x trig_mode=%x\n",
+ entry.fields.dest, entry.fields.dest_mode,
+ entry.fields.delivery_mode, entry.fields.vector,
+ entry.fields.trig_mode);
+
+#ifdef CONFIG_X86
+ /* Always delivery PIT interrupt to vcpu 0 */
+ if (irq == 0) {
+ entry.fields.dest_mode = 0; /* Physical mode. */
+ entry.fields.dest_id = ioapic->kvm->vcpus[0]->vcpu_id;
+ }
+#endif
+ return ioapic_deliver_entry(ioapic->kvm, &entry);
+}
+
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
{
u32 old_irr = ioapic->irr;
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index c8032ab..bedeea5 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -70,8 +70,8 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
-void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
+void kvm_get_intr_delivery_bitmask(struct kvm *kvm,
union kvm_ioapic_redirect_entry *entry,
unsigned long *deliver_bitmask);
-
+int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e);
#endif
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index b37126c..a25eb23 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -43,12 +43,11 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
}
-void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
+void kvm_get_intr_delivery_bitmask(struct kvm *kvm,
union kvm_ioapic_redirect_entry *entry,
unsigned long *deliver_bitmask)
{
int i;
- struct kvm *kvm = ioapic->kvm;
struct kvm_vcpu *vcpu;
bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
@@ -88,7 +87,7 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
switch (entry->fields.delivery_mode) {
case IOAPIC_LOWEST_PRIORITY:
/* Select one in deliver_bitmask */
- vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm,
+ vcpu = kvm_get_lowest_prio_vcpu(kvm,
entry->fields.vector, deliver_bitmask);
bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
if (!vcpu)
@@ -109,13 +108,7 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level)
{
- int vcpu_id, r = -1;
- struct kvm_vcpu *vcpu;
- struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
union kvm_ioapic_redirect_entry entry;
- DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
-
- BUG_ON(!ioapic);
entry.bits = 0;
entry.fields.dest_id = (e->msi.address_lo &
@@ -131,26 +124,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
(unsigned long *)&e->msi.data);
/* TODO Deal with RH bit of MSI message address */
-
- kvm_get_intr_delivery_bitmask(ioapic, &entry, deliver_bitmask);
-
- if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) {
- printk(KERN_WARNING "kvm: no destination for MSI delivery!");
- return -1;
- }
- while ((vcpu_id = find_first_bit(deliver_bitmask,
- KVM_MAX_VCPUS)) < KVM_MAX_VCPUS) {
- __clear_bit(vcpu_id, deliver_bitmask);
- vcpu = ioapic->kvm->vcpus[vcpu_id];
- if (vcpu) {
- if (r < 0)
- r = 0;
- r += kvm_apic_set_irq(vcpu, entry.fields.vector,
- entry.fields.dest_mode,
- entry.fields.trig_mode);
- }
- }
- return r;
+ return ioapic_deliver_entry(kvm, &entry);
}
/* This should be called with the kvm->lock mutex held
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] Consolidate ioapic/ipi interrupt delivery logic.
2009-03-04 13:30 [PATCH 0/3] ioapic/lapic/msi cleanup Gleb Natapov
2009-03-04 13:30 ` [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts Gleb Natapov
2009-03-04 13:30 ` [PATCH 2/3] ioapic/msi interrupt delivery consolidation Gleb Natapov
@ 2009-03-04 13:30 ` Gleb Natapov
2009-03-04 18:01 ` Marcelo Tosatti
2 siblings, 1 reply; 6+ messages in thread
From: Gleb Natapov @ 2009-03-04 13:30 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
Use kvm_apic_match_dest() in kvm_get_intr_delivery_bitmask() instead
of duplicating the same code. Use kvm_get_intr_delivery_bitmask() in
apic_send_ipi() to figure out ipi destination instead of reimplementing
the logic.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/ia64/kvm/kvm-ia64.c | 25 ++++-----
arch/ia64/kvm/lapic.h | 4 +
arch/x86/include/asm/kvm_host.h | 2 -
arch/x86/kvm/lapic.c | 114 +++++++++++----------------------------
arch/x86/kvm/lapic.h | 2 +
virt/kvm/ioapic.c | 5 +-
virt/kvm/ioapic.h | 11 ++--
virt/kvm/irq_comm.c | 82 +++++++++-------------------
8 files changed, 90 insertions(+), 155 deletions(-)
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 708b1fc..952209a 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1834,20 +1834,21 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
return 0;
}
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long bitmap)
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
{
- struct kvm_vcpu *lvcpu = kvm->vcpus[0];
- int i;
-
- for (i = 1; i < kvm->arch.online_vcpus; i++) {
- if (!kvm->vcpus[i])
- continue;
- if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp)
- lvcpu = kvm->vcpus[i];
- }
+ return vcpu1->arch.xtp - vcpu2->arch.xtp;
+}
- return lvcpu;
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode)
+{
+ if (dest_mode == 0) {
+ /* Physical mode. */
+ result = kvm_apic_match_physical_addr(target, dest);
+ } else
+ /* Logical mode. */
+ result = kvm_apic_match_logical_addr(target, dest);
+ return 0;
}
static int find_highest_bits(int *dat)
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
index cbcfaa6..e42109e 100644
--- a/arch/ia64/kvm/lapic.h
+++ b/arch/ia64/kvm/lapic.h
@@ -20,6 +20,10 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode);
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
+bool kvm_apic_present(struct kvm_vcpu *vcpu);
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
#endif
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index f0faf58..4627627 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -286,6 +286,7 @@ struct kvm_vcpu_arch {
u64 shadow_efer;
u64 apic_base;
struct kvm_lapic *apic; /* kernel irqchip context */
+ int32_t apic_arb_prio;
int mp_state;
int sipi_vector;
u64 ia32_misc_enable_msr;
@@ -400,7 +401,6 @@ struct kvm_arch{
struct hlist_head irq_ack_notifier_list;
int vapics_in_nmi_mode;
- int round_robin_prev_vcpu;
unsigned int tss_addr;
struct page *apic_access_page;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index d58268f..5e4dd4f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -260,7 +260,7 @@ static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
{
- return kvm_apic_id(apic) == dest;
+ return dest == 0xff || kvm_apic_id(apic) == dest;
}
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
@@ -289,37 +289,34 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
return result;
}
-static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
int short_hand, int dest, int dest_mode)
{
int result = 0;
struct kvm_lapic *target = vcpu->arch.apic;
apic_debug("target %p, source %p, dest 0x%x, "
- "dest_mode 0x%x, short_hand 0x%x",
+ "dest_mode 0x%x, short_hand 0x%x\n",
target, source, dest, dest_mode, short_hand);
ASSERT(!target);
switch (short_hand) {
case APIC_DEST_NOSHORT:
- if (dest_mode == 0) {
+ if (dest_mode == 0)
/* Physical mode. */
- if ((dest == 0xFF) || (dest == kvm_apic_id(target)))
- result = 1;
- } else
+ result = kvm_apic_match_physical_addr(target, dest);
+ else
/* Logical mode. */
result = kvm_apic_match_logical_addr(target, dest);
break;
case APIC_DEST_SELF:
- if (target == source)
- result = 1;
+ result = (target == source);
break;
case APIC_DEST_ALLINC:
result = 1;
break;
case APIC_DEST_ALLBUT:
- if (target != source)
- result = 1;
+ result = (target != source);
break;
default:
printk(KERN_WARNING "Bad dest shorthand value %x\n",
@@ -341,8 +338,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
struct kvm_vcpu *vcpu = apic->vcpu;
switch (delivery_mode) {
- case APIC_DM_FIXED:
case APIC_DM_LOWEST:
+ vcpu->arch.apic_arb_prio++;
+ case APIC_DM_FIXED:
/* FIXME add logic for vcpu on reset */
if (unlikely(!apic_enabled(apic)))
break;
@@ -421,43 +419,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
return result;
}
-static struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
- unsigned long *bitmap)
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
{
- int last;
- int next;
- struct kvm_lapic *apic = NULL;
-
- last = kvm->arch.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]->arch.apic;
- if (apic && apic_enabled(apic))
- break;
- apic = NULL;
- } while (next != last);
- kvm->arch.round_robin_prev_vcpu = next;
-
- if (!apic)
- printk(KERN_DEBUG "vcpu not ready for apic_round_robin\n");
-
- return apic;
-}
-
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long *bitmap)
-{
- struct kvm_lapic *apic;
-
- apic = kvm_apic_round_robin(kvm, vector, bitmap);
- if (apic)
- return apic->vcpu;
- return NULL;
+ return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio;
}
static void apic_set_eoi(struct kvm_lapic *apic)
@@ -494,39 +458,27 @@ static void apic_send_ipi(struct kvm_lapic *apic)
unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
unsigned int vector = icr_low & APIC_VECTOR_MASK;
- struct kvm_vcpu *target;
- struct kvm_vcpu *vcpu;
- DECLARE_BITMAP(lpr_map, KVM_MAX_VCPUS);
+ DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
int i;
- bitmap_zero(lpr_map, KVM_MAX_VCPUS);
apic_debug("icr_high 0x%x, icr_low 0x%x, "
"short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
"dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n",
icr_high, icr_low, short_hand, dest,
trig_mode, level, dest_mode, delivery_mode, vector);
- for (i = 0; i < KVM_MAX_VCPUS; i++) {
- vcpu = apic->vcpu->kvm->vcpus[i];
- if (!vcpu)
- continue;
-
- if (vcpu->arch.apic &&
- apic_match_dest(vcpu, apic, short_hand, dest, dest_mode)) {
- if (delivery_mode == APIC_DM_LOWEST)
- __set_bit(vcpu->vcpu_id, lpr_map);
- else
- __apic_accept_irq(vcpu->arch.apic, delivery_mode,
- vector, level, trig_mode);
- }
- }
-
- if (delivery_mode == APIC_DM_LOWEST) {
- target = kvm_get_lowest_prio_vcpu(vcpu->kvm, vector, lpr_map);
- if (target != NULL)
- __apic_accept_irq(target->arch.apic, delivery_mode,
- vector, level, trig_mode);
- }
+ kvm_get_intr_delivery_bitmask(apic->vcpu->kvm, apic, dest, dest_mode,
+ delivery_mode == APIC_DM_LOWEST, short_hand,
+ deliver_bitmask);
+
+ while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS))
+ < KVM_MAX_VCPUS) {
+ struct kvm_vcpu *vcpu = apic->vcpu->kvm->vcpus[i];
+ __clear_bit(i, deliver_bitmask);
+ if (vcpu)
+ __apic_accept_irq(vcpu->arch.apic, delivery_mode,
+ vector, level, trig_mode);
+ }
}
static u32 apic_get_tmcct(struct kvm_lapic *apic)
@@ -924,6 +876,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
apic_update_ppr(apic);
+ vcpu->arch.apic_arb_prio = 0;
+
apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
"0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
vcpu, kvm_apic_id(apic),
@@ -931,16 +885,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_lapic_reset);
-int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+bool kvm_apic_present(struct kvm_vcpu *vcpu)
{
- struct kvm_lapic *apic = vcpu->arch.apic;
- int ret = 0;
-
- if (!apic)
- return 0;
- ret = apic_enabled(apic);
+ return vcpu->arch.apic && apic_hw_enabled(vcpu->arch.apic);
+}
- return ret;
+int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+{
+ return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic);
}
EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 2a07fab..2c1b8ae 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -40,6 +40,8 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
+bool kvm_apic_present(struct kvm_vcpu *vcpu);
+bool kvm_lapic_present(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index b71c044..43969bb 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -147,7 +147,10 @@ int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e)
DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
int i, r = -1;
- kvm_get_intr_delivery_bitmask(kvm, e, deliver_bitmask);
+ kvm_get_intr_delivery_bitmask(kvm, NULL, e->fields.dest_id,
+ e->fields.dest_mode,
+ e->fields.delivery_mode == IOAPIC_LOWEST_PRIORITY,
+ 0, deliver_bitmask);
if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) {
ioapic_debug("no target on destination\n");
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index bedeea5..f080f5d 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -64,14 +64,15 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
return kvm->arch.vioapic;
}
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long *bitmap);
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode);
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
-void kvm_get_intr_delivery_bitmask(struct kvm *kvm,
- union kvm_ioapic_redirect_entry *entry,
- unsigned long *deliver_bitmask);
+void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
+ int dest_id, int dest_mode, bool low_prio, int short_hand,
+ unsigned long *deliver_bitmask);
int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e);
#endif
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index a25eb23..e071153 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -43,66 +43,38 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
}
-void kvm_get_intr_delivery_bitmask(struct kvm *kvm,
- union kvm_ioapic_redirect_entry *entry,
- unsigned long *deliver_bitmask)
+void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
+ int dest_id, int dest_mode, bool low_prio, int short_hand,
+ unsigned long *deliver_bitmask)
{
- int i;
- struct kvm_vcpu *vcpu;
+ int i, lowest = -1;
+ struct kvm_vcpu *vcpu;
- bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
+ WARN_ON(dest_mode == 0 && dest_id == 0xff && low_prio);
- if (entry->fields.dest_mode == 0) { /* Physical mode. */
- if (entry->fields.dest_id == 0xFF) { /* Broadcast. */
- /* Lowest priority shouldn't combine with broadcast */
- WARN_ON(entry->fields.delivery_mode ==
- IOAPIC_LOWEST_PRIORITY);
- for (i = 0; i < KVM_MAX_VCPUS; ++i)
- if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic)
- __set_bit(i, deliver_bitmask);
- 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);
+ bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
+ for (i = 0; i < KVM_MAX_VCPUS; i++) {
+ vcpu = kvm->vcpus[i];
+
+ if (!vcpu || !kvm_apic_present(vcpu))
+ continue;
+
+ if (!kvm_apic_match_dest(vcpu, src, short_hand, dest_id,
+ dest_mode))
+ continue;
+
+ if (!low_prio) {
+ __set_bit(i, deliver_bitmask);
+ } else {
+ if (lowest < 0)
+ lowest = i;
+ if (kvm_apic_compare_prio(vcpu, kvm->vcpus[lowest]) < 0)
+ lowest = i;
}
-
- switch (entry->fields.delivery_mode) {
- case IOAPIC_LOWEST_PRIORITY:
- /* Select one in deliver_bitmask */
- vcpu = kvm_get_lowest_prio_vcpu(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:
- case IOAPIC_NMI:
- break;
- default:
- if (printk_ratelimit())
- printk(KERN_INFO "kvm: unsupported delivery mode %d\n",
- entry->fields.delivery_mode);
- bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
}
+
+ if (lowest != -1)
+ __set_bit(lowest, deliver_bitmask);
}
static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts.
2009-03-04 13:30 ` [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts Gleb Natapov
@ 2009-03-04 17:48 ` Marcelo Tosatti
0 siblings, 0 replies; 6+ messages in thread
From: Marcelo Tosatti @ 2009-03-04 17:48 UTC (permalink / raw)
To: Gleb Natapov; +Cc: avi, kvm
Hi Gleb,
On Wed, Mar 04, 2009 at 03:30:11PM +0200, Gleb Natapov wrote:
> Get rid of ioapic_inj_irq() and ioapic_inj_nmi() functions.
>
> Signed-off-by: Gleb Natapov <gleb@redhat.com>
> ---
>
> index afc59b2..d58268f 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
> }
> EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
>
> -int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
> +static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
> + int vector, int level, int trig_mode);
> +
> +int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
> {
> struct kvm_lapic *apic = vcpu->arch.apic;
> + int lapic_dmode;
>
> - if (!apic_test_and_set_irr(vec, apic)) {
> - /* a new pending irq is set in IRR */
> - if (trig)
> - apic_set_vector(vec, apic->regs + APIC_TMR);
> - else
> - apic_clear_vector(vec, apic->regs + APIC_TMR);
> - kvm_vcpu_kick(apic->vcpu);
> - return 1;
> + switch(dmode) {
> + case IOAPIC_LOWEST_PRIORITY:
> + lapic_dmode = APIC_DM_LOWEST;
> + break;
> + case IOAPIC_FIXED:
> + lapic_dmode = APIC_DM_FIXED;
> + break;
> + case IOAPIC_NMI:
> + lapic_dmode = APIC_DM_NMI;
> + break;
> + default:
> + printk(KERN_DEBUG"Ignoring delivery mode %d\n", dmode);
> + return 0;
> + break;
> }
> - return 0;
> + return __apic_accept_irq(apic, lapic_dmode, vec, 1, trig);
The FIXED/LOWEST handling in __apic_accept_irqs is not as straightforward
as the old kvm_apic_set_irq. Perhaps replace
orig_irr = apic_test_and_set_irr(vector, apic);
if (orig_irr && trig_mode) {
apic_debug("level trig mode repeatedly for vector %d",
vector);
break;
}
if (trig_mode) {
apic_debug("level trig mode for vector %d", vector);
apic_set_vector(vector, apic->regs + APIC_TMR);
} else
apic_clear_vector(vector, apic->regs + APIC_TMR);
kvm_vcpu_kick(vcpu);
With the old
> - if (!apic_test_and_set_irr(vec, apic)) {
> - /* a new pending irq is set in IRR */
> - if (trig)
> - apic_set_vector(vec, apic->regs + APIC_TMR);
> - else
> - apic_clear_vector(vec, apic->regs + APIC_TMR);
> - kvm_vcpu_kick(apic->vcpu);
Note they are slightly different. The first version will update APIC_TMR
even if the IRR was already set, for trig_mode == 0.
Otherwise looks very nice, I've updated Sheng's "KVM: Merge
kvm_ioapic_get_delivery_bitmask into kvm_get_intr_delivery_bitmask",
so please rebase against that.
git://git.kernel.org/pub/scm/linux/kernel/git/marcelo/kvm.git kvm-devel
branch, will push in a few minutes.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] Consolidate ioapic/ipi interrupt delivery logic.
2009-03-04 13:30 ` [PATCH 3/3] Consolidate ioapic/ipi interrupt delivery logic Gleb Natapov
@ 2009-03-04 18:01 ` Marcelo Tosatti
0 siblings, 0 replies; 6+ messages in thread
From: Marcelo Tosatti @ 2009-03-04 18:01 UTC (permalink / raw)
To: Gleb Natapov; +Cc: avi, kvm
On Wed, Mar 04, 2009 at 03:30:22PM +0200, Gleb Natapov wrote:
> Use kvm_apic_match_dest() in kvm_get_intr_delivery_bitmask() instead
> of duplicating the same code. Use kvm_get_intr_delivery_bitmask() in
> apic_send_ipi() to figure out ipi destination instead of reimplementing
> the logic.
>
> Signed-off-by: Gleb Natapov <gleb@redhat.com>
> ---
> -struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
> - unsigned long *bitmap)
> -{
> - struct kvm_lapic *apic;
> -
> - apic = kvm_apic_round_robin(kvm, vector, bitmap);
> - if (apic)
> - return apic->vcpu;
> - return NULL;
> + return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio;
> }
Can you split the round robin logic change to a separate patch, and
have only code unification in this?
Also mind the tabs.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-03-04 18:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-04 13:30 [PATCH 0/3] ioapic/lapic/msi cleanup Gleb Natapov
2009-03-04 13:30 ` [PATCH 1/3] Make kvm_apic_set_irq() deliver all kinds of interrupts Gleb Natapov
2009-03-04 17:48 ` Marcelo Tosatti
2009-03-04 13:30 ` [PATCH 2/3] ioapic/msi interrupt delivery consolidation Gleb Natapov
2009-03-04 13:30 ` [PATCH 3/3] Consolidate ioapic/ipi interrupt delivery logic Gleb Natapov
2009-03-04 18:01 ` Marcelo Tosatti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox