All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhao Liu <zhao1.liu@linux.intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>,
	Sean Christopherson <seanjc@google.com>,
	"Rafael J . Wysocki" <rafael@kernel.org>,
	Daniel Lezcano <daniel.lezcano@linaro.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	"H . Peter Anvin" <hpa@zytor.com>,
	kvm@vger.kernel.org, linux-pm@vger.kernel.org,
	linux-kernel@vger.kernel.org, x86@kernel.org
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>,
	Len Brown <len.brown@intel.com>, Zhang Rui <rui.zhang@intel.com>,
	Zhenyu Wang <zhenyu.z.wang@intel.com>,
	Zhuocheng Ding <zhuocheng.ding@intel.com>,
	Dapeng Mi <dapeng1.mi@intel.com>,
	Yanting Jiang <yanting.jiang@intel.com>,
	Yongwei Ma <yongwei.ma@intel.com>,
	Vineeth Pillai <vineeth@bitbyteword.org>,
	Suleiman Souhlal <suleiman@google.com>,
	Masami Hiramatsu <mhiramat@google.com>,
	David Dai <davidai@google.com>,
	Saravana Kannan <saravanak@google.com>,
	Zhao Liu <zhao1.liu@intel.com>
Subject: [RFC 20/26] KVM: x86: Expose HFI feature bit and HFI info in CPUID
Date: Sat,  3 Feb 2024 17:12:08 +0800	[thread overview]
Message-ID: <20240203091214.411862-21-zhao1.liu@linux.intel.com> (raw)
In-Reply-To: <20240203091214.411862-1-zhao1.liu@linux.intel.com>

From: Zhao Liu <zhao1.liu@intel.com>

The HFI feature contains the following relevant CPUID fields:

* 0x06.eax[bit 19]: HFI feature bit
* 0x06.ecx[bits 08-15]: Number of HFI/ITD supported classes
* 0x06.edx[bits 00-07]: Bitmap of supported HFI capabilities
* 0x06.edx[bits 08-11]: Enumerates the size of the HFI table in number
                        of 4 KB pages
* 0x06.edx[bits 16-31]: HFI table index of processor

Guest's HFI feature bit (0x06.eax[bit 19]) is based on Host's HFI
enabling.

For other HFI related CPUID fields, since they affect the memory
allocation and HFI data filling of the virtual HFI table in KVM, check
the hfi related CPUID fields after KVM_SET_CPUID/KVM_SET_CPUID2 to
ensure the valid HFI feature information and the valid memory size.

And about the HFI table index, since the current KVM creates the same
CPUID template for all vCPUs, we refer to the CPU topology handling and
leave the specific filling of the HFI table index to the user, if the
user does not specifically specify the HFI index, all vCPUs will share
the HFI entry with hfi index 0.

The shared HFI index is valid in spec [1], but considering that the data
of the virtual HFI table is all from the pCPU on which the vCPU is
running, the shared hfi index of vCPUs on different pCPUs might cause
frequent HFI updates, and the virtual HFI table cannot accurately reflect
the actual processor situation, which might have a negative impact on
the Guest performance. Therefore, it is better to assign different HFI
table indexes to different vCPUs.

[1]: SDM, vol. 2A, chap. CPUID--CPU Identification, CPUID.06H.EDX[Bits
     31-16], about HFI table index sharing, it said, "Note that on some
     parts the index may be same for multiple logical processors".

Tested-by: Yanting Jiang <yanting.jiang@intel.com>
Co-developed-by: Zhuocheng Ding <zhuocheng.ding@intel.com>
Signed-off-by: Zhuocheng Ding <zhuocheng.ding@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
 arch/x86/kvm/cpuid.c   | 136 ++++++++++++++++++++++++++++++++++++-----
 arch/x86/kvm/vmx/vmx.c |   7 +++
 2 files changed, 128 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index eaac2c8d98b9..4da8f3319917 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -17,6 +17,7 @@
 #include <linux/uaccess.h>
 #include <linux/sched/stat.h>
 
+#include <asm/hfi.h>
 #include <asm/processor.h>
 #include <asm/user.h>
 #include <asm/fpu/xstate.h>
