diff options
author | Nadav Amit <namit@cs.technion.ac.il> | 2014-09-16 08:10:03 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-09-24 08:07:48 -0400 |
commit | dd598091de4aabbc8bd7290a04f364e443c03455 (patch) | |
tree | 72123be86eb587d26b0bce0cca474aa05d3a2555 /arch/x86 | |
parent | 3c3c29fd0d7cddc32862c350d0700ce69953e3bd (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.c | 21 | ||||
-rw-r--r-- | arch/x86/kvm/cpuid.h | 2 |
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 | ||
56 | void kvm_update_cpuid(struct kvm_vcpu *vcpu) | 56 | int 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 | ||
94 | static int is_efer_nx(void) | 104 | static 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 | ||
159 | out_free: | 168 | out_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 | |||
184 | out: | 191 | out: |
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 | ||
6 | void kvm_update_cpuid(struct kvm_vcpu *vcpu); | 6 | int kvm_update_cpuid(struct kvm_vcpu *vcpu); |
7 | struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, | 7 | struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, |
8 | u32 function, u32 index); | 8 | u32 function, u32 index); |
9 | int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, | 9 | int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, |