diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-03-25 04:44:51 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:57:06 -0400 |
commit | 92a1f12d2598f429bd8639e21d89305e787115c5 (patch) | |
tree | 48a6b7d6c50b5583b5163185dd097db100a471c6 /arch/x86/kvm | |
parent | 857e40999e35906baa367a79137019912cfb5434 (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>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/svm.c | 20 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 35 |
2 files changed, 55 insertions, 0 deletions
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 | ||
68 | static bool erratum_383_found __read_mostly; | 70 | static bool erratum_383_found __read_mostly; |
69 | 71 | ||
@@ -189,6 +191,7 @@ static int nested_svm_intercept(struct vcpu_svm *svm); | |||
189 | static int nested_svm_vmexit(struct vcpu_svm *svm); | 191 | static int nested_svm_vmexit(struct vcpu_svm *svm); |
190 | static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, | 192 | static 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); |
194 | static u64 __scale_tsc(u64 ratio, u64 tsc); | ||
192 | 195 | ||
193 | enum { | 196 | enum { |
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); | |||
87 | int ignore_msrs = 0; | 87 | int ignore_msrs = 0; |
88 | module_param_named(ignore_msrs, ignore_msrs, bool, S_IRUGO | S_IWUSR); | 88 | module_param_named(ignore_msrs, ignore_msrs, bool, S_IRUGO | S_IWUSR); |
89 | 89 | ||
90 | bool kvm_has_tsc_control; | ||
91 | EXPORT_SYMBOL_GPL(kvm_has_tsc_control); | ||
92 | u32 kvm_max_guest_tsc_khz; | ||
93 | EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz); | ||
94 | |||
90 | #define KVM_NR_SHARED_MSRS 16 | 95 | #define KVM_NR_SHARED_MSRS 16 |
91 | 96 | ||
92 | struct kvm_shared_msrs_global { | 97 | struct 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 | } |