summaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-11-18 12:23:00 -0500
committerBen Hutchings <ben@decadent.org.uk>2020-02-11 20:03:46 +0000
commit11795d4863bd64c348b7b6388ef6f6c0804902b7 (patch)
tree7a6953e4bf12f9a6c2fb4ad2ddad48f79220538d /arch/x86
parent6398f8c938d3eb074b5108a32d80c56f7a91b5c1 (diff)
downloadlinux-stable-11795d4863bd64c348b7b6388ef6f6c0804902b7.tar.gz
linux-stable-11795d4863bd64c348b7b6388ef6f6c0804902b7.tar.bz2
linux-stable-11795d4863bd64c348b7b6388ef6f6c0804902b7.zip
KVM: x86: do not modify masked bits of shared MSRs
commit de1fca5d6e0105c9d33924e1247e2f386efc3ece upstream. "Shared MSRs" are guest MSRs that are written to the host MSRs but keep their value until the next return to userspace. They support a mask, so that some bits keep the host value, but this mask is only used to skip an unnecessary MSR write and the value written to the MSR is always the guest MSR. Fix this and, while at it, do not update smsr->values[slot].curr if for whatever reason the wrmsr fails. This should only happen due to reserved bits, so the value written to smsr->values[slot].curr will not match when the user-return notifier and the host value will always be restored. However, it is untidy and in rare cases this can actually avoid spurious WRMSRs on return to userspace. Reviewed-by: Jim Mattson <jmattson@google.com> Tested-by: Jim Mattson <jmattson@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kvm/x86.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bb4ed9190cbc..9d4d3e0eaa6b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -242,13 +242,14 @@ int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
int err;
- if (((value ^ smsr->values[slot].curr) & mask) == 0)
+ value = (value & mask) | (smsr->values[slot].host & ~mask);
+ if (value == smsr->values[slot].curr)
return 0;
- smsr->values[slot].curr = value;
err = wrmsrl_safe(shared_msrs_global.msrs[slot], value);
if (err)
return 1;
+ smsr->values[slot].curr = value;
if (!smsr->registered) {
smsr->urn.on_user_return = kvm_on_user_return;
user_return_notifier_register(&smsr->urn);