diff options
author | Gleb Natapov <gleb@redhat.com> | 2011-03-07 07:55:06 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2011-03-17 12:08:33 -0400 |
commit | 5601d05b8c340ee2643febc146099325eff187eb (patch) | |
tree | 61fb3298bb267eecfd899621cc852114d636de52 /arch/x86/kvm/x86.c | |
parent | 831ca6093ca486060721f5c3c74f97b10f3172b9 (diff) |
KVM: emulator: Fix io permission checking for 64bit guest
Current implementation truncates upper 32bit of TR base address during IO
permission bitmap check. The patch fixes this.
Reported-and-tested-by: Francis Moreau <francis.moro@gmail.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b9c2b8e6c70c..01f08a65d09b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4162,8 +4162,8 @@ static unsigned long emulator_get_cached_segment_base(int seg, | |||
4162 | return get_segment_base(vcpu, seg); | 4162 | return get_segment_base(vcpu, seg); |
4163 | } | 4163 | } |
4164 | 4164 | ||
4165 | static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg, | 4165 | static bool emulator_get_cached_descriptor(struct desc_struct *desc, u32 *base3, |
4166 | struct kvm_vcpu *vcpu) | 4166 | int seg, struct kvm_vcpu *vcpu) |
4167 | { | 4167 | { |
4168 | struct kvm_segment var; | 4168 | struct kvm_segment var; |
4169 | 4169 | ||
@@ -4176,6 +4176,10 @@ static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg, | |||
4176 | var.limit >>= 12; | 4176 | var.limit >>= 12; |
4177 | set_desc_limit(desc, var.limit); | 4177 | set_desc_limit(desc, var.limit); |
4178 | set_desc_base(desc, (unsigned long)var.base); | 4178 | set_desc_base(desc, (unsigned long)var.base); |
4179 | #ifdef CONFIG_X86_64 | ||
4180 | if (base3) | ||
4181 | *base3 = var.base >> 32; | ||
4182 | #endif | ||
4179 | desc->type = var.type; | 4183 | desc->type = var.type; |
4180 | desc->s = var.s; | 4184 | desc->s = var.s; |
4181 | desc->dpl = var.dpl; | 4185 | desc->dpl = var.dpl; |
@@ -4188,8 +4192,8 @@ static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg, | |||
4188 | return true; | 4192 | return true; |
4189 | } | 4193 | } |
4190 | 4194 | ||
4191 | static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg, | 4195 | static void emulator_set_cached_descriptor(struct desc_struct *desc, u32 base3, |
4192 | struct kvm_vcpu *vcpu) | 4196 | int seg, struct kvm_vcpu *vcpu) |
4193 | { | 4197 | { |
4194 | struct kvm_segment var; | 4198 | struct kvm_segment var; |
4195 | 4199 | ||
@@ -4197,6 +4201,9 @@ static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg, | |||
4197 | kvm_get_segment(vcpu, &var, seg); | 4201 | kvm_get_segment(vcpu, &var, seg); |
4198 | 4202 | ||
4199 | var.base = get_desc_base(desc); | 4203 | var.base = get_desc_base(desc); |
4204 | #ifdef CONFIG_X86_64 | ||
4205 | var.base |= ((u64)base3) << 32; | ||
4206 | #endif | ||
4200 | var.limit = get_desc_limit(desc); | 4207 | var.limit = get_desc_limit(desc); |
4201 | if (desc->g) | 4208 | if (desc->g) |
4202 | var.limit = (var.limit << 12) | 0xfff; | 4209 | var.limit = (var.limit << 12) | 0xfff; |