aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2009-08-11 16:57:59 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 03:46:44 -0400
commitc0c7c04b874bf98a10d8e0c8322a5d3bc93536bc (patch)
treefd1fd86a26767fb8b59db3190f17b2c40a035ba4 /arch/x86/kvm
parent345dcaa8fde7fa70252d58c862bf41fd2149ca2c (diff)
KVM: When switching to a vm8086 task, load segments as 16-bit
According to 16.2.5 in the SDM, eflags.vm in the tss is consulted before loading and new segments. If eflags.vm == 1, then the segments are treated as 16-bit segments. The LDTR and TR are not normally available in vm86 mode so if they happen to somehow get loaded, they need to be treated as 32-bit segments. This fixes an invalid vmentry failure in a custom OS that was happening after a task switch into vm8086 mode. Since the segments were being mistakenly treated as 32-bit, we loaded garbage state. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/x86.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 31bf98427f4e..1aa7e6d91d4f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4101,12 +4101,19 @@ static int kvm_load_realmode_segment(struct kvm_vcpu *vcpu, u16 selector, int se
4101 return 0; 4101 return 0;
4102} 4102}
4103 4103
4104static int is_vm86_segment(struct kvm_vcpu *vcpu, int seg)
4105{
4106 return (seg != VCPU_SREG_LDTR) &&
4107 (seg != VCPU_SREG_TR) &&
4108 (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_VM);
4109}
4110
4104int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, 4111int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
4105 int type_bits, int seg) 4112 int type_bits, int seg)
4106{ 4113{
4107 struct kvm_segment kvm_seg; 4114 struct kvm_segment kvm_seg;
4108 4115
4109 if (!(vcpu->arch.cr0 & X86_CR0_PE)) 4116 if (is_vm86_segment(vcpu, seg) || !(vcpu->arch.cr0 & X86_CR0_PE))
4110 return kvm_load_realmode_segment(vcpu, selector, seg); 4117 return kvm_load_realmode_segment(vcpu, selector, seg);
4111 if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg)) 4118 if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
4112 return 1; 4119 return 1;