Instead of blindly attempting to inject an event before each guest entry,
check for a possible event first in vcpu->requests.  Sites that can trigger
event injection are modified to set KVM_REQ_EVENT:

- interrupt, nmi window opening
- ppr updates
- i8259 output changes
- local apic irr changes
- rflags updates
- gif flag set
- event set on exit

This improves non-injecting entry performance, and sets the stage for
non-atomic injection.

Signed-off-by: Avi Kivity <a...@redhat.com>
---
 arch/x86/kvm/i8259.c     |    1 +
 arch/x86/kvm/lapic.c     |   12 ++++++++++--
 arch/x86/kvm/svm.c       |    8 +++++++-
 arch/x86/kvm/vmx.c       |    6 ++++++
 arch/x86/kvm/x86.c       |   35 ++++++++++++++++++++++++++---------
 include/linux/kvm_host.h |    1 +
 6 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 8d10c06..9f7ab44 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -64,6 +64,7 @@ static void pic_unlock(struct kvm_pic *s)
                if (!found)
                        found = s->kvm->bsp_vcpu;
 
+               kvm_make_request(KVM_REQ_EVENT, found);
                kvm_vcpu_kick(found);
        }
 }
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 77d8c0f..e83d203 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -259,9 +259,10 @@ static inline int apic_find_highest_isr(struct kvm_lapic 
*apic)
 
 static void apic_update_ppr(struct kvm_lapic *apic)
 {
-       u32 tpr, isrv, ppr;
+       u32 tpr, isrv, ppr, old_ppr;
        int isr;
 
+       old_ppr = apic_get_reg(apic, APIC_PROCPRI);
        tpr = apic_get_reg(apic, APIC_TASKPRI);
        isr = apic_find_highest_isr(apic);
        isrv = (isr != -1) ? isr : 0;
@@ -274,7 +275,10 @@ static void apic_update_ppr(struct kvm_lapic *apic)
        apic_debug("vlapic %p, ppr 0x%x, isr 0x%x, isrv 0x%x",
                   apic, ppr, isr, isrv);
 
-       apic_set_reg(apic, APIC_PROCPRI, ppr);
+       if (old_ppr != ppr) {
+               apic_set_reg(apic, APIC_PROCPRI, ppr);
+               kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
+       }
 }
 
 static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
@@ -391,6 +395,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int 
delivery_mode,
                        break;
                }
 
+               kvm_make_request(KVM_REQ_EVENT, vcpu);
                kvm_vcpu_kick(vcpu);
                break;
 
@@ -416,6 +421,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int 
delivery_mode,
                                       "INIT on a runnable vcpu %d\n",
                                       vcpu->vcpu_id);
                        vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+                       kvm_make_request(KVM_REQ_EVENT, vcpu);
                        kvm_vcpu_kick(vcpu);
                } else {
                        apic_debug("Ignoring de-assert INIT to vcpu %d\n",
@@ -430,6 +436,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int 
delivery_mode,
                        result = 1;
                        vcpu->arch.sipi_vector = vector;
                        vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
+                       kvm_make_request(KVM_REQ_EVENT, vcpu);
                        kvm_vcpu_kick(vcpu);
                }
                break;
@@ -475,6 +482,7 @@ static void apic_set_eoi(struct kvm_lapic *apic)
                trigger_mode = IOAPIC_EDGE_TRIG;
        if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI))
                kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode);
+       kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
 }
 
 static void apic_send_ipi(struct kvm_lapic *apic)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 56c9b6b..a51e067 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2258,6 +2258,7 @@ static int stgi_interception(struct vcpu_svm *svm)
 
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
        skip_emulated_instruction(&svm->vcpu);
+       kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 
        enable_gif(svm);
 
