Commit 93ea5388 authored by Gleb Natapov's avatar Gleb Natapov Committed by Marcelo Tosatti

KVM: VMX: Initialize vm86 TSS only once.

Currently vm86 task is initialized on each real mode entry and vcpu
reset. Initialization is done by zeroing TSS and updating relevant
fields. But since all vcpus are using the same TSS there is a race where
one vcpu may use TSS while other vcpu is initializing it, so the vcpu
that uses TSS will see wrong TSS content and will behave incorrectly.
Fix that by initializing TSS only once.
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent a8ba6c26
...@@ -176,7 +176,6 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu) ...@@ -176,7 +176,6 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
return container_of(vcpu, struct vcpu_vmx, vcpu); return container_of(vcpu, struct vcpu_vmx, vcpu);
} }
static int init_rmode(struct kvm *kvm);
static u64 construct_eptp(unsigned long root_hpa); static u64 construct_eptp(unsigned long root_hpa);
static void kvm_cpu_vmxon(u64 addr); static void kvm_cpu_vmxon(u64 addr);
static void kvm_cpu_vmxoff(void); static void kvm_cpu_vmxoff(void);
...@@ -1802,7 +1801,6 @@ static void enter_rmode(struct kvm_vcpu *vcpu) ...@@ -1802,7 +1801,6 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
continue_rmode: continue_rmode:
kvm_mmu_reset_context(vcpu); kvm_mmu_reset_context(vcpu);
init_rmode(vcpu->kvm);
} }
static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer) static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
...@@ -2737,22 +2735,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) ...@@ -2737,22 +2735,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
return 0; return 0;
} }
static int init_rmode(struct kvm *kvm)
{
int idx, ret = 0;
idx = srcu_read_lock(&kvm->srcu);
if (!init_rmode_tss(kvm))
goto exit;
if (!init_rmode_identity_map(kvm))
goto exit;
ret = 1;
exit:
srcu_read_unlock(&kvm->srcu, idx);
return ret;
}
static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
...@@ -2760,10 +2742,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) ...@@ -2760,10 +2742,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
int ret; int ret;
vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)); vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
if (!init_rmode(vmx->vcpu.kvm)) {
ret = -ENOMEM;
goto out;
}
vmx->rmode.vm86_active = 0; vmx->rmode.vm86_active = 0;
...@@ -3009,6 +2987,9 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr) ...@@ -3009,6 +2987,9 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
if (ret) if (ret)
return ret; return ret;
kvm->arch.tss_addr = addr; kvm->arch.tss_addr = addr;
if (!init_rmode_tss(kvm))
return -ENOMEM;
return 0; return 0;
} }
...@@ -4224,8 +4205,11 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) ...@@ -4224,8 +4205,11 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
if (!kvm->arch.ept_identity_map_addr) if (!kvm->arch.ept_identity_map_addr)
kvm->arch.ept_identity_map_addr = kvm->arch.ept_identity_map_addr =
VMX_EPT_IDENTITY_PAGETABLE_ADDR; VMX_EPT_IDENTITY_PAGETABLE_ADDR;
err = -ENOMEM;
if (alloc_identity_pagetable(kvm) != 0) if (alloc_identity_pagetable(kvm) != 0)
goto free_vmcs; goto free_vmcs;
if (!init_rmode_identity_map(kvm))
goto free_vmcs;
} }
return &vmx->vcpu; return &vmx->vcpu;
......
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