Skip to content

Commit

Permalink
KVM: SVM: disable CR8 intercept when tpr is not masking interrupts
Browse files Browse the repository at this point in the history
This patch disables the intercept of CR8 writes if the TPR is not masking
interrupts. This reduces the total number CR8 intercepts to below 1 percent of
what we have without this patch using Windows 64 bit guests.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Joerg Roedel authored and Avi Kivity committed Apr 27, 2008
1 parent d7bf822 commit aaacfc9
Showing 1 changed file with 27 additions and 4 deletions.
31 changes: 27 additions & 4 deletions arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,27 @@ static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
svm_inject_irq(svm, irq);
}

static void update_cr8_intercept(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
struct vmcb *vmcb = svm->vmcb;
int max_irr, tpr;

if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
return;

vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;

max_irr = kvm_lapic_find_highest_irr(vcpu);
if (max_irr == -1)
return;

tpr = kvm_lapic_get_cr8(vcpu) << 4;

if (tpr >= (max_irr & 0xf0))
vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
}

static void svm_intr_assist(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
Expand All @@ -1514,27 +1535,29 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
SVM_EVTINJ_VEC_MASK;
vmcb->control.exit_int_info = 0;
svm_inject_irq(svm, intr_vector);
return;
goto out;
}

if (vmcb->control.int_ctl & V_IRQ_MASK)
return;
goto out;

if (!kvm_cpu_has_interrupt(vcpu))
return;
goto out;

if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
(vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
/* unable to deliver irq, set pending irq */
vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR);
svm_inject_irq(svm, 0x0);
return;
goto out;
}
/* Okay, we can deliver the interrupt: grab it and update PIC state. */
intr_vector = kvm_cpu_get_interrupt(vcpu);
svm_inject_irq(svm, intr_vector);
kvm_timer_intr_post(vcpu, intr_vector);
out:
update_cr8_intercept(vcpu);
}

static void kvm_reput_irq(struct vcpu_svm *svm)
Expand Down

0 comments on commit aaacfc9

Please sign in to comment.