Skip to content

Commit

Permalink
KVM: deliver PIC interrupt only to vcpu0
Browse files Browse the repository at this point in the history
This patch changes the PIC interrupts delivery. Now it is only delivered
to vcpu0 when either condition is met (on vcpu0):
  1. local APIC is hardware disabled
  2. LVT0 is unmasked and configured to delivery mode ExtInt

It fixes the 2x faster wall clock on x86_64 and SMP i386 Linux guests

Signed-off-by: Eddie (Yaozu) Dong <eddie.dong@intel.com>
Signed-off-by: Qing He <qing.he@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Qing He authored and Avi Kivity committed Oct 13, 2007
1 parent 5cd4f6f commit 40487c6
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 5 deletions.
15 changes: 10 additions & 5 deletions drivers/kvm/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
struct kvm_pic *s;

if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */
s = pic_irqchip(v->kvm); /* PIC */
return s->output;
if (kvm_apic_accept_pic_intr(v)) {
s = pic_irqchip(v->kvm); /* PIC */
return s->output;
} else
return 0;
}
return 1;
}
Expand All @@ -50,9 +53,11 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)

vector = kvm_get_apic_interrupt(v); /* APIC */
if (vector == -1) {
s = pic_irqchip(v->kvm);
s->output = 0; /* PIC */
vector = kvm_pic_read_irq(s);
if (kvm_apic_accept_pic_intr(v)) {
s = pic_irqchip(v->kvm);
s->output = 0; /* PIC */
vector = kvm_pic_read_irq(s);
}
}
return vector;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/kvm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ do { \

void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);
int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu);
int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu);
int kvm_create_lapic(struct kvm_vcpu *vcpu);
void kvm_free_apic(struct kvm_lapic *apic);
Expand Down
17 changes: 17 additions & 0 deletions drivers/kvm/lapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,8 @@ static void lapic_reset(struct kvm_vcpu *vcpu)

for (i = 0; i < APIC_LVT_NUM; i++)
apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
apic_set_reg(apic, APIC_LVT0,
SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT));

apic_set_reg(apic, APIC_DFR, 0xffffffffU);
apic_set_reg(apic, APIC_SPIV, 0xff);
Expand Down Expand Up @@ -932,6 +934,21 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
return highest_irr;
}

int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu)
{
u32 lvt0 = apic_get_reg(vcpu->apic, APIC_LVT0);
int r = 0;

if (vcpu->vcpu_id == 0) {
if (!apic_hw_enabled(vcpu->apic))
r = 1;
if ((lvt0 & APIC_LVT_MASKED) == 0 &&
GET_APIC_DELIVERY_MODE(lvt0) == APIC_MODE_EXTINT)
r = 1;
}
return r;
}

void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->apic;
Expand Down

0 comments on commit 40487c6

Please sign in to comment.