Commit f2740a8d authored by Emanuele Giuseppe Esposito's avatar Emanuele Giuseppe Esposito Committed by Paolo Bonzini

KVM: nSVM: introduce svm->nested.save to cache save area before checks

This is useful in the next patch, to keep a saved copy
of vmcb12 registers and pass it around more easily.

Instead of blindly copying everything, we just copy EFER, CR0, CR3, CR4,
DR6 and DR7 which are needed by the VMRUN checks.  If more fields will
need to be checked, it will be quite obvious to see that they must be added
in struct vmcb_save_area_cached and in nested_copy_vmcb_save_to_cache().

__nested_copy_vmcb_save_to_cache() takes a vmcb_save_area_cached
parameter, which is useful in order to save the state to a local
variable.
Signed-off-by: default avatarEmanuele Giuseppe Esposito <eesposit@redhat.com>
Message-Id: <20211103140527.752797-3-eesposit@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 907afa48
......@@ -328,6 +328,28 @@ void nested_load_control_from_vmcb12(struct vcpu_svm *svm,
svm->nested.ctl.iopm_base_pa &= ~0x0fffULL;
}
static void __nested_copy_vmcb_save_to_cache(struct vmcb_save_area_cached *to,
struct vmcb_save_area *from)
{
/*
* Copy only fields that are validated, as we need them
* to avoid TOC/TOU races.
*/
to->efer = from->efer;
to->cr0 = from->cr0;
to->cr3 = from->cr3;
to->cr4 = from->cr4;
to->dr6 = from->dr6;
to->dr7 = from->dr7;
}
void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm,
struct vmcb_save_area *save)
{
__nested_copy_vmcb_save_to_cache(&svm->nested.save, save);
}
/*
* Synchronize fields that are written by the processor, so that
* they can be copied back into the vmcb12.
......@@ -670,6 +692,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu)
return -EINVAL;
nested_load_control_from_vmcb12(svm, &vmcb12->control);
nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
if (!nested_vmcb_valid_sregs(vcpu, &vmcb12->save) ||
!nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) {
......
......@@ -4435,6 +4435,7 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
vmcb12 = map.hva;
nested_load_control_from_vmcb12(svm, &vmcb12->control);
nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false);
unmap_save:
......
......@@ -105,6 +105,15 @@ struct kvm_vmcb_info {
uint64_t asid_generation;
};
struct vmcb_save_area_cached {
u64 efer;
u64 cr4;
u64 cr3;
u64 cr0;
u64 dr7;
u64 dr6;
};
struct svm_nested_state {
struct kvm_vmcb_info vmcb02;
u64 hsave_msr;
......@@ -122,6 +131,12 @@ struct svm_nested_state {
/* cache for control fields of the guest */
struct vmcb_control_area ctl;
/*
* Note: this struct is not kept up-to-date while L2 runs; it is only
* valid within nested_svm_vmrun.
*/
struct vmcb_save_area_cached save;
bool initialized;
};
......@@ -496,6 +511,8 @@ void nested_svm_update_tsc_ratio_msr(struct kvm_vcpu *vcpu);
void svm_write_tsc_multiplier(struct kvm_vcpu *vcpu, u64 multiplier);
void nested_load_control_from_vmcb12(struct vcpu_svm *svm,
struct vmcb_control_area *control);
void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm,
struct vmcb_save_area *save);
void nested_sync_control_from_vmcb02(struct vcpu_svm *svm);
void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm);
void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment