KVM: x86: Allow userspace to set maximum VCPU id for VM
authorZeng Guang <guang.zeng@intel.com>
Tue, 19 Apr 2022 15:44:44 +0000 (23:44 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 8 Jun 2022 08:47:31 +0000 (04:47 -0400)
Introduce new max_vcpu_ids in KVM for x86 architecture. Userspace
can assign maximum possible vcpu id for current VM session using
KVM_CAP_MAX_VCPU_ID of KVM_ENABLE_CAP ioctl().

This is done for x86 only because the sole use case is to guide
memory allocation for PID-pointer table, a structure needed to
enable VMX IPI.

By default, max_vcpu_ids set as KVM_MAX_VCPU_IDS.

Suggested-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: Zeng Guang <guang.zeng@intel.com>
Message-Id: <20220419154444.11888-1-guang.zeng@intel.com>
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

index 94d73ec..421479a 100644 (file)
@@ -7494,6 +7494,27 @@ The valid bits in cap.args[0] are:
                                     generate a #UD within the guest.
 =================================== ============================================
 
+7.32 KVM_CAP_MAX_VCPU_ID
+------------------------
+
+:Architectures: x86
+:Target: VM
+:Parameters: args[0] - maximum APIC ID value set for current VM
+:Returns: 0 on success, -EINVAL if args[0] is beyond KVM_MAX_VCPU_IDS
+          supported in KVM or if it has been set.
+
+This capability allows userspace to specify maximum possible APIC ID
+assigned for current VM session prior to the creation of vCPUs, saving
+memory for data structures indexed by the APIC ID.  Userspace is able
+to calculate the limit to APIC ID values from designated
+CPU topology.
+
+The value can be changed only until KVM_ENABLE_CAP is set to a nonzero
+value or until a vCPU is created.  Upon creation of the first vCPU,
+if the value was set to zero or KVM_ENABLE_CAP was not invoked, KVM
+uses the return value of KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPU_ID) as
+the maximum APIC ID.
+
 8. Other capabilities.
 ======================
 
index 8109805..9dc8d6d 100644 (file)
@@ -1243,6 +1243,12 @@ struct kvm_arch {
        hpa_t   hv_root_tdp;
        spinlock_t hv_root_tdp_lock;
 #endif
+       /*
+        * VM-scope maximum vCPU ID. Used to determine the size of structures
+        * that increase along with the maximum vCPU ID, in which case, using
+        * the global KVM_MAX_VCPU_IDS may lead to significant memory waste.
+        */
+       u32 max_vcpu_ids;
 };
 
 struct kvm_vm_stat {
index 9c2e2b6..25fbb90 100644 (file)
@@ -6087,6 +6087,20 @@ split_irqchip_unlock:
                }
                mutex_unlock(&kvm->lock);
                break;
+       case KVM_CAP_MAX_VCPU_ID:
+               r = -EINVAL;
+               if (cap->args[0] > KVM_MAX_VCPU_IDS)
+                       break;
+
+               mutex_lock(&kvm->lock);
+               if (kvm->arch.max_vcpu_ids == cap->args[0]) {
+                       r = 0;
+               } else if (!kvm->arch.max_vcpu_ids) {
+                       kvm->arch.max_vcpu_ids = cap->args[0];
+                       r = 0;
+               }
+               mutex_unlock(&kvm->lock);
+               break;
        default:
                r = -EINVAL;
                break;
@@ -11246,6 +11260,12 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
                pr_warn_once("kvm: SMP vm created on host with unstable TSC; "
                             "guest TSC will not be reliable\n");
 
+       if (!kvm->arch.max_vcpu_ids)
+               kvm->arch.max_vcpu_ids = KVM_MAX_VCPU_IDS;
+
+       if (id >= kvm->arch.max_vcpu_ids)
+               return -EINVAL;
+
        return 0;
 }