From: Avi Kivity <avi@redhat.com>
To: "Nadav Har'El" <nyh@il.ibm.com>
Cc: kvm@vger.kernel.org, gleb@redhat.com
Subject: Re: [PATCH 19/28] nVMX: Exiting from L2 to L1
Date: Thu, 09 Dec 2010 14:55:20 +0200 [thread overview]
Message-ID: <4D00D1B8.5020807@redhat.com> (raw)
In-Reply-To: <201012081709.oB8H9fgE008756@rice.haifa.ibm.com>
On 12/08/2010 07:09 PM, Nadav Har'El wrote:
> This patch implements nested_vmx_vmexit(), called when the nested L2 guest
> exits and we want to run its L1 parent and let it handle this exit.
>
> Note that this will not necessarily be called on every L2 exit. L0 may decide
> to handle a particular exit on its own, without L1's involvement; In that
> case, L0 will handle the exit, and resume running L2, without running L1 and
> without calling nested_vmx_vmexit(). The logic for deciding whether to handle
> a particular exit in L1 or in L0, i.e., whether to call nested_vmx_vmexit(),
> will appear in the next patch.
>
>
> +void prepare_vmcs12(struct kvm_vcpu *vcpu)
> +{
> + struct vmcs_fields *vmcs12 = get_vmcs12_fields(vcpu);
> +
> + /* update guest state fields: */
> + vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
> + vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
> +
> + vmcs12->guest_dr7 = vmcs_readl(GUEST_DR7);
> + vmcs12->guest_rsp = vmcs_readl(GUEST_RSP);
> + vmcs12->guest_rip = vmcs_readl(GUEST_RIP);
> + vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
kvm_register_read() etc.
> +
> +static int nested_vmx_vmexit(struct kvm_vcpu *vcpu, bool is_interrupt)
> +{
> + struct vcpu_vmx *vmx = to_vmx(vcpu);
> + int efer_offset;
> + struct vmcs_fields *vmcs01 = vmx->nested.vmcs01_fields;
> +
> + if (!is_guest_mode(vcpu)) {
> + printk(KERN_INFO "WARNING: %s called but not in nested mode\n",
> + __func__);
> + return 0;
> + }
> +
> + sync_cached_regs_to_vmcs(vcpu);
> +
> + prepare_vmcs12(vcpu);
> +
> + if (is_interrupt)
> + get_vmcs12_fields(vcpu)->vm_exit_reason =
> + EXIT_REASON_EXTERNAL_INTERRUPT;
> +
> + vmx->nested.current_vmcs12->launched = vmx->launched;
> + vmx->nested.current_vmcs12->cpu = vcpu->cpu;
> +
> + vmx->vmcs = vmx->nested.vmcs01;
> + vcpu->cpu = vmx->nested.l1_state.cpu;
> + vmx->launched = vmx->nested.l1_state.launched;
> +
> + leave_guest_mode(vcpu);
> +
> + vmx_vcpu_load(vcpu, get_cpu());
> + put_cpu();
> +
> + vcpu->arch.efer = vmx->nested.l1_state.efer;
> + if ((vcpu->arch.efer& EFER_LMA)&&
> + !(vcpu->arch.efer& EFER_SCE))
> + vcpu->arch.efer |= EFER_SCE;
set_efer() in x86.c for the side effects.
> +
> + efer_offset = __find_msr_index(vmx, MSR_EFER);
> + if (update_transition_efer(vmx, efer_offset))
> + wrmsrl(MSR_EFER, vmx->guest_msrs[efer_offset].data);
Including this.
> +
> + /*
> + * L2 perhaps switched to real mode and set vmx->rmode, but we're back
> + * in L1 and as it is running VMX, it can't be in real mode.
> + */
> + vmx->rmode.vm86_active = 0;
L2 cannot be in real mode since vmx does not support it (except for
unrestricted guest, in which case rmode.vm86_active would be clear).
> +
> + /*
> + * If L1 set the HOST_* fields in the VMCS, when exiting from L2 to L1
> + * we need to return those, not L1's old values.
> + */
> + vmcs_writel(GUEST_RIP, get_vmcs12_fields(vcpu)->host_rip);
> + vmcs_writel(GUEST_RSP, get_vmcs12_fields(vcpu)->host_rsp);
kvm_register_write() etc.
> + vmcs01->cr0_read_shadow = get_vmcs12_fields(vcpu)->host_cr0;
> +
> + /*
> + * We're running a regular L1 guest again, so we do the regular KVM
> + * thing: run vmx_set_cr0 with the cr0 bits the guest thinks it has.
> + * vmx_set_cr0 might use slightly different bits on the new guest_cr0
> + * it sets, e.g., add TS when !fpu_active.
> + * Note that vmx_set_cr0 refers to rmode and efer set above.
> + */
> + vmx_set_cr0(vcpu, guest_readable_cr0(vmcs01));
kvm_set_cr0() takes care of some extra stuff. Why guest_readable_cr0?
want vmcs12->host_cr0.
> + /*
> + * If we did fpu_activate()/fpu_deactive() during l2's run, we need to
> + * apply the same changes to l1's vmcs. We just set cr0 correctly, but
> + * now we need to also update cr0_guest_host_mask and exception_bitmap.
> + */
> + vmcs_write32(EXCEPTION_BITMAP,
> + (vmcs01->exception_bitmap& ~(1u<<NM_VECTOR)) |
> + (vcpu->fpu_active ? 0 : (1u<<NM_VECTOR)));
> + vcpu->arch.cr0_guest_owned_bits = (vcpu->fpu_active ? X86_CR0_TS : 0);
> + vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
Should be a side effect of kvm_set_cr0().
> +
> + vmx_set_cr4(vcpu, guest_readable_cr4(vmcs01));
> + vcpu->arch.cr4_guest_owned_bits = ~vmcs01->cr4_guest_host_mask;
kvm_set_cr4(vmcs12->host_cr4)
> +
> + if (enable_ept) {
> + /* shadow page tables on EPT: */
> + set_cr3_and_pdptrs(vcpu, get_vmcs12_fields(vcpu)->host_cr3);
> + } else {
> + /* shadow page tables on shadow page tables: */
> + kvm_set_cr3(vcpu, vmx->nested.l1_arch_cr3);
> + kvm_mmu_reset_context(vcpu);
> + kvm_mmu_load(vcpu);
> + }
kvm_set_cr3() should suffice in both cases.
kvm_mmu_reset_context()/kvm_mmu_load() is probably unneeded.
> +
> + kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs01->guest_rsp);
> + kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs01->guest_rip);
vmcs12->host_rip
> +
> + if (unlikely(vmx->fail)) {
> + /*
> + * When L1 launches L2 and then we (L0) fail to launch L2,
> + * we nested_vmx_vmexit back to L1, but now should let it know
> + * that the VMLAUNCH failed - with the same error that we
> + * got when launching L2.
> + */
> + vmx->fail = 0;
> + nested_vmx_failValid(vcpu, vmcs_read32(VM_INSTRUCTION_ERROR));
> + } else
> + nested_vmx_succeed(vcpu);
> +
> + return 0;
> +}
> +
> static struct kvm_x86_ops vmx_x86_ops = {
> .cpu_has_kvm_support = cpu_has_kvm_support,
> .disabled_by_bios = vmx_disabled_by_bios,
--
error compiling committee.c: too many arguments to function
next prev parent reply other threads:[~2010-12-09 12:55 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-08 16:59 [PATCH 0/28] nVMX: Nested VMX, v7 Nadav Har'El
2010-12-08 17:00 ` [PATCH 01/28] nVMX: Add "nested" module option to vmx.c Nadav Har'El
2010-12-08 17:00 ` [PATCH 02/28] nVMX: Add VMX and SVM to list of supported cpuid features Nadav Har'El
2010-12-09 11:38 ` Joerg Roedel
2010-12-15 13:25 ` Nadav Har'El
2010-12-08 17:01 ` [PATCH 03/28] nVMX: Implement VMXON and VMXOFF Nadav Har'El
2010-12-08 17:02 ` [PATCH 04/28] nVMX: Allow setting the VMXE bit in CR4 Nadav Har'El
2010-12-08 17:02 ` [PATCH 05/28] nVMX: Introduce vmcs12: a VMCS structure for L1 Nadav Har'El
2010-12-08 17:03 ` [PATCH 06/28] nVMX: Implement reading and writing of VMX MSRs Nadav Har'El
2010-12-09 11:04 ` Avi Kivity
2010-12-08 17:03 ` [PATCH 07/28] nVMX: Decoding memory operands of VMX instructions Nadav Har'El
2010-12-09 11:08 ` Avi Kivity
2010-12-08 17:04 ` [PATCH 08/28] nVMX: Hold a vmcs02 for each vmcs12 Nadav Har'El
2010-12-09 12:41 ` Avi Kivity
2010-12-08 17:04 ` [PATCH 09/28] nVMX: Add VMCS fields to the vmcs12 Nadav Har'El
2010-12-09 12:43 ` Avi Kivity
2010-12-10 12:10 ` Nadav Har'El
2010-12-08 17:05 ` [PATCH 10/28] nVMX: Success/failure of VMX instructions Nadav Har'El
2010-12-08 17:05 ` [PATCH 11/28] nVMX: Implement VMCLEAR Nadav Har'El
2010-12-08 17:06 ` [PATCH 12/28] nVMX: Implement VMPTRLD Nadav Har'El
2010-12-08 17:06 ` [PATCH 13/28] nVMX: Implement VMPTRST Nadav Har'El
2010-12-08 17:07 ` [PATCH 14/28] nVMX: Implement VMREAD and VMWRITE Nadav Har'El
2010-12-08 17:07 ` [PATCH 15/28] nVMX: Prepare vmcs02 from vmcs01 and vmcs12 Nadav Har'El
2010-12-08 17:08 ` [PATCH 16/28] nVMX: Move register-syncing to a function Nadav Har'El
2010-12-08 17:08 ` [PATCH 17/28] nVMX: Implement VMLAUNCH and VMRESUME Nadav Har'El
2010-12-08 17:09 ` [PATCH 18/28] nVMX: No need for handle_vmx_insn function any more Nadav Har'El
2010-12-08 17:09 ` [PATCH 19/28] nVMX: Exiting from L2 to L1 Nadav Har'El
2010-12-09 12:55 ` Avi Kivity [this message]
2010-12-08 17:10 ` [PATCH 20/28] nVMX: Deciding if L0 or L1 should handle an L2 exit Nadav Har'El
2010-12-08 17:10 ` [PATCH 21/28] nVMX: Correct handling of interrupt injection Nadav Har'El
2010-12-08 17:11 ` [PATCH 22/28] nVMX: Correct handling of exception injection Nadav Har'El
2010-12-08 17:11 ` [PATCH 23/28] nVMX: Correct handling of idt vectoring info Nadav Har'El
2010-12-08 17:12 ` [PATCH 24/28] nVMX: Handling of CR0 and CR4 modifying instructions Nadav Har'El
2010-12-09 13:19 ` Avi Kivity
2010-12-08 17:12 ` [PATCH 25/28] nVMX: Further fixes for lazy FPU loading Nadav Har'El
2010-12-09 13:05 ` Avi Kivity
2010-12-08 17:13 ` [PATCH 26/28] nVMX: Additional TSC-offset handling Nadav Har'El
2010-12-08 17:13 ` [PATCH 27/28] nVMX: Miscellenous small corrections Nadav Har'El
2010-12-08 17:14 ` [PATCH 28/28] nVMX: Documentation Nadav Har'El
2010-12-09 12:44 ` [PATCH 0/28] nVMX: Nested VMX, v7 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=4D00D1B8.5020807@redhat.com \
--to=avi@redhat.com \
--cc=gleb@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=nyh@il.ibm.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.