Skip to contentSkip to conversation

kvm: fix hyperv tsc page clear wrong address

PATCH In review newtongao(高小明) 2 participants 3 messages Jun 19, 2014 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

PATCH 1/1 kvm: fix hyperv tsc page clear wrong address

Quoted 1 line

From 6010e24da995d4161cb879e98fda989e3cdb41c4 Mon Sep 17 00:00:00 2001

From: Xiaoming Gao <[email protected]>
Date: Thu, 19 Jun 2014 17:46:05 +0800
Subject: [PATCH] kvm: fix hyperv tsc page clear wrong address

tsc page addr need clear the low HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT bits before kvm_write_guest write the zero tsc_ref structure to guest, or it will lead guest to get wrong clocksource.

windows guest will get strong impact, QueryPerformanceCounter will always return 0 ,all things in windows rely on clock source will in serious chaos.

---
 arch/x86/kvm/x86.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/kvm/x86.c +1 -0
index f32a025..ed716cf 100644
@@ -1898,6 +1898,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
 			break;
 		gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
+		data &= ~((1 << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT) - 1);
 		if (kvm_write_guest(kvm, data,
 			&tsc_ref, sizeof(tsc_ref)))
 			return 1;
Signature · 1 line
1.7.1
Quoted 1 line

From 6010e24da995d4161cb879e98fda989e3cdb41c4 Mon Sep 17 00:00:00 2001

From: Xiaoming Gao <[email protected]>
Date: Thu, 19 Jun 2014 17:46:05 +0800
Subject: [PATCH] kvm: fix hyperv tsc page clear wrong address

tsc page addr need clear the low HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT bits before kvm_write_guest write the zero tsc_ref structure to guest, or it will lead guest to get wrong clocksource.

windows guest will get strong impact, QueryPerformanceCounter will always return 0 ,all things in windows rely on clock source, will in serious chaos.

---
 arch/x86/kvm/x86.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/kvm/x86.c +1 -0
index f32a025..ed716cf 100644
@@ -1898,6 +1898,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
 			break;
 		gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
+		data &= ~((1 << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT) - 1);
 		if (kvm_write_guest(kvm, data,
 			&tsc_ref, sizeof(tsc_ref)))
 			return 1;
Signature · 1 line
1.7.1
#2 lore raw

This is more concisely

Quoted 1 line

From 6ddeb18347f9dda0fe37702e0d067a4129a89b54 Mon Sep 17 00:00:00 2001

From: Xiaoming Gao <[email protected]>
Date: Thu, 19 Jun 2014 19:14:57 +0800
Subject: [PATCH] kvm: fix hyperv tsc page clear wrong address

tsc page addr need clear the low HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT bits before kvm_write_guest write the zero tsc_ref structure to guest, or it will lead guest to get wrong clocksource.

windows guest will get strong impact, QueryPerformanceCounter will always return 0 ,all things in windows rely on clock source, will in serious chaos.

---
 arch/x86/kvm/x86.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kvm/x86.c +1 -1
index f32a025..f644933 100644
@@ -1898,7 +1898,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
 			break;
 		gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
-		if (kvm_write_guest(kvm, data,
+		if (kvm_write_guest(kvm, gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
 			&tsc_ref, sizeof(tsc_ref)))
 			return 1;
 		mark_page_dirty(kvm, gfn);
Signature · 1 line
1.7.1
Quoted 1 line

From 6ddeb18347f9dda0fe37702e0d067a4129a89b54 Mon Sep 17 00:00:00 2001

From: Xiaoming Gao <[email protected]>
Date: Thu, 19 Jun 2014 19:14:57 +0800
Subject: [PATCH] kvm: fix hyperv tsc page clear wrong address

tsc page addr need clear the low HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT bits before kvm_write_guest write the zero tsc_ref structure to guest, or it will lead guest to get wrong clocksource.

windows guest will get strong impact, QueryPerformanceCounter will always return 0 ,all things in windows rely on clock source, will in serious chaos.

---
 arch/x86/kvm/x86.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kvm/x86.c +1 -1
index f32a025..f644933 100644
@@ -1898,7 +1898,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
 			break;
 		gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
-		if (kvm_write_guest(kvm, data,
+		if (kvm_write_guest(kvm, gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
 			&tsc_ref, sizeof(tsc_ref)))
 			return 1;
 		mark_page_dirty(kvm, gfn);
Signature · 1 line
1.7.1
maintainer
#3 lore raw

Il 19/06/2014 13:17, "newtongao(高小明)" ha scritto:

Quoted 7 lines

This is more concisely

From 6ddeb18347f9dda0fe37702e0d067a4129a89b54 Mon Sep 17 00:00:00 2001
From: Xiaoming Gao <[email protected]>
Date: Thu, 19 Jun 2014 19:14:57 +0800
Subject: [PATCH] kvm: fix hyperv tsc page clear wrong address

Quoted 6 lines

tsc page addr need clear the low HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT bits before kvm_write_guest write the zero tsc_ref structure to guest, or it will lead guest to get wrong clocksource.

windows guest will get strong impact, QueryPerformanceCounter will always return 0 ,all things in windows rely on clock source, will in serious chaos.

Right, this can happen if Windows passes a non-zero page to KVM.

Thanks,

Paolo

Quoted 19 lines
---
 arch/x86/kvm/x86.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kvm/x86.c +1 -1
index f32a025..f644933 100644
@@ -1898,7 +1898,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
 			break;
 		gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
-		if (kvm_write_guest(kvm, data,
+		if (kvm_write_guest(kvm, gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
 			&tsc_ref, sizeof(tsc_ref)))
 			return 1;
 		mark_page_dirty(kvm, gfn);