diff options
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r-- | drivers/kvm/vmx.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index b353eaa0a441..e39ebe0b6958 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1042,23 +1042,11 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu, | |||
1042 | var->unusable = (ar >> 16) & 1; | 1042 | var->unusable = (ar >> 16) & 1; |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | static void vmx_set_segment(struct kvm_vcpu *vcpu, | 1045 | static u32 vmx_segment_access_rights(struct kvm_segment *var) |
1046 | struct kvm_segment *var, int seg) | ||
1047 | { | 1046 | { |
1048 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
1049 | u32 ar; | 1047 | u32 ar; |
1050 | 1048 | ||
1051 | vmcs_writel(sf->base, var->base); | 1049 | if (var->unusable) |
1052 | vmcs_write32(sf->limit, var->limit); | ||
1053 | vmcs_write16(sf->selector, var->selector); | ||
1054 | if (vcpu->rmode.active && var->s) { | ||
1055 | /* | ||
1056 | * Hack real-mode segments into vm86 compatibility. | ||
1057 | */ | ||
1058 | if (var->base == 0xffff0000 && var->selector == 0xf000) | ||
1059 | vmcs_writel(sf->base, 0xf0000); | ||
1060 | ar = 0xf3; | ||
1061 | } else if (var->unusable) | ||
1062 | ar = 1 << 16; | 1050 | ar = 1 << 16; |
1063 | else { | 1051 | else { |
1064 | ar = var->type & 15; | 1052 | ar = var->type & 15; |
@@ -1072,6 +1060,35 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu, | |||
1072 | } | 1060 | } |
1073 | if (ar == 0) /* a 0 value means unusable */ | 1061 | if (ar == 0) /* a 0 value means unusable */ |
1074 | ar = AR_UNUSABLE_MASK; | 1062 | ar = AR_UNUSABLE_MASK; |
1063 | |||
1064 | return ar; | ||
1065 | } | ||
1066 | |||
1067 | static void vmx_set_segment(struct kvm_vcpu *vcpu, | ||
1068 | struct kvm_segment *var, int seg) | ||
1069 | { | ||
1070 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
1071 | u32 ar; | ||
1072 | |||
1073 | if (vcpu->rmode.active && seg == VCPU_SREG_TR) { | ||
1074 | vcpu->rmode.tr.selector = var->selector; | ||
1075 | vcpu->rmode.tr.base = var->base; | ||
1076 | vcpu->rmode.tr.limit = var->limit; | ||
1077 | vcpu->rmode.tr.ar = vmx_segment_access_rights(var); | ||
1078 | return; | ||
1079 | } | ||
1080 | vmcs_writel(sf->base, var->base); | ||
1081 | vmcs_write32(sf->limit, var->limit); | ||
1082 | vmcs_write16(sf->selector, var->selector); | ||
1083 | if (vcpu->rmode.active && var->s) { | ||
1084 | /* | ||
1085 | * Hack real-mode segments into vm86 compatibility. | ||
1086 | */ | ||
1087 | if (var->base == 0xffff0000 && var->selector == 0xf000) | ||
1088 | vmcs_writel(sf->base, 0xf0000); | ||
1089 | ar = 0xf3; | ||
1090 | } else | ||
1091 | ar = vmx_segment_access_rights(var); | ||
1075 | vmcs_write32(sf->ar_bytes, ar); | 1092 | vmcs_write32(sf->ar_bytes, ar); |
1076 | } | 1093 | } |
1077 | 1094 | ||