@@ -130,12 +131,77 @@ static inline struct kvm_cpuid_entry2 *cpuid_entry2_find(
 	return NULL;
 }
 
+static int kvm_check_hfi_cpuid(struct kvm_vcpu *vcpu,
+			       struct kvm_cpuid_entry2 *entries,
+			       int nent)
+{
+	struct hfi_features hfi_features;
+	struct kvm_cpuid_entry2 *best = NULL;
+	bool has_hfi;
+	int nr_classes, ret;
+	union cpuid6_ecx ecx;
+	union cpuid6_edx edx;
+	unsigned int data_size;
+
+	best = cpuid_entry2_find(entries, nent, 0x6, 0);
+	if (!best)
+		return 0;
+
+	has_hfi = cpuid_entry_has(best, X86_FEATURE_HFI);
+	if (!has_hfi)
+		return 0;
+
+	/*
+	 * Only the platform with 1 HFI instance (i.e., client platform)
+	 * can enable HFI in Guest. For more information, please refer to
+	 * the comment in kvm_set_cpu_caps().
+	 */
+	if (intel_hfi_max_instances() != 1)
+		return -EINVAL;
+
+	/*
+	 * Currently we haven't supported ITD. HFI is the default feature
+	 * with 1 class.
+	 */
+	nr_classes = 1;
+	ret = intel_hfi_build_virt_features(&hfi_features,
+					    nr_classes,
+					    vcpu->kvm->created_vcpus);
+	if (ret)
+		return ret;
+
+	ecx.full = best->ecx;
+	edx.full = best->edx;
+
+	if (ecx.split.nr_classes != hfi_features.nr_classes)
+		return -EINVAL;
+
+	if (hweight8(edx.split.capabilities.bits) != hfi_features.class_stride)
+		return -EINVAL;
+
+	if (edx.split.table_pages + 1 != hfi_features.nr_table_pages)
+		return -EINVAL;
+
+	/*
+	 * The total size of the row corresponding to index and all
+	 * previous data.
+	 */
+	data_size = hfi_features.hdr_size + (edx.split.index + 1) *
+		    hfi_features.cpu_stride;
+	/* Invalid index. */
+	if (data_size > hfi_features.nr_table_pages << PAGE_SHIFT)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
 			   struct kvm_cpuid_entry2 *entries,
 			   int nent)
 {
 	struct kvm_cpuid_entry2 *best;
 	u64 xfeatures;
+	int ret;
 
 	/*
 	 * The existing code assumes virtual address is 48-bit or 57-bit in the
@@ -155,15 +221,18 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
 	 * enabling in the FPU, e.g. to expand the guest XSAVE state size.
 	 */
 	best = cpuid_entry2_find(entries, nent, 0xd, 0);
-	if (!best)
-		return 0;
-
-	xfeatures = best->eax | ((u64)best->edx << 32);
-	xfeatures &= XFEATURE_MASK_USER_DYNAMIC;
-	if (!xfeatures)
-		return 0;
+	if (best) {
+		xfeatures = best->eax | ((u64)best->edx << 32);
+		xfeatures &= XFEATURE_MASK_USER_DYNAMIC;
+		if (xfeatures) {
+			ret = fpu_enable_guest_xfd_features(&vcpu->arch.guest_fpu,
+							    xfeatures);
+			if (ret)
+				return ret;
+		}
+	}
 
-	return fpu_enable_guest_xfd_features(&vcpu->arch.guest_fpu, xfeatures);
+	return kvm_check_hfi_cpuid(vcpu, entries, nent);
 }
 
 /* Check whether the supplied CPUID data is equal to what is already set for the vCPU. */
