KVM: VMX: Skip emulation required checks during pmode/rmode transitions
Don't refresh "emulation required" when stuffing segments during transitions to/from real mode when running without unrestricted guest. The checks are unnecessary as vmx_set_cr0() unconditionally rechecks "emulation required". They also happen to be broken, as enter_pmode() and enter_rmode() run with a stale vcpu->arch.cr0. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20210713163324.627647-29-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
32437c2aea
commit
1dd7a4f18f
@ -2719,6 +2719,8 @@ static __init int alloc_kvm_area(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
|
||||
|
||||
static void fix_pmode_seg(struct kvm_vcpu *vcpu, int seg,
|
||||
struct kvm_segment *save)
|
||||
{
|
||||
@ -2735,7 +2737,7 @@ static void fix_pmode_seg(struct kvm_vcpu *vcpu, int seg,
|
||||
save->dpl = save->selector & SEGMENT_RPL_MASK;
|
||||
save->s = 1;
|
||||
}
|
||||
vmx_set_segment(vcpu, save, seg);
|
||||
__vmx_set_segment(vcpu, save, seg);
|
||||
}
|
||||
|
||||
static void enter_pmode(struct kvm_vcpu *vcpu)
|
||||
@ -2756,7 +2758,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
|
||||
|
||||
vmx->rmode.vm86_active = 0;
|
||||
|
||||
vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
|
||||
__vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
|
||||
|
||||
flags = vmcs_readl(GUEST_RFLAGS);
|
||||
flags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
|
||||
@ -3291,7 +3293,7 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var)
|
||||
return ar;
|
||||
}
|
||||
|
||||
void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
|
||||
static void __vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
|
||||
@ -3304,7 +3306,7 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
|
||||
vmcs_write16(sf->selector, var->selector);
|
||||
else if (var->s)
|
||||
fix_rmode_seg(seg, &vmx->rmode.segs[seg]);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
vmcs_writel(sf->base, var->base);
|
||||
@ -3326,9 +3328,13 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
|
||||
var->type |= 0x1; /* Accessed */
|
||||
|
||||
vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
|
||||
}
|
||||
|
||||
out:
|
||||
vmx->emulation_required = emulation_required(vcpu);
|
||||
void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
|
||||
{
|
||||
__vmx_set_segment(vcpu, var, seg);
|
||||
|
||||
to_vmx(vcpu)->emulation_required = emulation_required(vcpu);
|
||||
}
|
||||
|
||||
static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
|
||||
|
Loading…
Reference in New Issue
Block a user