aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-09-16 08:10:03 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-09-24 08:07:48 -0400
commitdd598091de4aabbc8bd7290a04f364e443c03455 (patch)
tree72123be86eb587d26b0bce0cca474aa05d3a2555 /arch/x86
parent3c3c29fd0d7cddc32862c350d0700ce69953e3bd (diff)
KVM: x86: Warn if guest virtual address space is not 48-bits
The KVM emulator code assumes that the guest virtual address space (in 64-bit) is 48-bits wide. Fail the KVM_SET_CPUID and KVM_SET_CPUID2 ioctl if userspace tries to create a guest that does not obey this restriction. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kvm/cpuid.c21
-rw-r--r--arch/x86/kvm/cpuid.h2
2 files changed, 15 insertions, 8 deletions
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index f4bad87ef256..e28d798f7277 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -53,14 +53,14 @@ u64 kvm_supported_xcr0(void)
53 return xcr0; 53 return xcr0;
54} 54}
55 55
56void kvm_update_cpuid(struct kvm_vcpu *vcpu) 56int kvm_update_cpuid(struct kvm_vcpu *vcpu)
57{ 57{
58 struct kvm_cpuid_entry2 *best; 58 struct kvm_cpuid_entry2 *best;
59 struct kvm_lapic *apic = vcpu->arch.apic; 59 struct kvm_lapic *apic = vcpu->arch.apic;
60 60
61 best = kvm_find_cpuid_entry(vcpu, 1, 0); 61 best = kvm_find_cpuid_entry(vcpu, 1, 0);
62 if (!best) 62 if (!best)
63 return; 63 return 0;
64 64
65 /* Update OSXSAVE bit */ 65 /* Update OSXSAVE bit */
66 if (cpu_has_xsave && best->function == 0x1) { 66 if (cpu_has_xsave && best->function == 0x1) {
@@ -88,7 +88,17 @@ void kvm_update_cpuid(struct kvm_vcpu *vcpu)
88 xstate_required_size(vcpu->arch.xcr0); 88 xstate_required_size(vcpu->arch.xcr0);
89 } 89 }
90 90
91 /*
92 * The existing code assumes virtual address is 48-bit in the canonical
93 * address checks; exit if it is ever changed.
94 */
95 best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
96 if (best && ((best->eax & 0xff00) >> 8) != 48 &&
97 ((best->eax & 0xff00) >> 8) != 0)
98 return -EINVAL;
99
91 kvm_pmu_cpuid_update(vcpu); 100 kvm_pmu_cpuid_update(vcpu);
101 return 0;
92} 102}
93 103
94static int is_efer_nx(void) 104static int is_efer_nx(void)
@@ -151,10 +161,9 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
151 } 161 }
152 vcpu->arch.cpuid_nent = cpuid->nent; 162 vcpu->arch.cpuid_nent = cpuid->nent;
153 cpuid_fix_nx_cap(vcpu); 163 cpuid_fix_nx_cap(vcpu);
154 r = 0;
155 kvm_apic_set_version(vcpu); 164 kvm_apic_set_version(vcpu);
156 kvm_x86_ops->cpuid_update(vcpu); 165 kvm_x86_ops->cpuid_update(vcpu);
157 kvm_update_cpuid(vcpu); 166 r = kvm_update_cpuid(vcpu);
158 167
159out_free: 168out_free:
160 vfree(cpuid_entries); 169 vfree(cpuid_entries);
@@ -178,9 +187,7 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
178 vcpu->arch.cpuid_nent = cpuid->nent; 187 vcpu->arch.cpuid_nent = cpuid->nent;
179 kvm_apic_set_version(vcpu); 188 kvm_apic_set_version(vcpu);
180 kvm_x86_ops->cpuid_update(vcpu); 189 kvm_x86_ops->cpuid_update(vcpu);
181 kvm_update_cpuid(vcpu); 190 r = kvm_update_cpuid(vcpu);
182 return 0;
183
184out: 191out:
185 return r; 192 return r;
186} 193}
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 43b33e301e68..4452eedfaedd 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -3,7 +3,7 @@
3 3
4#include "x86.h" 4#include "x86.h"
5 5
6void kvm_update_cpuid(struct kvm_vcpu *vcpu); 6int kvm_update_cpuid(struct kvm_vcpu *vcpu);
7struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, 7struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
8 u32 function, u32 index); 8 u32 function, u32 index);
9int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, 9int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,