aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Rozenfeld <vrozenfe@redhat.com>2014-01-16 04:18:37 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2014-01-17 04:22:08 -0500
commite984097b553ed2d6551c805223e4057421370f00 (patch)
tree8bc58542fbd9680ee70ea83174ea092aa1baf8ad
parentaab6d7ce37cf20753a336dc74473cf8a8aefa7c0 (diff)
add support for Hyper-V reference time counter
Signed-off: Peter Lieven <pl@kamp.de> Signed-off: Gleb Natapov Signed-off: Vadim Rozenfeld <vrozenfe@redhat.com> After some consideration I decided to submit only Hyper-V reference counters support this time. I will submit iTSC support as a separate patch as soon as it is ready. v1 -> v2 1. mark TSC page dirty as suggested by Eric Northup <digitaleric@google.com> and Gleb 2. disable local irq when calling get_kernel_ns, as it was done by Peter Lieven <pl@amp.de> 3. move check for TSC page enable from second patch to this one. v3 -> v4     Get rid of ref counter offset. v4 -> v5 replace __copy_to_user with kvm_write_guest when updateing iTSC page. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/include/uapi/asm/hyperv.h13
-rw-r--r--arch/x86/kvm/x86.c28
-rw-r--r--include/uapi/linux/kvm.h1
4 files changed, 42 insertions, 1 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index ae5d7830855c..33fef0738a29 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -605,6 +605,7 @@ struct kvm_arch {
605 /* fields used by HYPER-V emulation */ 605 /* fields used by HYPER-V emulation */
606 u64 hv_guest_os_id; 606 u64 hv_guest_os_id;
607 u64 hv_hypercall; 607 u64 hv_hypercall;
608 u64 hv_tsc_page;
608 609
609 #ifdef CONFIG_KVM_MMU_AUDIT 610 #ifdef CONFIG_KVM_MMU_AUDIT
610 int audit_point; 611 int audit_point;
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index b8f1c0176cbc..462efe746d77 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -28,6 +28,9 @@
28/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/ 28/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
29#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1) 29#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
30 30
31/* A partition's reference time stamp counter (TSC) page */
32#define HV_X64_MSR_REFERENCE_TSC 0x40000021
33
31/* 34/*
32 * There is a single feature flag that signifies the presence of the MSR 35 * There is a single feature flag that signifies the presence of the MSR
33 * that can be used to retrieve both the local APIC Timer frequency as 36 * that can be used to retrieve both the local APIC Timer frequency as
@@ -198,6 +201,9 @@
198#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK \ 201#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK \
199 (~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1)) 202 (~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
200 203
204#define HV_X64_MSR_TSC_REFERENCE_ENABLE 0x00000001
205#define HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT 12
206
201#define HV_PROCESSOR_POWER_STATE_C0 0 207#define HV_PROCESSOR_POWER_STATE_C0 0
202#define HV_PROCESSOR_POWER_STATE_C1 1 208#define HV_PROCESSOR_POWER_STATE_C1 1
203#define HV_PROCESSOR_POWER_STATE_C2 2 209#define HV_PROCESSOR_POWER_STATE_C2 2
@@ -210,4 +216,11 @@
210#define HV_STATUS_INVALID_ALIGNMENT 4 216#define HV_STATUS_INVALID_ALIGNMENT 4
211#define HV_STATUS_INSUFFICIENT_BUFFERS 19 217#define HV_STATUS_INSUFFICIENT_BUFFERS 19
212 218
219typedef struct _HV_REFERENCE_TSC_PAGE {
220 __u32 tsc_sequence;
221 __u32 res1;
222 __u64 tsc_scale;
223 __s64 tsc_offset;
224} HV_REFERENCE_TSC_PAGE, *PHV_REFERENCE_TSC_PAGE;
225
213#endif 226#endif
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0fbdced78737..0b3fd809a3c7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -839,11 +839,12 @@ EXPORT_SYMBOL_GPL(kvm_rdpmc);
839 * kvm-specific. Those are put in the beginning of the list. 839 * kvm-specific. Those are put in the beginning of the list.
840 */ 840 */
841 841
842#define KVM_SAVE_MSRS_BEGIN 10 842#define KVM_SAVE_MSRS_BEGIN 12
843static u32 msrs_to_save[] = { 843static u32 msrs_to_save[] = {
844 MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, 844 MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
845 MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, 845 MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
846 HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, 846 HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
847 HV_X64_MSR_TIME_REF_COUNT, HV_X64_MSR_REFERENCE_TSC,
847 HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME, 848 HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
848 MSR_KVM_PV_EOI_EN, 849 MSR_KVM_PV_EOI_EN,
849 MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, 850 MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
@@ -1788,6 +1789,8 @@ static bool kvm_hv_msr_partition_wide(u32 msr)
1788 switch (msr) { 1789 switch (msr) {
1789 case HV_X64_MSR_GUEST_OS_ID: 1790 case HV_X64_MSR_GUEST_OS_ID:
1790 case HV_X64_MSR_HYPERCALL: 1791 case HV_X64_MSR_HYPERCALL:
1792 case HV_X64_MSR_REFERENCE_TSC:
1793 case HV_X64_MSR_TIME_REF_COUNT:
1791 r = true; 1794 r = true;
1792 break; 1795 break;
1793 } 1796 }
@@ -1829,6 +1832,20 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
1829 kvm->arch.hv_hypercall = data; 1832 kvm->arch.hv_hypercall = data;
1830 break; 1833 break;
1831 } 1834 }
1835 case HV_X64_MSR_REFERENCE_TSC: {
1836 u64 gfn;
1837 HV_REFERENCE_TSC_PAGE tsc_ref;
1838 memset(&tsc_ref, 0, sizeof(tsc_ref));
1839 kvm->arch.hv_tsc_page = data;
1840 if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
1841 break;
1842 gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
1843 if (kvm_write_guest(kvm, data,
1844 &tsc_ref, sizeof(tsc_ref)))
1845 return 1;
1846 mark_page_dirty(kvm, gfn);
1847 break;
1848 }
1832 default: 1849 default:
1833 vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x " 1850 vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
1834 "data 0x%llx\n", msr, data); 1851 "data 0x%llx\n", msr, data);
@@ -2253,6 +2270,14 @@ static int get_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
2253 case HV_X64_MSR_HYPERCALL: 2270 case HV_X64_MSR_HYPERCALL:
2254 data = kvm->arch.hv_hypercall; 2271 data = kvm->arch.hv_hypercall;
2255 break; 2272 break;
2273 case HV_X64_MSR_TIME_REF_COUNT: {
2274 data =
2275 div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100);
2276 break;
2277 }
2278 case HV_X64_MSR_REFERENCE_TSC:
2279 data = kvm->arch.hv_tsc_page;
2280 break;
2256 default: 2281 default:
2257 vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); 2282 vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
2258 return 1; 2283 return 1;
@@ -2566,6 +2591,7 @@ int kvm_dev_ioctl_check_extension(long ext)
2566#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT 2591#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
2567 case KVM_CAP_ASSIGN_DEV_IRQ: 2592 case KVM_CAP_ASSIGN_DEV_IRQ:
2568 case KVM_CAP_PCI_2_3: 2593 case KVM_CAP_PCI_2_3:
2594 case KVM_CAP_HYPERV_TIME:
2569#endif 2595#endif
2570 r = 1; 2596 r = 1;
2571 break; 2597 break;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index b647c2917391..932d7f2637d6 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -674,6 +674,7 @@ struct kvm_ppc_smmu_info {
674#define KVM_CAP_ARM_EL1_32BIT 93 674#define KVM_CAP_ARM_EL1_32BIT 93
675#define KVM_CAP_SPAPR_MULTITCE 94 675#define KVM_CAP_SPAPR_MULTITCE 94
676#define KVM_CAP_EXT_EMUL_CPUID 95 676#define KVM_CAP_EXT_EMUL_CPUID 95
677#define KVM_CAP_HYPERV_TIME 96
677 678
678#ifdef KVM_CAP_IRQ_ROUTING 679#ifdef KVM_CAP_IRQ_ROUTING
679 680