aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-03-25 04:44:51 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:06 -0400
commit92a1f12d2598f429bd8639e21d89305e787115c5 (patch)
tree48a6b7d6c50b5583b5163185dd097db100a471c6
parent857e40999e35906baa367a79137019912cfb5434 (diff)
KVM: X86: Implement userspace interface to set virtual_tsc_khz
This patch implements two new vm-ioctls to get and set the virtual_tsc_khz if the machine supports tsc-scaling. Setting the tsc-frequency is only possible before userspace creates any vcpu. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/kvm/api.txt23
-rw-r--r--arch/x86/include/asm/kvm_host.h7
-rw-r--r--arch/x86/kvm/svm.c20
-rw-r--r--arch/x86/kvm/x86.c35
-rw-r--r--include/linux/kvm.h5
5 files changed, 90 insertions, 0 deletions
diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt
index 9bef4e4cec50..1b9eaa7e8856 100644
--- a/Documentation/kvm/api.txt
+++ b/Documentation/kvm/api.txt
@@ -1263,6 +1263,29 @@ struct kvm_assigned_msix_entry {
1263 __u16 padding[3]; 1263 __u16 padding[3];
1264}; 1264};
1265 1265
12664.54 KVM_SET_TSC_KHZ
1267
1268Capability: KVM_CAP_TSC_CONTROL
1269Architectures: x86
1270Type: vcpu ioctl
1271Parameters: virtual tsc_khz
1272Returns: 0 on success, -1 on error
1273
1274Specifies the tsc frequency for the virtual machine. The unit of the
1275frequency is KHz.
1276
12774.55 KVM_GET_TSC_KHZ
1278
1279Capability: KVM_CAP_GET_TSC_KHZ
1280Architectures: x86
1281Type: vcpu ioctl
1282Parameters: none
1283Returns: virtual tsc-khz on success, negative value on error
1284
1285Returns the tsc frequency of the guest. The unit of the return value is
1286KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
1287error.
1288
12665. The kvm_run structure 12895. The kvm_run structure
1267 1290
1268Application code obtains a pointer to the kvm_run structure by 1291Application code obtains a pointer to the kvm_run structure by
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index da0a8ce3a139..bd57639fd5db 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -655,6 +655,13 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
655 655
656extern bool tdp_enabled; 656extern bool tdp_enabled;
657 657
658/* control of guest tsc rate supported? */
659extern bool kvm_has_tsc_control;
660/* minimum supported tsc_khz for guests */
661extern u32 kvm_min_guest_tsc_khz;
662/* maximum supported tsc_khz for guests */
663extern u32 kvm_max_guest_tsc_khz;
664
658enum emulation_result { 665enum emulation_result {
659 EMULATE_DONE, /* no further processing */ 666 EMULATE_DONE, /* no further processing */
660 EMULATE_DO_MMIO, /* kvm_run filled with mmio request */ 667 EMULATE_DO_MMIO, /* kvm_run filled with mmio request */
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 8c4549bef4ed..a98873762433 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -64,6 +64,8 @@ MODULE_LICENSE("GPL");
64#define DEBUGCTL_RESERVED_BITS (~(0x3fULL)) 64#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
65 65
66#define TSC_RATIO_RSVD 0xffffff0000000000ULL 66#define TSC_RATIO_RSVD 0xffffff0000000000ULL
67#define TSC_RATIO_MIN 0x0000000000000001ULL
68#define TSC_RATIO_MAX 0x000000ffffffffffULL
67 69
68static bool erratum_383_found __read_mostly; 70static bool erratum_383_found __read_mostly;
69 71
@@ -189,6 +191,7 @@ static int nested_svm_intercept(struct vcpu_svm *svm);
189static int nested_svm_vmexit(struct vcpu_svm *svm); 191static int nested_svm_vmexit(struct vcpu_svm *svm);
190static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, 192static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
191 bool has_error_code, u32 error_code); 193 bool has_error_code, u32 error_code);
194static u64 __scale_tsc(u64 ratio, u64 tsc);
192 195
193enum { 196enum {
194 VMCB_INTERCEPTS, /* Intercept vectors, TSC offset, 197 VMCB_INTERCEPTS, /* Intercept vectors, TSC offset,
@@ -798,6 +801,23 @@ static __init int svm_hardware_setup(void)
798 if (boot_cpu_has(X86_FEATURE_FXSR_OPT)) 801 if (boot_cpu_has(X86_FEATURE_FXSR_OPT))
799 kvm_enable_efer_bits(EFER_FFXSR); 802 kvm_enable_efer_bits(EFER_FFXSR);
800 803
804 if (boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
805 u64 max;
806
807 kvm_has_tsc_control = true;
808
809 /*
810 * Make sure the user can only configure tsc_khz values that
811 * fit into a signed integer.
812 * A min value is not calculated needed because it will always
813 * be 1 on all machines and a value of 0 is used to disable
814 * tsc-scaling for the vcpu.
815 */
816 max = min(0x7fffffffULL, __scale_tsc(tsc_khz, TSC_RATIO_MAX));
817
818 kvm_max_guest_tsc_khz = max;
819 }
820
801 if (nested) { 821 if (nested) {
802 printk(KERN_INFO "kvm: Nested Virtualization enabled\n"); 822 printk(KERN_INFO "kvm: Nested Virtualization enabled\n");
803 kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE); 823 kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 579ce34e7904..1d5a7f418795 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -87,6 +87,11 @@ EXPORT_SYMBOL_GPL(kvm_x86_ops);
87int ignore_msrs = 0; 87int ignore_msrs = 0;
88module_param_named(ignore_msrs, ignore_msrs, bool, S_IRUGO | S_IWUSR); 88module_param_named(ignore_msrs, ignore_msrs, bool, S_IRUGO | S_IWUSR);
89 89
90bool kvm_has_tsc_control;
91EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
92u32 kvm_max_guest_tsc_khz;
93EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz);
94
90#define KVM_NR_SHARED_MSRS 16 95#define KVM_NR_SHARED_MSRS 16
91 96
92struct kvm_shared_msrs_global { 97struct kvm_shared_msrs_global {
@@ -1986,6 +1991,7 @@ int kvm_dev_ioctl_check_extension(long ext)
1986 case KVM_CAP_X86_ROBUST_SINGLESTEP: 1991 case KVM_CAP_X86_ROBUST_SINGLESTEP:
1987 case KVM_CAP_XSAVE: 1992 case KVM_CAP_XSAVE:
1988 case KVM_CAP_ASYNC_PF: 1993 case KVM_CAP_ASYNC_PF:
1994 case KVM_CAP_GET_TSC_KHZ:
1989 r = 1; 1995 r = 1;
1990 break; 1996 break;
1991 case KVM_CAP_COALESCED_MMIO: 1997 case KVM_CAP_COALESCED_MMIO:
@@ -2012,6 +2018,9 @@ int kvm_dev_ioctl_check_extension(long ext)
2012 case KVM_CAP_XCRS: 2018 case KVM_CAP_XCRS:
2013 r = cpu_has_xsave; 2019 r = cpu_has_xsave;
2014 break; 2020 break;
2021 case KVM_CAP_TSC_CONTROL:
2022 r = kvm_has_tsc_control;
2023 break;
2015 default: 2024 default:
2016 r = 0; 2025 r = 0;
2017 break; 2026 break;
@@ -3045,6 +3054,32 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
3045 r = kvm_vcpu_ioctl_x86_set_xcrs(vcpu, u.xcrs); 3054 r = kvm_vcpu_ioctl_x86_set_xcrs(vcpu, u.xcrs);
3046 break; 3055 break;
3047 } 3056 }
3057 case KVM_SET_TSC_KHZ: {
3058 u32 user_tsc_khz;
3059
3060 r = -EINVAL;
3061 if (!kvm_has_tsc_control)
3062 break;
3063
3064 user_tsc_khz = (u32)arg;
3065
3066 if (user_tsc_khz >= kvm_max_guest_tsc_khz)
3067 goto out;
3068
3069 kvm_x86_ops->set_tsc_khz(vcpu, user_tsc_khz);
3070
3071 r = 0;
3072 goto out;
3073 }
3074 case KVM_GET_TSC_KHZ: {
3075 r = -EIO;
3076 if (check_tsc_unstable())
3077 goto out;
3078
3079 r = vcpu_tsc_khz(vcpu);
3080
3081 goto out;
3082 }
3048 default: 3083 default:
3049 r = -EINVAL; 3084 r = -EINVAL;
3050 } 3085 }
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index ea2dc1a2e13d..2f63ebeac639 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -541,6 +541,8 @@ struct kvm_ppc_pvinfo {
541#define KVM_CAP_PPC_GET_PVINFO 57 541#define KVM_CAP_PPC_GET_PVINFO 57
542#define KVM_CAP_PPC_IRQ_LEVEL 58 542#define KVM_CAP_PPC_IRQ_LEVEL 58
543#define KVM_CAP_ASYNC_PF 59 543#define KVM_CAP_ASYNC_PF 59
544#define KVM_CAP_TSC_CONTROL 60
545#define KVM_CAP_GET_TSC_KHZ 61
544 546
545#ifdef KVM_CAP_IRQ_ROUTING 547#ifdef KVM_CAP_IRQ_ROUTING
546 548
@@ -677,6 +679,9 @@ struct kvm_clock_data {
677#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2) 679#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
678/* Available with KVM_CAP_PPC_GET_PVINFO */ 680/* Available with KVM_CAP_PPC_GET_PVINFO */
679#define KVM_PPC_GET_PVINFO _IOW(KVMIO, 0xa1, struct kvm_ppc_pvinfo) 681#define KVM_PPC_GET_PVINFO _IOW(KVMIO, 0xa1, struct kvm_ppc_pvinfo)
682/* Available with KVM_CAP_TSC_CONTROL */
683#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2)
684#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3)
680 685
681/* 686/*
682 * ioctls for vcpu fds 687 * ioctls for vcpu fds