All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@redhat.com>
To: Avi Kivity <avi@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>, kvm@vger.kernel.org
Subject: Re: [PATCH 1/6] KVM: Check for pending events before attempting injection
Date: Thu, 29 Jul 2010 09:51:27 +0300	[thread overview]
Message-ID: <20100729065127.GL31711@redhat.com> (raw)
In-Reply-To: <1280236780-5847-2-git-send-email-avi@redhat.com>

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@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 majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
			Gleb.

  parent reply	other threads:[~2010-07-29  6:51 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-27 13:19 [PATCH 0/6] Nonatomic interrupt injection Avi Kivity
2010-07-27 13:19 ` [PATCH 1/6] KVM: Check for pending events before attempting injection Avi Kivity
2010-07-28 16:21   ` Marcelo Tosatti
2010-07-28 16:31     ` Avi Kivity
2010-07-28 16:37       ` Marcelo Tosatti
2010-07-28 16:53         ` Avi Kivity
2010-07-28 17:22           ` Marcelo Tosatti
2010-07-29  8:49             ` Avi Kivity
2010-07-29 15:44               ` Marcelo Tosatti
2010-07-29  6:51   ` Gleb Natapov [this message]
2010-07-29  8:56     ` Avi Kivity
2010-07-27 13:19 ` [PATCH 2/6] KVM: VMX: Split up vmx_complete_interrupts() Avi Kivity
2010-07-27 13:19 ` [PATCH 3/6] KVM: VMX: Move real-mode interrupt injection fixup to vmx_complete_interrupts() Avi Kivity
2010-07-27 13:19 ` [PATCH 4/6] KVM: VMX: Parameterize vmx_complete_interrupts() for both exit and entry Avi Kivity
2010-07-27 13:19 ` [PATCH 5/6] KVM: Non-atomic interrupt injection Avi Kivity
2010-07-27 13:19 ` [PATCH 6/6] KVM: VMX: Move fixup_rmode_irq() to avoid forward declaration Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100729065127.GL31711@redhat.com \
    --to=gleb@redhat.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.