| From de1fca5d6e0105c9d33924e1247e2f386efc3ece Mon Sep 17 00:00:00 2001 |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| Date: Mon, 18 Nov 2019 12:23:00 -0500 |
| Subject: KVM: x86: do not modify masked bits of shared MSRs |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| 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. |
| |
| Cc: stable@vger.kernel.org |
| 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kvm/x86.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -235,13 +235,14 @@ int kvm_set_shared_msr(unsigned slot, u6 |
| 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); |