KVM: VMX: Move RESET emulation to vmx_vcpu_reset()
Move vCPU RESET emulation, including initializating of select VMCS state, to vmx_vcpu_reset(). Drop the open coded "vCPU load" sequence, as ->vcpu_reset() is invoked while the vCPU is properly loaded (which is kind of the point of ->vcpu_reset()...). Hopefully KVM will someday expose a dedicated RESET ioctl(), and in the meantime separating "create" from "RESET" is a nice cleanup. Deferring VMCS initialization is effectively a nop as it's impossible to safely access the VMCS between the current call site and its new home, as both the vCPU and the pCPU are put immediately after init_vmcs(), i.e. the VMCS isn't guaranteed to be loaded. Note, task preemption is not a problem as vmx_sched_in() _can't_ touch the VMCS as ->sched_in() is invoked before the vCPU, and thus VMCS, is reloaded. I.e. the preemption path also can't consume VMCS state. Cc: Reiji Watanabe <reijiw@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20210921000303.400537-9-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
d06567353e
commit
06692e4b80
@ -4328,10 +4328,6 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
|
||||
|
||||
#define VMX_XSS_EXIT_BITMAP 0
|
||||
|
||||
/*
|
||||
* Noting that the initialization of Guest-state Area of VMCS is in
|
||||
* vmx_vcpu_reset().
|
||||
*/
|
||||
static void init_vmcs(struct vcpu_vmx *vmx)
|
||||
{
|
||||
if (nested)
|
||||
@ -4436,10 +4432,40 @@ static void init_vmcs(struct vcpu_vmx *vmx)
|
||||
vmx_setup_uret_msrs(vmx);
|
||||
}
|
||||
|
||||
static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
init_vmcs(vmx);
|
||||
|
||||
if (nested)
|
||||
memcpy(&vmx->nested.msrs, &vmcs_config.nested, sizeof(vmx->nested.msrs));
|
||||
|
||||
vcpu_setup_sgx_lepubkeyhash(vcpu);
|
||||
|
||||
vmx->nested.posted_intr_nv = -1;
|
||||
vmx->nested.vmxon_ptr = INVALID_GPA;
|
||||
vmx->nested.current_vmptr = INVALID_GPA;
|
||||
vmx->nested.hv_evmcs_vmptr = EVMPTR_INVALID;
|
||||
|
||||
vcpu->arch.microcode_version = 0x100000000ULL;
|
||||
vmx->msr_ia32_feature_control_valid_bits = FEAT_CTL_LOCKED;
|
||||
|
||||
/*
|
||||
* Enforce invariant: pi_desc.nv is always either POSTED_INTR_VECTOR
|
||||
* or POSTED_INTR_WAKEUP_VECTOR.
|
||||
*/
|
||||
vmx->pi_desc.nv = POSTED_INTR_VECTOR;
|
||||
vmx->pi_desc.sn = 1;
|
||||
}
|
||||
|
||||
static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
if (!init_event)
|
||||
__vmx_vcpu_reset(vcpu);
|
||||
|
||||
vmx->rmode.vm86_active = 0;
|
||||
vmx->spec_ctrl = 0;
|
||||
|
||||
@ -6816,7 +6842,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vmx_uret_msr *tsx_ctrl;
|
||||
struct vcpu_vmx *vmx;
|
||||
int i, cpu, err;
|
||||
int i, err;
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct vcpu_vmx, vcpu) != 0);
|
||||
vmx = to_vmx(vcpu);
|
||||
@ -6875,12 +6901,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
vmx->loaded_vmcs = &vmx->vmcs01;
|
||||
cpu = get_cpu();
|
||||
vmx_vcpu_load(vcpu, cpu);
|
||||
vcpu->cpu = cpu;
|
||||
init_vmcs(vmx);
|
||||
vmx_vcpu_put(vcpu);
|
||||
put_cpu();
|
||||
|
||||
if (cpu_need_virtualize_apic_accesses(vcpu)) {
|
||||
err = alloc_apic_access_page(vcpu->kvm);
|
||||
if (err)
|
||||
@ -6893,26 +6914,6 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
|
||||
goto free_vmcs;
|
||||
}
|
||||
|
||||
if (nested)
|
||||
memcpy(&vmx->nested.msrs, &vmcs_config.nested, sizeof(vmx->nested.msrs));
|
||||
|
||||
vcpu_setup_sgx_lepubkeyhash(vcpu);
|
||||
|
||||
vmx->nested.posted_intr_nv = -1;
|
||||
vmx->nested.vmxon_ptr = INVALID_GPA;
|
||||
vmx->nested.current_vmptr = INVALID_GPA;
|
||||
vmx->nested.hv_evmcs_vmptr = EVMPTR_INVALID;
|
||||
|
||||
vcpu->arch.microcode_version = 0x100000000ULL;
|
||||
vmx->msr_ia32_feature_control_valid_bits = FEAT_CTL_LOCKED;
|
||||
|
||||
/*
|
||||
* Enforce invariant: pi_desc.nv is always either POSTED_INTR_VECTOR
|
||||
* or POSTED_INTR_WAKEUP_VECTOR.
|
||||
*/
|
||||
vmx->pi_desc.nv = POSTED_INTR_VECTOR;
|
||||
vmx->pi_desc.sn = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
free_vmcs:
|
||||
|
Loading…
x
Reference in New Issue
Block a user