vmx_vcpu_run kvm_load_guest_xsave_state vmx_vcpu_enter_exit(vcpu, vmx); /* The actual VMENTER/EXIT is in the .noinstr.text section. */ kvm_load_host_xsave_state
1 2 3 4 5 6 7 8 9 10 11 12 13 14
voidkvm_load_guest_xsave_state(struct kvm_vcpu *vcpu) { ... if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)) {
if (vcpu->arch.xcr0 != host_xcr0) xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
voidkvm_load_host_xsave_state(struct kvm_vcpu *vcpu) { ... if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)) {
if (vcpu->arch.xcr0 != host_xcr0) xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
if (vcpu->arch.xsaves_enabled && vcpu->arch.ia32_xss != host_xss) wrmsrl(MSR_IA32_XSS, host_xss); } }
3. kvm_load_guest_fpu and kvm_put_guest_fpu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
structkvm_vcpu_arch { ... /* * QEMU userspace and the guest each have their own FPU state. * In vcpu_run, we switch between the user and guest FPU contexts. * While running a VCPU, the VCPU thread will have the guest FPU * context. * * Note that while the PKRU state lives inside the fpu registers, * it is switched out separately at VMENTER and VMEXIT time. The * "guest_fpstate" state here contains the guest FPU context, with the * host PRKU bits. */ structfpu_guestguest_fpu; ... }
1 2 3 4 5 6 7 8 9 10
/* Swap (qemu) user FPU context for the guest FPU context. */ staticvoidkvm_load_guest_fpu(struct kvm_vcpu *vcpu) { /* * Exclude PKRU from restore as restored separately in * kvm_x86_ops.run(). */ fpu_swap_kvm_fpstate(&vcpu->arch.guest_fpu, true); ... }
1 2 3 4 5 6
/* When vcpu_run ends, restore user space FPU context. */ staticvoidkvm_put_guest_fpu(struct kvm_vcpu *vcpu) { fpu_swap_kvm_fpstate(&vcpu->arch.guest_fpu, false); ... }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
structfpu { ... /* * @fpstate: * * Pointer to the active struct fpstate. Initialized to * point at @__fpstate below. */ structfpstate *fpstate;
/* * @__task_fpstate: * * Pointer to an inactive struct fpstate. Initialized to NULL. Is * used only for KVM support to swap out the regular task fpstate. */ structfpstate *__task_fpstate; ... }
if (!cur_fps->is_confidential) { /* Includes XFD update */ restore_fpregs_from_fpstate(cur_fps, XFEATURE_MASK_FPSTATE); } else { /* * XSTATE is restored by firmware from encrypted * memory. Make sure XFD state is correct while * running with guest fpstate */ xfd_update_state(cur_fps); }
/** * __copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer * @to: membuf descriptor * @fpstate: The fpstate buffer from which to copy * @pkru_val: The PKRU value to store in the PKRU component * @copy_mode: The requested copy mode * * Converts from kernel XSAVE or XSAVES compacted format to UABI conforming * format, i.e. from the kernel internal hardware dependent storage format * to the requested @mode. UABI XSTATE is always uncompacted! * * It supports partial copy but @to.pos always starts from zero. */ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate, u32 pkru_val, enum xstate_copy_mode copy_mode) { ... }