| From 51c4b8bba674cfd2260d173602c4dac08e4c3a99 Mon Sep 17 00:00:00 2001 |
| From: Liran Alon <liran.alon@oracle.com> |
| Date: Sun, 5 Nov 2017 16:11:30 +0200 |
| Subject: KVM: x86: pvclock: Handle first-time write to pvclock-page contains random junk |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Liran Alon <liran.alon@oracle.com> |
| |
| commit 51c4b8bba674cfd2260d173602c4dac08e4c3a99 upstream. |
| |
| When guest passes KVM it's pvclock-page GPA via WRMSR to |
| MSR_KVM_SYSTEM_TIME / MSR_KVM_SYSTEM_TIME_NEW, KVM don't initialize |
| pvclock-page to some start-values. It just requests a clock-update which |
| will happen before entering to guest. |
| |
| The clock-update logic will call kvm_setup_pvclock_page() to update the |
| pvclock-page with info. However, kvm_setup_pvclock_page() *wrongly* |
| assumes that the version-field is initialized to an even number. This is |
| wrong because at first-time write, field could be any-value. |
| |
| Fix simply makes sure that if first-time version-field is odd, increment |
| it once more to make it even and only then start standard logic. |
| This follows same logic as done in other pvclock shared-pages (See |
| kvm_write_wall_clock() and record_steal_time()). |
| |
| Signed-off-by: Liran Alon <liran.alon@oracle.com> |
| Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com> |
| Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kvm/x86.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -1812,6 +1812,9 @@ static int kvm_guest_time_update(struct |
| */ |
| BUILD_BUG_ON(offsetof(struct pvclock_vcpu_time_info, version) != 0); |
| |
| + if (guest_hv_clock.version & 1) |
| + ++guest_hv_clock.version; /* first time write, random junk */ |
| + |
| vcpu->hv_clock.version = guest_hv_clock.version + 1; |
| kvm_write_guest_cached(v->kvm, &vcpu->pv_time, |
| &vcpu->hv_clock, |