aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/svm.c')
-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)