KVM: VMX: fix incorrect cached cpl value with real/v8086 modes
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
arch/x86/kvm/vmx.c +7 -7
@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)static int __vmx_get_cpl (struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ; }
@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* * If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations * fail; use the cache instead.
A message that is not in the archive (sent off-list or not yet received): CAEbWair0awmpB9QXFGXJmooSsHg3B6P3uZrmLcyzs=T70TS7VA@mail.gmail.com
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/*
Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).
True. Marcelo what failure do you see without the patch?
--
Gleb.
Quoted 53 lines · Gleb Natapov
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).
Quoted 4 lines
True. Marcelo what failure do you see without the patch?
--
Gleb.
On transition _to_ real mode, linearize fails due to CPL checks (FreeBSD). I'll resend the patch with use of cache for VMREAD(GUEST_RFLAGS), which is already implemented.
Quoted 54 lines · Marcelo Tosatti
Quoted 53 lines · Gleb Natapov
Quoted 52 lines · Avi Kivity
Quoted 43 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* * If we enter real mode with cs.sel & 3 != 0, the normal CPL Quoted 3 lines
calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).
Quoted 8 lines
Quoted 4 lines
True. Marcelo what failure do you see without the patch?
--
Gleb.On transition _to_ real mode, linearize fails due to CPL checks (FreeBSD). I'll resend the patch with use of cache for
VMREAD(GUEST_RFLAGS), which is already implemented.
I am curious does it still fails with all my vmx patches applied too? The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
--
Gleb.
Quoted 57 lines · Gleb Natapov
Quoted 56 lines · Marcelo Tosatti
Quoted 55 lines · Gleb Natapov
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).True. Marcelo what failure do you see without the patch?
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines
--
Gleb.On transition _to_ real mode, linearize fails due to CPL checks (FreeBSD). I'll resend the patch with use of cache for
VMREAD(GUEST_RFLAGS), which is already implemented.I am curious does it still fails with all my vmx patches applied too?
Yes.
Quoted 3 lines
The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
Its transition _to_ real mode (from protected).
Quoted 61 lines · Marcelo Tosatti
Quoted 60 lines · Gleb Natapov
Quoted 59 lines · Marcelo Tosatti
Quoted 57 lines · Gleb Natapov
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).True. Marcelo what failure do you see without the patch?
--
Gleb.
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
On transition _to_ real mode, linearize fails due to CPL checks (FreeBSD). I'll resend the patch with use of cache for
VMREAD(GUEST_RFLAGS), which is already implemented.I am curious does it still fails with all my vmx patches applied too?
Yes.
Which FreeBSD exactly? Cannot reproduce with FreeBSD 9 64 bits here.
Quoted 5 lines
Quoted 3 lines
The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
Its transition _to_ real mode (from protected).
But in protected mode CPL should be 0 during boot.
--
Gleb.
Quoted 62 lines · Gleb Natapov
Quoted 61 lines · Marcelo Tosatti
Quoted 60 lines · Gleb Natapov
Quoted 59 lines · Marcelo Tosatti
Quoted 57 lines · Gleb Natapov
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).True. Marcelo what failure do you see without the patch?
--
Gleb.
Quoted 8 lines
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
On transition _to_ real mode, linearize fails due to CPL checks (FreeBSD). I'll resend the patch with use of cache for
VMREAD(GUEST_RFLAGS), which is already implemented.I am curious does it still fails with all my vmx patches applied too?
Yes.
Which FreeBSD exactly? Cannot reproduce with FreeBSD 9 64 bits here.
FreeBSD 9.1 with -smp 2.
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
Its transition _to_ real mode (from protected).
But in protected mode CPL should be 0 during boot.
BTX (FreeBSD's bootloader) does:
Quoted 66 lines · Marcelo Tosatti
Quoted 65 lines · Gleb Natapov
Quoted 64 lines · Marcelo Tosatti
Quoted 63 lines · Gleb Natapov
Quoted 62 lines · Marcelo Tosatti
Quoted 53 lines · Gleb Natapov
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/* Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).Quoted 4 lines
True. Marcelo what failure do you see without the patch?
--
Gleb.On transition _to_ real mode, linearize fails due to CPL checks (FreeBSD). I'll resend the patch with use of cache for
VMREAD(GUEST_RFLAGS), which is already implemented.
Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line
I am curious does it still fails with all my vmx patches applied too?
Yes.
Which FreeBSD exactly? Cannot reproduce with FreeBSD 9 64 bits here.
FreeBSD 9.1 with -smp 2.
I cannot reproduce. I do see boot failure on the next branch with 9.[01] 64 bit -smp 2 here, but it is caused but segment registers been all incorrect on a secondary vcpu and this patch does not help. Applying
http://comments.gmane.org/gmane.comp.emulators.kvm.devel/102593 fixes it.
Quoted 11 lines
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
Its transition _to_ real mode (from protected).
But in protected mode CPL should be 0 during boot.
BTX (FreeBSD's bootloader) does:
Crazy. Regardless, I think your patch is correct and the current code that uses cpl cache during emulation is wrong and it remains wrong even after your patch. What if last time cpl cache was updated was while vcpu ran in cpl 3? Commit message says that it tries to fix the case when CS.selector&3 != 0 during transition to protected mode, but this can be fixed by setting cpl cache to 0 in vmx_set_cr0() instead of clearing it.
Two things about the patch itself. Get rid of __vmx_get_cpl() and call to vmx_read_guest_seg_selector() directly from vmx_get_cpl() and drop __clear_bit(VCPU_EXREG_CPL) from vmx_set_rflags() and vmx_set_cr0() since vmx->cpl no longer depends on rflags and cr0.
--
Gleb.
Quoted 17 lines · Gleb Natapov
Quoted 1 line
FreeBSD 9.1 with -smp 2.
I cannot reproduce. I do see boot failure on the next branch with 9.[01] 64 bit -smp 2 here, but it is caused but segment registers been all incorrect on a secondary vcpu and this patch does not help. Applying
http://comments.gmane.org/gmane.comp.emulators.kvm.devel/102593 fixes it.Quoted 10 lines
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
Its transition _to_ real mode (from protected).
But in protected mode CPL should be 0 during boot.
BTX (FreeBSD's bootloader) does:
Quoted 7 lines
Quoted 1 line
Crazy. Regardless, I think your patch is correct and the current code that uses cpl cache during emulation is wrong and it remains wrong even after your patch. What if last time cpl cache was updated was while vcpu ran in cpl 3? Commit message says that it tries to fix the case when CS.selector&3 != 0 during transition to protected mode, but this can be fixed by setting cpl cache to 0 in
vmx_set_cr0()instead of clearing it.
Yes, i suppose so, can be done by a separatch patch, though.
Quoted 4 lines
Two things about the patch itself. Get rid of
__vmx_get_cpl()and call tovmx_read_guest_seg_selector()directly fromvmx_get_cpl()and drop__clear_bit(VCPU_EXREG_CPL)fromvmx_set_rflags()andvmx_set_cr0()sincevmx->cplno longer depends on rflags and cr0.
You still want to invalidate vmx->cpl cache on cr0 writes:
think protected -> real -> protected transition. And as for EFLAGS, agreed. Sending new patch.
Quoted 19 lines · Marcelo Tosatti
Quoted 18 lines · Gleb Natapov
Quoted 1 line
FreeBSD 9.1 with -smp 2.
I cannot reproduce. I do see boot failure on the next branch with 9.[01] 64 bit -smp 2 here, but it is caused but segment registers been all incorrect on a secondary vcpu and this patch does not help. Applying
http://comments.gmane.org/gmane.comp.emulators.kvm.devel/102593 fixes it.Quoted 11 lines
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
The question is how does it happen that we enter real mode while cache is set to 3. It should never be 3 during boot since boot process never enters the userspace.
Its transition _to_ real mode (from protected).
But in protected mode CPL should be 0 during boot.
BTX (FreeBSD's bootloader) does:
Quoted 9 lines
Quoted 6 lines
Crazy. Regardless, I think your patch is correct and the current code that uses cpl cache during emulation is wrong and it remains wrong even after your patch. What if last time cpl cache was updated was while vcpu ran in cpl 3? Commit message says that it tries to fix the case when CS.selector&3 != 0 during transition to protected mode, but this can be fixed by setting cpl cache to 0 in
vmx_set_cr0()instead of clearing it.Yes, i suppose so, can be done by a separatch patch, though.
Yes. I will send the patch.
Quoted 7 lines
Quoted 4 lines
Two things about the patch itself. Get rid of
__vmx_get_cpl()and call tovmx_read_guest_seg_selector()directly fromvmx_get_cpl()and drop__clear_bit(VCPU_EXREG_CPL)fromvmx_set_rflags()andvmx_set_cr0()sincevmx->cplno longer depends on rflags and cr0.You still want to invalidate
vmx->cplcache on cr0 writes:
think protected -> real -> protected transition.
If CS.selector didn't change during the transition vmx->cpl will be set to the same value and if it changes cpl cache will be cleared either by vmx_set_segment() or vmexit.
Quoted 1 line
And as for EFLAGS, agreed. Sending new patch.
--
Gleb.
Quoted 44 lines · Avi Kivity
Quoted 42 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/vmx.c +0
-7@@ -3215,13 +3215,6 @@ static u64 vmx_get_segment_base(struct kvm_vcpu*vcpu, int seg) static int __vmx_get_cpl(struct kvm_vcpu *vcpu) { -if (!is_protmode (vcpu)) -return 0 ; - -if (!is_long_mode (vcpu) - && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ -return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ;}
arch/x86/kvm/vmx.c +7
-0@@ -3229,6 +3222,13 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu)) +return 0 ; + +if (!is_long_mode (vcpu) + && (kvm_get_rflags (vcpu) &X86_EFLAGS_VM ))/* if virtual 8086 */ +return 3 ; +/*
Quoted 8 lines
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0* If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
* fail; use the cache instead.This undoes the cache, now every
vmx_get_cpl()in protected mode has toVMREAD(GUEST_RFLAGS).
Yes, but GUEST_RFLAGS reads are cached. So its read once per exit.
KVM: VMX: fix incorrect cached cpl value with real/v8086 modes (v2)
In reply to Marcelo TosattiCPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
arch/x86/kvm/vmx.c +4 -10
@@ -1696,7 +1696,6 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)static void vmx_set_rflags (struct kvm_vcpu *vcpu,unsigned long rflags) {__set_bit (VCPU_EXREG_RFLAGS , (ulong *)&vcpu->arch.regs_avail); -__clear_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail);to_vmx (vcpu)->rflags = rflags;if (to_vmx (vcpu)->rmode.vm86_active) {to_vmx (vcpu)->rmode.save_rflags = rflags;
@@ -3220,8 +3219,10 @@ static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)return vmx_read_guest_seg_base (to_vmx (vcpu), seg); } -static int __vmx_get_cpl (struct kvm_vcpu *vcpu) +static int vmx_get_cpl (struct kvm_vcpu *vcpu) { +struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu))return 0 ;
@@ -3229,13 +3230,6 @@ static int __vmx_get_cpl(struct kvm_vcpu *vcpu) && (kvm_get_rflags(vcpu) & X86_EFLAGS_VM)) /* if virtual 8086 */return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ; -} - -static int vmx_get_cpl (struct kvm_vcpu *vcpu) -{ -struct vcpu_vmx *vmx =to_vmx (vcpu); -/* * If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations * fail; use the cache instead.
@@ -3246,7 +3240,7 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu)if (!test_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail)) {__set_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail); - vmx->cpl =__vmx_get_cpl (vcpu); + vmx->cpl =vmx_read_guest_seg_selector (vmx,VCPU_SREG_CS ) &3 ; }return vmx->cpl;
KVM: VMX: fix incorrect cached cpl value with real/v8086 modes (v3)
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
arch/x86/kvm/vmx.c +4 -11
@@ -1696,7 +1696,6 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)static void vmx_set_rflags (struct kvm_vcpu *vcpu,unsigned long rflags) {__set_bit (VCPU_EXREG_RFLAGS , (ulong *)&vcpu->arch.regs_avail); -__clear_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail);to_vmx (vcpu)->rflags = rflags;if (to_vmx (vcpu)->rmode.vm86_active) {to_vmx (vcpu)->rmode.save_rflags = rflags;
@@ -3110,7 +3109,6 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)vmcs_writel (CR0_READ_SHADOW , cr0);vmcs_writel (GUEST_CR0 , hw_cr0); vcpu->arch.cr0 = cr0; -__clear_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail); }static u64 construct_eptp (unsigned long root_hpa)
@@ -3220,8 +3218,10 @@ static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)return vmx_read_guest_seg_base (to_vmx (vcpu), seg); } -static int __vmx_get_cpl (struct kvm_vcpu *vcpu) +static int vmx_get_cpl (struct kvm_vcpu *vcpu) { +struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu))return 0 ;
@@ -3229,13 +3229,6 @@ static int __vmx_get_cpl(struct kvm_vcpu *vcpu) && (kvm_get_rflags(vcpu) & X86_EFLAGS_VM)) /* if virtual 8086 */return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ; -} - -static int vmx_get_cpl (struct kvm_vcpu *vcpu) -{ -struct vcpu_vmx *vmx =to_vmx (vcpu); -/* * If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations * fail; use the cache instead.
@@ -3246,7 +3239,7 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu)if (!test_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail)) {__set_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail); - vmx->cpl =__vmx_get_cpl (vcpu); + vmx->cpl =vmx_read_guest_seg_selector (vmx,VCPU_SREG_CS ) &3 ; }return vmx->cpl;
Gleb Natapov
Reviewed-byRe: KVM: VMX: fix incorrect cached cpl value with real/v8086 modes (v3)
Quoted 8 lines · Marcelo Tosatti
CPL is always 0 when in real mode, and always 3 when virtual 8086 mode.
Using values other than those can cause failures on operations that check CPL.
Signed-off-by Marcelo Tosatti <[email protected]>
Quoted 47 lines
arch/x86/kvm/vmx.c +3
-10@@ -1696,7 +1696,6 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)static void vmx_set_rflags (struct kvm_vcpu *vcpu,unsigned long rflags) {__set_bit (VCPU_EXREG_RFLAGS , (ulong *)&vcpu->arch.regs_avail); -__clear_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail);to_vmx (vcpu)->rflags = rflags;if (to_vmx (vcpu)->rmode.vm86_active) {to_vmx (vcpu)->rmode.save_rflags = rflags;@@ -3110,7 +3109,6 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)vmcs_writel (CR0_READ_SHADOW , cr0);vmcs_writel (GUEST_CR0 , hw_cr0); vcpu->arch.cr0 = cr0; -__clear_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail); }static u64 construct_eptp (unsigned long root_hpa)@@ -3220,8 +3218,10 @@ static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)return vmx_read_guest_seg_base (to_vmx (vcpu), seg); } -static int __vmx_get_cpl (struct kvm_vcpu *vcpu) +static int vmx_get_cpl (struct kvm_vcpu *vcpu) { +struct vcpu_vmx *vmx =to_vmx (vcpu); +if (!is_protmode (vcpu))return 0 ;@@ -3229,13 +3229,6 @@ static int __vmx_get_cpl(struct kvm_vcpu *vcpu) && (kvm_get_rflags(vcpu) & X86_EFLAGS_VM)) /* if virtual 8086 */return 3 ; -return vmx_read_guest_seg_selector (to_vmx (vcpu),VCPU_SREG_CS ) &3 ; -} - -static int vmx_get_cpl (struct kvm_vcpu *vcpu) -{ -struct vcpu_vmx *vmx =to_vmx (vcpu); -/* * If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations * fail; use the cache instead.
arch/x86/kvm/vmx.c static int vmx_get_cpl(struct kvm_vcpu *vcpu) · line 3245
Quoted 8 lines
arch/x86/kvm/vmx.c +1
-1@@ -3246,7 +3239,7 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu)if (!test_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail)) {__set_bit (VCPU_EXREG_CPL , (ulong *)&vcpu->arch.regs_avail); - vmx->cpl =__vmx_get_cpl (vcpu); + vmx->cpl =vmx_read_guest_seg_selector (vmx,VCPU_SREG_CS ) &3 ; }return vmx->cpl;
--
Gleb.