diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 34c8f94331f8..0033df32a745 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -229,20 +229,25 @@ static void kvm_shared_msr_cpu_online(void) | |||
229 | shared_msr_update(i, shared_msrs_global.msrs[i]); | 229 | shared_msr_update(i, shared_msrs_global.msrs[i]); |
230 | } | 230 | } |
231 | 231 | ||
232 | void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) | 232 | int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) |
233 | { | 233 | { |
234 | unsigned int cpu = smp_processor_id(); | 234 | unsigned int cpu = smp_processor_id(); |
235 | struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); | 235 | struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); |
236 | int err; | ||
236 | 237 | ||
237 | if (((value ^ smsr->values[slot].curr) & mask) == 0) | 238 | if (((value ^ smsr->values[slot].curr) & mask) == 0) |
238 | return; | 239 | return 0; |
239 | smsr->values[slot].curr = value; | 240 | smsr->values[slot].curr = value; |
240 | wrmsrl(shared_msrs_global.msrs[slot], value); | 241 | err = wrmsrl_safe(shared_msrs_global.msrs[slot], value); |
242 | if (err) | ||
243 | return 1; | ||
244 | |||
241 | if (!smsr->registered) { | 245 | if (!smsr->registered) { |
242 | smsr->urn.on_user_return = kvm_on_user_return; | 246 | smsr->urn.on_user_return = kvm_on_user_return; |
243 | user_return_notifier_register(&smsr->urn); | 247 | user_return_notifier_register(&smsr->urn); |
244 | smsr->registered = true; | 248 | smsr->registered = true; |
245 | } | 249 | } |
250 | return 0; | ||
246 | } | 251 | } |
247 | EXPORT_SYMBOL_GPL(kvm_set_shared_msr); | 252 | EXPORT_SYMBOL_GPL(kvm_set_shared_msr); |
248 | 253 | ||
@@ -987,7 +992,6 @@ void kvm_enable_efer_bits(u64 mask) | |||
987 | } | 992 | } |
988 | EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); | 993 | EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); |
989 | 994 | ||
990 | |||
991 | /* | 995 | /* |
992 | * Writes msr value into into the appropriate "register". | 996 | * Writes msr value into into the appropriate "register". |
993 | * Returns 0 on success, non-0 otherwise. | 997 | * Returns 0 on success, non-0 otherwise. |
@@ -995,8 +999,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); | |||
995 | */ | 999 | */ |
996 | int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) | 1000 | int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) |
997 | { | 1001 | { |
1002 | switch (msr->index) { | ||
1003 | case MSR_FS_BASE: | ||
1004 | case MSR_GS_BASE: | ||
1005 | case MSR_KERNEL_GS_BASE: | ||
1006 | case MSR_CSTAR: | ||
1007 | case MSR_LSTAR: | ||
1008 | if (is_noncanonical_address(msr->data)) | ||
1009 | return 1; | ||
1010 | break; | ||
1011 | case MSR_IA32_SYSENTER_EIP: | ||
1012 | case MSR_IA32_SYSENTER_ESP: | ||
1013 | /* | ||
1014 | * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if | ||
1015 | * non-canonical address is written on Intel but not on | ||
1016 | * AMD (which ignores the top 32-bits, because it does | ||
1017 | * not implement 64-bit SYSENTER). | ||
1018 | * | ||
1019 | * 64-bit code should hence be able to write a non-canonical | ||
1020 | * value on AMD. Making the address canonical ensures that | ||
1021 | * vmentry does not fail on Intel after writing a non-canonical | ||
1022 | * value, and that something deterministic happens if the guest | ||
1023 | * invokes 64-bit SYSENTER. | ||
1024 | */ | ||
1025 | msr->data = get_canonical(msr->data); | ||
1026 | } | ||
998 | return kvm_x86_ops->set_msr(vcpu, msr); | 1027 | return kvm_x86_ops->set_msr(vcpu, msr); |
999 | } | 1028 | } |
1029 | EXPORT_SYMBOL_GPL(kvm_set_msr); | ||
1000 | 1030 | ||
1001 | /* | 1031 | /* |
1002 | * Adapt set_msr() to msr_io()'s calling convention | 1032 | * Adapt set_msr() to msr_io()'s calling convention |