KVM: x86: Accept KVM_[GS]ET_TSC_KHZ as a VM ioctl.
authorDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 25 Feb 2022 14:53:02 +0000 (14:53 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Sat, 2 Apr 2022 09:41:19 +0000 (05:41 -0400)
This sets the default TSC frequency for subsequently created vCPUs.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Message-Id: <20220225145304.36166-2-dwmw2@infradead.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Documentation/virt/kvm/api.rst
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/x86.c
include/uapi/linux/kvm.h

index fdfd9e1..b102ba7 100644 (file)
@@ -1897,22 +1897,25 @@ the future.
 4.55 KVM_SET_TSC_KHZ
 --------------------
 
-:Capability: KVM_CAP_TSC_CONTROL
+:Capability: KVM_CAP_TSC_CONTROL / KVM_CAP_VM_TSC_CONTROL
 :Architectures: x86
-:Type: vcpu ioctl
+:Type: vcpu ioctl / vm ioctl
 :Parameters: virtual tsc_khz
 :Returns: 0 on success, -1 on error
 
 Specifies the tsc frequency for the virtual machine. The unit of the
 frequency is KHz.
 
+If the KVM_CAP_VM_TSC_CONTROL capability is advertised, this can also
+be used as a vm ioctl to set the initial tsc frequency of subsequently
+created vCPUs.
 
 4.56 KVM_GET_TSC_KHZ
 --------------------
 
-:Capability: KVM_CAP_GET_TSC_KHZ
+:Capability: KVM_CAP_GET_TSC_KHZ / KVM_CAP_VM_TSC_CONTROL
 :Architectures: x86
-:Type: vcpu ioctl
+:Type: vcpu ioctl / vm ioctl
 :Parameters: none
 :Returns: virtual tsc-khz on success, negative value on error
 
index 5370744..fac990c 100644 (file)
@@ -1126,6 +1126,8 @@ struct kvm_arch {
        u64 cur_tsc_generation;
        int nr_vcpus_matched_tsc;
 
+       u32 default_tsc_khz;
+
        seqcount_raw_spinlock_t pvclock_sc;
        bool use_master_clock;
        u64 master_kernel_ns;
index 1a7d1b5..c069b97 100644 (file)
@@ -4324,6 +4324,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                r = boot_cpu_has(X86_FEATURE_XSAVE);
                break;
        case KVM_CAP_TSC_CONTROL:
+       case KVM_CAP_VM_TSC_CONTROL:
                r = kvm_has_tsc_control;
                break;
        case KVM_CAP_X2APIC_API:
@@ -6522,6 +6523,28 @@ set_pit2_out:
        case KVM_GET_CLOCK:
                r = kvm_vm_ioctl_get_clock(kvm, argp);
                break;
+       case KVM_SET_TSC_KHZ: {
+               u32 user_tsc_khz;
+
+               r = -EINVAL;
+               user_tsc_khz = (u32)arg;
+
+               if (kvm_has_tsc_control &&
+                   user_tsc_khz >= kvm_max_guest_tsc_khz)
+                       goto out;
+
+               if (user_tsc_khz == 0)
+                       user_tsc_khz = tsc_khz;
+
+               WRITE_ONCE(kvm->arch.default_tsc_khz, user_tsc_khz);
+               r = 0;
+
+               goto out;
+       }
+       case KVM_GET_TSC_KHZ: {
+               r = READ_ONCE(kvm->arch.default_tsc_khz);
+               goto out;
+       }
        case KVM_MEMORY_ENCRYPT_OP: {
                r = -ENOTTY;
                if (!kvm_x86_ops.mem_enc_ioctl)
@@ -11266,7 +11289,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
        kvm_xen_init_vcpu(vcpu);
        kvm_vcpu_mtrr_init(vcpu);
        vcpu_load(vcpu);
-       kvm_set_tsc_khz(vcpu, max_tsc_khz);
+       kvm_set_tsc_khz(vcpu, vcpu->kvm->arch.default_tsc_khz);
        kvm_vcpu_reset(vcpu, false);
        kvm_init_mmu(vcpu);
        vcpu_put(vcpu);
@@ -11714,6 +11737,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        pvclock_update_vm_gtod_copy(kvm);
        raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 
+       kvm->arch.default_tsc_khz = max_tsc_khz;
        kvm->arch.guest_can_read_msr_platform_info = true;
        kvm->arch.enable_pmu = enable_pmu;
 
index ee5cc9e..8616af8 100644 (file)
@@ -1144,6 +1144,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_MEM_OP_EXTENSION 211
 #define KVM_CAP_PMU_CAPABILITY 212
 #define KVM_CAP_DISABLE_QUIRKS2 213
+#define KVM_CAP_VM_TSC_CONTROL 214
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1471,7 +1472,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_SET_PIT2              _IOW(KVMIO,  0xa0, struct kvm_pit_state2)
 /* Available with KVM_CAP_PPC_GET_PVINFO */
 #define KVM_PPC_GET_PVINFO       _IOW(KVMIO,  0xa1, struct kvm_ppc_pvinfo)
-/* Available with KVM_CAP_TSC_CONTROL */
+/* Available with KVM_CAP_TSC_CONTROL for a vCPU, or with
+*  KVM_CAP_VM_TSC_CONTROL to set defaults for a VM */
 #define KVM_SET_TSC_KHZ           _IO(KVMIO,  0xa2)
 #define KVM_GET_TSC_KHZ           _IO(KVMIO,  0xa3)
 /* Available with KVM_CAP_PCI_2_3 */