@@ -2644,6 +2645,7 @@ static int interrupt_window_interception(struct vcpu_svm 
*svm)
 {
        struct kvm_run *kvm_run = svm->vcpu.run;
 
+       kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
        svm_clear_vintr(svm);
        svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
        /*
@@ -3089,8 +3091,10 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
 
        svm->int3_injected = 0;
 
-       if (svm->vcpu.arch.hflags & HF_IRET_MASK)
+       if (svm->vcpu.arch.hflags & HF_IRET_MASK) {
                svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
+               kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
+       }
 
        svm->vcpu.arch.nmi_injected = false;
        kvm_clear_exception_queue(&svm->vcpu);
@@ -3099,6 +3103,8 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
        if (!(exitintinfo & SVM_EXITINTINFO_VALID))
                return;
 
+       kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
+
        vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
        type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 2fdcc98..d8edfe3 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3348,6 +3348,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu)
 
 static int handle_tpr_below_threshold(struct kvm_vcpu *vcpu)
 {
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
        return 1;
 }
 
@@ -3360,6 +3361,8 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu)
        cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
        vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
 
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
+
        ++vcpu->stat.irq_window_exits;
 
        /*
@@ -3616,6 +3619,7 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu)
        cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
        vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
        ++vcpu->stat.nmi_window_exits;
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
 
        return 1;
 }
@@ -3849,6 +3853,8 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
        if (!idtv_info_valid)
                return;
 
+       kvm_make_request(KVM_REQ_EVENT, &vmx->vcpu);
+
        vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
        type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 76fbc32..38e91b6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -282,6 +282,8 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
        u32 prev_nr;
        int class1, class2;
 
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
+
        if (!vcpu->arch.exception.pending) {
        queue:
                vcpu->arch.exception.pending = true;
@@ -337,6 +339,7 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned 
long addr,
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
 {
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
        vcpu->arch.nmi_pending = 1;
 }
 EXPORT_SYMBOL_GPL(kvm_inject_nmi);
@@ -2356,6 +2359,8 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct 
kvm_vcpu *vcpu,
        if (events->flags & KVM_VCPUEVENT_VALID_SIPI_VECTOR)
                vcpu->arch.sipi_vector = events->sipi_vector;
 
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
+
        return 0;
 }
 
@@ -4059,6 +4064,7 @@ restart:
 
        toggle_interruptibility(vcpu, vcpu->arch.emulate_ctxt.interruptibility);
        kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
        memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
        kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
 
@@ -4731,17 +4737,19 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                goto out;
        }
 
-       inject_pending_event(vcpu);
+       if (kvm_check_request(KVM_REQ_EVENT, vcpu)) {
+               inject_pending_event(vcpu);
 
-       /* enable NMI/IRQ window open exits if needed */
-       if (vcpu->arch.nmi_pending)
-               kvm_x86_ops->enable_nmi_window(vcpu);
-       else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
-               kvm_x86_ops->enable_irq_window(vcpu);
+               /* enable NMI/IRQ window open exits if needed */
+               if (vcpu->arch.nmi_pending)
+                       kvm_x86_ops->enable_nmi_window(vcpu);
+               else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+                       kvm_x86_ops->enable_irq_window(vcpu);
 
-       if (kvm_lapic_enabled(vcpu)) {
-               update_cr8_intercept(vcpu);
-               kvm_lapic_sync_to_vapic(vcpu);
+               if (kvm_lapic_enabled(vcpu)) {
+                       update_cr8_intercept(vcpu);
+                       kvm_lapic_sync_to_vapic(vcpu);
+               }
        }
 
        srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
@@ -4980,6 +4988,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
 
        vcpu->arch.exception.pending = false;
 
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
+
        return 0;
 }
 
@@ -5043,6 +5053,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
                                    struct kvm_mp_state *mp_state)
 {
        vcpu->arch.mp_state = mp_state->mp_state;
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
        return 0;
 }
 
@@ -5077,6 +5088,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 
tss_selector, int reason,
        memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
        kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
        kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
        return EMULATE_DONE;
 }
 EXPORT_SYMBOL_GPL(kvm_task_switch);
@@ -5147,6 +5159,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
            !is_protmode(vcpu))
                vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
+
        return 0;
 }
 
@@ -5375,6 +5389,8 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
        vcpu->arch.dr6 = DR6_FIXED_1;
        vcpu->arch.dr7 = DR7_FIXED_1;
 
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
+
        return kvm_x86_ops->vcpu_reset(vcpu);
 }
 
@@ -5683,6 +5699,7 @@ void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long 
rflags)
            kvm_is_linear_rip(vcpu, vcpu->arch.singlestep_rip))
                rflags |= X86_EFLAGS_TF;
        kvm_x86_ops->set_rflags(vcpu, rflags);
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_set_rflags);
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c13cc48..e41e66b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -39,6 +39,7 @@
 #define KVM_REQ_KVMCLOCK_UPDATE    8
 #define KVM_REQ_KICK               9
 #define KVM_REQ_DEACTIVATE_FPU    10
+#define KVM_REQ_EVENT             11
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID    0
 
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to