From: Avi Kivity <avi@redhat.com>
To: Sheng Yang <sheng@linux.intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>,
kvm@vger.kernel.org, Dexuan Cui <dexuan.cui@intel.com>
Subject: Re: [PATCH v4] KVM: VMX: Enable XSAVE/XRSTORE for guest
Date: Mon, 24 May 2010 16:36:12 +0300 [thread overview]
Message-ID: <4BFA80CC.9070800@redhat.com> (raw)
In-Reply-To: <1274695425-14185-1-git-send-email-sheng@linux.intel.com>
On 05/24/2010 01:03 PM, Sheng Yang wrote:
> From: Dexuan Cui<dexuan.cui@intel.com>
>
> Enable XSAVE/XRSTORE for guest.
>
> Change from V3:
> 1. Enforced the assumption that host OS would use all available xstate bits.
> 2. Various fixes, addressed Avi's comments.
>
> I am still not clear about why we need to reload guest xcr0 when cr4.osxsave
> set...
>
When cr4.osxsave=0, then the guest executes with the host xcr0 (since
xgetbv will trap; this is similar to the guest running with the host fpu
if cr0.ts=0). So if cr4.osxsave transtions, we need to transition xcr0
as well.
> @@ -3354,6 +3356,29 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu)
> return 1;
> }
>
> +static int handle_xsetbv(struct kvm_vcpu *vcpu)
> +{
> + u64 new_bv = kvm_read_edx_eax(vcpu);
> +
> + if (kvm_register_read(vcpu, VCPU_REGS_RCX) != 0)
> + goto err;
> + if (vmx_get_cpl(vcpu) != 0)
> + goto err;
> + if (!(new_bv& XSTATE_FP))
> + goto err;
> + if ((new_bv& XSTATE_YMM)&& !(new_bv& XSTATE_SSE))
> + goto err;
> + if (new_bv& ~XCNTXT_MASK)
> + goto err;
>
Ok. This means we must update kvm immediately when XCNTXT_MASK changes.
(Otherwise we would use KVM_XCNTXT_MASK which is always smaller than
than XCNTXT_MASK).
> + vcpu->arch.xcr0 = new_bv;
> + xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
> + skip_emulated_instruction(vcpu);
> + return 1;
> +err:
> + kvm_inject_gp(vcpu, 0);
> + return 1;
> +}
> +
>
>
> @@ -4124,6 +4176,8 @@ int kvm_arch_init(void *opaque)
>
> perf_register_guest_info_callbacks(&kvm_guest_cbs);
>
> + host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
> +
> return 0;
>
Will fault on old cpu.
> EXPORT_SYMBOL_GPL(fx_init);
> @@ -5134,6 +5195,12 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
>
> vcpu->guest_fpu_loaded = 1;
> unlazy_fpu(current);
> + /*
> + * Restore all possible states in the guest,
> + * and assume host would use all available bits.
> + */
> + if (cpu_has_xsave&& vcpu->arch.xcr0)
> + xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
> fpu_restore_checking(&vcpu->arch.guest_fpu);
>
I think we need to reload xcr0 now to the guest's value.
> trace_kvm_fpu(1);
> }
> @@ -5144,6 +5211,13 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
> return;
>
> vcpu->guest_fpu_loaded = 0;
> + /*
> + * Save all possible states in the guest,
> + * and assume host would use all available bits.
> + * Also load host_xcr0 for host usage.
> + */
> + if (cpu_has_xsave&& vcpu->arch.xcr0)
> + xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
> fpu_save_init(&vcpu->arch.guest_fpu);
> ++vcpu->stat.fpu_reload;
> set_bit(KVM_REQ_DEACTIVATE_FPU,&vcpu->requests);
>
This might be unnecessary.
So far xcr0 life cycle is almost that of
save_host_state()/load_host_state(), but not exactly. When loading the
guest fpu we switch temporarily to host xcr0, then we have to switch
back, but only if gcr4.osxsave. When saving the guest fpu, we're
already using the host xcr0:
> void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> {
> kvm_x86_ops->vcpu_put(vcpu);
> kvm_put_guest_fpu(vcpu);
> }
One way to simplify this is to have a vcpu->guest_xcr0_loaded flag and
check it when needed. So the transition matrix is:
save_host_state: if gcr4.osxsave, set guest_xcr0_loaded, load it
set gcr4.osxsave: ditto
clear gcr4.osxsave: do nothing
load_host_state: if guest_xcr0_loaded, clear it, reload host xcr0
fpu switching: if (switched) switch; reload fpu; if (switched) switch
may be simplified if we move xcr0 reload back to guest entry (... :)
but make it lazy:
save_host_state: nothing
set cr4.osxsave: nothing
clear cr4.osxsave: nothing
guest entry: if (gcr4.osxsave && !guest_xcr0_loaded) {
guest_xcr0_loaded = true, load gxcr0 }
load_host_state: if (guest_xcr0_loaded) { guest_xcr0_loaded = false;
load host xcr0 }
fpu switching: if (guest_xcr0_loaded) { guest_xcr0_loaded = false;
load host xcr0 }, do fpu stuff
So we delay xcr0 reload as late as possible for both entry and exit.
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
next prev parent reply other threads:[~2010-05-24 13:36 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-24 10:03 [PATCH v4] KVM: VMX: Enable XSAVE/XRSTORE for guest Sheng Yang
2010-05-24 13:36 ` Avi Kivity [this message]
2010-05-24 13:40 ` Avi Kivity
2010-05-25 6:28 ` Sheng Yang
2010-05-25 7:14 ` Avi Kivity
2010-05-24 13:47 ` 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=4BFA80CC.9070800@redhat.com \
--to=avi@redhat.com \
--cc=dexuan.cui@intel.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=sheng@linux.intel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox