On Tue, Jul 27, 2010 at 04:19:35PM +0300, Avi Kivity wrote: > 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 > What about userspace irq chip? Does it work with this patch? I don't see that you set KVM_REQ_EVENT on ioctl(KVM_INTERRUPT) for instance and vcpu->run->request_interrupt_window should be probably checked out of if (KVM_REQ_EVEN). It looks like with this approach we scatter irq injection logic all over the code instead of having it in one place. > This improves non-injecting entry performance, and sets the stage for > non-atomic injection. > > Signed-off-by: Avi Kivity <avi@xxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html