aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-04-16 10:51:18 -0400
committerAvi Kivity <avi@qumranet.com>2008-04-27 11:21:43 -0400
commitaaacfc9ae225e88695e610a35627d2256dc08633 (patch)
treeb8cbde694378ab340b4cc3ee2442ae87b9bb6096
parentd7bf8221a3037d0d0760a1ccf1833bda03213abf (diff)
KVM: SVM: disable CR8 intercept when tpr is not masking interrupts
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>
-rw-r--r--arch/x86/kvm/svm.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index ee2ee83f3c48..61bb2cb51215 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1502,6 +1502,27 @@ static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
1502 svm_inject_irq(svm, irq); 1502 svm_inject_irq(svm, irq);
1503} 1503}
1504 1504
1505static void update_cr8_intercept(struct kvm_vcpu *vcpu)
1506{
1507 struct vcpu_svm *svm = to_svm(vcpu);
1508 struct vmcb *vmcb = svm->vmcb;
1509 int max_irr, tpr;
1510
1511 if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
1512 return;
1513
1514 vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
1515
1516 max_irr = kvm_lapic_find_highest_irr(vcpu);
1517 if (max_irr == -1)
1518 return;
1519
1520 tpr = kvm_lapic_get_cr8(vcpu) << 4;
1521
1522 if (tpr >= (max_irr & 0xf0))
1523 vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
1524}
1525
1505static void svm_intr_assist(struct kvm_vcpu *vcpu) 1526static void svm_intr_assist(struct kvm_vcpu *vcpu)
1506{ 1527{
1507 struct vcpu_svm *svm = to_svm(vcpu); 1528 struct vcpu_svm *svm = to_svm(vcpu);
@@ -1514,14 +1535,14 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
1514 SVM_EVTINJ_VEC_MASK; 1535 SVM_EVTINJ_VEC_MASK;
1515 vmcb->control.exit_int_info = 0; 1536 vmcb->control.exit_int_info = 0;
1516 svm_inject_irq(svm, intr_vector); 1537 svm_inject_irq(svm, intr_vector);
1517 return; 1538 goto out;
1518 } 1539 }
1519 1540
1520 if (vmcb->control.int_ctl & V_IRQ_MASK) 1541 if (vmcb->control.int_ctl & V_IRQ_MASK)
1521 return; 1542 goto out;
1522 1543
1523 if (!kvm_cpu_has_interrupt(vcpu)) 1544 if (!kvm_cpu_has_interrupt(vcpu))
1524 return; 1545 goto out;
1525 1546
1526 if (!(vmcb->save.rflags & X86_EFLAGS_IF) || 1547 if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
1527 (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) || 1548 (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
@@ -1529,12 +1550,14 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
1529 /* unable to deliver irq, set pending irq */ 1550 /* unable to deliver irq, set pending irq */
1530 vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR); 1551 vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR);
1531 svm_inject_irq(svm, 0x0); 1552 svm_inject_irq(svm, 0x0);
1532 return; 1553 goto out;
1533 } 1554 }
1534 /* Okay, we can deliver the interrupt: grab it and update PIC state. */ 1555 /* Okay, we can deliver the interrupt: grab it and update PIC state. */
1535 intr_vector = kvm_cpu_get_interrupt(vcpu); 1556 intr_vector = kvm_cpu_get_interrupt(vcpu);
1536 svm_inject_irq(svm, intr_vector); 1557 svm_inject_irq(svm, intr_vector);
1537 kvm_timer_intr_post(vcpu, intr_vector); 1558 kvm_timer_intr_post(vcpu, intr_vector);
1559out:
1560 update_cr8_intercept(vcpu);
1538} 1561}
1539 1562
1540static void kvm_reput_irq(struct vcpu_svm *svm) 1563static void kvm_reput_irq(struct vcpu_svm *svm)