@@ -633,14 +702,27 @@ void kvm_set_cpu_caps(void)
 	);
 
 	/*
-	 * PTS is the dependency of ITD, currently we only use PTS for
-	 * enabling ITD in KVM. Since KVM does not support msr topology at
-	 * present, the emulation of PTS has restrictions on the topology of
-	 * Guest, so we only expose PTS when Host enables ITD.
+	 * PTS and HFI are the dependencies of ITD, currently we only use PTS/HFI
+	 * for enabling ITD in KVM. Since KVM does not support msr topology at
+	 * present, the emulation of PTS/HFI has restrictions on the topology of
+	 * Guest, so we only expose PTS/HFI when Host enables ITD.
+	 *
+	 * We also restrict HFI virtualization support to platforms with only 1 HFI
+	 * instance (i.e., this is the client platform, and ITD is currently a
+	 * client-specific feature), while server platforms with multiple instances
+	 * do not require HFI virtualization. This restriction avoids adding
+	 * additional complex logic to handle notification register updates when
+	 * vCPUs migrate between different HFI instances.
 	 */
-	if (cpu_feature_enabled(X86_FEATURE_ITD)) {
+	if (cpu_feature_enabled(X86_FEATURE_ITD) && intel_hfi_max_instances() == 1) {
 		if (boot_cpu_has(X86_FEATURE_PTS))
 			kvm_cpu_cap_set(X86_FEATURE_PTS);
+		/*
+		 * Set HFI based on hardware capability. Only when the Host has
+		 * the valid HFI instance, KVM can build the virtual HFI table.
+		 */
+		if (intel_hfi_enabled())
+			kvm_cpu_cap_set(X86_FEATURE_HFI);
 	}
 
 	kvm_cpu_cap_mask(CPUID_7_0_EBX,
@@ -986,8 +1068,32 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
 			entry->eax |= 0x4;
 
 		entry->ebx = 0;
-		entry->ecx = 0;
-		entry->edx = 0;
+
+		if (kvm_cpu_cap_has(X86_FEATURE_HFI)) {
+			union cpuid6_ecx ecx;
+			union cpuid6_edx edx;
+
+			ecx.full = 0;
+			edx.full = 0;
+			/* Number of supported HFI classes */
+			ecx.split.nr_classes = 1;
+			/* HFI supports performance and energy efficiency capabilities. */
+			edx.split.capabilities.split.performance = 1;
+			edx.split.capabilities.split.energy_efficiency = 1;
+			/* As default, keep the same HFI table size as host. */
+			edx.split.table_pages = ((union cpuid6_edx)entry->edx).split.table_pages;
+			/*
+			 * Default HFI index = 0. User should be careful that
+			 * the index differ for each CPUs.
+			 */
+			edx.split.index = 0;
+
+			entry->ecx = ecx.full;
+			entry->edx = edx.full;
+		} else {
+			entry->ecx = 0;
+			entry->edx = 0;
+		}
 		break;
 	/* function 7 has additional index. */
 	case 7:
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 9c28d4ea0b2d..636f2bd68546 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -8434,6 +8434,13 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 		vmx->msr_ia32_feature_control_valid_bits &=
 			~FEAT_CTL_SGX_LC_ENABLED;
 
+	if (guest_cpuid_has(vcpu, X86_FEATURE_HFI) && intel_hfi_enabled()) {
+		struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry_index(vcpu, 0x6, 0);
+
+		if (best)
+			vmx->hfi_table_idx = ((union cpuid6_edx)best->edx).split.index;
+	}
+
 	/* Refresh #PF interception to account for MAXPHYADDR changes. */
 	vmx_update_exception_bitmap(vcpu);
 }
-- 
2.34.1


  parent reply	other threads:[~2024-02-03  9:01 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-03  9:11 [RFC 00/26] Intel Thread Director Virtualization Zhao Liu
2024-02-03  9:11 ` [RFC 01/26] thermal: Add bit definition for x86 thermal related MSRs Zhao Liu
2024-02-03  9:11 ` [RFC 02/26] thermal: intel: hfi: Add helpers to build HFI/ITD structures Zhao Liu
2024-02-03  9:11 ` [RFC 03/26] thermal: intel: hfi: Add HFI notifier helpers to notify HFI update Zhao Liu
2024-02-03  9:11 ` [RFC 04/26] KVM: Add kvm_arch_sched_out() hook Zhao Liu
2024-02-03  9:11 ` [RFC 05/26] KVM: x86: Reset hardware history at vCPU's sched_in/out Zhao Liu
2024-02-03  9:11 ` [RFC 06/26] KVM: VMX: Add helpers to handle the writes to MSR's R/O and R/WC0 bits Zhao Liu
2024-02-03  9:11 ` [RFC 07/26] KVM: VMX: Emulate ACPI (CPUID.0x01.edx[bit 22]) feature Zhao Liu
2024-02-03  9:11 ` [RFC 08/26] KVM: x86: Expose TM/ACC (CPUID.0x01.edx[bit 29]) feature bit to VM Zhao Liu
2024-02-03  9:11 ` [RFC 09/26] KVM: x86: cpuid: Define CPUID 0x06.eax by kvm_cpu_cap_mask() Zhao Liu
2024-02-03  9:11 ` [RFC 10/26] KVM: VMX: Emulate PTM/PTS (CPUID.0x06.eax[bit 6]) feature Zhao Liu
2024-02-03  9:11 ` [RFC 11/26] KVM: VMX: Introduce HFI description structure Zhao Liu
2024-02-03  9:12 ` [RFC 12/26] KVM: VMX: Introduce HFI table index for vCPU Zhao Liu
2024-02-03  9:12 ` [RFC 13/26] KVM: VMX: Support virtual HFI table for VM Zhao Liu
2024-02-03  9:12 ` [RFC 14/26] KVM: x86: Introduce the HFI dynamic update request and kvm_x86_ops Zhao Liu
2024-02-03  9:12 ` [RFC 15/26] KVM: VMX: Sync update of Host HFI table to Guest Zhao Liu
2024-02-03  9:12 ` [RFC 16/26] KVM: VMX: Update HFI table when vCPU migrates Zhao Liu
2024-02-03  9:12 ` [RFC 17/26] KVM: VMX: Allow to inject thermal interrupt without HFI update Zhao Liu
2024-02-03  9:12 ` [RFC 18/26] KVM: VMX: Emulate HFI related bits in package thermal MSRs Zhao Liu
2024-02-03  9:12 ` [RFC 19/26] KVM: VMX: Emulate the MSRs of HFI feature Zhao Liu
2024-02-03  9:12 ` Zhao Liu [this message]
2024-02-03  9:12 ` [RFC 21/26] KVM: VMX: Extend HFI table and MSR emulation to support ITD Zhao Liu
2024-02-03  9:12 ` [RFC 22/26] KVM: VMX: Pass through ITD classification related MSRs to Guest Zhao Liu
2024-02-03  9:12 ` [RFC 23/26] KVM: x86: Expose ITD feature bit and related info in CPUID Zhao Liu
2024-02-03  9:12 ` [RFC 24/26] KVM: VMX: Emulate the MSR of HRESET feature Zhao Liu
2024-02-03  9:12 ` [RFC 25/26] KVM: x86: Expose HRESET feature's CPUID to Guest Zhao Liu
2024-02-03  9:12 ` [RFC 26/26] Documentation: KVM: Add description of pkg_therm_lock Zhao Liu
2024-02-22  7:42 ` [RFC 00/26] Intel Thread Director Virtualization Zhao Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240203091214.411862-21-zhao1.liu@linux.intel.com \
    --to=zhao1.liu@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=daniel.lezcano@linaro.org \
    --cc=dapeng1.mi@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=davidai@google.com \
    --cc=hpa@zytor.com \
    --cc=kvm@vger.kernel.org \
    --cc=len.brown@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=mhiramat@google.com \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=rafael@kernel.org \
    --cc=ricardo.neri-calderon@linux.intel.com \
    --cc=rui.zhang@intel.com \
    --cc=saravanak@google.com \
    --cc=seanjc@google.com \
    --cc=suleiman@google.com \
    --cc=tglx@linutronix.de \
    --cc=vineeth@bitbyteword.org \
    --cc=x86@kernel.org \
    --cc=yanting.jiang@intel.com \
    --cc=yongwei.ma@intel.com \
    --cc=zhao1.liu@intel.com \
    --cc=zhenyu.z.wang@intel.com \
    --cc=zhuocheng.ding@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.