diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/svm.c | 31 |
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 | ||
1505 | static 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 | |||
1505 | static void svm_intr_assist(struct kvm_vcpu *vcpu) | 1526 | static 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); |
1559 | out: | ||
1560 | update_cr8_intercept(vcpu); | ||
1538 | } | 1561 | } |
1539 | 1562 | ||
1540 | static void kvm_reput_irq(struct vcpu_svm *svm) | 1563 | static void kvm_reput_irq(struct vcpu_svm *svm) |