From: Gleb Natapov <gleb@redhat.com>
To: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>, kvm <kvm@vger.kernel.org>,
"Nadav Har'El" <nyh@math.technion.ac.il>,
"Nakajima, Jun" <jun.nakajima@intel.com>
Subject: Re: [PATCH] KVM: nVMX: Rework event injection and recovery
Date: Wed, 20 Feb 2013 18:46:34 +0200 [thread overview]
Message-ID: <20130220164634.GR3600@redhat.com> (raw)
In-Reply-To: <5124C93B.50902@siemens.com>
On Wed, Feb 20, 2013 at 02:01:47PM +0100, Jan Kiszka wrote:
> This aligns VMX more with SVM regarding event injection and recovery for
> nested guests. The changes allow to inject interrupts directly from L0
> to L2.
>
> One difference to SVM is that we always transfer the pending event
> injection into the architectural state of the VCPU and then drop it from
> there if it turns out that we left L2 to enter L1.
>
> VMX and SVM are now identical in how they recover event injections from
> unperformed vmlaunch/vmresume: We detect that VM_ENTRY_INTR_INFO_FIELD
> still contains a valid event and, if yes, transfer the content into L1's
> idt_vectoring_info_field.
>
> To avoid that we incorrectly leak an event into the architectural VCPU
> state that L1 wants to inject, we skip cancellation on nested run.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>
> Survived moderate testing here and (currently) makes sense to me, but
> please review very carefully. I wouldn't be surprised if I'm still
> missing some subtle corner case.
>
> arch/x86/kvm/vmx.c | 57 +++++++++++++++++++++++----------------------------
> 1 files changed, 26 insertions(+), 31 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index dd3a8a0..7d2fbd2 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -6489,8 +6489,6 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
>
> static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
> {
> - if (is_guest_mode(&vmx->vcpu))
> - return;
> __vmx_complete_interrupts(vmx, vmx->idt_vectoring_info,
> VM_EXIT_INSTRUCTION_LEN,
> IDT_VECTORING_ERROR_CODE);
> @@ -6498,7 +6496,7 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
>
> static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
> {
> - if (is_guest_mode(vcpu))
> + if (to_vmx(vcpu)->nested.nested_run_pending)
> return;
Why is this needed here?
> __vmx_complete_interrupts(to_vmx(vcpu),
> vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
> @@ -6531,21 +6529,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
> struct vcpu_vmx *vmx = to_vmx(vcpu);
> unsigned long debugctlmsr;
>
> - if (is_guest_mode(vcpu) && !vmx->nested.nested_run_pending) {
> - struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
> - if (vmcs12->idt_vectoring_info_field &
> - VECTORING_INFO_VALID_MASK) {
> - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
> - vmcs12->idt_vectoring_info_field);
> - vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
> - vmcs12->vm_exit_instruction_len);
> - if (vmcs12->idt_vectoring_info_field &
> - VECTORING_INFO_DELIVER_CODE_MASK)
> - vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
> - vmcs12->idt_vectoring_error_code);
> - }
> - }
> -
> /* Record the guest's net vcpu time for enforced NMI injections. */
> if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
> vmx->entry_time = ktime_get();
> @@ -6704,17 +6687,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
>
> vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
>
> - if (is_guest_mode(vcpu)) {
> - struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
> - vmcs12->idt_vectoring_info_field = vmx->idt_vectoring_info;
> - if (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) {
> - vmcs12->idt_vectoring_error_code =
> - vmcs_read32(IDT_VECTORING_ERROR_CODE);
> - vmcs12->vm_exit_instruction_len =
> - vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
> - }
> - }
> -
> vmx->loaded_vmcs->launched = 1;
>
> vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
> @@ -7403,9 +7375,32 @@ void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
> vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
> vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
>
> - /* clear vm-entry fields which are to be cleared on exit */
> - if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
> + /* drop what we picked up for L0 via vmx_complete_interrupts */
> + vcpu->arch.nmi_injected = false;
> + kvm_clear_exception_queue(vcpu);
> + kvm_clear_interrupt_queue(vcpu);
> +
> + if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) &&
> + vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) {
> + /*
> + * Preserve the event that was supposed to be injected
> + * by emulating it would have been returned in
> + * IDT_VECTORING_INFO_FIELD.
> + */
> + if (vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) &
> + INTR_INFO_VALID_MASK) {
> + vmcs12->idt_vectoring_info_field =
> + vmcs12->vm_entry_intr_info_field;
> + vmcs12->idt_vectoring_error_code =
> + vmcs12->vm_entry_exception_error_code;
> + vmcs12->vm_exit_instruction_len =
> + vmcs12->vm_entry_instruction_len;
> + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
> + }
> +
> + /* clear vm-entry fields which are to be cleared on exit */
> vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;
> + }
> }
>
> /*
> --
> 1.7.3.4
--
Gleb.
next prev parent reply other threads:[~2013-02-20 16:46 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-20 13:01 [PATCH] KVM: nVMX: Rework event injection and recovery Jan Kiszka
2013-02-20 14:14 ` Nadav Har'El
2013-02-20 14:37 ` Jan Kiszka
2013-02-20 17:01 ` Gleb Natapov
2013-02-20 17:24 ` Jan Kiszka
2013-02-20 17:50 ` Jan Kiszka
2013-02-21 9:22 ` Gleb Natapov
2013-02-21 9:43 ` Jan Kiszka
2013-02-21 10:06 ` Gleb Natapov
2013-02-21 10:18 ` Jan Kiszka
2013-02-21 10:28 ` Jan Kiszka
2013-02-21 10:33 ` Jan Kiszka
2013-02-21 13:13 ` Gleb Natapov
2013-02-21 13:22 ` Jan Kiszka
2013-02-21 13:37 ` Nadav Har'El
2013-02-21 13:45 ` Gleb Natapov
2013-02-21 13:28 ` Nadav Har'El
2013-02-20 14:53 ` Jan Kiszka
2013-02-20 15:30 ` Gleb Natapov
2013-02-20 15:51 ` Jan Kiszka
2013-02-20 15:57 ` Gleb Natapov
2013-02-20 16:00 ` Jan Kiszka
2013-02-20 16:46 ` Gleb Natapov [this message]
2013-02-20 16:48 ` Jan Kiszka
2013-02-20 16:51 ` Gleb Natapov
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=20130220164634.GR3600@redhat.com \
--to=gleb@redhat.com \
--cc=jan.kiszka@siemens.com \
--cc=jun.nakajima@intel.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=nyh@math.technion.ac.il \
/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.