From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F94B20EB for ; Fri, 5 Sep 2025 12:15:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074526; cv=none; b=BzWKcV1/Tfy/IblnjAymno2IKsBFyxGGQHNZVAOMf1Ny4UUMxJDeoQ6DWoRUal4WNgzYRmGd8Qwe1HE8iK9ZQdYJwjU8UUxrAn5ldx3uIWL3aUsFbcKpMnf4l+d8UJiFQqWWUOSG2WDPFTl0JWpGqA2XVTjUuy30yqfksSvIfZ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074526; c=relaxed/simple; bh=l8ElQRAT1Hszveqk+X21k8IIcIZzDZmj+WUDZsTY2C0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nr/y0zbHX1ZDus9WLXba/avLOftsgm07YEKgGeNkszHkFKsxE+ofaNYCwLOpojzqIsnz1jcRXx+ZKhqoqEVwT5Uv78ows+WTXPTetiYCU58vYbWseyWirWQzoeaCdOGyKvTvtS9FrNn6vH8Utgv3Uz0dQ7P6CaQX/BiDi9z/nLM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=DwA3397L; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=Vd3qLtYb; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="DwA3397L"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="Vd3qLtYb" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074523; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ILIDCHvFGsvZiwtpyNNKEdOsJOlcSIX04cXR7l0HOA4=; b=DwA3397LhSlgh5+HBdsWv8v1ZxjliC3F0XLaTLc9bjzoVmoFZtew2mD54FW0wvpnkn9q9B dhSybgaux4geGazQ7akCZDcPrJxY7S8KVxsaKtSdZ7JvFa+x6tSOPjkRNIA0flDBPPudut U9KasVeMkG6mCxxriQ6xrIZbL9WFDgFYNMajhsyXVnZbdOd6cqDacNQWPKSEK6tHJ0it/1 m3DnP3ujII8QGaFBXrxLUvRLAhiVSbUbdUmlSu0QWFYuJ6i/8ZtC8fBN7AfiWoFwiE9vXF d3hrwVFZ1031QuV6rtDFSpsGIklgZLvuyl19y6d2caPQdhsYkKNmFgdeQ0XfoA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074523; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ILIDCHvFGsvZiwtpyNNKEdOsJOlcSIX04cXR7l0HOA4=; b=Vd3qLtYbjjVHZxZQqxkw/X9M2naa/EPcYpNw5/dfEHVBH5/YgbDDtsqBA73d3oEKN/nmDk aChUrxO/lm+UPQBw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 01/35] ASoC: Intel: avs: Include CPUID header at file scope Date: Fri, 5 Sep 2025 14:14:41 +0200 Message-ID: <20250905121515.192792-2-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platform= s") includes the main CPUID header from within a C function. This works by luck and forbids valid refactorings inside the CPUID header. Include the CPUID header at file scope instead. Note, for the CPUID(0x15) leaf number, use CPUID_LEAF_TSC instead of defining a custom local macro for it. Signed-off-by: Ahmed S. Darwish Acked-by: Cezary Rojewski --- sound/soc/intel/avs/tgl.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index 9dbb3ad0954a..cf19d3a7ced2 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -10,8 +10,6 @@ #include "avs.h" #include "messages.h" =20 -#define CPUID_TSC_LEAF 0x15 - static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, boo= l power) { core_mask &=3D AVS_MAIN_CORE_MASK; @@ -39,22 +37,31 @@ static int avs_tgl_dsp_core_stall(struct avs_dev *adev,= u32 core_mask, bool stal return avs_dsp_core_stall(adev, core_mask, stall); } =20 +#ifdef CONFIG_X86 +#include +static unsigned int intel_crystal_freq_hz(void) +{ + return cpuid_ecx(CPUID_LEAF_TSC); +} +#else +static unsigned int intel_crystal_freq_hz(void) +{ + return 0; +} +#endif /* !CONFIG_X86 */ + static int avs_tgl_config_basefw(struct avs_dev *adev) { + unsigned int freq =3D intel_crystal_freq_hz(); struct pci_dev *pci =3D adev->base.pci; struct avs_bus_hwid hwid; int ret; -#ifdef CONFIG_X86 - unsigned int ecx; =20 -#include - ecx =3D cpuid_ecx(CPUID_TSC_LEAF); - if (ecx) { - ret =3D avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(e= cx), &ecx); + if (freq) { + ret =3D avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(f= req), &freq); if (ret) return AVS_IPC_RET(ret); } -#endif =20 hwid.device =3D pci->device; hwid.subsystem =3D pci->subsystem_vendor | (pci->subsystem_device << 16); --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 722BD34DCD5 for ; Fri, 5 Sep 2025 12:15:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074531; cv=none; b=ObkmE3adZRhQsAucqjTzGN99eeoP/NXMHvOLHRjvBNpDsujkXkNd0RavFFgLvt2ju+17/e7t3R+v7TkkfWnzKEqRFDLP3QhlZe09aF7UtEZ49oIIqtQ9RztfrH4kOt8m7YIakNXSqiAlT0a7c2u6B3AowjJkcZQ/dZqAiKnkjoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074531; c=relaxed/simple; bh=4PXqpUYGafDTVrlV2qbAd7cl+31iZbMkUDLTO2gBsFw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OHCxxe9VfS24NagvFnAi6C2loGGgL5t7oMDK5ghiTAiv4nvIy7B6xy/cBm4E5rNz/8Ltmao4OWSJnrOD/eWj0W1JviUmKxpVfRQaqfw+evIbLuwf4adayOsxjf3s1+4SClr9OKUgjZ9L9rHxzhRqjRofYztOXbOhloW4DAryyuI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=YTqZAXd6; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=TcgttwLj; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="YTqZAXd6"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="TcgttwLj" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074526; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zw29j1lbWPBStMF6iGRQU7p2den5CWnWMWt7BcbB74A=; b=YTqZAXd6XzBAm5Ue67io+Af++ElGMBXlhdkmFkbw9VmEJ4c9LUSfiiih6YnH613Ia1iV51 4Fc0z0bH25JUx7jRRNiXRIbh6rb/sim+z9k+JUfoPvM291Jfd9NPRzmMOBVXQwuKytKUGN 9uQOZUs6C9W8mtw8MTwNNU+Y9Jc/O1N1EVrviQtgCD5g7Gc9uXKJ9muMdj6OAmYW4YWEoK pqgoesC3j6DuUbcVzqdKT4fxYIYzfXXCSwczdymKNLCOr4O2cDg+IKJaio1uzbR8VxPgOI m55Dy1+L1RjdLOUp4t6pFjD5cgbPx3SV0C9XoiVuHBLMKO4LDXI5Du9O8QUT/g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074526; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zw29j1lbWPBStMF6iGRQU7p2den5CWnWMWt7BcbB74A=; b=TcgttwLjE9oFKFk2B3nMlfbqJseVrFuiKj6OTG9LgCA+y4VijWtTldnM1gJz1h0Mg7Pneg kfQvL3gMzj8oMeAA== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 02/35] treewide: Explicitly include the x86 CPUID headers Date: Fri, 5 Sep 2025 14:14:42 +0200 Message-ID: <20250905121515.192792-3-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Modify all CPUID call sites which implicitly include any of the CPUID headers to explicitly include them instead. For arch/x86/kvm/reverse_cpuid.h, just include since it references the CPUID_EAX..EDX symbols without using any of the CPUID APIs. Note, adding explicit CPUID includes for all call sites allows removing the include from next. This way, the CPUID API header can include at a later step without introducing a circular dependency. Signed-off-by: Ahmed S. Darwish --- arch/x86/boot/compressed/pgtable_64.c | 1 + arch/x86/boot/startup/sme.c | 1 + arch/x86/coco/tdx/tdx.c | 1 + arch/x86/events/amd/core.c | 2 ++ arch/x86/events/amd/ibs.c | 1 + arch/x86/events/amd/lbr.c | 2 ++ arch/x86/events/amd/power.c | 3 +++ arch/x86/events/amd/uncore.c | 1 + arch/x86/events/intel/core.c | 1 + arch/x86/events/intel/lbr.c | 1 + arch/x86/events/zhaoxin/core.c | 1 + arch/x86/include/asm/acrn.h | 2 ++ arch/x86/include/asm/microcode.h | 1 + arch/x86/include/asm/xen/hypervisor.h | 1 + arch/x86/kernel/apic/apic.c | 1 + arch/x86/kernel/cpu/amd.c | 1 + arch/x86/kernel/cpu/centaur.c | 1 + arch/x86/kernel/cpu/hygon.c | 1 + arch/x86/kernel/cpu/mce/core.c | 1 + arch/x86/kernel/cpu/mce/inject.c | 1 + arch/x86/kernel/cpu/microcode/amd.c | 1 + arch/x86/kernel/cpu/microcode/core.c | 1 + arch/x86/kernel/cpu/microcode/intel.c | 1 + arch/x86/kernel/cpu/mshyperv.c | 1 + arch/x86/kernel/cpu/resctrl/core.c | 1 + arch/x86/kernel/cpu/resctrl/monitor.c | 1 + arch/x86/kernel/cpu/scattered.c | 1 + arch/x86/kernel/cpu/sgx/driver.c | 3 +++ arch/x86/kernel/cpu/sgx/main.c | 3 +++ arch/x86/kernel/cpu/topology_amd.c | 1 + arch/x86/kernel/cpu/topology_common.c | 1 + arch/x86/kernel/cpu/topology_ext.c | 1 + arch/x86/kernel/cpu/transmeta.c | 3 +++ arch/x86/kernel/cpu/vmware.c | 1 + arch/x86/kernel/cpu/zhaoxin.c | 1 + arch/x86/kernel/cpuid.c | 1 + arch/x86/kernel/jailhouse.c | 1 + arch/x86/kernel/kvm.c | 1 + arch/x86/kernel/paravirt.c | 1 + arch/x86/kvm/mmu/mmu.c | 1 + arch/x86/kvm/mmu/spte.c | 1 + arch/x86/kvm/reverse_cpuid.h | 2 ++ arch/x86/kvm/svm/sev.c | 1 + arch/x86/kvm/svm/svm.c | 1 + arch/x86/kvm/vmx/pmu_intel.c | 1 + arch/x86/kvm/vmx/sgx.c | 1 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/mm/pti.c | 1 + arch/x86/pci/xen.c | 2 +- arch/x86/xen/enlighten_hvm.c | 1 + arch/x86/xen/pmu.c | 1 + arch/x86/xen/time.c | 1 + drivers/char/agp/efficeon-agp.c | 1 + drivers/cpufreq/longrun.c | 1 + drivers/cpufreq/powernow-k7.c | 2 +- drivers/cpufreq/powernow-k8.c | 1 + drivers/cpufreq/speedstep-lib.c | 1 + drivers/firmware/efi/libstub/x86-5lvl.c | 1 + drivers/gpu/drm/gma500/mmu.c | 2 ++ drivers/hwmon/fam15h_power.c | 1 + drivers/hwmon/k10temp.c | 2 ++ drivers/hwmon/k8temp.c | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 1 + drivers/ras/amd/fmpm.c | 1 + drivers/thermal/intel/intel_hfi.c | 1 + drivers/thermal/intel/x86_pkg_temp_thermal.c | 1 + drivers/virt/acrn/hsm.c | 1 + drivers/xen/events/events_base.c | 1 + drivers/xen/grant-table.c | 1 + drivers/xen/xenbus/xenbus_xs.c | 3 +++ 70 files changed, 86 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compress= ed/pgtable_64.c index bdd26050dff7..d94d98595780 100644 --- a/arch/x86/boot/compressed/pgtable_64.c +++ b/arch/x86/boot/compressed/pgtable_64.c @@ -2,6 +2,7 @@ #include "misc.h" #include #include +#include #include #include #include "../string.h" diff --git a/arch/x86/boot/startup/sme.c b/arch/x86/boot/startup/sme.c index 70ea1748c0a7..1b1bcb41bf23 100644 --- a/arch/x86/boot/startup/sme.c +++ b/arch/x86/boot/startup/sme.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include =20 diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 7b2833705d47..168388be3a3e 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index b20661b8621d..d28d45ceb707 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c @@ -7,8 +7,10 @@ #include #include #include + #include #include +#include #include #include =20 diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 112f43b23ebf..0c7848e6149e 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c @@ -15,6 +15,7 @@ #include =20 #include +#include #include =20 #include "../perf_event.h" diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c index d24da377df77..5b437dc8e4ce 100644 --- a/arch/x86/events/amd/lbr.c +++ b/arch/x86/events/amd/lbr.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include + +#include #include #include =20 diff --git a/arch/x86/events/amd/power.c b/arch/x86/events/amd/power.c index dad42790cf7d..744dffa42dee 100644 --- a/arch/x86/events/amd/power.c +++ b/arch/x86/events/amd/power.c @@ -10,8 +10,11 @@ #include #include #include + #include +#include #include + #include "../perf_event.h" =20 /* Event code: LSB 8 bits, passed in attr->config any other bit is reserve= d. */ diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index e8b6af199c73..c602542f3a36 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -16,6 +16,7 @@ #include =20 #include +#include #include =20 #define NUM_COUNTERS_NB 4 diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index c2fb729c270e..ebbcdf82b494 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -17,6 +17,7 @@ #include =20 #include +#include #include #include #include diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 7aa59966e7c3..0d1ec3651735 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -3,6 +3,7 @@ #include =20 #include +#include #include #include =20 diff --git a/arch/x86/events/zhaoxin/core.c b/arch/x86/events/zhaoxin/core.c index 4bdfcf091200..6ed644fe89aa 100644 --- a/arch/x86/events/zhaoxin/core.c +++ b/arch/x86/events/zhaoxin/core.c @@ -13,6 +13,7 @@ #include =20 #include +#include #include #include #include diff --git a/arch/x86/include/asm/acrn.h b/arch/x86/include/asm/acrn.h index fab11192c60a..db42b477c41d 100644 --- a/arch/x86/include/asm/acrn.h +++ b/arch/x86/include/asm/acrn.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_ACRN_H #define _ASM_X86_ACRN_H =20 +#include + /* * This CPUID returns feature bitmaps in EAX. * Guest VM uses this to detect the appropriate feature bit. diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microc= ode.h index 8b41f26f003b..645e65ac1586 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -3,6 +3,7 @@ #define _ASM_X86_MICROCODE_H =20 #include +#include =20 struct cpu_signature { unsigned int sig; diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/x= en/hypervisor.h index c2fc7869b996..7c596cebfb78 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -37,6 +37,7 @@ extern struct shared_info *HYPERVISOR_shared_info; extern struct start_info *xen_start_info; =20 #include +#include #include =20 #define XEN_SIGNATURE "XenVMMXenVMM" diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index d73ba5a7b623..42045b7200ac 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index a6f88ca1a6b4..91d8dce3d510 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index a3b55db35c96..cc5a390dcd07 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -5,6 +5,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c index 1fda6c3a2b65..dd6fa85dd9c6 100644 --- a/arch/x86/kernel/cpu/hygon.c +++ b/arch/x86/kernel/cpu/hygon.c @@ -10,6 +10,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index 4da4eab56c81..2b0da00b9d4b 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -48,6 +48,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inj= ect.c index d02c4f556cd0..42c82c14c48a 100644 --- a/arch/x86/kernel/cpu/mce/inject.c +++ b/arch/x86/kernel/cpu/mce/inject.c @@ -26,6 +26,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/micr= ocode/amd.c index 514f63340880..4622d1162e46 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -34,6 +34,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/mic= rocode/core.c index b92e09a87c69..f3b433d90e0d 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -34,6 +34,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index 371ca6eac00e..dacfbffe4cd2 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -22,6 +22,7 @@ #include =20 #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index c78f860419d6..b397c1385ebd 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/core.c index 187d527ef73b..c1dd1a3d4b38 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -22,6 +22,7 @@ #include =20 #include +#include #include #include #include "internal.h" diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/re= sctrl/monitor.c index c261558276cd..5dffb9453d77 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -21,6 +21,7 @@ #include =20 #include +#include #include =20 #include "internal.h" diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattere= d.c index 6b868afb26c3..047cccd21d3a 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -6,6 +6,7 @@ =20 #include #include +#include #include =20 #include "cpu.h" diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/dri= ver.c index 7f8d1e11dbee..f0c0a001bce6 100644 --- a/arch/x86/kernel/cpu/sgx/driver.c +++ b/arch/x86/kernel/cpu/sgx/driver.c @@ -6,7 +6,10 @@ #include #include #include + +#include #include + #include "driver.h" #include "encl.h" =20 diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 2de01b379aa3..00bf42f4c536 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -14,8 +14,11 @@ #include #include #include + +#include #include #include + #include "driver.h" #include "encl.h" #include "encls.h" diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topol= ogy_amd.c index 827dd0dbb6e9..42d91aa9b23a 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -2,6 +2,7 @@ #include =20 #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/to= pology_common.c index b5a5e1411469..b8c55f025b7e 100644 --- a/arch/x86/kernel/cpu/topology_common.c +++ b/arch/x86/kernel/cpu/topology_common.c @@ -6,6 +6,7 @@ #include #include #include +#include #include =20 #include "cpu.h" diff --git a/arch/x86/kernel/cpu/topology_ext.c b/arch/x86/kernel/cpu/topol= ogy_ext.c index 467b0326bf1a..eb915c73895f 100644 --- a/arch/x86/kernel/cpu/topology_ext.c +++ b/arch/x86/kernel/cpu/topology_ext.c @@ -2,6 +2,7 @@ #include =20 #include +#include #include #include =20 diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmet= a.c index 42c939827621..1fdcd69c625c 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -3,8 +3,11 @@ #include #include #include + #include +#include #include + #include "cpu.h" =20 static void early_init_transmeta(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index cb3f900c46fc..fe181620f8f6 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c index 89b1c8a70fe8..cfcfb6221e3f 100644 --- a/arch/x86/kernel/cpu/zhaoxin.c +++ b/arch/x86/kernel/cpu/zhaoxin.c @@ -4,6 +4,7 @@ =20 #include #include +#include #include =20 #include "cpu.h" diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index dae436253de4..cbd04b677fd1 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -37,6 +37,7 @@ #include #include =20 +#include #include #include =20 diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c index 9e9a591a5fec..f58ce9220e0f 100644 --- a/arch/x86/kernel/jailhouse.c +++ b/arch/x86/kernel/jailhouse.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 8ae750cde0c6..f89e3fea5e97 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index ab3e172dcc69..15f608f057ac 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 6e838cb6c9e1..024d8990b1a7 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c index df31039b5d63..86053e52ca4f 100644 --- a/arch/x86/kvm/mmu/spte.c +++ b/arch/x86/kvm/mmu/spte.c @@ -15,6 +15,7 @@ #include "x86.h" #include "spte.h" =20 +#include #include #include #include diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index c53b92379e6e..77bdc3fe3fc5 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -3,8 +3,10 @@ #define ARCH_X86_KVM_REVERSE_CPUID_H =20 #include + #include #include +#include =20 /* * Define a KVM-only feature flag. diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 0635bd71c10e..eb25f461953f 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -23,6 +23,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index d9931c6c4bc6..fcb780352ac9 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 0b173602821b..c3c43c15bc5a 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "x86.h" #include "cpuid.h" #include "lapic.h" diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c index df1d0cf76947..29a1f8e3be60 100644 --- a/arch/x86/kvm/vmx/sgx.c +++ b/arch/x86/kvm/vmx/sgx.c @@ -2,6 +2,7 @@ /* Copyright(c) 2021 Intel Corporation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 +#include #include #include =20 diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index aa157fe5b7b3..4b21cace955f 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index b10d4d131dce..f45fd1482c86 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -31,6 +31,7 @@ =20 #include #include +#include #include #include #include diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index b8755cde2419..6acfbdbaf4d5 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -18,6 +18,7 @@ #include #include #include +#include =20 #include =20 @@ -583,4 +584,3 @@ int __init pci_xen_initial_domain(void) return 0; } #endif - diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c index fe57ff85d004..bd57259a02e6 100644 --- a/arch/x86/xen/enlighten_hvm.c +++ b/arch/x86/xen/enlighten_hvm.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include =20 diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c index 8f89ce0b67e3..5f50a3ee08f5 100644 --- a/arch/x86/xen/pmu.c +++ b/arch/x86/xen/pmu.c @@ -2,6 +2,7 @@ #include #include =20 +#include #include #include #include diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 96521b1874ac..d935cc1f2896 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -17,6 +17,7 @@ #include #include =20 +#include #include #include #include diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-ag= p.c index 0d25bbdc7e6a..4d0b7d7c0aad 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "agp.h" #include "intel-agp.h" =20 diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 1caaec7c280b..f3aaca0496a4 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c @@ -14,6 +14,7 @@ #include #include #include +#include =20 static struct cpufreq_driver longrun_driver; =20 diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 31039330a3ba..ee122aafa56a 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -29,6 +29,7 @@ #include /* Needed for recalibrate_cpu_khz() */ #include #include +#include =20 #ifdef CONFIG_X86_POWERNOW_K7_ACPI #include @@ -691,4 +692,3 @@ MODULE_LICENSE("GPL"); =20 late_initcall(powernow_init); module_exit(powernow_exit); - diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index f7512b4e923e..84d7a737203b 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -39,6 +39,7 @@ =20 #include #include +#include =20 #include #include diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-li= b.c index 0b66df4ed513..b3fe873103a8 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c @@ -15,6 +15,7 @@ #include #include =20 +#include #include #include #include "speedstep-lib.h" diff --git a/drivers/firmware/efi/libstub/x86-5lvl.c b/drivers/firmware/efi= /libstub/x86-5lvl.c index f1c5fb45d5f7..029ad80cf0b4 100644 --- a/drivers/firmware/efi/libstub/x86-5lvl.c +++ b/drivers/firmware/efi/libstub/x86-5lvl.c @@ -2,6 +2,7 @@ #include =20 #include +#include #include #include =20 diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c index e6753282e70e..4d2aba31a78c 100644 --- a/drivers/gpu/drm/gma500/mmu.c +++ b/drivers/gpu/drm/gma500/mmu.c @@ -7,6 +7,8 @@ #include #include =20 +#include + #include "mmu.h" #include "psb_drv.h" #include "psb_reg.h" diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 8ecebea53651..e200c7b7a698 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -19,6 +19,7 @@ #include #include #include +#include #include =20 MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index babf2413d666..12115654689a 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -20,7 +20,9 @@ #include #include #include + #include +#include #include =20 MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 2b80ac410cd1..53241164570e 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -15,6 +15,7 @@ #include #include #include +#include =20 #define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000) #define REG_TEMP 0xe4 diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/ne= t/ethernet/stmicro/stmmac/dwmac-intel.c index ea33ae39be6b..7612759c7267 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "dwmac-intel.h" #include "dwmac4.h" #include "stmmac.h" diff --git a/drivers/ras/amd/fmpm.c b/drivers/ras/amd/fmpm.c index 8877c6ff64c4..416a14bbd714 100644 --- a/drivers/ras/amd/fmpm.c +++ b/drivers/ras/amd/fmpm.c @@ -52,6 +52,7 @@ #include =20 #include +#include #include =20 #include "../debugfs.h" diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/inte= l_hfi.c index bd2fca7dc017..c910cc563d9d 100644 --- a/drivers/thermal/intel/intel_hfi.c +++ b/drivers/thermal/intel/intel_hfi.c @@ -41,6 +41,7 @@ #include #include =20 +#include #include =20 #include "intel_hfi.h" diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal= /intel/x86_pkg_temp_thermal.c index 3fc679b6f11b..80f98e4ae61f 100644 --- a/drivers/thermal/intel/x86_pkg_temp_thermal.c +++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c @@ -20,6 +20,7 @@ #include =20 #include +#include #include =20 #include "thermal_interrupt.h" diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c index e4e196abdaac..67119f9da449 100644 --- a/drivers/virt/acrn/hsm.c +++ b/drivers/virt/acrn/hsm.c @@ -16,6 +16,7 @@ #include =20 #include +#include #include =20 #include "acrn_drv.h" diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_b= ase.c index 41309d38f78c..4d847dcd6d76 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -40,6 +40,7 @@ #include =20 #ifdef CONFIG_X86 +#include #include #include #include diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 04a6b470b15d..ae3e384c2d1b 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -59,6 +59,7 @@ #include #include #ifdef CONFIG_X86 +#include #include #endif #include diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 528682bf0c7f..b56c4ed2119c 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -47,6 +47,9 @@ #include #include #include +#ifdef CONFIG_X86 +#include +#endif #include #include #include "xenbus.h" --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F8DC34DCF1 for ; Fri, 5 Sep 2025 12:15:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074533; cv=none; b=gCAlExdlzfoyi+/Sl3aNBCK5xKAAsl9u/h7NoWBw/bd6reKe/iC3Cy0Ry86xg7ZkAw8xtmOYPJo4WELhgQb9I2m8x/EScIfZ3lzVrdiMbocBiGXe2PKNzjyOwEM1iVUkt1ZQSpv1ig0pNTQsTY2ZxF+g43UkS3ctwoF+KuO7WOU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074533; c=relaxed/simple; bh=NqhvlfUYaDV/+2XHHooAozZ1Ma4TP4Tc6co3ykPUrHA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mFAZlJPcdGSb3RHNI7A9KeZlDBd8vfM/MjHdsI9di9y1kRxsbs7YLG4LwYeHnwyChtaKOEbIMSk3kXV12NVEfHDzikikdarYOHabA2mgnlBIcYsFQSP1FEXp/ZCoGHRApe5PkzMPr4cGJD5eY/Tzvqu1cZ+HT5v9A8hle1VFNqI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=YwRKe3Gq; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=m67rlNbX; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="YwRKe3Gq"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="m67rlNbX" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074529; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OAEsC2skIOSaWZt2MlflxtyQsbT7+BYF8vFWwagm9QY=; b=YwRKe3GqJBa3yv19GFVyfmqeN1i9legG9BMvWF5NaeDlmttbMIscUnIxtInbW2XpumHE6E rm7kh5sWAlksofwmWJEefEBCfERYaENlqWlqrIy1wYhdRfuA1kkyhTaMz4JB7iRqOedVzW IWWvM8VFigHhuKbT+a7qGnGY7tc1wXRIIno8eu4W7nTETeHXuYs4qfd/6xqxUdPj+V061U cM5QYfdfeFlFHy/Yq4KLRQ/VjZJ4Q+I6pNQ5RKgn7AbcJwi4Sq0noR/QaLZRdOmGcmt654 YOM0qRX8qEDKm56jkk8mUqk8ho93CfWCXDxooFeE5ELInqtdBXDZ8hvp0Vdlug== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074529; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OAEsC2skIOSaWZt2MlflxtyQsbT7+BYF8vFWwagm9QY=; b=m67rlNbXmSKZsshHY0o9NmnU4FSqKoppGWXlbFV5dnb4toX+5SPXZJRO+U20pN6di0pIUC VtrIK0z5Jzku9PAw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 03/35] x86/cpu: : Do not include the CPUID API header Date: Fri, 5 Sep 2025 14:14:43 +0200 Message-ID: <20250905121515.192792-4-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" includes the main CPUID API header but it does not need it. Remove the include. Note, this allows the CPUID API header to include at a later step, which is needed for the upcoming CPUID model and parser, without introducing a circular dependency. Note, all call sites which implicitly included the CPUID API header through have been already modified to explicitly include the CPUID API instead. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/processor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/proces= sor.h index bde58f6510ac..910e36b0c00d 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -16,7 +16,6 @@ struct vm86; #include #include #include -#include #include #include #include --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4577C34AAFF for ; Fri, 5 Sep 2025 12:15:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074535; cv=none; b=JpT7oe3w/ioeMv2oUJtKm+CfQoByv4/qsNLUKwdiL/7niS6QyUcrXg60Q0At895TF7TLNfSsHFST+GWrTfctxMtIp+GrfIxImbkNBg5PfpYt8gmFDFJ/5RAmk2NoPjvC7f19CX/LJvK4li38aJgSjSQlZ1k84MGoNaptxWRDf14= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074535; c=relaxed/simple; bh=E54gyw0AGLBY5Iv7Mdbwe+8baprlamI06AECAPTiiIU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UOJwoz7mAI6A1zeaO1gZU3/y5wsWiiZaDkjb01BDX/8MYeHLpsMP8gngt+/Zv6Y+1v9Bcy5JQMMomjSEoNX5AUkAxPESp/oaKfs0IXlZgKZ8cw0x5InkvB0d3Ucacz3hUO38faAj2sabeL3qvyPRpT86pTHVGIVB6PdzpG6kcPg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=qiRCjuFV; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=EVkLMxg1; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="qiRCjuFV"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="EVkLMxg1" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074532; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cfexTI82Y9dSPh8MK3LjQNX70lfzP/67Ss1JC9lednk=; b=qiRCjuFV4eqUDx6bmPFaepZPhPVp1ce/Z3+MK35n/wrx+S5owoPELDeFJBlvHlbA/rzzvE mfSYI3kQLP71bvx996nzAovD1A1r2c5dne5Eq7EMw50dbi++b3hfbRFtlOEedmv16oDQKO qSAFWwTLzHiG7pBH4a6vC33FY43HQswxQEWZTaJ1mAWzTI1sSa+LZmU8dFze30huO5wC7X Ik1lpUPsl07slPcVXyvnj5DQWgYALweRaX5ii8CPSmqqWTdnMVvROedmTrGo0P/9ZGc04u 0zNzF+W6oc18mCsZ4JvqRvD5EX2kDU4DC1na3QoIUP1xTD4d5obR5P/BG2NdYQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074532; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cfexTI82Y9dSPh8MK3LjQNX70lfzP/67Ss1JC9lednk=; b=EVkLMxg1/MZ6myFVxG1ORkUgwUEebUIOH5pEOQzXfsXckyFrruvjslzJJMm9anO7N3UpA8 ExxUDKVnviw/m0Bw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 04/35] x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs Date: Fri, 5 Sep 2025 14:14:44 +0200 Message-ID: <20250905121515.192792-5-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A new CPUID model will be added where its APIs will be designated as the "official" CPUID API. Free the cpuid_leaf() and cpuid_subleaf() function names for that model. Rename them accordingly to cpuid_read() and cpuid_read_subleaf(). Note, for kernel/cpuid.c, rename its local file operations read function from cpuid_read() to cpuid_read_f() so that it does not conflict with the new names. No functional change. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/api.h | 6 +++--- arch/x86/kernel/cpu/topology_amd.c | 2 +- arch/x86/kernel/cpu/topology_ext.c | 2 +- arch/x86/kernel/cpuid.c | 5 ++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/= api.h index 44fa82e1267c..2b9750cc8a75 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -131,12 +131,12 @@ static inline void __cpuid_read(u32 leaf, u32 subleaf= , u32 *regs) __cpuid(regs + CPUID_EAX, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUI= D_EDX); } =20 -#define cpuid_subleaf(leaf, subleaf, regs) { \ +#define cpuid_read_subleaf(leaf, subleaf, regs) { \ static_assert(sizeof(*(regs)) =3D=3D 16); \ __cpuid_read(leaf, subleaf, (u32 *)(regs)); \ } =20 -#define cpuid_leaf(leaf, regs) { \ +#define cpuid_read(leaf, regs) { \ static_assert(sizeof(*(regs)) =3D=3D 16); \ __cpuid_read(leaf, 0, (u32 *)(regs)); \ } @@ -228,7 +228,7 @@ static inline u32 cpuid_base_hypervisor(const char *sig= , u32 leaves) */ static inline void cpuid_leaf_0x2(union leaf_0x2_regs *regs) { - cpuid_leaf(0x2, regs); + cpuid_read(0x2, regs); =20 /* * All Intel CPUs must report an iteration count of 1. In case diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topol= ogy_amd.c index 42d91aa9b23a..0e48509301c8 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -80,7 +80,7 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool= has_topoext) if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) return false; =20 - cpuid_leaf(0x8000001e, &leaf); + cpuid_read(0x8000001e, &leaf); =20 /* * If leaf 0xb/0x26 is available, then the APIC ID and the domain diff --git a/arch/x86/kernel/cpu/topology_ext.c b/arch/x86/kernel/cpu/topol= ogy_ext.c index eb915c73895f..60dfaa02ffd0 100644 --- a/arch/x86/kernel/cpu/topology_ext.c +++ b/arch/x86/kernel/cpu/topology_ext.c @@ -71,7 +71,7 @@ static inline bool topo_subleaf(struct topo_scan *tscan, = u32 leaf, u32 subleaf, default: return false; } =20 - cpuid_subleaf(leaf, subleaf, &sl); + cpuid_read_subleaf(leaf, subleaf, &sl); =20 if (!sl.num_processors || sl.type =3D=3D INVALID_TYPE) return false; diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index cbd04b677fd1..b55fe9c7359a 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -59,8 +59,7 @@ static void cpuid_smp_cpuid(void *cmd_block) complete(&cmd->done); } =20 -static ssize_t cpuid_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t cpuid_read_f(struct file *file, char __user *buf, size_t co= unt, loff_t *ppos) { char __user *tmp =3D buf; struct cpuid_regs_done cmd; @@ -120,7 +119,7 @@ static int cpuid_open(struct inode *inode, struct file = *file) static const struct file_operations cpuid_fops =3D { .owner =3D THIS_MODULE, .llseek =3D no_seek_end_llseek, - .read =3D cpuid_read, + .read =3D cpuid_read_f, .open =3D cpuid_open, }; =20 --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AFF734F497 for ; Fri, 5 Sep 2025 12:15:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074539; cv=none; b=dA4yWfZnpXWXdkgy+HL6mGkRgon2g7HJS7itJll1CbDDuWzZ1Hu0FrLh5ql+vJgQSIDtk16ijyo0CWqKvURTUjRZgVCmEDf+z2mGVYWn2vUFuEB413y20wjoPGHAEmGWbRn5HJk1AnCiMaDKgMJU3MtsDOQFMArXQMRBH+GxaF8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074539; c=relaxed/simple; bh=Ha8n4UGVQ8iAPIKbr1RkFgZ4t1VhsTiE1tiK68g30+k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fU5zdfv+2XthOCRl+eSJ5Kkk/LgoSbuygf3ah1063qrHh/5knzGYJSY3go3ZfJ93GUWPxmJVWRY1CMk3x/tRIvaqQ0o6XSqh2+8hPA8RfOM6ZQhPfBTlphqvhv7p0bbfrhfcyVudnlvzmO6s+YIKIyp6TKUJ/DfL+7U2mD3I6Oo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=o4WJh9Zz; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=pEJXjxL4; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="o4WJh9Zz"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="pEJXjxL4" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074535; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6fdxarbMldtZEadRNUal90N3QLS36tZpJv/UAmJIjwA=; b=o4WJh9Zzwkdho0yCpxmI/HSGuqVH8JPfMaasA9OMhI0AjyY/sCfcw4WvT9a/FGbeKdbczk I3f/j0cW8FqXJw+VO+KTlv2Al8KQlcBG+qLikNtEURsLsINN2J+XHnW03OFT0xaDVD5C1U Tf5ivg19vhBDHU3dsAXKhU9JrKckJWi+J5AwVOs800CkAgNgKvxx/RiJhI8kuj036itmHb DdvnU8mC063uAN6Gcc09Y+OaPt0HGmC8N3r4UrdYNdYs+occwDxqAmVKURsb3Ay1v42yR6 qsc879LtOcSxGzTScwQnY9A98Sh8PxTzpOdVmgj92mV7HMZSfwvB3G7xNORZ8Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074535; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6fdxarbMldtZEadRNUal90N3QLS36tZpJv/UAmJIjwA=; b=pEJXjxL4XU6/UYkR5NB1L/Q0ENOMrBRRl+6qlqtKA7Bm6mSZTEDJlKePAxkZa9vckd4W4T 9WUaowkSNBS7N9CQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 05/35] x86/cpu/cacheinfo: Simplify cacheinfo_amd_init_llc_id() using _cpuid4_info Date: Fri, 5 Sep 2025 14:14:45 +0200 Message-ID: <20250905121515.192792-6-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: K Prateek Nayak struct _cpuid4_info has the same layout as the CPUID leaf 0x8000001d. Use the encoded definition and amd_fill_cpuid4_info(), get_cache_id() helpers instead of open coding masks and shifts to calculate the llc_id. cacheinfo_amd_init_llc_id() is only called on AMD systems that support X86_FEATURE_TOPOEXT and amd_fill_cpuid4_info() uses the information from CPUID leaf 0x8000001d on all these systems which is consistent with the current open coded implementation. While at it, avoid reading cpu_data() every time get_cache_id() is called and instead pass the APIC ID necessary to return the _cpuid4_info.id from get_cache_id(). No functional changes intended. [ bp: do what Ahmed suggests: merge into one patch, make id4 ptr const. ] Signed-off-by: K Prateek Nayak Signed-off-by: Borislav Petkov (AMD) Acked-by: Ahmed S. Darwish Link: https://lore.kernel.org/20250821051910.7351-2-kprateek.nayak@amd.com --- arch/x86/kernel/cpu/cacheinfo.c | 48 +++++++++++++++------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index adfa7e8bb865..51a95b07831f 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -289,6 +289,22 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c) return i; } =20 +/* + * The max shared threads number comes from CPUID(0x4) EAX[25-14] with inp= ut + * ECX as cache index. Then right shift apicid by the number's order to get + * cache id for this cache node. + */ +static unsigned int get_cache_id(u32 apicid, const struct _cpuid4_info *id= 4) +{ + unsigned long num_threads_sharing; + int index_msb; + + num_threads_sharing =3D 1 + id4->eax.split.num_threads_sharing; + index_msb =3D get_count_order(num_threads_sharing); + + return apicid >> index_msb; +} + /* * AMD/Hygon CPUs may have multiple LLCs if L3 caches exist. */ @@ -312,18 +328,11 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c,= u16 die_id) * Newer families: LLC ID is calculated from the number * of threads sharing the L3 cache. */ - u32 eax, ebx, ecx, edx, num_sharing_cache =3D 0; u32 llc_index =3D find_num_cache_leaves(c) - 1; + struct _cpuid4_info id4 =3D {}; =20 - cpuid_count(0x8000001d, llc_index, &eax, &ebx, &ecx, &edx); - if (eax) - num_sharing_cache =3D ((eax >> 14) & 0xfff) + 1; - - if (num_sharing_cache) { - int index_msb =3D get_count_order(num_sharing_cache); - - c->topo.llc_id =3D c->topo.apicid >> index_msb; - } + if (!amd_fill_cpuid4_info(llc_index, &id4)) + c->topo.llc_id =3D get_cache_id(c->topo.apicid, &id4); } } =20 @@ -598,27 +607,12 @@ int init_cache_level(unsigned int cpu) return 0; } =20 -/* - * The max shared threads number comes from CPUID(0x4) EAX[25-14] with inp= ut - * ECX as cache index. Then right shift apicid by the number's order to get - * cache id for this cache node. - */ -static void get_cache_id(int cpu, struct _cpuid4_info *id4) -{ - struct cpuinfo_x86 *c =3D &cpu_data(cpu); - unsigned long num_threads_sharing; - int index_msb; - - num_threads_sharing =3D 1 + id4->eax.split.num_threads_sharing; - index_msb =3D get_count_order(num_threads_sharing); - id4->id =3D c->topo.apicid >> index_msb; -} - int populate_cache_leaves(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); struct cacheinfo *ci =3D this_cpu_ci->info_list; u8 cpu_vendor =3D boot_cpu_data.x86_vendor; + u32 apicid =3D cpu_data(cpu).topo.apicid; struct amd_northbridge *nb =3D NULL; struct _cpuid4_info id4 =3D {}; int idx, ret; @@ -628,7 +622,7 @@ int populate_cache_leaves(unsigned int cpu) if (ret) return ret; =20 - get_cache_id(cpu, &id4); + id4.id =3D get_cache_id(apicid, &id4); =20 if (cpu_vendor =3D=3D X86_VENDOR_AMD || cpu_vendor =3D=3D X86_VENDOR_HYG= ON) nb =3D amd_init_l3_cache(idx); --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F031135083F for ; Fri, 5 Sep 2025 12:15:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074545; cv=none; b=XcSR7GPj2znoRCe8SWVc7yVoD3x8fR3pN7UZvNmQphF//qlVkovmF3iHwFPUQplmyBrQhZdTwIULNsP4FZwrL3GCz1yBY8GbC8l1Oy5Tb3W1rWY8M0sVH11HHIZaBTe+KPYIeUkmqbMuTA0HkV/DCutJQe/6FqDjUHprkaFywGQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074545; c=relaxed/simple; bh=oOhQBG9xl2aBxJBwS3jmV/5r98KsvhPXxdqEA1mK1cM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KxAkc2yuyvTUc6KZiy13buNBd2kfaj07Gj6T3V479+MfqupKuabe+EFjLIq5gHdqZX99isXnvaGIm2JWneso3EV9y8qNGSiXVKF7VZCiuuwWyOHKV/N43VqmjxB4YZPj+yVLIhNOgRJBNEbUqlnvrOyNSc1wXAzm1T5P26osDFY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=14uhMAOG; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=mP45w36u; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="14uhMAOG"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="mP45w36u" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074539; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NVJGugy/teKFrnKZ5pz/A1xp+ILKbeCzJreQ3rnKiec=; b=14uhMAOGQHkLu25hVtspzZoX0cIPmKm1raInZjOBJUcUOIOTqUk69yOQjHVGPdwVe4pkmO VBiNES/iMVPfVaCso1ro3bwyq03TVzszXwjcUNSvusQg+M81EfX3IGOU5hYxqZ0CDQvGwA oT31Lan++Ccwck3745lgI3i1JR7vvWpGimFhqjhzfsAmho4J7tjjsr/1TYg2c3aT6PYa+S rbpKq4TQqTddTYRrN4b9aBN1nWEiIIx1Bs+pZ4uxV20/+31RQ/JHmC3L5teQjOx4OVbL0C 6YodrKNjKzQN9ipgKZUsF+oWTtWmYCzV08zsZ2FA9d6NJOK3di3uH7/KSmrlrw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074539; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NVJGugy/teKFrnKZ5pz/A1xp+ILKbeCzJreQ3rnKiec=; b=mP45w36uNtuJkdo9GlxCl/gNcG7jWrxyLxm5q6hPB0OPj59ofmQ8Tl7/hen209+M4vd2pQ wp/wZu8TVQ4JjTAw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 06/35] x86/cpuid: Introduce Date: Fri, 5 Sep 2025 14:14:46 +0200 Message-ID: <20250905121515.192792-7-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To centralize CPUID access across the x86 subsystem, introduce . It is generated by the x86-cpuid-db project and includes detailed C99 bitfield listings for all publicly known CPUID leaves. Add the header to MAINTAINERS x86 CPUID database entry. Suggested-by: Thomas Gleixner Signed-off-by: Ahmed S. Darwish Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db/-/blob/v2.5/CHANGELOG.r= st --- MAINTAINERS | 1 + arch/x86/include/asm/cpuid/leaf_types.h | 2090 +++++++++++++++++++++++ 2 files changed, 2091 insertions(+) create mode 100644 arch/x86/include/asm/cpuid/leaf_types.h diff --git a/MAINTAINERS b/MAINTAINERS index 6dcfbd11efef..0804bb080908 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -27270,6 +27270,7 @@ R: Ahmed S. Darwish L: x86-cpuid@lists.linux.dev S: Maintained W: https://x86-cpuid.org +F: arch/x86/include/asm/cpuid/leaf_types.h F: tools/arch/x86/kcpuid/ =20 X86 ENTRY CODE diff --git a/arch/x86/include/asm/cpuid/leaf_types.h b/arch/x86/include/asm= /cpuid/leaf_types.h new file mode 100644 index 000000000000..d141138d4bc0 --- /dev/null +++ b/arch/x86/include/asm/cpuid/leaf_types.h @@ -0,0 +1,2090 @@ +/* SPDX-License-Identifier: MIT */ +/* Generator: x86-cpuid-db v2.5 */ + +/* + * Auto-generated file. + * Please submit all updates and bugfixes to https://x86-cpuid.org + */ + +#ifndef _ASM_X86_CPUID_LEAF_TYPES +#define _ASM_X86_CPUID_LEAF_TYPES + +#include + +/* + * Leaf 0x0 + * Maximum standard leaf + CPU vendor string + */ + +struct leaf_0x0_0 { + // eax + u32 max_std_leaf : 32; // Highest standard CPUID leaf + // ebx + u32 cpu_vendorid_0 : 32; // CPU vendor ID string bytes 0 - 3 + // ecx + u32 cpu_vendorid_2 : 32; // CPU vendor ID string bytes 8 - 11 + // edx + u32 cpu_vendorid_1 : 32; // CPU vendor ID string bytes 4 - 7 +}; + +/* + * Leaf 0x1 + * CPU FMS (Family/Model/Stepping) + standard feature flags + */ + +struct leaf_0x1_0 { + // eax + u32 stepping : 4, // Stepping ID + base_model : 4, // Base CPU model ID + base_family_id : 4, // Base CPU family ID + cpu_type : 2, // CPU type + : 2, // Reserved + ext_model : 4, // Extended CPU model ID + ext_family : 8, // Extended CPU family ID + : 4; // Reserved + // ebx + u32 brand_id : 8, // Brand index + clflush_size : 8, // CLFLUSH instruction cache line size + n_logical_cpu : 8, // Logical CPU count + local_apic_id : 8; // Initial local APIC physical ID + // ecx + u32 sse3 : 1, // Streaming SIMD Extensions 3 (SSE3) + pclmulqdq : 1, // PCLMULQDQ instruction support + dtes64 : 1, // 64-bit DS save area + monitor : 1, // MONITOR/MWAIT support + dscpl : 1, // CPL Qualified Debug Store + vmx : 1, // Virtual Machine Extensions + smx : 1, // Safer Mode Extensions + est : 1, // Enhanced Intel SpeedStep + tm2 : 1, // Thermal Monitor 2 + ssse3 : 1, // Supplemental SSE3 + cntxt_id : 1, // L1 Context ID + sdbg : 1, // Silicon Debug + fma : 1, // FMA extensions using YMM state + cx16 : 1, // CMPXCHG16B instruction support + xtpr_update : 1, // xTPR Update Control + pdcm : 1, // Perfmon and Debug Capability + : 1, // Reserved + pcid : 1, // Process-context identifiers + dca : 1, // Direct Cache Access + sse4_1 : 1, // SSE4.1 + sse4_2 : 1, // SSE4.2 + x2apic : 1, // X2APIC support + movbe : 1, // MOVBE instruction support + popcnt : 1, // POPCNT instruction support + tsc_deadline_timer : 1, // APIC timer one-shot operation + aes : 1, // AES instructions + xsave : 1, // XSAVE (and related instructions) support + osxsave : 1, // XSAVE (and related instructions) are enabled by OS + avx : 1, // AVX instructions support + f16c : 1, // Half-precision floating-point conversion support + rdrand : 1, // RDRAND instruction support + guest_status : 1; // System is running as guest; (para-)virtualized s= ystem + // edx + u32 fpu : 1, // Floating-Point Unit on-chip (x87) + vme : 1, // Virtual-8086 Mode Extensions + de : 1, // Debugging Extensions + pse : 1, // Page Size Extension + tsc : 1, // Time Stamp Counter + msr : 1, // Model-Specific Registers (RDMSR and WRMSR support) + pae : 1, // Physical Address Extensions + mce : 1, // Machine Check Exception + cx8 : 1, // CMPXCHG8B instruction + apic : 1, // APIC on-chip + : 1, // Reserved + sep : 1, // SYSENTER, SYSEXIT, and associated MSRs + mtrr : 1, // Memory Type Range Registers + pge : 1, // Page Global Extensions + mca : 1, // Machine Check Architecture + cmov : 1, // Conditional Move Instruction + pat : 1, // Page Attribute Table + pse36 : 1, // Page Size Extension (36-bit) + psn : 1, // Processor Serial Number + clflush : 1, // CLFLUSH instruction + : 1, // Reserved + ds : 1, // Debug Store + acpi : 1, // Thermal monitor and clock control + mmx : 1, // MMX instructions + fxsr : 1, // FXSAVE and FXRSTOR instructions + sse : 1, // SSE instructions + sse2 : 1, // SSE2 instructions + selfsnoop : 1, // Self Snoop + htt : 1, // Hyper-threading + tm : 1, // Thermal Monitor + ia64 : 1, // Legacy IA-64 (Itanium) support bit, now reserved + pbe : 1; // Pending Break Enable +}; + +/* + * Leaf 0x2 + * Intel cache and TLB information one-byte descriptors + */ + +struct leaf_0x2_0 { + // eax + u32 iteration_count : 8, // Number of times this leaf must be queried + desc1 : 8, // Descriptor #1 + desc2 : 8, // Descriptor #2 + desc3 : 7, // Descriptor #3 + eax_invalid : 1; // Descriptors 1-3 are invalid if set + // ebx + u32 desc4 : 8, // Descriptor #4 + desc5 : 8, // Descriptor #5 + desc6 : 8, // Descriptor #6 + desc7 : 7, // Descriptor #7 + ebx_invalid : 1; // Descriptors 4-7 are invalid if set + // ecx + u32 desc8 : 8, // Descriptor #8 + desc9 : 8, // Descriptor #9 + desc10 : 8, // Descriptor #10 + desc11 : 7, // Descriptor #11 + ecx_invalid : 1; // Descriptors 8-11 are invalid if set + // edx + u32 desc12 : 8, // Descriptor #12 + desc13 : 8, // Descriptor #13 + desc14 : 8, // Descriptor #14 + desc15 : 7, // Descriptor #15 + edx_invalid : 1; // Descriptors 12-15 are invalid if set +}; + +/* + * Leaf 0x4 + * Intel deterministic cache parameters + */ + +struct leaf_0x4_n { + // eax + u32 cache_type : 5, // Cache type field + cache_level : 3, // Cache level (1-based) + cache_self_init : 1, // Self-initializing cache level + fully_associative : 1, // Fully-associative cache + : 4, // Reserved + num_threads_sharing : 12, // Number logical CPUs sharing this cache + num_cores_on_die : 6; // Number of cores in the physical package + // ebx + u32 cache_linesize : 12, // System coherency line size (0-based) + cache_npartitions : 10, // Physical line partitions (0-based) + cache_nways : 10; // Ways of associativity (0-based) + // ecx + u32 cache_nsets : 31, // Cache number of sets (0-based) + : 1; // Reserved + // edx + u32 wbinvd_rll_no_guarantee : 1, // WBINVD/INVD not guaranteed for Remo= te Lower-Level caches + ll_inclusive : 1, // Cache is inclusive of Lower-Level caches + complex_indexing : 1, // Not a direct-mapped cache (complex function) + : 29; // Reserved +}; + +#define LEAF_0x4_SUBLEAF_N_FIRST 0 +#define LEAF_0x4_SUBLEAF_N_LAST 31 + +/* + * Leaf 0x5 + * MONITOR/MWAIT instructions + */ + +struct leaf_0x5_0 { + // eax + u32 min_mon_size : 16, // Smallest monitor-line size, in bytes + : 16; // Reserved + // ebx + u32 max_mon_size : 16, // Largest monitor-line size, in bytes + : 16; // Reserved + // ecx + u32 mwait_ext : 1, // MONITOR/MWAIT extensions + mwait_irq_break : 1, // Interrupts as a break event for MWAIT + : 30; // Reserved + // edx + u32 n_c0_substates : 4, // Number of C0 sub C-states + n_c1_substates : 4, // Number of C1 sub C-states + n_c2_substates : 4, // Number of C2 sub C-states + n_c3_substates : 4, // Number of C3 sub C-states + n_c4_substates : 4, // Number of C4 sub C-states + n_c5_substates : 4, // Number of C5 sub C-states + n_c6_substates : 4, // Number of C6 sub C-states + n_c7_substates : 4; // Number of C7 sub C-states +}; + +/* + * Leaf 0x6 + * Thermal and power management + */ + +struct leaf_0x6_0 { + // eax + u32 digital_temp : 1, // Digital temperature sensor + turbo_boost : 1, // Intel Turbo Boost + lapic_timer_always_on : 1, // Always-Running APIC Timer (not affected = by p-state) + : 1, // Reserved + power_limit_event : 1, // Power Limit Notification (PLN) event + ecmd : 1, // Clock modulation duty cycle extension + package_thermal : 1, // Package thermal management + hwp_base_regs : 1, // HWP (Hardware P-states) base registers + hwp_notify : 1, // HWP notification (IA32_HWP_INTERRUPT MSR) + hwp_activity_window : 1, // HWP activity window (IA32_HWP_REQUEST[bits= 41:32]) + hwp_energy_perf_pr : 1, // HWP Energy Performance Preference + hwp_package_req : 1, // HWP Package Level Request + : 1, // Reserved + hdc_base_regs : 1, // HDC base registers + turbo_boost_3_0 : 1, // Intel Turbo Boost Max 3.0 + hwp_capabilities : 1, // HWP Highest Performance change + hwp_peci_override : 1, // HWP PECI override + hwp_flexible : 1, // Flexible HWP + hwp_fast : 1, // IA32_HWP_REQUEST MSR fast access mode + hw_feedback : 1, // HW_FEEDBACK MSRs + hwp_ignore_idle : 1, // Ignoring idle logical CPU HWP request is supp= orted + : 2, // Reserved + thread_director : 1, // Intel thread director + therm_interrupt_bit25 : 1, // IA32_THERM_INTERRUPT MSR bit 25 + : 7; // Reserved + // ebx + u32 n_therm_thresholds : 4, // Digital thermometer thresholds + : 28; // Reserved + // ecx + u32 aperf_mperf : 1, // MPERF/APERF MSRs (effective frequency interfac= e) + : 2, // Reserved + energy_perf_bias : 1, // IA32_ENERGY_PERF_BIAS MSR + : 4, // Reserved + thrd_director_nclasses : 8, // Number of classes, Intel thread director + : 16; // Reserved + // edx + u32 perfcap_reporting : 1, // Performance capability reporting + encap_reporting : 1, // Energy efficiency capability reporting + : 6, // Reserved + feedback_sz : 4, // Feedback interface structure size, in 4K pages + : 4, // Reserved + this_lcpu_hwfdbk_idx : 16; // This logical CPU hardware feedback interf= ace index +}; + +/* + * Leaf 0x7 + * Extended CPU features + */ + +struct leaf_0x7_0 { + // eax + u32 leaf7_n_subleaves : 32; // Number of leaf 0x7 subleaves + // ebx + u32 fsgsbase : 1, // FSBASE/GSBASE read/write + tsc_adjust : 1, // IA32_TSC_ADJUST MSR + sgx : 1, // Intel SGX (Software Guard Extensions) + bmi1 : 1, // Bit manipulation extensions group 1 + hle : 1, // Hardware Lock Elision + avx2 : 1, // AVX2 instruction set + fdp_excptn_only : 1, // FPU Data Pointer updated only on x87 exceptio= ns + smep : 1, // Supervisor Mode Execution Protection + bmi2 : 1, // Bit manipulation extensions group 2 + erms : 1, // Enhanced REP MOVSB/STOSB + invpcid : 1, // INVPCID instruction (Invalidate Processor Context ID) + rtm : 1, // Intel restricted transactional memory + pqm : 1, // Intel RDT-CMT / AMD Platform-QoS cache monitoring + zero_fcs_fds : 1, // Deprecated FPU CS/DS (stored as zero) + mpx : 1, // Intel memory protection extensions + rdt_a : 1, // Intel RDT / AMD Platform-QoS Enforcement + avx512f : 1, // AVX-512 foundation instructions + avx512dq : 1, // AVX-512 double/quadword instructions + rdseed : 1, // RDSEED instruction + adx : 1, // ADCX/ADOX instructions + smap : 1, // Supervisor mode access prevention + avx512ifma : 1, // AVX-512 integer fused multiply add + : 1, // Reserved + clflushopt : 1, // CLFLUSHOPT instruction + clwb : 1, // CLWB instruction + intel_pt : 1, // Intel processor trace + avx512pf : 1, // AVX-512 prefetch instructions + avx512er : 1, // AVX-512 exponent/reciprocal instructions + avx512cd : 1, // AVX-512 conflict detection instructions + sha : 1, // SHA/SHA256 instructions + avx512bw : 1, // AVX-512 byte/word instructions + avx512vl : 1; // AVX-512 VL (128/256 vector length) extensions + // ecx + u32 prefetchwt1 : 1, // PREFETCHWT1 (Intel Xeon Phi only) + avx512vbmi : 1, // AVX-512 Vector byte manipulation instructions + umip : 1, // User mode instruction protection + pku : 1, // Protection keys for user-space + ospke : 1, // OS protection keys enable + waitpkg : 1, // WAITPKG instructions + avx512_vbmi2 : 1, // AVX-512 vector byte manipulation instructions gr= oup 2 + cet_ss : 1, // CET shadow stack features + gfni : 1, // Galois field new instructions + vaes : 1, // Vector AES instructions + vpclmulqdq : 1, // VPCLMULQDQ 256-bit instruction + avx512_vnni : 1, // Vector neural network instructions + avx512_bitalg : 1, // AVX-512 bitwise algorithms + tme : 1, // Intel total memory encryption + avx512_vpopcntdq : 1, // AVX-512: POPCNT for vectors of DWORD/QWORD + : 1, // Reserved + la57 : 1, // 57-bit linear addresses (five-level paging) + mawau_val_lm : 5, // BNDLDX/BNDSTX MAWAU value in 64-bit mode + rdpid : 1, // RDPID instruction + key_locker : 1, // Intel key locker + bus_lock_detect : 1, // OS bus-lock detection + cldemote : 1, // CLDEMOTE instruction + : 1, // Reserved + movdiri : 1, // MOVDIRI instruction + movdir64b : 1, // MOVDIR64B instruction + enqcmd : 1, // Enqueue stores (ENQCMD{,S}) + sgx_lc : 1, // Intel SGX launch configuration + pks : 1; // Protection keys for supervisor-mode pages + // edx + u32 : 1, // Reserved + sgx_keys : 1, // Intel SGX attestation services + avx512_4vnniw : 1, // AVX-512 neural network instructions + avx512_4fmaps : 1, // AVX-512 multiply accumulation single precision + fsrm : 1, // Fast short REP MOV + uintr : 1, // User interrupts + : 2, // Reserved + avx512_vp2intersect : 1, // VP2INTERSECT{D,Q} instructions + srdbs_ctrl : 1, // SRBDS mitigation MSR + md_clear : 1, // VERW MD_CLEAR microcode + rtm_always_abort : 1, // XBEGIN (RTM transaction) always aborts + : 1, // Reserved + tsx_force_abort : 1, // MSR TSX_FORCE_ABORT, RTM_ABORT bit + serialize : 1, // SERIALIZE instruction + hybrid_cpu : 1, // The CPU is identified as a 'hybrid part' + tsxldtrk : 1, // TSX suspend/resume load address tracking + : 1, // Reserved + pconfig : 1, // PCONFIG instruction + arch_lbr : 1, // Intel architectural LBRs + cet_ibt : 1, // CET indirect branch tracking + : 1, // Reserved + amx_bf16 : 1, // AMX-BF16: tile bfloat16 + avx512_fp16 : 1, // AVX-512 FP16 instructions + amx_tile : 1, // AMX-TILE: tile architecture + amx_int8 : 1, // AMX-INT8: tile 8-bit integer + spec_ctrl : 1, // Speculation Control (IBRS/IBPB: indirect branch res= trictions) + intel_stibp : 1, // Single thread indirect branch predictors + flush_l1d : 1, // FLUSH L1D cache: IA32_FLUSH_CMD MSR + arch_capabilities : 1, // Intel IA32_ARCH_CAPABILITIES MSR + core_capabilities : 1, // IA32_CORE_CAPABILITIES MSR + spec_ctrl_ssbd : 1; // Speculative store bypass disable +}; + +struct leaf_0x7_1 { + // eax + u32 : 4, // Reserved + avx_vnni : 1, // AVX-VNNI instructions + avx512_bf16 : 1, // AVX-512 bfloat16 instructions + lass : 1, // Linear address space separation + cmpccxadd : 1, // CMPccXADD instructions + arch_perfmon_ext : 1, // ArchPerfmonExt: leaf 0x23 + : 1, // Reserved + fzrm : 1, // Fast zero-length REP MOVSB + fsrs : 1, // Fast short REP STOSB + fsrc : 1, // Fast Short REP CMPSB/SCASB + : 4, // Reserved + fred : 1, // FRED: Flexible return and event delivery transitions + lkgs : 1, // LKGS: Load 'kernel' (userspace) GS + wrmsrns : 1, // WRMSRNS instruction (WRMSR-non-serializing) + nmi_src : 1, // NMI-source reporting with FRED event data + amx_fp16 : 1, // AMX-FP16: FP16 tile operations + hreset : 1, // HRESET (Thread director history reset) + avx_ifma : 1, // Integer fused multiply add + : 2, // Reserved + lam : 1, // Linear address masking + rd_wr_msrlist : 1, // RDMSRLIST/WRMSRLIST instructions + : 4; // Reserved + // ebx + u32 intel_ppin : 1, // Protected processor inventory number (PPIN{,_CT= L} MSRs) + : 31; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 4, // Reserved + avx_vnni_int8 : 1, // AVX-VNNI-INT8 instructions + avx_ne_convert : 1, // AVX-NE-CONVERT instructions + : 2, // Reserved + amx_complex : 1, // AMX-COMPLEX instructions (starting from Granite R= apids) + : 5, // Reserved + prefetchit_0_1 : 1, // PREFETCHIT0/1 instructions + : 3, // Reserved + cet_sss : 1, // CET supervisor shadow stacks safe to use + : 13; // Reserved +}; + +struct leaf_0x7_2 { + // eax + u32 : 32; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 intel_psfd : 1, // Intel predictive store forward disable + ipred_ctrl : 1, // MSR bits IA32_SPEC_CTRL.IPRED_DIS_{U,S} + rrsba_ctrl : 1, // MSR bits IA32_SPEC_CTRL.RRSBA_DIS_{U,S} + ddp_ctrl : 1, // MSR bit IA32_SPEC_CTRL.DDPD_U + bhi_ctrl : 1, // MSR bit IA32_SPEC_CTRL.BHI_DIS_S + mcdt_no : 1, // MCDT mitigation not needed + uclock_disable : 1, // UC-lock disable + : 25; // Reserved +}; + +/* + * Leaf 0x9 + * Intel DCA (Direct Cache Access) + */ + +struct leaf_0x9_0 { + // eax + u32 dca_enabled_in_bios : 1, // DCA is enabled in BIOS + : 31; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0xa + * Intel PMU (Performance Monitoring Unit) + */ + +struct leaf_0xa_0 { + // eax + u32 pmu_version : 8, // Performance monitoring unit version ID + pmu_n_gcounters : 8, // Number of general PMU counters per logical CPU + pmu_gcounters_nbits : 8, // Bitwidth of PMU general counters + pmu_cpuid_ebx_bits : 8; // Length of leaf 0xa EBX bit vector + // ebx + u32 no_core_cycle_evt : 1, // Core cycle event not available + no_insn_retired_evt : 1, // Instruction retired event not available + no_refcycle_evt : 1, // Reference cycles event not available + no_llc_ref_evt : 1, // LLC-reference event not available + no_llc_miss_evt : 1, // LLC-misses event not available + no_br_insn_ret_evt : 1, // Branch instruction retired event not availa= ble + no_br_mispredict_evt : 1, // Branch mispredict retired event not avail= able + no_td_slots_evt : 1, // Topdown slots event not available + : 24; // Reserved + // ecx + u32 pmu_fcounters_bitmap : 32; // Fixed-function PMU counters support bi= tmap + // edx + u32 pmu_n_fcounters : 5, // Number of fixed PMU counters + pmu_fcounters_nbits : 8, // Bitwidth of PMU fixed counters + : 2, // Reserved + anythread_depr : 1, // AnyThread deprecation + : 16; // Reserved +}; + +/* + * Leaf 0xb + * CPU extended topology v1 + */ + +struct leaf_0xb_n { + // eax + u32 x2apic_id_shift : 5, // Bit width of this level (previous levels i= nclusive) + : 27; // Reserved + // ebx + u32 domain_lcpus_count : 16, // Logical CPUs count across all instances = of this domain + : 16; // Reserved + // ecx + u32 domain_nr : 8, // This domain level (subleaf ID) + domain_type : 8, // This domain type + : 16; // Reserved + // edx + u32 x2apic_id : 32; // x2APIC ID of current logical CPU +}; + +#define LEAF_0xb_SUBLEAF_N_FIRST 0 +#define LEAF_0xb_SUBLEAF_N_LAST 1 + +/* + * Leaf 0xd + * CPU extended state + */ + +struct leaf_0xd_0 { + // eax + u32 xcr0_x87 : 1, // XCR0.X87 + xcr0_sse : 1, // XCR0.SSE + xcr0_avx : 1, // XCR0.AVX + xcr0_mpx_bndregs : 1, // XCR0.BNDREGS: MPX BND0-BND3 registers + xcr0_mpx_bndcsr : 1, // XCR0.BNDCSR: MPX BNDCFGU/BNDSTATUS registers + xcr0_avx512_opmask : 1, // XCR0.OPMASK: AVX-512 k0-k7 registers + xcr0_avx512_zmm_hi256 : 1, // XCR0.ZMM_Hi256: AVX-512 ZMM0->ZMM7/15 re= gisters + xcr0_avx512_hi16_zmm : 1, // XCR0.HI16_ZMM: AVX-512 ZMM16->ZMM31 regis= ters + : 1, // Reserved + xcr0_pkru : 1, // XCR0.PKRU: XSAVE PKRU registers + : 1, // Reserved + xcr0_cet_u : 1, // XCR0.CET_U: CET user state + xcr0_cet_s : 1, // XCR0.CET_S: CET supervisor state + : 4, // Reserved + xcr0_tileconfig : 1, // XCR0.TILECONFIG: AMX can manage TILECONFIG + xcr0_tiledata : 1, // XCR0.TILEDATA: AMX can manage TILEDATA + : 13; // Reserved + // ebx + u32 xsave_sz_xcr0 : 32; // XSAVE/XRSTOR area byte size, for XCR0 enable= d features + // ecx + u32 xsave_sz_max : 32; // XSAVE/XRSTOR area max byte size, all CPU feat= ures + // edx + u32 : 30, // Reserved + xcr0_lwp : 1, // AMD XCR0.LWP: Light-weight Profiling + : 1; // Reserved +}; + +struct leaf_0xd_1 { + // eax + u32 xsaveopt : 1, // XSAVEOPT instruction + xsavec : 1, // XSAVEC instruction + xgetbv1 : 1, // XGETBV instruction with ECX =3D 1 + xsaves : 1, // XSAVES/XRSTORS instructions (and XSS MSR) + xfd : 1, // Extended feature disable + : 27; // Reserved + // ebx + u32 xsave_sz_xcr0_xss : 32; // XSAVES/XSAVEC area byte size, for XCR0|XS= S enabled features + // ecx + u32 : 8, // Reserved + xss_pt : 1, // PT state + : 1, // Reserved + xss_pasid : 1, // PASID state + xss_cet_u : 1, // CET user state + xss_cet_p : 1, // CET supervisor state + xss_hdc : 1, // HDC state + xss_uintr : 1, // UINTR state + xss_lbr : 1, // LBR state + xss_hwp : 1, // HWP state + : 15; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0xd_n { + // eax + u32 xsave_sz : 32; // Subleaf-N feature save area size, in bytes + // ebx + u32 xsave_offset : 32; // Subleaf-N feature save area offset, in bytes + // ecx + u32 is_xss_bit : 1, // Subleaf N describes an XSS bit (otherwise XCR0) + compacted_xsave_64byte_aligned : 1, // When compacted, subleaf-N XSAVE = area is 64-byte aligned + : 30; // Reserved + // edx + u32 : 32; // Reserved +}; + +#define LEAF_0xd_SUBLEAF_N_FIRST 2 +#define LEAF_0xd_SUBLEAF_N_LAST 63 + +/* + * Leaf 0xf + * Intel RDT / AMD PQoS resource monitoring + */ + +struct leaf_0xf_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 core_rmid_max : 32; // RMID max within this core (0-based) + // ecx + u32 : 32; // Reserved + // edx + u32 : 1, // Reserved + llc_qos_mon : 1, // LLC QoS-monitoring + : 30; // Reserved +}; + +struct leaf_0xf_1 { + // eax + u32 l3c_qm_bitwidth : 8, // L3 QoS-monitoring counter bitwidth (24-bas= ed) + l3c_qm_overflow_bit : 1, // QM_CTR MSR bit 61 is an overflow bit + : 23; // Reserved + // ebx + u32 l3c_qm_conver_factor : 32; // QM_CTR MSR conversion factor to bytes + // ecx + u32 l3c_qm_rmid_max : 32; // L3 QoS-monitoring max RMID + // edx + u32 l3c_qm_occupancy : 1, // L3 QoS occupancy monitoring + l3c_qm_mbm_total : 1, // L3 QoS total bandwidth monitoring + l3c_qm_mbm_local : 1, // L3 QoS local bandwidth monitoring + : 29; // Reserved +}; + +/* + * Leaf 0x10 + * Intel RDT / AMD PQoS allocation + */ + +struct leaf_0x10_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 : 1, // Reserved + cat_l3 : 1, // L3 Cache Allocation Technology + cat_l2 : 1, // L2 Cache Allocation Technology + mba : 1, // Memory Bandwidth Allocation + : 28; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x10_n { + // eax + u32 cat_cbm_len : 5, // L3/L2_CAT capacity bitmask length, minus-one n= otation + : 27; // Reserved + // ebx + u32 cat_units_bitmap : 32; // L3/L2_CAT allocation units bitmap + // ecx + u32 : 1, // Reserved + l3_cat_cos_infreq_updates : 1, // L3_CAT COS updates should be infreque= nt + cat_cdp_supported : 1, // L3/L2_CAT Code and Data Prioritization + cat_sparse_1s : 1, // L3/L2_CAT non-contiguous 1s value + : 28; // Reserved + // edx + u32 cat_cos_max : 16, // L3/L2_CAT max Class of Service + : 16; // Reserved +}; + +#define LEAF_0x10_SUBLEAF_N_FIRST 1 +#define LEAF_0x10_SUBLEAF_N_LAST 2 + +struct leaf_0x10_3 { + // eax + u32 mba_max_delay : 12, // Max MBA throttling value; minus-one notation + : 20; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 mba_per_thread : 1, // Per-thread MBA controls + : 1, // Reserved + mba_delay_linear : 1, // Delay values are linear + : 29; // Reserved + // edx + u32 mba_cos_max : 16, // MBA max Class of Service + : 16; // Reserved +}; + +/* + * Leaf 0x12 + * Intel SGX (Software Guard Extensions) + */ + +struct leaf_0x12_0 { + // eax + u32 sgx1 : 1, // SGX1 leaf functions + sgx2 : 1, // SGX2 leaf functions + : 3, // Reserved + enclv_leaves : 1, // ENCLV leaves + encls_leaves : 1, // ENCLS leaves + enclu_everifyreport2 : 1, // ENCLU leaf EVERIFYREPORT2 + : 2, // Reserved + encls_eupdatesvn : 1, // ENCLS leaf EUPDATESVN + enclu_edeccssa : 1, // ENCLU leaf EDECCSSA + : 20; // Reserved + // ebx + u32 miscselect_exinfo : 1, // SSA.MISC frame: Enclave #PF and #GP repor= ting + miscselect_cpinfo : 1, // SSA.MISC frame: Enclave #CP reporting + : 30; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 max_enclave_sz_not64 : 8, // Maximum enclave size in non-64-bit mod= e (log2) + max_enclave_sz_64 : 8, // Maximum enclave size in 64-bit mode (log2) + : 16; // Reserved +}; + +struct leaf_0x12_1 { + // eax + u32 secs_attr_init : 1, // Enclave initialized by EINIT + secs_attr_debug : 1, // Enclave permits debugger read/write + secs_attr_mode64bit : 1, // Enclave runs in 64-bit mode + : 1, // Reserved + secs_attr_provisionkey : 1, // Provisioning key + secs_attr_einittoken_key : 1, // EINIT token key + secs_attr_cet : 1, // CET attributes + secs_attr_kss : 1, // Key Separation and Sharing + : 2, // Reserved + secs_attr_aexnotify : 1, // Enclave threads: AEX notifications + : 21; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 xfrm_x87 : 1, // Enclave XFRM.X87 + xfrm_sse : 1, // Enclave XFRM.SEE + xfrm_avx : 1, // Enclave XFRM.AVX + xfrm_mpx_bndregs : 1, // Enclave XFRM.BNDREGS (MPX BND0-BND3 registers) + xfrm_mpx_bndcsr : 1, // Enclave XFRM.BNDCSR (MPX BNDCFGU/BNDSTATUS re= gisters) + xfrm_avx512_opmask : 1, // Enclave XFRM.OPMASK (AVX-512 k0-k7 register= s) + xfrm_avx512_zmm_hi256 : 1, // Enclave XFRM.ZMM_Hi256 (AVX-512 ZMM0->ZM= M7/15 registers) + xfrm_avx512_hi16_zmm : 1, // Enclave XFRM.HI16_ZMM (AVX-512 ZMM16->ZMM= 31 registers) + : 1, // Reserved + xfrm_pkru : 1, // Enclave XFRM.PKRU (XSAVE PKRU registers) + : 7, // Reserved + xfrm_tileconfig : 1, // Enclave XFRM.TILECONFIG (AMX can manage TILEC= ONFIG) + xfrm_tiledata : 1, // Enclave XFRM.TILEDATA (AMX can manage TILEDATA) + : 13; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x12_n { + // eax + u32 subleaf_type : 4, // Subleaf type + : 8, // Reserved + epc_sec_base_addr_0 : 20; // EPC section base address, bits[12:31] + // ebx + u32 epc_sec_base_addr_1 : 20, // EPC section base address, bits[32:51] + : 12; // Reserved + // ecx + u32 epc_sec_type : 4, // EPC section type / property encoding + : 8, // Reserved + epc_sec_size_0 : 20; // EPC section size, bits[12:31] + // edx + u32 epc_sec_size_1 : 20, // EPC section size, bits[32:51] + : 12; // Reserved +}; + +#define LEAF_0x12_SUBLEAF_N_FIRST 2 +#define LEAF_0x12_SUBLEAF_N_LAST 31 + +/* + * Leaf 0x14 + * Intel Processor Trace + */ + +struct leaf_0x14_0 { + // eax + u32 pt_max_subleaf : 32; // Maximum leaf 0x14 subleaf + // ebx + u32 cr3_filtering : 1, // IA32_RTIT_CR3_MATCH is accessible + psb_cyc : 1, // Configurable PSB and cycle-accurate mode + ip_filtering : 1, // IP/TraceStop filtering; Warm-reset PT MSRs prese= rvation + mtc_timing : 1, // MTC timing packet; COFI-based packets suppression + ptwrite : 1, // PTWRITE instruction + power_event_trace : 1, // Power Event Trace + psb_pmi_preserve : 1, // PSB and PMI preservation + event_trace : 1, // Event Trace packet generation + tnt_disable : 1, // TNT packet generation disable + : 23; // Reserved + // ecx + u32 topa_output : 1, // ToPA output scheme + topa_multiple_entries : 1, // ToPA tables can hold multiple entries + single_range_output : 1, // Single-range output + trance_transport_output : 1, // Trace Transport subsystem output + : 27, // Reserved + ip_payloads_lip : 1; // IP payloads have LIP values (CS base included) + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x14_1 { + // eax + u32 num_address_ranges : 3, // Number of configurable Address Ranges + : 13, // Reserved + mtc_periods_bmp : 16; // MTC period encodings bitmap + // ebx + u32 cycle_thresholds_bmp : 16, // Cycle Threshold encodings bitmap + psb_periods_bmp : 16; // Configurable PSB frequency encodings bitmap + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x15 + * Intel TSC (Time Stamp Counter) + */ + +struct leaf_0x15_0 { + // eax + u32 tsc_denominator : 32; // Denominator of the TSC/'core crystal clock= ' ratio + // ebx + u32 tsc_numerator : 32; // Numerator of the TSC/'core crystal clock' ra= tio + // ecx + u32 cpu_crystal_hz : 32; // Core crystal clock nominal frequency, in Hz + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x16 + * Intel processor frequency + */ + +struct leaf_0x16_0 { + // eax + u32 cpu_base_mhz : 16, // Processor base frequency, in MHz + : 16; // Reserved + // ebx + u32 cpu_max_mhz : 16, // Processor max frequency, in MHz + : 16; // Reserved + // ecx + u32 bus_mhz : 16, // Bus reference frequency, in MHz + : 16; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x17 + * Intel SoC vendor attributes + */ + +struct leaf_0x17_0 { + // eax + u32 soc_max_subleaf : 32; // Maximum leaf 0x17 subleaf + // ebx + u32 soc_vendor_id : 16, // SoC vendor ID + is_vendor_scheme : 1, // Assigned by industry enumeration scheme (not = Intel) + : 15; // Reserved + // ecx + u32 soc_proj_id : 32; // SoC project ID, assigned by vendor + // edx + u32 soc_stepping_id : 32; // Soc project stepping ID, assigned by vendor +}; + +struct leaf_0x17_n { + // eax + u32 vendor_brand_a : 32; // Vendor Brand ID string, bytes subleaf_nr * = (0 -> 3) + // ebx + u32 vendor_brand_b : 32; // Vendor Brand ID string, bytes subleaf_nr * = (4 -> 7) + // ecx + u32 vendor_brand_c : 32; // Vendor Brand ID string, bytes subleaf_nr * = (8 -> 11) + // edx + u32 vendor_brand_d : 32; // Vendor Brand ID string, bytes subleaf_nr * = (12 -> 15) +}; + +#define LEAF_0x17_SUBLEAF_N_FIRST 1 +#define LEAF_0x17_SUBLEAF_N_LAST 3 + +/* + * Leaf 0x18 + * Intel deterministic address translation (TLB) parameters + */ + +struct leaf_0x18_n { + // eax + u32 tlb_max_subleaf : 32; // Maximum leaf 0x18 subleaf + // ebx + u32 tlb_4k_page : 1, // TLB supports 4KB-page entries + tlb_2m_page : 1, // TLB supports 2MB-page entries + tlb_4m_page : 1, // TLB supports 4MB-page entries + tlb_1g_page : 1, // TLB supports 1GB-page entries + : 4, // Reserved + hard_partitioning : 3, // Partitioning between logical CPUs + : 5, // Reserved + n_way_associative : 16; // Ways of associativity + // ecx + u32 n_sets : 32; // Number of sets + // edx + u32 tlb_type : 5, // Translation cache type (TLB type) + tlb_cache_level : 3, // Translation cache level (1-based) + is_fully_associative : 1, // Fully-associative + : 5, // Reserved + tlb_max_addressible_ids : 12, // Max number of addressable IDs - 1 + : 6; // Reserved +}; + +#define LEAF_0x18_SUBLEAF_N_FIRST 0 +#define LEAF_0x18_SUBLEAF_N_LAST 31 + +/* + * Leaf 0x19 + * Intel key locker + */ + +struct leaf_0x19_0 { + // eax + u32 kl_cpl0_only : 1, // CPL0-only key Locker restriction + kl_no_encrypt : 1, // No-encrypt key locker restriction + kl_no_decrypt : 1, // No-decrypt key locker restriction + : 29; // Reserved + // ebx + u32 aes_keylocker : 1, // AES key locker instructions + : 1, // Reserved + aes_keylocker_wide : 1, // AES wide key locker instructions + : 1, // Reserved + kl_msr_iwkey : 1, // Key locker MSRs and IWKEY backups + : 27; // Reserved + // ecx + u32 loadiwkey_no_backup : 1, // LOADIWKEY NoBackup parameter + iwkey_rand : 1, // IWKEY randomization + : 30; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x1a + * Intel hybrid CPUs identification (e.g. Atom, Core) + */ + +struct leaf_0x1a_0 { + // eax + u32 core_native_model : 24, // This core's native model ID + core_type : 8; // This core's type + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x1b + * Intel PCONFIG (Platform configuration) + */ + +struct leaf_0x1b_n { + // eax + u32 pconfig_subleaf_type : 12, // CPUID 0x1b subleaf type + : 20; // Reserved + // ebx + u32 pconfig_target_id_x : 32; // A supported PCONFIG target ID + // ecx + u32 pconfig_target_id_y : 32; // A supported PCONFIG target ID + // edx + u32 pconfig_target_id_z : 32; // A supported PCONFIG target ID +}; + +#define LEAF_0x1b_SUBLEAF_N_FIRST 0 +#define LEAF_0x1b_SUBLEAF_N_LAST 31 + +/* + * Leaf 0x1c + * Intel LBR (Last Branch Record) + */ + +struct leaf_0x1c_0 { + // eax + u32 lbr_depth_8 : 1, // Max stack depth =3D 8 + lbr_depth_16 : 1, // Max stack depth =3D 16 + lbr_depth_24 : 1, // Max stack depth =3D 24 + lbr_depth_32 : 1, // Max stack depth =3D 32 + lbr_depth_40 : 1, // Max stack depth =3D 40 + lbr_depth_48 : 1, // Max stack depth =3D 48 + lbr_depth_56 : 1, // Max stack depth =3D 56 + lbr_depth_64 : 1, // Max stack depth =3D 64 + : 22, // Reserved + lbr_deep_c_reset : 1, // LBRs maybe cleared on MWAIT C-state > C1 + lbr_ip_is_lip : 1; // LBR IP contain Last IP (otherwise effective IP) + // ebx + u32 lbr_cpl : 1, // CPL filtering + lbr_branch_filter : 1, // Branch filtering + lbr_call_stack : 1, // Call-stack mode + : 29; // Reserved + // ecx + u32 lbr_mispredict : 1, // Branch misprediction bit + lbr_timed_lbr : 1, // Timed LBRs (CPU cycles since last LBR entry) + lbr_branch_type : 1, // Branch type field + : 13, // Reserved + lbr_events_gpc_bmp : 4, // PMU-events logging support + : 12; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x1d + * Intel AMX (Advanced Matrix Extensions) tile information + */ + +struct leaf_0x1d_0 { + // eax + u32 amx_max_palette : 32; // Highest palette ID / subleaf ID + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x1d_1 { + // eax + u32 amx_palette_size : 16, // AMX palette total tiles size, in bytes + amx_tile_size : 16; // AMX single tile's size, in bytes + // ebx + u32 amx_tile_row_size : 16, // AMX tile single row's size, in bytes + amx_palette_nr_tiles : 16; // AMX palette number of tiles + // ecx + u32 amx_tile_nr_rows : 16, // AMX tile max number of rows + : 16; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x1e + * Intel TMUL (Tile-matrix Multiply) + */ + +struct leaf_0x1e_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 tmul_maxk : 8, // TMUL unit maximum height, K (rows or columns) + tmul_maxn : 16, // TMUL unit maximum SIMD dimension, N (column bytes) + : 8; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x1f + * Intel extended topology v2 + */ + +struct leaf_0x1f_n { + // eax + u32 x2apic_id_shift : 5, // Bit width of this level (previous levels i= nclusive) + : 27; // Reserved + // ebx + u32 domain_lcpus_count : 16, // Logical CPUs count across all instances = of this domain + : 16; // Reserved + // ecx + u32 domain_level : 8, // This domain level (subleaf ID) + domain_type : 8, // This domain type + : 16; // Reserved + // edx + u32 x2apic_id : 32; // x2APIC ID of current logical CPU +}; + +#define LEAF_0x1f_SUBLEAF_N_FIRST 0 +#define LEAF_0x1f_SUBLEAF_N_LAST 5 + +/* + * Leaf 0x20 + * Intel HRESET (History Reset) + */ + +struct leaf_0x20_0 { + // eax + u32 hreset_nr_subleaves : 32; // CPUID 0x20 max subleaf + 1 + // ebx + u32 hreset_thread_director : 1, // Intel thread director HRESET + : 31; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x21 + * Intel TD (Trust Domain) + */ + +struct leaf_0x21_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 tdx_vendorid_0 : 32; // TDX vendor ID string bytes 0 - 3 + // ecx + u32 tdx_vendorid_2 : 32; // CPU vendor ID string bytes 8 - 11 + // edx + u32 tdx_vendorid_1 : 32; // CPU vendor ID string bytes 4 - 7 +}; + +/* + * Leaf 0x23 + * Intel Architectural Performance Monitoring Extended (ArchPerfmonExt) + */ + +struct leaf_0x23_0 { + // eax + u32 : 1, // Reserved + subleaf_1_counters : 1, // Subleaf 1, PMU counters bitmaps, is valid + : 1, // Reserved + subleaf_3_events : 1, // Subleaf 3, PMU events bitmaps, is valid + : 28; // Reserved + // ebx + u32 unitmask2 : 1, // IA32_PERFEVTSELx MSRs UnitMask2 + zbit : 1, // IA32_PERFEVTSELx MSRs Z-bit + : 30; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x23_1 { + // eax + u32 pmu_gp_counters_bitmap : 32; // General-purpose PMU counters bitmap + // ebx + u32 pmu_f_counters_bitmap : 32; // Fixed PMU counters bitmap + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x23_3 { + // eax + u32 core_cycles_evt : 1, // Core cycles event + insn_retired_evt : 1, // Instructions retired event + ref_cycles_evt : 1, // Reference cycles event + llc_refs_evt : 1, // Last-level cache references event + llc_misses_evt : 1, // Last-level cache misses event + br_insn_ret_evt : 1, // Branch instruction retired event + br_mispr_evt : 1, // Branch mispredict retired event + td_slots_evt : 1, // Topdown slots event + td_backend_bound_evt : 1, // Topdown backend bound event + td_bad_spec_evt : 1, // Topdown bad speculation event + td_frontend_bound_evt : 1, // Topdown frontend bound event + td_retiring_evt : 1, // Topdown retiring event + : 20; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x40000000 + * Maximum hypervisor leaf + hypervisor vendor string + */ + +struct leaf_0x40000000_0 { + // eax + u32 max_hyp_leaf : 32; // Maximum hypervisor leaf + // ebx + u32 hypervisor_id_0 : 32; // Hypervisor ID string bytes 0 - 3 + // ecx + u32 hypervisor_id_1 : 32; // Hypervisor ID string bytes 4 - 7 + // edx + u32 hypervisor_id_2 : 32; // Hypervisor ID string bytes 8 - 11 +}; + +/* + * Leaf 0x80000000 + * Maximum extended leaf + CPU vendor string + */ + +struct leaf_0x80000000_0 { + // eax + u32 max_ext_leaf : 32; // Maximum extended CPUID leaf + // ebx + u32 cpu_vendorid_0 : 32; // Vendor ID string bytes 0 - 3 + // ecx + u32 cpu_vendorid_2 : 32; // Vendor ID string bytes 8 - 11 + // edx + u32 cpu_vendorid_1 : 32; // Vendor ID string bytes 4 - 7 +}; + +/* + * Leaf 0x80000001 + * Extended CPU features + */ + +struct leaf_0x80000001_0 { + // eax + u32 e_stepping_id : 4, // Stepping ID + e_base_model : 4, // Base processor model + e_base_family : 4, // Base processor family + e_base_type : 2, // Base processor type (Transmeta) + : 2, // Reserved + e_ext_model : 4, // Extended processor model + e_ext_family : 8, // Extended processor family + : 4; // Reserved + // ebx + u32 brand_id : 16, // Brand ID + : 12, // Reserved + pkg_type : 4; // Package type + // ecx + u32 lahf_lm : 1, // LAHF and SAHF in 64-bit mode + cmp_legacy : 1, // Multi-processing legacy mode (No HT) + svm : 1, // Secure Virtual Machine + extapic : 1, // Extended APIC space + cr8_legacy : 1, // LOCK MOV CR0 means MOV CR8 + lzcnt_abm : 1, // LZCNT advanced bit manipulation + sse4a : 1, // SSE4A support + misaligned_sse : 1, // Misaligned SSE mode + _3dnow_prefetch : 1, // 3DNow PREFETCH/PREFETCHW support + osvw : 1, // OS visible workaround + ibs : 1, // Instruction based sampling + xop : 1, // XOP: extended operation (AVX instructions) + skinit : 1, // SKINIT/STGI support + wdt : 1, // Watchdog timer support + : 1, // Reserved + lwp : 1, // Lightweight profiling + fma4 : 1, // 4-operand FMA instruction + tce : 1, // Translation cache extension + : 1, // Reserved + nodeid_msr : 1, // NodeId MSR (0xc001100c) + : 1, // Reserved + tbm : 1, // Trailing bit manipulations + topoext : 1, // Topology Extensions (leaf 0x8000001d) + perfctr_core : 1, // Core performance counter extensions + perfctr_nb : 1, // NB/DF performance counter extensions + : 1, // Reserved + data_bp_ext : 1, // Data access breakpoint extension + perf_tsc : 1, // Performance time-stamp counter + perfctr_llc : 1, // LLC (L3) performance counter extensions + mwaitx : 1, // MWAITX/MONITORX support + addr_mask_ext : 1, // Breakpoint address mask extension (to bit 31) + : 1; // Reserved + // edx + u32 e_fpu : 1, // Floating-Point Unit on-chip (x87) + e_vme : 1, // Virtual-8086 Mode Extensions + e_de : 1, // Debugging Extensions + e_pse : 1, // Page Size Extension + e_tsc : 1, // Time Stamp Counter + e_msr : 1, // Model-Specific Registers (RDMSR and WRMSR support) + pae : 1, // Physical Address Extensions + mce : 1, // Machine Check Exception + cx8 : 1, // CMPXCHG8B instruction + apic : 1, // APIC on-chip + : 1, // Reserved + syscall : 1, // SYSCALL and SYSRET instructions + mtrr : 1, // Memory Type Range Registers + pge : 1, // Page Global Extensions + mca : 1, // Machine Check Architecture + cmov : 1, // Conditional Move Instruction + pat : 1, // Page Attribute Table + pse36 : 1, // Page Size Extension (36-bit) + : 1, // Reserved + obsolete_mp_bit : 1, // Out-of-spec AMD Multiprocessing bit + nx : 1, // No-execute page protection + : 1, // Reserved + mmxext : 1, // AMD MMX extensions + e_mmx : 1, // MMX instructions + e_fxsr : 1, // FXSAVE and FXRSTOR instructions + fxsr_opt : 1, // FXSAVE and FXRSTOR optimizations + page1gb : 1, // 1-GB large page support + rdtscp : 1, // RDTSCP instruction + : 1, // Reserved + lm : 1, // Long mode (x86-64, 64-bit support) + _3dnowext : 1, // AMD 3DNow extensions + _3dnow : 1; // 3DNow instructions +}; + +/* + * Leaf 0x80000002 + * CPU brand ID string, bytes 0 - 15 + */ + +struct leaf_0x80000002_0 { + // eax + u32 cpu_brandid_0 : 32; // CPU brand ID string, bytes 0 - 3 + // ebx + u32 cpu_brandid_1 : 32; // CPU brand ID string, bytes 4 - 7 + // ecx + u32 cpu_brandid_2 : 32; // CPU brand ID string, bytes 8 - 11 + // edx + u32 cpu_brandid_3 : 32; // CPU brand ID string, bytes 12 - 15 +}; + +/* + * Leaf 0x80000003 + * CPU brand ID string, bytes 16 - 31 + */ + +struct leaf_0x80000003_0 { + // eax + u32 cpu_brandid_4 : 32; // CPU brand ID string bytes, 16 - 19 + // ebx + u32 cpu_brandid_5 : 32; // CPU brand ID string bytes, 20 - 23 + // ecx + u32 cpu_brandid_6 : 32; // CPU brand ID string bytes, 24 - 27 + // edx + u32 cpu_brandid_7 : 32; // CPU brand ID string bytes, 28 - 31 +}; + +/* + * Leaf 0x80000004 + * CPU brand ID string, bytes 32 - 47 + */ + +struct leaf_0x80000004_0 { + // eax + u32 cpu_brandid_8 : 32; // CPU brand ID string, bytes 32 - 35 + // ebx + u32 cpu_brandid_9 : 32; // CPU brand ID string, bytes 36 - 39 + // ecx + u32 cpu_brandid_10 : 32; // CPU brand ID string, bytes 40 - 43 + // edx + u32 cpu_brandid_11 : 32; // CPU brand ID string, bytes 44 - 47 +}; + +/* + * Leaf 0x80000005 + * AMD/Transmeta L1 cache and TLB + */ + +struct leaf_0x80000005_0 { + // eax + u32 l1_itlb_2m_4m_nentries : 8, // L1 ITLB #entries, 2M and 4M pages + l1_itlb_2m_4m_assoc : 8, // L1 ITLB associativity, 2M and 4M pages + l1_dtlb_2m_4m_nentries : 8, // L1 DTLB #entries, 2M and 4M pages + l1_dtlb_2m_4m_assoc : 8; // L1 DTLB associativity, 2M and 4M pages + // ebx + u32 l1_itlb_4k_nentries : 8, // L1 ITLB #entries, 4K pages + l1_itlb_4k_assoc : 8, // L1 ITLB associativity, 4K pages + l1_dtlb_4k_nentries : 8, // L1 DTLB #entries, 4K pages + l1_dtlb_4k_assoc : 8; // L1 DTLB associativity, 4K pages + // ecx + u32 l1_dcache_line_size : 8, // L1 dcache line size, in bytes + l1_dcache_nlines : 8, // L1 dcache lines per tag + l1_dcache_assoc : 8, // L1 dcache associativity + l1_dcache_size_kb : 8; // L1 dcache size, in KB + // edx + u32 l1_icache_line_size : 8, // L1 icache line size, in bytes + l1_icache_nlines : 8, // L1 icache lines per tag + l1_icache_assoc : 8, // L1 icache associativity + l1_icache_size_kb : 8; // L1 icache size, in KB +}; + +/* + * Leaf 0x80000006 + * (Mostly AMD) L2/L3 cache and TLB + */ + +struct leaf_0x80000006_0 { + // eax + u32 l2_itlb_2m_4m_nentries : 12, // L2 iTLB #entries, 2M and 4M pages + l2_itlb_2m_4m_assoc : 4, // L2 iTLB associativity, 2M and 4M pages + l2_dtlb_2m_4m_nentries : 12, // L2 dTLB #entries, 2M and 4M pages + l2_dtlb_2m_4m_assoc : 4; // L2 dTLB associativity, 2M and 4M pages + // ebx + u32 l2_itlb_4k_nentries : 12, // L2 iTLB #entries, 4K pages + l2_itlb_4k_assoc : 4, // L2 iTLB associativity, 4K pages + l2_dtlb_4k_nentries : 12, // L2 dTLB #entries, 4K pages + l2_dtlb_4k_assoc : 4; // L2 dTLB associativity, 4K pages + // ecx + u32 l2_line_size : 8, // L2 cache line size, in bytes + l2_nlines : 4, // L2 cache number of lines per tag + l2_assoc : 4, // L2 cache associativity + l2_size_kb : 16; // L2 cache size, in KB + // edx + u32 l3_line_size : 8, // L3 cache line size, in bytes + l3_nlines : 4, // L3 cache number of lines per tag + l3_assoc : 4, // L3 cache associativity + : 2, // Reserved + l3_size_range : 14; // L3 cache size range +}; + +/* + * Leaf 0x80000007 + * CPU power management (mostly AMD) and AMD RAS + */ + +struct leaf_0x80000007_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 mca_overflow_recovery : 1, // MCA overflow conditions not fatal + succor : 1, // Software containment of uncorrectable errors + hw_assert : 1, // Hardware assert MSRs + scalable_mca : 1, // Scalable MCA (MCAX MSRs) + : 28; // Reserved + // ecx + u32 cpu_pwr_sample_ratio : 32; // CPU power sample time ratio + // edx + u32 digital_temp : 1, // Digital temperature sensor + powernow_freq_id : 1, // PowerNOW! frequency scaling + powernow_volt_id : 1, // PowerNOW! voltage scaling + thermal_trip : 1, // THERMTRIP (Thermal Trip) + hw_thermal_control : 1, // Hardware thermal control + sw_thermal_control : 1, // Software thermal control + _100mhz_steps : 1, // 100 MHz multiplier control + hw_pstate : 1, // Hardware P-state control + constant_tsc : 1, // TSC ticks at constant rate across all P and C st= ates + core_perf_boost : 1, // Core performance boost + eff_freq_ro : 1, // Read-only effective frequency interface + proc_feedback : 1, // Processor feedback interface (deprecated) + proc_power_reporting : 1, // Processor power reporting interface + connected_standby : 1, // CPU Connected Standby support + rapl_interface : 1, // Runtime Average Power Limit interface + : 17; // Reserved +}; + +/* + * Leaf 0x80000008 + * CPU capacity parameters and extended feature flags (mostly AMD) + */ + +struct leaf_0x80000008_0 { + // eax + u32 phys_addr_bits : 8, // Max physical address bits + virt_addr_bits : 8, // Max virtual address bits + guest_phys_addr_bits : 8, // Max nested-paging guest physical address = bits + : 8; // Reserved + // ebx + u32 clzero : 1, // CLZERO instruction + insn_retired_perf : 1, // Instruction retired counter MSR + xsave_err_ptr : 1, // XSAVE/XRSTOR always saves/restores FPU error po= inters + invlpgb : 1, // INVLPGB broadcasts a TLB invalidate + rdpru : 1, // RDPRU (Read Processor Register at User level) + : 1, // Reserved + mba : 1, // Memory Bandwidth Allocation (AMD bit) + : 1, // Reserved + mcommit : 1, // MCOMMIT instruction + wbnoinvd : 1, // WBNOINVD instruction + : 2, // Reserved + ibpb : 1, // Indirect Branch Prediction Barrier + wbinvd_int : 1, // Interruptible WBINVD/WBNOINVD + ibrs : 1, // Indirect Branch Restricted Speculation + stibp : 1, // Single Thread Indirect Branch Prediction mode + ibrs_always_on : 1, // IBRS always-on preferred + stibp_always_on : 1, // STIBP always-on preferred + ibrs_fast : 1, // IBRS is preferred over software solution + ibrs_same_mode : 1, // IBRS provides same mode protection + no_efer_lmsle : 1, // Long-Mode Segment Limit Enable unsupported + tlb_flush_nested : 1, // INVLPGB RAX[5] bit can be set + : 1, // Reserved + amd_ppin : 1, // Protected Processor Inventory Number + amd_ssbd : 1, // Speculative Store Bypass Disable + virt_ssbd : 1, // virtualized SSBD (Speculative Store Bypass Disable) + amd_ssb_no : 1, // SSBD is not needed (fixed in hardware) + cppc : 1, // Collaborative Processor Performance Control + amd_psfd : 1, // Predictive Store Forward Disable + btc_no : 1, // CPU not affected by Branch Type Confusion + ibpb_ret : 1, // IBPB clears RSB/RAS too + branch_sampling : 1; // Branch Sampling + // ecx + u32 cpu_nthreads : 8, // Number of physical threads - 1 + : 4, // Reserved + apicid_coreid_len : 4, // Number of thread core ID bits (shift) in API= C ID + perf_tsc_len : 2, // Performance time-stamp counter size + : 14; // Reserved + // edx + u32 invlpgb_max_pages : 16, // INVLPGB maximum page count + rdpru_max_reg_id : 16; // RDPRU max register ID (ECX input) +}; + +/* + * Leaf 0x8000000a + * AMD SVM (Secure Virtual Machine) + */ + +struct leaf_0x8000000a_0 { + // eax + u32 svm_version : 8, // SVM revision number + : 24; // Reserved + // ebx + u32 svm_nasid : 32; // Number of address space identifiers (ASID) + // ecx + u32 : 4, // Reserved + pml : 1, // Page Modification Logging (PML) + : 27; // Reserved + // edx + u32 nested_pt : 1, // Nested paging + lbr_virt : 1, // LBR virtualization + svm_lock : 1, // SVM lock + nrip_save : 1, // NRIP save support on #VMEXIT + tsc_rate_msr : 1, // MSR based TSC rate control + vmcb_clean : 1, // VMCB clean bits support + flush_by_asid : 1, // Flush by ASID + Extended VMCB TLB_Control + decode_assists : 1, // Decode Assists support + : 2, // Reserved + pause_filter : 1, // Pause intercept filter + : 1, // Reserved + pf_threshold : 1, // Pause filter threshold + avic : 1, // Advanced virtual interrupt controller + : 1, // Reserved + v_vmsave_vmload : 1, // Virtual VMSAVE/VMLOAD (nested virtualization) + v_gif : 1, // Virtualize the Global Interrupt Flag + gmet : 1, // Guest mode execution trap + x2avic : 1, // Virtual x2APIC + sss_check : 1, // Supervisor Shadow Stack restrictions + v_spec_ctrl : 1, // Virtual SPEC_CTRL + ro_gpt : 1, // Read-Only guest page table support + : 1, // Reserved + h_mce_override : 1, // Host MCE override + tlbsync_int : 1, // TLBSYNC intercept + INVLPGB/TLBSYNC in VMCB + nmi_virt : 1, // NMI virtualization + ibs_virt : 1, // IBS Virtualization + ext_lvt_off_chg : 1, // Extended LVT offset fault change + svme_addr_chk : 1, // Guest SVME address check + : 3; // Reserved +}; + +/* + * Leaf 0x80000019 + * AMD TLB characteristics for 1GB pages + */ + +struct leaf_0x80000019_0 { + // eax + u32 l1_itlb_1g_nentries : 12, // L1 iTLB #entries, 1G pages + l1_itlb_1g_assoc : 4, // L1 iTLB associativity, 1G pages + l1_dtlb_1g_nentries : 12, // L1 dTLB #entries, 1G pages + l1_dtlb_1g_assoc : 4; // L1 dTLB associativity, 1G pages + // ebx + u32 l2_itlb_1g_nentries : 12, // L2 iTLB #entries, 1G pages + l2_itlb_1g_assoc : 4, // L2 iTLB associativity, 1G pages + l2_dtlb_1g_nentries : 12, // L2 dTLB #entries, 1G pages + l2_dtlb_1g_assoc : 4; // L2 dTLB associativity, 1G pages + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x8000001a + * AMD instruction optimizations + */ + +struct leaf_0x8000001a_0 { + // eax + u32 fp_128 : 1, // Internal FP/SIMD exec data path is 128-bits wide + movu_preferred : 1, // SSE: MOVU* better than MOVL*/MOVH* + fp_256 : 1, // internal FP/SSE exec data path is 256-bits wide + : 29; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x8000001b + * AMD IBS (Instruction-Based Sampling) + */ + +struct leaf_0x8000001b_0 { + // eax + u32 ibs_flags : 1, // IBS feature flags + ibs_fetch_sampling : 1, // IBS fetch sampling + ibs_op_sampling : 1, // IBS execution sampling + ibs_rdwr_op_counter : 1, // IBS read/write of op counter + ibs_op_count : 1, // IBS OP counting mode + ibs_branch_target : 1, // IBS branch target address reporting + ibs_op_counters_ext : 1, // IBS IbsOpCurCnt/IbsOpMaxCnt extend by 7 bi= ts + ibs_rip_invalid_chk : 1, // IBS invalid RIP indication + ibs_op_branch_fuse : 1, // IBS fused branch micro-op indication + ibs_fetch_ctl_ext : 1, // IBS Fetch Control Extended MSR + ibs_op_data_4 : 1, // IBS op data 4 MSR + ibs_l3_miss_filter : 1, // IBS L3-miss filtering (Zen4+) + : 20; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x8000001c + * AMD LWP (Lightweight Profiling) + */ + +struct leaf_0x8000001c_0 { + // eax + u32 os_lwp_avail : 1, // OS: LWP is available to application programs + os_lpwval : 1, // OS: LWPVAL instruction + os_lwp_ire : 1, // OS: Instructions Retired Event + os_lwp_bre : 1, // OS: Branch Retired Event + os_lwp_dme : 1, // OS: Dcache Miss Event + os_lwp_cnh : 1, // OS: CPU Clocks Not Halted event + os_lwp_rnh : 1, // OS: CPU Reference clocks Not Halted event + : 22, // Reserved + os_lwp_cont : 1, // OS: LWP sampling in continuous mode + os_lwp_ptsc : 1, // OS: Performance Time Stamp Counter in event recor= ds + os_lwp_int : 1; // OS: Interrupt on threshold overflow + // ebx + u32 lwp_lwpcb_sz : 8, // Control Block size, in quadwords + lwp_event_sz : 8, // Event record size, in bytes + lwp_max_events : 8, // Max EventID supported + lwp_event_offset : 8; // Control Block events area offset + // ecx + u32 lwp_latency_max : 5, // Cache latency counters number of bits + lwp_data_addr : 1, // Cache miss events report data cache address + lwp_latency_rnd : 3, // Cache latency rounding amount + lwp_version : 7, // LWP version + lwp_buf_min_sz : 8, // LWP event ring buffer min size, 32 event recor= ds units + : 4, // Reserved + lwp_branch_predict : 1, // Branches Retired events can be filtered + lwp_ip_filtering : 1, // IP filtering (IPI, IPF, BaseIP, and LimitIP @= LWPCP) + lwp_cache_levels : 1, // Cache-related events: filter by cache level + lwp_cache_latency : 1; // Cache-related events: filter by latency + // edx + u32 hw_lwp_avail : 1, // HW: LWP available + hw_lpwval : 1, // HW: LWPVAL available + hw_lwp_ire : 1, // HW: Instructions Retired Event + hw_lwp_bre : 1, // HW: Branch Retired Event + hw_lwp_dme : 1, // HW: Dcache Miss Event + hw_lwp_cnh : 1, // HW: Clocks Not Halted event + hw_lwp_rnh : 1, // HW: Reference clocks Not Halted event + : 22, // Reserved + hw_lwp_cont : 1, // HW: LWP sampling in continuous mode + hw_lwp_ptsc : 1, // HW: Performance Time Stamp Counter in event recor= ds + hw_lwp_int : 1; // HW: Interrupt on threshold overflow +}; + +/* + * Leaf 0x8000001d + * AMD deterministic cache parameters + */ + +struct leaf_0x8000001d_n { + // eax + u32 cache_type : 5, // Cache type field + cache_level : 3, // Cache level (1-based) + cache_self_init : 1, // Self-initializing cache level + fully_associative : 1, // Fully-associative cache + : 4, // Reserved + num_threads_sharing : 12, // Number of logical CPUs sharing cache + : 6; // Reserved + // ebx + u32 cache_linesize : 12, // System coherency line size (0-based) + cache_npartitions : 10, // Physical line partitions (0-based) + cache_nways : 10; // Ways of associativity (0-based) + // ecx + u32 cache_nsets : 31, // Cache number of sets (0-based) + : 1; // Reserved + // edx + u32 wbinvd_rll_no_guarantee : 1, // WBINVD/INVD not guaranteed for Remo= te Lower-Level caches + ll_inclusive : 1, // Cache is inclusive of Lower-Level caches + : 30; // Reserved +}; + +#define LEAF_0x8000001d_SUBLEAF_N_FIRST 0 +#define LEAF_0x8000001d_SUBLEAF_N_LAST 31 + +/* + * Leaf 0x8000001e + * AMD CPU topology + */ + +struct leaf_0x8000001e_0 { + // eax + u32 ext_apic_id : 32; // Extended APIC ID + // ebx + u32 core_id : 8, // Unique per-socket logical core unit ID + core_nthreas : 8, // #Threads per core (zero-based) + : 16; // Reserved + // ecx + u32 node_id : 8, // Node (die) ID of invoking logical CPU + nnodes_per_socket : 3, // #nodes in invoking logical CPU's package/soc= ket + : 21; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x8000001f + * AMD encrypted memory capabilities (SME/SEV) + */ + +struct leaf_0x8000001f_0 { + // eax + u32 sme : 1, // Secure Memory Encryption + sev : 1, // Secure Encrypted Virtualization + vm_page_flush : 1, // VM Page Flush MSR + sev_encrypted_state : 1, // SEV Encrypted State + sev_nested_paging : 1, // SEV secure nested paging + vm_permission_levels : 1, // VMPL + rpmquery : 1, // RPMQUERY instruction + vmpl_sss : 1, // VMPL supervisor shadow stack + secure_tsc : 1, // Secure TSC + virt_tsc_aux : 1, // Hardware virtualizes TSC_AUX + sme_coherent : 1, // Cache coherency enforcement across encryption do= mains + req_64bit_hypervisor : 1, // SEV guest mandates 64-bit hypervisor + restricted_injection : 1, // Restricted Injection supported + alternate_injection : 1, // Alternate Injection supported + debug_swap : 1, // SEV-ES: Full debug state swap + disallow_host_ibs : 1, // SEV-ES: Disallowing IBS use by the host + virt_transparent_enc : 1, // Virtual Transparent Encryption + vmgexit_paremeter : 1, // SEV_FEATURES: VmgexitParameter + virt_tom_msr : 1, // Virtual TOM MSR + virt_ibs : 1, // SEV-ES guests: IBS state virtualization + : 4, // Reserved + vmsa_reg_protection : 1, // VMSA register protection + smt_protection : 1, // SMT protection + : 2, // Reserved + svsm_page_msr : 1, // SVSM communication page MSR + nested_virt_snp_msr : 1, // VIRT_RMPUPDATE/VIRT_PSMASH MSRs + : 2; // Reserved + // ebx + u32 pte_cbit_pos : 6, // PTE bit number to enable memory encryption + phys_addr_reduction_nbits : 6, // Reduction of phys address space in bi= ts + vmpl_count : 4, // Number of VM permission levels (VMPL) + : 16; // Reserved + // ecx + u32 enc_guests_max : 32; // Max number of simultaneous encrypted guests + // edx + u32 min_sev_asid_no_sev_es : 32; // Minimum ASID for SEV-enabled SEV-ES-= disabled guest +}; + +/* + * Leaf 0x80000020 + * AMD PQoS (Platform QoS) extended features + */ + +struct leaf_0x80000020_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 : 1, // Reserved + mba : 1, // Memory Bandwidth Allocation support + smba : 1, // Slow Memory Bandwidth Allocation support + bmec : 1, // Bandwidth Monitoring Event Configuration support + l3rr : 1, // L3 Range Reservation support + abmc : 1, // Assignable Bandwidth Monitoring Counters + sdciae : 1, // Smart Data Cache Injection (SDCI) Allocation Enforcem= ent + : 25; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +struct leaf_0x80000020_1 { + // eax + u32 mba_limit_len : 32; // MBA enforcement limit size + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 mba_cos_max : 32; // MBA max Class of Service number (zero-based) +}; + +struct leaf_0x80000020_2 { + // eax + u32 smba_limit_len : 32; // SMBA enforcement limit size + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 smba_cos_max : 32; // SMBA max Class of Service number (zero-based) +}; + +struct leaf_0x80000020_3 { + // eax + u32 : 32; // Reserved + // ebx + u32 bmec_num_events : 8, // BMEC number of bandwidth events available + : 24; // Reserved + // ecx + u32 bmec_local_reads : 1, // Local NUMA reads can be tracked + bmec_remote_reads : 1, // Remote NUMA reads can be tracked + bmec_local_nontemp_wr : 1, // Local NUMA non-temporal writes can be tr= acked + bmec_remote_nontemp_wr : 1, // Remote NUMA non-temporal writes can be = tracked + bmec_local_slow_mem_rd : 1, // Local NUMA slow-memory reads can be tra= cked + bmec_remote_slow_mem_rd : 1, // Remote NUMA slow-memory reads can be t= racked + bmec_all_dirty_victims : 1, // Dirty QoS victims to all types of memor= y can be tracked + : 25; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x80000021 + * AMD extended CPU features 2 + */ + +struct leaf_0x80000021_0 { + // eax + u32 no_nested_data_bp : 1, // No nested data breakpoints + fsgs_non_serializing : 1, // WRMSR to {FS,GS,KERNEL_GS}_BASE is non-se= rializing + lfence_serializing : 1, // LFENCE always serializing / synchronizes RD= TSC + smm_page_cfg_lock : 1, // SMM paging configuration lock + : 2, // Reserved + null_sel_clr_base : 1, // Null selector clears base + upper_addr_ignore : 1, // EFER MSR Upper Address Ignore + auto_ibrs : 1, // EFER MSR Automatic IBRS + no_smm_ctl_msr : 1, // SMM_CTL MSR not available + fsrs : 1, // Fast Short Rep STOSB + fsrc : 1, // Fast Short Rep CMPSB + : 1, // Reserved + prefetch_ctl_msr : 1, // Prefetch control MSR + : 2, // Reserved + opcode_reclaim : 1, // Reserves opcode space + user_cpuid_disable : 1, // #GP when executing CPUID at CPL > 0 + epsf : 1, // Enhanced Predictive Store Forwarding + : 3, // Reserved + wl_feedback : 1, // Workload-based heuristic feedback to OS + : 1, // Reserved + eraps : 1, // Enhanced Return Address Predictor Security + : 2, // Reserved + sbpb : 1, // Selective Branch Predictor Barrier + ibpb_brtype : 1, // Branch predictions flushed from CPU branch predic= tor + srso_no : 1, // No SRSO vulnerability + srso_uk_no : 1, // No SRSO at user-kernel boundary + srso_msr_fix : 1; // MSR BP_CFG[BpSpecReduce] SRSO mitigation + // ebx + u32 microcode_patch_size : 16, // Microcode patch size, in 16-byte units + rap_size : 8, // Return Address Predictor size + : 8; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x80000022 + * AMD extended performance monitoring + */ + +struct leaf_0x80000022_0 { + // eax + u32 perfmon_v2 : 1, // Performance monitoring v2 + lbr_v2 : 1, // Last Branch Record v2 extensions (LBR Stack) + lbr_pmc_freeze : 1, // Freezing core performance counters / LBR Stack + : 29; // Reserved + // ebx + u32 n_pmc_core : 4, // Number of core performance counters + lbr_v2_stack_size : 6, // Number of LBR stack entries + n_pmc_northbridge : 6, // Number of northbridge performance counters + n_pmc_umc : 6, // Number of UMC performance counters + : 10; // Reserved + // ecx + u32 active_umc_bitmask : 32; // Active UMCs bitmask + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x80000023 + * AMD multi-key encrypted memory + */ + +struct leaf_0x80000023_0 { + // eax + u32 mem_hmk_mode : 1, // MEM-HMK encryption mode + : 31; // Reserved + // ebx + u32 mem_hmk_avail_keys : 16, // Total number of available encryption keys + : 16; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x80000026 + * AMD extended CPU topology + */ + +struct leaf_0x80000026_n { + // eax + u32 x2apic_id_shift : 5, // Bit width of this level (previous levels i= nclusive) + : 24, // Reserved + core_has_pwreff_ranking : 1, // This core has a power efficiency ranki= ng + domain_has_hybrid_cores : 1, // This domain level has hybrid (E, P) co= res + domain_core_count_asymm : 1; // The 'Core' domain has asymmetric cores= count + // ebx + u32 domain_lcpus_count : 16, // Number of logical CPUs at this domain in= stance + core_pwreff_ranking : 8, // This core's static power efficiency ranking + core_native_model_id : 4, // This core's native model ID + core_type : 4; // This core's type + // ecx + u32 domain_level : 8, // This domain level (subleaf ID) + domain_type : 8, // This domain type + : 16; // Reserved + // edx + u32 x2apic_id : 32; // x2APIC ID of current logical CPU +}; + +#define LEAF_0x80000026_SUBLEAF_N_FIRST 0 +#define LEAF_0x80000026_SUBLEAF_N_LAST 3 + +/* + * Leaf 0x80860000 + * Maximum Transmeta leaf + CPU vendor string + */ + +struct leaf_0x80860000_0 { + // eax + u32 max_tra_leaf : 32; // Maximum Transmeta leaf + // ebx + u32 cpu_vendorid_0 : 32; // Transmeta Vendor ID string bytes 0 - 3 + // ecx + u32 cpu_vendorid_2 : 32; // Transmeta Vendor ID string bytes 8 - 11 + // edx + u32 cpu_vendorid_1 : 32; // Transmeta Vendor ID string bytes 4 - 7 +}; + +/* + * Leaf 0x80860001 + * Transmeta extended CPU features + */ + +struct leaf_0x80860001_0 { + // eax + u32 stepping : 4, // Stepping ID + base_model : 4, // Base CPU model ID + base_family_id : 4, // Base CPU family ID + cpu_type : 2, // CPU type + : 18; // Reserved + // ebx + u32 cpu_rev_mask_minor : 8, // CPU revision ID, mask minor + cpu_rev_mask_major : 8, // CPU revision ID, mask major + cpu_rev_minor : 8, // CPU revision ID, minor + cpu_rev_major : 8; // CPU revision ID, major + // ecx + u32 cpu_base_mhz : 32; // CPU nominal frequency, in MHz + // edx + u32 recovery : 1, // Recovery CMS is active (after bad flush) + longrun : 1, // LongRun power management capabilities + : 1, // Reserved + lrti : 1, // LongRun Table Interface + : 28; // Reserved +}; + +/* + * Leaf 0x80860002 + * Transmeta CMS (Code Morphing Software) + */ + +struct leaf_0x80860002_0 { + // eax + u32 cpu_rev_id : 32; // CPU revision ID + // ebx + u32 cms_rev_mask_2 : 8, // CMS revision ID, mask component 2 + cms_rev_mask_1 : 8, // CMS revision ID, mask component 1 + cms_rev_minor : 8, // CMS revision ID, minor + cms_rev_major : 8; // CMS revision ID, major + // ecx + u32 cms_rev_mask_3 : 32; // CMS revision ID, mask component 3 + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0x80860003 + * Transmeta CPU information string, bytes 0 - 15 + */ + +struct leaf_0x80860003_0 { + // eax + u32 cpu_info_0 : 32; // CPU info string bytes 0 - 3 + // ebx + u32 cpu_info_1 : 32; // CPU info string bytes 4 - 7 + // ecx + u32 cpu_info_2 : 32; // CPU info string bytes 8 - 11 + // edx + u32 cpu_info_3 : 32; // CPU info string bytes 12 - 15 +}; + +/* + * Leaf 0x80860004 + * Transmeta CPU information string, bytes 16 - 31 + */ + +struct leaf_0x80860004_0 { + // eax + u32 cpu_info_4 : 32; // CPU info string bytes 16 - 19 + // ebx + u32 cpu_info_5 : 32; // CPU info string bytes 20 - 23 + // ecx + u32 cpu_info_6 : 32; // CPU info string bytes 24 - 27 + // edx + u32 cpu_info_7 : 32; // CPU info string bytes 28 - 31 +}; + +/* + * Leaf 0x80860005 + * Transmeta CPU information string, bytes 32 - 47 + */ + +struct leaf_0x80860005_0 { + // eax + u32 cpu_info_8 : 32; // CPU info string bytes 32 - 35 + // ebx + u32 cpu_info_9 : 32; // CPU info string bytes 36 - 39 + // ecx + u32 cpu_info_10 : 32; // CPU info string bytes 40 - 43 + // edx + u32 cpu_info_11 : 32; // CPU info string bytes 44 - 47 +}; + +/* + * Leaf 0x80860006 + * Transmeta CPU information string, bytes 48 - 63 + */ + +struct leaf_0x80860006_0 { + // eax + u32 cpu_info_12 : 32; // CPU info string bytes 48 - 51 + // ebx + u32 cpu_info_13 : 32; // CPU info string bytes 52 - 55 + // ecx + u32 cpu_info_14 : 32; // CPU info string bytes 56 - 59 + // edx + u32 cpu_info_15 : 32; // CPU info string bytes 60 - 63 +}; + +/* + * Leaf 0x80860007 + * Transmeta live CPU information + */ + +struct leaf_0x80860007_0 { + // eax + u32 cpu_cur_mhz : 32; // Current CPU frequency, in MHz + // ebx + u32 cpu_cur_voltage : 32; // Current CPU voltage, in millivolts + // ecx + u32 cpu_cur_perf_pctg : 32; // Current CPU performance percentage, 0 - 1= 00 + // edx + u32 cpu_cur_gate_delay : 32; // Current CPU gate delay, in femtoseconds +}; + +/* + * Leaf 0xc0000000 + * Maximum Centaur/Zhaoxin leaf + */ + +struct leaf_0xc0000000_0 { + // eax + u32 max_cntr_leaf : 32; // Maximum Centaur/Zhaoxin leaf + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 : 32; // Reserved +}; + +/* + * Leaf 0xc0000001 + * Centaur/Zhaoxin extended CPU features + */ + +struct leaf_0xc0000001_0 { + // eax + u32 : 32; // Reserved + // ebx + u32 : 32; // Reserved + // ecx + u32 : 32; // Reserved + // edx + u32 ccs_sm2 : 1, // CCS SM2 instructions + ccs_sm2_en : 1, // CCS SM2 enabled + rng : 1, // Random Number Generator + rng_en : 1, // RNG enabled + ccs_sm3_sm4 : 1, // CCS SM3 and SM4 instructions + ccs_sm3_sm4_en : 1, // CCS SM3/SM4 enabled + ace : 1, // Advanced Cryptography Engine + ace_en : 1, // ACE enabled + ace2 : 1, // Advanced Cryptography Engine v2 + ace2_en : 1, // ACE v2 enabled + phe : 1, // PadLock Hash Engine + phe_en : 1, // PHE enabled + pmm : 1, // PadLock Montgomery Multiplier + pmm_en : 1, // PMM enabled + : 2, // Reserved + parallax : 1, // Parallax auto adjust processor voltage + parallax_en : 1, // Parallax enabled + : 2, // Reserved + tm3 : 1, // Thermal Monitor v3 + tm3_en : 1, // TM v3 enabled + : 3, // Reserved + phe2 : 1, // PadLock Hash Engine v2 (SHA384/SHA512) + phe2_en : 1, // PHE v2 enabled + rsa : 1, // RSA instructions (XMODEXP/MONTMUL2) + rsa_en : 1, // RSA instructions enabled + : 3; // Reserved +}; + +#endif /* _ASM_X86_CPUID_LEAF_TYPES */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B234334DCEA for ; Fri, 5 Sep 2025 12:15:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074546; cv=none; b=T2kwat8PzQsh6mte59fywSCeP3gAOQ6xf/9ux1GV+muanqLVrU+/YY6lelykt47Le3neTUqnLIBaT7F7zepLRapLtDokiogzY9+gjwVZGqg+DA+KtnA7Njpx6bOR5HOuYO/rcO4tR1Yfu8ggP0KDVkOaT1T/WywzTtg++7lKmEw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074546; c=relaxed/simple; bh=nVzmx+VBFMAIeK1xZkch6zN41rKSSM7fSfVwTKYfqmw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OHL+rAN8LNXkkTlePQ5GCJ6T4xkncky+Foyf98YYq4QDZ1j3dAb+IaWtwXfihryU7d7aQFjTfm1dPYXr4zhLRv32oI6XfwU42ExhuhkKEP4K6xlPXNewBbT3lLkTzkKLcWjoaY27JIxspmD3QxMItHrL9PH9CqEm2gtxE+xMD7Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=tGsK9NcW; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=drrTUPEo; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="tGsK9NcW"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="drrTUPEo" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074542; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PL+ILi/B3wQ4riPW8csosjR4rJ3qnOvXyB/TuLz+BUk=; b=tGsK9NcWqsQ1DpPm8Rf85bOUvwQ41FVRXgexE/tb/o0bKqs2p1XvxEnVQ5ezOu2TaB06Fz 7KVXww2yYZ3Q9czmfJ/M0280sxk7ZH/T6QdiWkFPL6OSgg43uXGF2RbR4zh5uJG/76Z736 fQucvg9gCqlXMZftT1q2IGTAuCbErwvXZnB6eZkDupFW0ZgnUeTyX/tfOqn9KSkpOgbun6 HIPZ3QJGGDVWLh7vTwc5NwbRud9/Pfi3YvfYVJIPltRlEOOGAGCjg2NJKwVRNyTeI8zoHM 5HPH2wjTe1nxnetcB1yqFrtrJpk/SSBeePQVrFAF7WDNjR1ksWRHHYTmcO4tWA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074542; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PL+ILi/B3wQ4riPW8csosjR4rJ3qnOvXyB/TuLz+BUk=; b=drrTUPEoIH/SyYafrTY3IOp+lQ6+ug7Kgk48XLNlflZFwha3l7oKiHQE75GnfYm24BhAVn xJThLTA1C5X/jzBg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 07/35] x86: Introduce a centralized CPUID data model Date: Fri, 5 Sep 2025 14:14:47 +0200 Message-ID: <20250905121515.192792-8-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable ** Context The x86-cpuid-db project generates a C header file with full C99 bitfield listings for all known CPUID leaf/subleaf query outputs. That header is now merged by parent commits at , and is in the form: struct leaf_0x0_0 { /* CPUID(0x0).0 C99 bitfields */ }; ... struct leaf_0x4_n { /* CPUID(0x4).n C99 bitfields */ }; ... struct leaf_0xd_0 { /* CPUID(0xd).0 C99 bitfields */ }; struct leaf_0xd_1 { /* CPUID(0xd).1 C99 bitfields */ }; struct leaf_0xd_n { /* CPUID(0xd).n C99 bitfields */ }; ... ** Goal Introduce a structured, size-efficient, per-CPU, CPUID data repository. Use the x86-cpuid-db auto-generated data types, and custom CPUID leaf parsers, to build that repository. Given a leaf, subleaf, and index, provide direct memory access to the parsed and cached per-CPU CPUID output. ** Long-term goal Remove the need for drivers and other areas in the kernel to invoke direct CPUID queries. Only one place in the kernel should be allowed to use the CPUID instruction: the CPUID parser code. ** Implementation Introduce CPUID_LEAF()/CPUID_LEAF_N() to build a compact CPUID storage layout in the form: struct leaf_0x0_0 leaf_0x0_0[1]; struct leaf_query_info leaf_0x0_0_info; struct leaf_0x1_0 leaf_0x1_0[1]; struct leaf_query_info leaf_0x0_0_info; struct leaf_0x4_n leaf_0x4_n[8]; struct leaf_query_info leaf_0x4_n_info; ... where each CPUID query stores its output at the designated leaf/subleaf array and has an associated "CPUID query info" structure. Introduce 'struct cpuid_leaves' to group all the parsed CPUID outputs and their metadata =E2=80=93in the layout above=E2=80=93 in one structure. Def= ine a 'struct cpuid_table' to wrap it, so that global per-table CPUID data can be added later. Embed 'struct cpuid_table' inside 'struct cpuinfo_x86' to ensure early-boot and per-CPU access through the CPU(s) capability structures. Given the data layout above, and assuming a CPU capability structure 'c', a macro can access CPUID(0x7) subleaf 0 parsed query output using the compile-time tokenization below: const struct leaf_0x7_0 *l7_0; l7_0 =3D cpuid_subleaf(c, 0x7, 0); | | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | * * * &c.cpuid.leaf_0x7_0[0] Similarly, CPUID(0x7) subleaf 1 output can be accessed using the CPP tokenization: const struct leaf_0x7_1 *l7_1; l7_1 =3D cpuid_subleaf(c, 0x7, 1); | | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | * * * &c.cpuid.leaf_0x7_1[0] which all translate to a single assembly instruction offset calculation. Use an array of CPUID output storage entries for each leaf/subleaf combination to accommodate leaves which produce the same output format for a large subleaf range. This is typical for CPUID leaves enumerating hierarchical objects; e.g. CPUID(0x4) cache topology enumeration, CPUID(0xd) XSAVE enumeration, and CPUID(0x12) SGX Enclave Page Cache enumeration. In the CPUID table layout above, CPUID(0x4) has 8 storage entries to accomodate suleaves 0 to 7, which all have the same bitfield's output format. With that, CPUID(0x4) can be accessed using the compile time tokenization: const struct leaf_0x4_n *l4_0, *l4_1, l4_2; l4_0 =3D cpuid_subleaf_n(c, 0x4, 0); | | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | * * v &c.cpuid.leaf_0x4_n[0] l4_1 =3D cpuid_subleaf_n(c, 0x4, 1); | | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | * * v &c.cpuid.leaf_0x4_n[1] l4_2 =3D cpuid_subleaf_n(c, 0x4, 2); | | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 | * * v &c.cpuid.leaf_0x4_n[2] where dynamic leaf types are marked by their "_n" suffix and the indices 0, 1, 2 above can be passed dynamically. This is by design: hierarchical CPUID enumeration usually passes the CPUID subleaf dynamically; e.g., within a for loop. For each of the CPUID leaf/subleaf output storage entries, attach a 'struct leaf_query_info' instance. It is to be set by the CPUID parser while filling the CPUID tables. For now, this info structure has one element: the number of filled slots at the respective output storage array. ** Call-site APIs Introduce below APIs for CPUID leaves with static subleaves: cpuid_leaf(_cpuinfo, _leaf) cpuid_leaf_raw(_cpuinfo, _leaf) cpuid_subleaf(_cpuinfo, _leaf, _subleaf) and below APIs for CPUID leaves with dynamic subleaves: cpuid_subleaf_n(_cpuinfo, _leaf, _idx) cpuid_subleaf_n_raw(_cpuinfo, _leaf, _idx) cpuid_subleaf_count(_cpuinfo, _leaf) At , add a clear rationale for why call sites should use the above APIs instead of directly invoking CPUID queries. ** Next steps For now, define entries for CPUID(0x0) and CPUID(0x1) in the CPUID table. Generic CPUID parser logic to fill the CPUID tables, along with more CPUID leaves support, will be added next. Suggested-by: Thomas Gleixner # CPUID data model Suggested-by: Andrew Cooper # x86-cpuid-db sche= ma Suggested-by: Borislav Petkov # Early CPUID centralization = drafts Suggested-by: Ingo Molnar # CPUID APIs restructuring Suggested-by: Sean Christopherson # Dynamic leaves CPUI= D API Signed-off-by: Ahmed S. Darwish Link: https://lore.kernel.org/lkml/874ixernra.ffs@tglx Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db Link: https://lore.kernel.org/lkml/aBnSgu_JyEi8fvog@gmail.com Link: https://lore.kernel.org/lkml/aJ9TbaNMgaplKSbH@google.com --- arch/x86/include/asm/cpuid/api.h | 273 +++++++++++++++++++++++++++++ arch/x86/include/asm/cpuid/types.h | 125 +++++++++++++ arch/x86/include/asm/processor.h | 2 + 3 files changed, 400 insertions(+) diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/= api.h index 2b9750cc8a75..dbe94c8c4900 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -289,4 +289,277 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) return cpuid_edx(0x80000006); } =20 +/* + * 'struct cpuid_leaves' accessors (without sanity checks): + * + * For internal use by the CPUID parser. + */ + +/* + * Return constified pointers for all call-site APIs + */ +#define __const_ptr(_ptr) \ + ((const __typeof__(*(_ptr)) *)(_ptr)) + +/* + * __cpuid_leaves_subleaf() - Get parsed CPUID output (without sanity chec= ks) + * @_leaves: &struct cpuid_leaves instance + * @_leaf: CPUID leaf, in compile-time 0xN format + * @_subleaf: CPUID subleaf, in compile-time decimal format + */ +#define __cpuid_leaves_subleaf(_leaves, _leaf, _subleaf) \ + __const_ptr(&((_leaves)->leaf_ ## _leaf ## _ ## _subleaf)[0]) + +/* + * __cpuid_leaves_subleaf_n() - Get parsed CPUID output for dynamic sublea= f (without checks) + * @_leaves: &struct cpuid_leaves instance + * @_leaf: CPUID leaf, in compile-time 0xN format + * @_index: Index within the dynamic subleaf storage array + */ +#define __cpuid_leaves_subleaf_n(_leaves, _leaf, _index) \ + __const_ptr(&((_leaves)->leaf_ ## _leaf ## _ ## n)[_index]) + +/* + * __cpuid_leaves_subleaf_info() - Get CPUID query info for @_leaf/@_suble= af + * @_leaves: &struct cpuid_leaves instance + * @_leaf: CPUID leaf, in compile-time 0xN format + * @_subleaf: CPUID subleaf, in compile-time decimal format, or just 'n' f= or + * leaves with a dynamic subleaf range. + */ +#define __cpuid_leaves_subleaf_info(_leaves, _leaf, _subleaf) \ + __const_ptr(&((_leaves)->leaf_ ## _leaf ## _ ## _subleaf ## _ ## info)) + +/* + * 'struct cpuid_table' accessors (with sanity checks): + * + * For internal use by the CPUID parser. + */ + +#define __cpuid_table_nr_filled_subleaves(_table, _leaf, _subleaf) \ + __cpuid_leaves_subleaf_info(&((_table)->leaves), _leaf, _subleaf)->nr_ent= ries + +#define __cpuid_table_dynamic_subleaf_storage(_table, _leaf) \ + ARRAY_SIZE((_table)->leaves.leaf_ ## _leaf ## _n) + +#define __cpuid_table_invalid_dynamic_subleaf(_table, _leaf, _subleaf) \ + (((_subleaf) < (__cpuid_leaf_first_dynamic_subleaf(_leaf))) || \ + ((_subleaf) > (__cpuid_leaf_first_dynamic_subleaf(_leaf) + \ + __cpuid_table_dynamic_subleaf_storage(_table, _leaf) - 1))) + +/* + * __cpuid_table_subleaf() - Get parsed CPUID output (with sanity checks) + * @_table: &struct cpuid_table instance + * @_leaf: CPUID leaf, in compile-time 0xN format + * @_subleaf: CPUID subleaf, in compile-time decimal format + * + * A return of NULL implies that the CPUID parser did not fill that leaf. = This + * can happen due to the conditions listed at cpuid_leaf(). + */ +#define __cpuid_table_subleaf(_table, _leaf, _subleaf) \ +({ \ + unsigned int ____f =3D __cpuid_table_nr_filled_subleaves(_table, _leaf, _= subleaf); \ + \ + /* CPUID parser fills exactly one entry for static leaves */ \ + (____f !=3D 1) ? NULL : __cpuid_leaves_subleaf(&((_table)->leaves), _leaf= , _subleaf); \ +}) + +/* + * __cpuid_table_subleaf_n() - Get parsed CPUID output (with sanity checks) + * @_table: &struct cpuid_table instance + * @_leaf: CPUID leaf, in compile-time 0xN format + * @_subleaf: CPUID subleaf, which can be given dynamically + * + * A return of NULL implies that the CPUID parser did not fill this leaf, = or that + * the given dynamic subleaf value is out of range. Check cpuid_subleaf_n= (). + */ +#define __cpuid_table_subleaf_n(_table, _leaf, _subleaf) \ +({ \ + unsigned int ____i =3D (_subleaf) - __cpuid_leaf_first_dynamic_subleaf(_l= eaf); \ + unsigned int ____f =3D __cpuid_table_nr_filled_subleaves(_table, _leaf, n= ); \ + \ + /* CPUID parser might not have filled the entire dynamic subleaf range */= \ + ((____i >=3D ____f) || __cpuid_table_invalid_dynamic_subleaf(_table, _lea= f, _subleaf)) ? \ + NULL : __cpuid_leaves_subleaf_n(&((_table)->leaves), _leaf, ____i); \ +}) + +/* + * Compile-time checks for leaves with a dynamic subleaf range: + */ + +#define __cpuid_assert_dynamic_subleaves(_cpuinfo, _leaf) \ + static_assert(__cpuid_table_dynamic_subleaf_storage(&(_cpuinfo)->cpuid, _= leaf) > 1) + +#define __cpuid_assert_dynamic_subleaf_range(_cpuinfo, _leaf, _subleaf) = \ + BUILD_BUG_ON(__builtin_constant_p(_subleaf) && \ + __cpuid_table_invalid_dynamic_subleaf(&(_cpuinfo)->cpuid, _leaf, _s= ubleaf)) + +/* + * CPUID Parser Call-site APIs + * + * Call sites should use below APIs instead of invoking direct CPUID queri= es. + * + * Benefits include: + * + * - Return CPUID output as typed C structures that are auto-generated fro= m a + * centralized database (see data type: 'struct leaf_0xM_N', wh= ere + * 0xM is the token provided at @_leaf, and N is the token provided at + * @_subleaf; e.g. struct leaf_0x7_0. + * + * Returns NULL if the requested CPUID @_leaf/@_subleaf query output is not + * present at the parsed CPUID table inside @_cpuinfo. This can happen if: + * + * - The CPUID table inside @_cpuinfo has not yet been populated. + * - The CPUID table inside @_cpuinfo was populated, but the CPU does not + * implement the requested CPUID @_leaf/@_subleaf combination. + * - The CPUID table inside @_cpuinfo was populated, but the kernel's CPUID + * parser has predetermined that the requested CPUID @_leaf/@_subleaf + * hardware output is invalid or unsupported. + * + * Example usage:: + * + * const struct leaf_0x7_0 *l7_0 =3D cpuid_subleaf(c, 0x7, 0); + * if (!l7_0) { + * // Handle error + * } + * + * const struct leaf_0x7_1 *l7_1 =3D cpuid_subleaf(c, 0x7, 1); + * if (!l7_1) { + * // Handle error + * } + */ +#define cpuid_subleaf(_cpuinfo, _leaf, _subleaf) \ + __cpuid_table_subleaf(&(_cpuinfo)->cpuid, _leaf, _subleaf) \ + +/** + * cpuid_leaf() - Access parsed CPUID data + * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') + * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x0, 0x2, 0x800000= 00 + * + * Similar to cpuid_subleaf(), but with a CPUID subleaf =3D 0. + * + * Example usage:: + * + * const struct leaf_0x0_0 *l0 =3D cpuid_leaf(c, 0x0); + * if (!l0) { + * // Handle error + * } + * + * const struct leaf_0x80000000_0 *el0 =3D cpuid_leaf(c, 0x80000000); + * if (!el0) { + * // Handle error + * } + */ +#define cpuid_leaf(_cpuinfo, _leaf) \ + cpuid_subleaf(_cpuinfo, _leaf, 0) + +/** + * cpuid_leaf_regs() - Access parsed CPUID data in raw format + * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') + * @_leaf: CPUID leaf, in compile-time 0xN format + * + * Similar to cpuid_leaf(), but returns a raw 'struct cpuid_regs' pointer = to + * the parsed CPUID data instead of a "typed" poi= nter. + */ +#define cpuid_leaf_regs(_cpuinfo, _leaf) \ + ((const struct cpuid_regs *)(cpuid_leaf(_cpuinfo, _leaf))) + +/* + * Call-site APIs for leaves with a dynamic subleaf range: + */ + +/** + * cpuid_subleaf_n() - Access parsed CPUID data for leaf with dynamic subl= eaf range + * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') + * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d + * @_subleaf: Subleaf number, which can be passed dynamically. It must be= smaller + * than cpuid_subleaf_count(@_cpuinfo, @_leaf). + * + * Build-time errors will be emitted in the following cases: + * + * - @_leaf has no dynamic subleaf range. Dynamic leaves have an '_n' dat= a type + * suffix and are listed at using the CPUID_LEAF_N()= macro. + * + * - @_subleaf is known at compile-time but is out of range. + * + * Example usage:: + * + * const struct leaf_0x4_n *l4; + * + * for (int i =3D 0; i < cpuid_subleaf_count(c, 0x4); i++) { + * l4 =3D cpuid_subleaf_n(c, 0x4, i); + * if (!l4) { + * // Handle error + * } + * ... + * } + * + * Beside the standard error situations detailed at cpuid_subleaf(), this + * macro will also return NULL if @_subleaf is out of runtime range. + */ +#define cpuid_subleaf_n(_cpuinfo, _leaf, _subleaf) \ +({ \ + __cpuid_assert_dynamic_subleaves(_cpuinfo, _leaf); \ + __cpuid_assert_dynamic_subleaf_range(_cpuinfo, _leaf, _subleaf); \ + __cpuid_table_subleaf_n(&(_cpuinfo)->cpuid, _leaf, _subleaf); \ +}) + +/** + * cpuid_subleaf_n_regs() - Access parsed CPUID data for leaf with dynamic= subleaf range + * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') + * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d + * @_subleaf: Subleaf number, which can be passed dynamically. It must be= smaller + * than cpuid_subleaf_count(@_cpuinfo, @_leaf). + * + * Similar to cpuid_subleaf_n(), but returns a raw 'struct cpuid_regs' poi= nter to + * the parsed CPUID data instead of a "typed" poi= nter. + */ +#define cpuid_subleaf_n_regs(_cpuinfo, _leaf, _subleaf) \ + ((const struct cpuid_regs *)cpuid_subleaf_n(_cpuinfo, _leaf, _subleaf)) + +/** + * cpuid_subleaf_count() - Number of filled subleaves for dynamic @_leaf + * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') + * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d + * + * Return the number of dynamic subleaves filled by the CPUID parser for @= _leaf. + * + * @_leaf must have a dynamic subleaf range. Dynamic leaves have an '_n' = type + * suffix and are listed at using the CPUID_LEAF_N() m= acro. + */ +#define cpuid_subleaf_count(_cpuinfo, _leaf) \ +({ \ + __cpuid_assert_dynamic_subleaves(_cpuinfo, _leaf); \ + __cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n); \ +}) + #endif /* _ASM_X86_CPUID_API_H */ diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index 8a00364b79de..bd6e016ef035 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -5,6 +5,8 @@ #include #include =20 +#include + /* * Types for raw CPUID access: */ @@ -124,4 +126,127 @@ extern const struct leaf_0x2_table cpuid_0x2_table[25= 6]; */ #define TLB_0x63_2M_4M_ENTRIES 32 =20 +/* + * Types for centralized CPUID tables: + * + * For internal use by the CPUID parser. + */ + +/** + * struct leaf_query_info - Parse info for a CPUID leaf/subleaf query + * @nr_entries: Number of valid output storage entries filled by the CPUID= parser + * + * In a CPUID table (struct cpuid_leaves), each CPUID leaf/subleaf query o= utput + * storage entry from is paired with a unique instanc= e of + * this type. + */ +struct leaf_query_info { + unsigned int nr_entries; +}; + +/** + * __CPUID_LEAF() - Define a CPUID output storage and query info entry + * @_name: Struct type name of the CPUID leaf/subleaf (e.g. 'leaf_0x7_0').= Such + * types are defined at and follow the leaf_0xM_N + * format, where 0xM is the leaf and N is the subleaf. If N is 'n' inste= ad + * of a decimal literal, then this storage entry is for a "dynamic" leaf. + * @_count: Number of storage entries to allocate for this leaf/subleaf. = Static + * leaves need only one entry, while dynamic leaves require more. + * + * For the given leaf/subleaf combination, define an array of CPUID output= storage + * entries and an associated query info structure =E2=80=94 both residing = at a + * 'struct cpuid_leaves' instance. + * + * Use an array of storage entries to accommodate "dynamic" CPUID leaves. = Such leaves + * have the same subleaf output format for a large subleaf range. This is= common for + * hierarchical enumeration; e.g., CPUID(0x4), CPUID(0x12), and CPUID(0x80= 00001d). + * + * The example invocation:: + * + * __CPUID_LEAF(leaf_0x7_0, 1); + * __CPUID_LEAF(leaf_0x7_1, 1); + * + * generates 'struct cpuid_leaves' storage entries in the form:: + * + * struct leaf_0x7_0 leaf_0x7_0[1]; + * struct leaf_query_info leaf_0x7_0_info; + * + * struct leaf_0x7_1 leaf_0x7_1[1]; + * struct leaf_query_info leaf_0x7_1_info; + * + * While the example invocation for CPUID(0x4) storage:: + * + * __CPUID_LEAF(leaf_0x4_n, 8); + * + * generates storage entries in the form:: + * + * struct leaf_0x4_n leaf_0x4_n[8]; + * struct leaf_query_info leaf_0x4_n_info; + * + * where the 'leaf_0x4_n[8]' storage array can accommodate the output of C= PUID(0x4) + * subleaves 0 -> 7, since they all have the same output format. + */ +#define __CPUID_LEAF(_name, _count) \ + struct _name _name[_count]; \ + struct leaf_query_info _name##_info + +/** + * CPUID_LEAF() - Define a 'struct cpuid_leaves' storage entry for static = leaf + * @_leaf: Leaf number, in compile-time 0xN format + * @_subleaf: Subleaf number, in compile-time decimal format + * + * Convenience wrapper around __CPUID_LEAF(). + */ +#define CPUID_LEAF(_leaf, _subleaf) \ + __CPUID_LEAF(leaf_ ## _leaf ## _ ## _subleaf, 1) + +#define __cpuid_leaf_first_dynamic_subleaf(_l) \ + LEAF_ ## _l ## _ ## SUBLEAF_N_FIRST +#define __cpuid_leaf_last_dynamic_subleaf(_l) \ + LEAF_ ## _l ## _ ## SUBLEAF_N_LAST + +#define __cpuid_leaf_subleaf_count_min(_l) 2 +#define __cpuid_leaf_subleaf_count_max(_l) \ + (__cpuid_leaf_last_dynamic_subleaf(_l) - __cpuid_leaf_first_dynamic_suble= af(_l) + 1) + +/** + * CPUID_LEAF_N() - Define a 'struct cpuid_leaves' storage entry for dynam= ic leaf + * @_leaf: Leaf number, in compile-time 0xN format + * @_count: Number of storage entries to allocate for that leaf with dynam= ic subleaf + * range. It must not exceed the limits defined at . + * + * Convenience wrapper around __CPUID_LEAF(). + */ +#define CPUID_LEAF_N(_leaf, _count) \ + static_assert(_count >=3D __cpuid_leaf_subleaf_count_min(_leaf)); \ + static_assert(_count <=3D __cpuid_leaf_subleaf_count_max(_leaf)); \ + __CPUID_LEAF(leaf_ ## _leaf ## _ ## n, _count) + +/* + * struct cpuid_leaves - Structured CPUID data repository + */ +struct cpuid_leaves { + /* Leaf Subleaf number (or max number of dynamic subleaves) */ + CPUID_LEAF ( 0x0, 0 ); + CPUID_LEAF ( 0x1, 0 ); +}; + +/* + * Types for centralized CPUID tables: + * + * For external use. + */ + +/** + * struct cpuid_table - Per-CPU CPUID data repository + * @leaves: CPUID leaf/subleaf queries output storage and metadata + * + * This is to be embedded inside 'struct cpuinfo_x86' to provide cached, p= arsed, and + * sanitized CPUID query output per CPU. Thus removing the need for direc= t CPUID + * queries from call sites code. + */ +struct cpuid_table { + struct cpuid_leaves leaves; +}; + #endif /* _ASM_X86_CPUID_TYPES_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/proces= sor.h index 910e36b0c00d..88f8ee33bfca 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -16,6 +16,7 @@ struct vm86; #include #include #include +#include #include #include #include @@ -164,6 +165,7 @@ struct cpuinfo_x86 { char x86_vendor_id[16]; char x86_model_id[64]; struct cpuinfo_topology topo; + struct cpuid_table cpuid; /* in KB - valid for CPUS which support this call: */ unsigned int x86_cache_size; int x86_cache_alignment; /* In bytes */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 816E234A333 for ; Fri, 5 Sep 2025 12:15:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074548; cv=none; b=KUCnUnPNI6Nge33XxfVxDpumICO7egGUpsW1nofCkH5BKOMqeN3peXLkWtuui1NKt4hpNTYlb1NMIyzvJLfE4mc55qHStrEabdNJoUaTOGflfj+0RU6EY3lWZDgchCMP93vasBIcPi+o0DVhuaJishL0gzWwqtIhmS3rqO1dFlw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074548; c=relaxed/simple; bh=UT2k8xPnlzdweRIzqWkKlHLzoKnY64KahQOkpWodKLM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uFy+RovoAusLmZ2xc0cbQkSSmuqZQFrYoIPT/Ag2ZH7vHdQHwcnxtC7uIX67bvc16dgMKdrqwu3X8heSsG/q7yWW5ZQSkOhwVAuHwN5toGTgOWFqzvEjAj2tXGNbYi3msEF9jZ1SWhs9yDToF8cnq7v0CzUZENHBxJg9R4xntcg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ongHyHb2; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=cwrAr7vY; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ongHyHb2"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="cwrAr7vY" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074545; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+9CmVpsEmD7IM8i/kOsBRaO429i2Fexcqa0TnN+USBI=; b=ongHyHb2aeylN2vXFtqrFjrOeJevSOx4UeEK3hicKzTVSjtoOGjH0SMFnwu9CTQTGWPy/i rpURUoY3/3bcx5PgEsyYUfBAhH/VcEUfF9jdBacKzgsyvKBxU5UIAbkGrWfultJQMP6+Uf s/jPGcJofJek3Q5KDu8nrF1o9zxwoJsJIWalTvHzdnzITvCu28EPRyPHRpNnh1gboQRWTV h6LzhR5u1M/AUK9KJXwZ5WyUGm+JwXRcfts+kmqlDqkWz9ijN8O81bHAo0MePo9pZmWCKt 1yiW6aC7u0lHliBRVM0Ypi54xa9OAG+YkDAnOUhObY7nINZ+ZVkx+x124+Gf+Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074545; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+9CmVpsEmD7IM8i/kOsBRaO429i2Fexcqa0TnN+USBI=; b=cwrAr7vYeWxJoKqqT/MbPslOGdtIZzxzngKXURT7bSiBkSAXi1pxYZZ47nqwiU7djf7Sln J9gIdww6KpKolICA== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 08/35] x86/cpuid: Introduce a centralized CPUID parser Date: Fri, 5 Sep 2025 14:14:48 +0200 Message-ID: <20250905121515.192792-9-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a centralized CPUID parser to populate the per-CPU CPUID tables. To ensures consistent and early availablity of parsed CPUID data, invoke this parser during both early boot and secondary CPUs bring up. Since accessing the CPUID leaf output storage areas at 'struct cpuid_table' requires compile time tokenization, split the parser implementation into two stages: compile time macros for tokenizing the leaf/subleaf output offsets within a CPUID table, and generic runtime code to access and populate the relevant CPUID leaf/subleaf data structures using such offsets. For flexible parsing of CPUID leaf/subleaf outputs, support both generic and leaf-specific CPUID read functions. Suggested-by: Thomas Gleixner Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/api.h | 17 +++- arch/x86/include/asm/cpuid/types.h | 3 + arch/x86/kernel/cpu/Makefile | 1 + arch/x86/kernel/cpu/common.c | 2 + arch/x86/kernel/cpu/cpuid_parser.c | 123 +++++++++++++++++++++++++++++ arch/x86/kernel/cpu/cpuid_parser.h | 115 +++++++++++++++++++++++++++ 6 files changed, 257 insertions(+), 4 deletions(-) create mode 100644 arch/x86/kernel/cpu/cpuid_parser.c create mode 100644 arch/x86/kernel/cpu/cpuid_parser.h diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/= api.h index dbe94c8c4900..7b7951b28105 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -5,8 +5,10 @@ #include =20 #include +#include #include =20 +#include #include =20 /* @@ -483,14 +485,14 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) cpuid_subleaf(_cpuinfo, _leaf, 0) =20 /** - * cpuid_leaf_regs() - Access parsed CPUID data in raw format + * cpuid_leaf_raw() - Access parsed CPUID data in raw format * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') * @_leaf: CPUID leaf, in compile-time 0xN format * * Similar to cpuid_leaf(), but returns a raw 'struct cpuid_regs' pointer = to * the parsed CPUID data instead of a "typed" poi= nter. */ -#define cpuid_leaf_regs(_cpuinfo, _leaf) \ +#define cpuid_leaf_raw(_cpuinfo, _leaf) \ ((const struct cpuid_regs *)(cpuid_leaf(_cpuinfo, _leaf))) =20 /* @@ -534,7 +536,7 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) }) =20 /** - * cpuid_subleaf_n_regs() - Access parsed CPUID data for leaf with dynamic= subleaf range + * cpuid_subleaf_n_raw() - Access parsed CPUID data for leaf with dynamic = subleaf range * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86') * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d * @_subleaf: Subleaf number, which can be passed dynamically. It must be= smaller @@ -543,7 +545,7 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) * Similar to cpuid_subleaf_n(), but returns a raw 'struct cpuid_regs' poi= nter to * the parsed CPUID data instead of a "typed" poi= nter. */ -#define cpuid_subleaf_n_regs(_cpuinfo, _leaf, _subleaf) \ +#define cpuid_subleaf_n_raw(_cpuinfo, _leaf, _subleaf) \ ((const struct cpuid_regs *)cpuid_subleaf_n(_cpuinfo, _leaf, _subleaf)) =20 /** @@ -562,4 +564,11 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) __cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n); \ }) =20 +/* + * CPUID parser exported APIs: + */ + +void __init cpuid_parser_early_scan_cpu(struct cpuinfo_x86 *c); +void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c); + #endif /* _ASM_X86_CPUID_API_H */ diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index bd6e016ef035..9b8bd6b22ff3 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -32,6 +32,9 @@ enum cpuid_regs_idx { #define CPUID_LEAF_FREQ 0x16 #define CPUID_LEAF_TILE 0x1d =20 +#define CPUID_BASE_START 0x0 +#define CPUID_BASE_END (CPUID_BASE_START + 0xffff) + /* * Types for CPUID(0x2) parsing: */ diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 1e26179ff18c..b2421cfb59ed 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -19,6 +19,7 @@ KCSAN_SANITIZE_common.o :=3D n =20 obj-y :=3D cacheinfo.o scattered.o obj-y +=3D topology_common.o topology_ext.o topology_amd.o +obj-y +=3D cpuid_parser.o obj-y +=3D common.o obj-y +=3D rdrand.o obj-y +=3D match.o diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 34a054181c4d..43582d7e167d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1729,6 +1729,7 @@ static void __init early_identify_cpu(struct cpuinfo_= x86 *c) =20 /* cyrix could have cpuid enabled via c_identify()*/ if (cpuid_feature()) { + cpuid_parser_scan_cpu(c); cpu_detect(c); get_cpu_vendor(c); intel_unlock_cpuid_leafs(c); @@ -2109,6 +2110,7 @@ void identify_secondary_cpu(unsigned int cpu) *c =3D boot_cpu_data; c->cpu_index =3D cpu; =20 + cpuid_parser_scan_cpu(c); identify_cpu(c); #ifdef CONFIG_X86_32 enable_sep_cpu(); diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c new file mode 100644 index 000000000000..15264696eaad --- /dev/null +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Centralized CPUID parser (for populating the system's CPUID tables.) + */ + +#include +#include + +#include +#include +#include + +#include "cpuid_parser.h" + +/* + * Leaf read functions: + */ + +/* + * Default CPUID parser read function + * + * Satisfies the requirements stated at 'struct cpuid_parse_entry'->read(). + */ +static void cpuid_read_generic(const struct cpuid_parse_entry *e, struct c= puid_read_output *output) +{ + for (int i =3D 0; i < e->maxcnt; i++, output->regs++, output->info->nr_en= tries++) + cpuid_read_subleaf(e->leaf, e->subleaf + i, output->regs); +} + +/* + * CPUID parser tables: + * + * Since these tables reference the leaf read functions above, they must be + * defined afterwards. + */ + +static const struct cpuid_parse_entry cpuid_parse_entries[] =3D { + CPUID_PARSE_ENTRIES +}; + +/* + * Leaf-independent parser code: + */ + +static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsi= gned int range) +{ + const struct leaf_0x0_0 *l0 =3D __cpuid_table_subleaf(t, 0x0, 0); + + switch (range) { + case CPUID_BASE_START: return l0 ? l0->max_std_leaf : 0; + default: return 0; + } +} + +static bool +cpuid_range_valid(const struct cpuid_table *t, unsigned int leaf, unsigned= int start, unsigned int end) +{ + if (leaf < start || leaf > end) + return false; + + return leaf =3D=3D start || leaf <=3D cpuid_range_max_leaf(t, start); +} + +static bool cpuid_leaf_in_range(const struct cpuid_table *t, unsigned int = leaf) +{ + return cpuid_range_valid(t, leaf, CPUID_BASE_START, CPUID_BASE_END); +} + +static void +cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry ent= ries[], unsigned int nr_entries) +{ + const struct cpuid_parse_entry *entry =3D entries; + + for (unsigned int i =3D 0; i < nr_entries; i++, entry++) { + struct cpuid_read_output output =3D { + .regs =3D cpuid_table_query_regs_p(t, entry->regs_offs), + .info =3D cpuid_table_query_info_p(t, entry->info_offs), + }; + + if (!cpuid_leaf_in_range(t, entry->leaf)) + continue; + + WARN_ON_ONCE(output.info->nr_entries !=3D 0); + entry->read(entry, &output); + } +} + +/* + * Exported APIs: + */ + +/** + * cpuid_parser_scan_cpu() - Populate current CPU's CPUID table + * @c: CPU capability structure associated with the current CPU + * + * Populate the CPUID table embedded within @c with parsed CPUID data. Si= nce all CPUID + * instructions are invoked locally, this must be called on the CPU associ= ated with @c. + */ +void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c) +{ + struct cpuid_table *table =3D &c->cpuid; + + /* + * For correctness, clear the CPUID table first. + * + * This is due to the CPUID parser APIs at using leaf->= nr_entries + * as a leaf validity check: non-zero means that the CPUID leaf's cached = output is + * valid. Otherwise, NULL is returned. + * + * For the primary CPU's early boot code, the tables are already zeroed. = For + * secondary CPUs though, their capability structures (containing the CPU= ID table) + * are copied from the primary CPU. This would result in a leaf->nr_entr= ies value + * carry over, unless the table is zeroed first. + * + * Also for CPUID table re-scans, which are triggered by hardware state c= hanges, + * previously valid CPUID leaves can become no longer available and thus = no longer + * parsed (leaving stale leaf "nr_entries" fields behind.) The table mus= t thus be + * also cleared. + */ + memset(table, 0, sizeof(*table)); + + cpuid_fill_table(table, cpuid_parse_entries, ARRAY_SIZE(cpuid_parse_entri= es)); +} diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h new file mode 100644 index 000000000000..acddcbc9bd06 --- /dev/null +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ARCH_X86_CPUID_PARSER_H +#define _ARCH_X86_CPUID_PARSER_H + +#include + +/* + * 'struct cpuid_leaves' CPUID query output storage area accessors: + * + * @_leaf: CPUID leaf, in compile-time 0xN format + * @_subleaf: CPUID subleaf, in compile-time decimal format + * + * Since accessing the CPUID leaf output storage areas at 'struct cpuid_le= aves' requires + * compile time tokenization, split the CPUID parser implementation into t= wo stages: + * compile time macros for tokenizing the leaf/subleaf output offsets with= in the CPUID + * table, and generic runtime code to access and populate the relevant CPU= ID leaf/subleaf + * output data structures using such offsets. + * + * That is, the output of the __cpuid_leaves_query_*_offset() macros will= be cached by a + * compile time "parse entry" (see 'struct cpuid_parse_entry'). The runti= me parser code + * will then utilize such offsets by passing them to cpuid_table_query_*_p= () functions. + */ + +#define __cpuid_leaves_query_regs_offset(_leaf, _subleaf) \ + offsetof(struct cpuid_leaves, leaf_ ## _leaf ## _ ## _subleaf) + +#define __cpuid_leaves_query_info_offset(_leaf, _subleaf) \ + offsetof(struct cpuid_leaves, leaf_ ## _leaf ## _ ## _subleaf ## _ ## inf= o) + +#define __cpuid_leaves_query_regs_maxcnt(_leaf, _subleaf) \ + ARRAY_SIZE(((struct cpuid_leaves *)NULL)->leaf_ ## _leaf ## _ ## _subleaf) + +static inline struct cpuid_regs * +cpuid_table_query_regs_p(const struct cpuid_table *t, unsigned long regs_o= ffset) +{ + return (struct cpuid_regs *)((unsigned long)(&t->leaves) + regs_offset); +} + +static inline struct leaf_query_info * +cpuid_table_query_info_p(const struct cpuid_table *t, unsigned long info_o= ffset) +{ + return (struct leaf_query_info *)((unsigned long)(&t->leaves) + info_offs= et); +} + +/** + * struct cpuid_read_output - Output of a CPUID parser read operation + * @regs: Pointer to an array of CPUID outputs, where each array element c= overs the + * full EAX->EDX output range. + * @info: Pointer to query info; for saving the number of filled @regs arr= ay elements. + * + * A CPUID parser read function like cpuid_read_generic() or cpuid_read_0x= N() uses this + * structure to save its CPUID query outputs. Actual storage for @regs an= d @info is provided + * by its caller, and is typically within a CPU's CPUID table (struct cpui= d_table.leaves). + * + * See struct cpuid_parse_entry.read(). + */ +struct cpuid_read_output { + struct cpuid_regs *regs; + struct leaf_query_info *info; +}; + +/** + * struct cpuid_parse_entry - Runtime CPUID parsing context for @leaf/@sub= leaf + * @leaf: Leaf number to be parsed + * @subleaf: Subleaf number to be parsed + * @regs_offs: Offset within 'struct cpuid_leaves' for saving CPUID @leaf/= @subleaf output; to be + * passed to cpuid_table_query_regs_p(). + * @info_offs: Offset within 'struct cpuid_leaves' for accessing @leaf/@su= bleaf parse info; to be + * passed to cpuid_table_query_info_p(). + * @maxcnt: Maximum number of output storage entries available for the @le= af/@subleaf query + * @read: Read function for this entry. It must save the parsed CPUID out= put to the passed + * 'struct cpuid_read_output'->regs registers array of size >=3D @maxcnt.= It must set + * 'struct cpuid_read_output'->info.nr_entries to the actual number of st= orage output + * entries filled. A generic implementation is provided at cpuid_read_ge= neric(). + */ +struct cpuid_parse_entry { + unsigned int leaf; + unsigned int subleaf; + unsigned int regs_offs; + unsigned int info_offs; + unsigned int maxcnt; + void (*read)(const struct cpuid_parse_entry *e, struct cpuid_read_output= *o); +}; + +#define __CPUID_PARSE_ENTRY(_leaf, _subleaf, _suffix, _reader_fn) \ + { \ + .leaf =3D _leaf, \ + .subleaf =3D _subleaf, \ + .regs_offs =3D __cpuid_leaves_query_regs_offset(_leaf, _suffix), \ + .info_offs =3D __cpuid_leaves_query_info_offset(_leaf, _suffix), \ + .maxcnt =3D __cpuid_leaves_query_regs_maxcnt(_leaf, _suffix), \ + .read =3D cpuid_read_ ## _reader_fn, \ + } + +/* + * CPUID_PARSE_ENTRY_N() is for CPUID leaves with a dynamic subleaf range. + * Check __CPUID_LEAF() and CPUID_LEAF_N(). + */ + +#define CPUID_PARSE_ENTRY(_leaf, _subleaf, _reader_fn) \ + __CPUID_PARSE_ENTRY(_leaf, _subleaf, _subleaf, _reader_fn) + +#define CPUID_PARSE_ENTRY_N(_leaf, _reader_fn) \ + __CPUID_PARSE_ENTRY(_leaf, __cpuid_leaf_first_dynamic_subleaf(_leaf), n, = _reader_fn) + +/* + * CPUID parser tables: + */ + +#define CPUID_PARSE_ENTRIES \ + /* Leaf Subleaf Reader function */ \ + CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \ + +#endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9524350848 for ; Fri, 5 Sep 2025 12:15:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074551; cv=none; b=ez/pS8NXWH7bSAa/bm7C32/N1RRZcRiDa5YVpGChdZwe70dPDDB5/+ovCyStGDsEavAP+Tm6MDC+8NvbdbhCq6KkguClrW0fM6MHxKFf1zCGbFJYY0JGSOGMdxMUZpGQNWlRXeCKLyMxBJpY+fzVRkPxLC/DdiF1vgrr+l0tFTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074551; c=relaxed/simple; bh=GZR8RHQZex4Pd9dmQhrZYFm58mezVjJewpqZgR2DRr4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RTBtnsBumA03u7RPfozWJtIyuDkWmyFyrCVCpSw4wAixn5dsFBLvrH8hrzyHG/Z7IJIyYe/WHycxNP/7hZsh0shPF7vLVDmVH79qb32sO9yW8ZdMJHQEdhLQuo0CXDLjMJYdsbDi8gfjRmAHemHFvSUeZF6V2uzrP8M5bCZNeIo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=sA6wyUrS; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=dw9LI+fH; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="sA6wyUrS"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="dw9LI+fH" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074548; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1FmzRFTeoeh2phfMhf2hDpLbShwrkipDxrnDX8PpCbU=; b=sA6wyUrSGqUQaMf+xZvg+C9z8TaT+WN9wlFkDXofdBWPPKfdvOL5aWluNH1RiCeEex0RRo ra5BCLjhXlQqSQP6VXK0Mv/8pSo/znJ+ph6yJeRO3OX3qrXjRvPxVwy6s1Kfo2SvPiV6by Vr9dIEge9Mku/k8X7IazK3w1SQUOp9aARzyWv2jl5a/uctTv5eMsUzXy9oZbW9Q3pPyiGL NFu4FlURrrx/7UCvcmvKYWCYObCUxzA02DklbJi/Di3QFDxDur+7YilRdvCbqgD2n5+wJF RWnjKyA7X6CSgoF0MkHNohoz4cXmrCrVcrsAfha5rUJL8cbhGnPhgiF6bZ/Upg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074548; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1FmzRFTeoeh2phfMhf2hDpLbShwrkipDxrnDX8PpCbU=; b=dw9LI+fHlZKkjRPDRVTxpvup1masJHL9QDi91AuHTLc+AXcE4ZRCWWo/ixE8GJ1lBvyK9d Q/QyGuraQ6nX8ZCw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 09/35] x86/cpu: Use parsed CPUID(0x0) Date: Fri, 5 Sep 2025 14:14:49 +0200 Message-ID: <20250905121515.192792-10-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use parsed CPUID(0x0) access instead of a direct CPUID query. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/common.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 43582d7e167d..e081f92ddfe9 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -896,11 +896,12 @@ void get_cpu_vendor(struct cpuinfo_x86 *c) =20 void cpu_detect(struct cpuinfo_x86 *c) { - /* Get vendor name */ - cpuid(0x00000000, (unsigned int *)&c->cpuid_level, - (unsigned int *)&c->x86_vendor_id[0], - (unsigned int *)&c->x86_vendor_id[8], - (unsigned int *)&c->x86_vendor_id[4]); + const struct leaf_0x0_0 *l0 =3D cpuid_leaf(c, 0x0); + + c->cpuid_level =3D l0->max_std_leaf; + *(u32 *)&c->x86_vendor_id[0] =3D l0->cpu_vendorid_0; + *(u32 *)&c->x86_vendor_id[4] =3D l0->cpu_vendorid_1; + *(u32 *)&c->x86_vendor_id[8] =3D l0->cpu_vendorid_2; =20 c->x86 =3D 4; /* Intel-defined flags: level 0x00000001 */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BE0B350856 for ; Fri, 5 Sep 2025 12:15:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074555; cv=none; b=jFYNyLSH3RY7ozRUrHYhtwJDSCiuAEbtmTIArEGqwZvLgeLQAmdCqNj58kjpuvMl1TvnV9NE11qr4c+vKY9koiCILkGzgxR/eTAxhItfHH+dvlaYC1kqM+HxzjajGXgW4zAZU/G5S4TwYn9NXRyjyiae6jURfLXurZIa9qQmPoM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074555; c=relaxed/simple; bh=CZQxvJ8yZW2Uybl6DNxQviBz3JoFOy/YVYuEocyTwn4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U+RMMSRvhg2dM/cCIpQayrbDqiY/sZtf26Me7837M+RBDUCJkgLJeeNHamgUOrnikHhxxGY+tXEETaPbeifmSOZsnZ+2wV002iZxZrSp0ef1hZEKjI3p8koXvEYXHMz8KiUg+iC8mRmLCO6ix3C8uhJXoiPeZ2LXW2Tz3xR19yE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=B2JfNfy+; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=bQnChvHy; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="B2JfNfy+"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="bQnChvHy" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074551; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pV8btSTDmEhVwNVX3DuRLi9n1R7LR7F6k5vsNfqRbDo=; b=B2JfNfy+9ybYMxYNnXVMtsvNCnRA9ny79B9zuCGUWJAZBZZIVfdCXvRyP6z7d68ExeNytm QCz+6u0qDQ+I+F9gJqgcROdNO6n1GB61ZtVfdFRSatlC9eUXL8ogmf1MZnX4CVzVc6uuUk BiiqarrstuYA0yKMzEEjD/YNEaScMBZWCUrUCPOt+sgb3rcrsFRGzloilNSde0vPjdRJpf iTUiHKMdlBzD4QRK0JwwomfYOB3XYJOXdqRT0Inlguuu+7Q60HzbdDIL+umBv0m9O96zM/ 43Rb5+ft/2BJXVfXHLYfS4P5O6MxI2+GYCDXtXpOZNK/yne6+Qs9fpl3Q8KZXA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074551; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pV8btSTDmEhVwNVX3DuRLi9n1R7LR7F6k5vsNfqRbDo=; b=bQnChvHyCXrLC0Ew9zpnTOKqLFDKSeOGn84GuyFZiZ0U+jZr+cxoJqZRxdVrxBtx8Zi05p yvK43YNoUEdWI8CA== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 10/35] x86/lib: Add CPUID(0x1) CPU family and model calculation Date: Fri, 5 Sep 2025 14:14:50 +0200 Message-ID: <20250905121515.192792-11-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The x86 library code provides x86_family() and x86_model(). They take raw CPUID(0x1) register output, extract the necessary fields with bitwise operations, then calculate the CPU family and model out of that. In follow-up work, the x86 subystem will use parsed CPUID access, along with its auto-generated CPUID leaf data types, instead of direct CPUID access. Introduce x86 family and model calculation functions to x86/lib that take such auto-generateds 'struct leaf_0x1_0' data types. Refactor the original bitwise operations code so that no logic is duplicated. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpu.h | 6 ++++++ arch/x86/lib/cpu.c | 41 ++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index ad235dda1ded..90902cd91335 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -7,7 +7,9 @@ #include #include #include + #include +#include =20 #ifndef CONFIG_SMP #define cpu_physical_id(cpu) boot_cpu_physical_apicid @@ -25,6 +27,10 @@ int mwait_usable(const struct cpuinfo_x86 *); unsigned int x86_family(unsigned int sig); unsigned int x86_model(unsigned int sig); unsigned int x86_stepping(unsigned int sig); + +unsigned int cpuid_family(const struct leaf_0x1_0 *l); +unsigned int cpuid_model(const struct leaf_0x1_0 *l); + #ifdef CONFIG_X86_BUS_LOCK_DETECT extern void __init sld_setup(struct cpuinfo_x86 *c); extern bool handle_user_split_lock(struct pt_regs *regs, long error_code); diff --git a/arch/x86/lib/cpu.c b/arch/x86/lib/cpu.c index 7ad68917a51e..eac217d637ac 100644 --- a/arch/x86/lib/cpu.c +++ b/arch/x86/lib/cpu.c @@ -1,36 +1,43 @@ // SPDX-License-Identifier: GPL-2.0-only #include #include + #include +#include =20 -unsigned int x86_family(unsigned int sig) +static unsigned int __x86_family(unsigned int base_fam, unsigned int ext_f= am) { - unsigned int x86; - - x86 =3D (sig >> 8) & 0xf; + return (base_fam =3D=3D 0xf) ? base_fam + ext_fam : base_fam; +} =20 - if (x86 =3D=3D 0xf) - x86 +=3D (sig >> 20) & 0xff; +static unsigned int +__x86_model(unsigned int family, unsigned int base_model, unsigned int ext= _model) +{ + return (family >=3D 0x6) ? base_model | ext_model << 4 : base_model; +} =20 - return x86; +unsigned int x86_family(unsigned int sig) +{ + return __x86_family((sig >> 8) & 0xf, (sig >> 20) & 0xff); } EXPORT_SYMBOL_GPL(x86_family); =20 -unsigned int x86_model(unsigned int sig) +unsigned int cpuid_family(const struct leaf_0x1_0 *l) { - unsigned int fam, model; - - fam =3D x86_family(sig); - - model =3D (sig >> 4) & 0xf; - - if (fam >=3D 0x6) - model +=3D ((sig >> 16) & 0xf) << 4; + return __x86_family(l->base_family_id, l->ext_family); +} =20 - return model; +unsigned int x86_model(unsigned int sig) +{ + return __x86_model(x86_family(sig), (sig >> 4) & 0xf, (sig >> 16) & 0xf); } EXPORT_SYMBOL_GPL(x86_model); =20 +unsigned int cpuid_model(const struct leaf_0x1_0 *l) +{ + return __x86_model(cpuid_family(l), l->base_model, l->ext_model); +} + unsigned int x86_stepping(unsigned int sig) { return sig & 0xf; --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A91E6350D5C for ; Fri, 5 Sep 2025 12:15:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074558; cv=none; b=WvqmDyVDQqbf81Vhhu37ncyHXc95XD4SvEiFddrRwgI6VVEi0N1N6LKAB+0lHuT+JG//HE9ab101MmVUMtn0cNevGCPANWrdPS+kB+o2gQRpYkrrRa2DY+rjDu6nv7CVAsPvK7J+Dxm1/trFGQHygwUJ/W0a1kRzhzCJqCpzaFc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074558; c=relaxed/simple; bh=ZbKPGgCVpT+HjHVyzGSP+eVNuk0jQWeGMUV8pTv848Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tuWw7Gi05uTvNPxlqW6deZM90Kho93L29umfUVysRcr3eGUT81sLDF9+yOrn3scW3b+081yn2PwZfQicfGry0pCG5d1E+58pZ+Crd+cGKp01x+ZPP1qCsQgEcmjRjOs+BGcQ86MuMWirknr6RKALqddkpcYlL2EKYNeIJi36auw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ZBeV/DaU; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=qfa75l7X; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ZBeV/DaU"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="qfa75l7X" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074555; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CYzQQ5I5COAby63SgxsfwehP/5pmXdd+M0EHhhjXcF0=; b=ZBeV/DaUfTD2QtelW1J9Mta2FmAmbUBuEvg0ogZA7P0iOedXebHdh3dyyLsCLzdzAKmo7b kwNPxRcPGNH8ivvA2GabRBUDuoYSjYH5zP5VcERzUL3YfUA/9XmvjW5yFesXyzhC50zSaR X/6ZsRbOaxUwsp+jUPC9m3hEkgFHSdUfwdnh5QxxZkaRSPN5vcmhcCwEWw4Ok82CleoKG2 EilnjXZiqjSV+2WRuksCnkbAQrX0D1wfe6DzMVpYYCwBHUJaqyO1et8N2MtUtPaSDRdb9F f12tVpp7A1GC4VbXJffz8Dmb/xOicWGGMDV2ZwRhYLC9ptr4HjJROeremuE7wg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074555; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CYzQQ5I5COAby63SgxsfwehP/5pmXdd+M0EHhhjXcF0=; b=qfa75l7XV/kmSUDna6aG6j6k4oudYNLLJ0I4LNDBBpBODmBxcwJ5VzDjKcQYvPJ9rIuNmc wcP18nrjVprxT5Bg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 11/35] x86/cpu: Use parsed CPUID(0x1) Date: Fri, 5 Sep 2025 14:14:51 +0200 Message-ID: <20250905121515.192792-12-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the early boot CPU detection code, use parsed CPUID(0x1) access instead of a direct CPUID query. Beside the CPUID parser centralization benefits, this allows using the auto-generated data types, and their full C99 bitfields, instead of doing ugly bitwise operations on CPUID register output. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/common.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index e081f92ddfe9..f989c8099490 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -897,6 +897,7 @@ void get_cpu_vendor(struct cpuinfo_x86 *c) void cpu_detect(struct cpuinfo_x86 *c) { const struct leaf_0x0_0 *l0 =3D cpuid_leaf(c, 0x0); + const struct leaf_0x1_0 *l1 =3D cpuid_leaf(c, 0x1); =20 c->cpuid_level =3D l0->max_std_leaf; *(u32 *)&c->x86_vendor_id[0] =3D l0->cpu_vendorid_0; @@ -904,17 +905,14 @@ void cpu_detect(struct cpuinfo_x86 *c) *(u32 *)&c->x86_vendor_id[8] =3D l0->cpu_vendorid_2; =20 c->x86 =3D 4; - /* Intel-defined flags: level 0x00000001 */ - if (c->cpuid_level >=3D 0x00000001) { - u32 junk, tfms, cap0, misc; =20 - cpuid(0x00000001, &tfms, &misc, &junk, &cap0); - c->x86 =3D x86_family(tfms); - c->x86_model =3D x86_model(tfms); - c->x86_stepping =3D x86_stepping(tfms); + if (l1) { + c->x86 =3D cpuid_family(l1); + c->x86_model =3D cpuid_model(l1); + c->x86_stepping =3D l1->stepping; =20 - if (cap0 & (1<<19)) { - c->x86_clflush_size =3D ((misc >> 8) & 0xff) * 8; + if (l1->clflush) { + c->x86_clflush_size =3D l1->clflush_size * 8; c->x86_cache_alignment =3D c->x86_clflush_size; } } --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3742352075 for ; Fri, 5 Sep 2025 12:15:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074561; cv=none; b=V5laqWgQyMrYsqTnRz5C1SY9AJqDnIJ5AYUDbmfVgCStTdiPjk/RGYuatovLya6YrvpAJJZCP1QngOzeghgNgYr2PTA+9vLpP8+boOCACpHBSz76ce2Mlot7a5QnLKGoQsQQI9zrHOXQDiCt52fNmjqh01Ysf6IQ+IKTUsnrchY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074561; c=relaxed/simple; bh=I1leyWVm0tz3zHKIhmHsfiXis5rK21DFkRDwhPEuJBw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=R//295E5nCr0+VEDe1fi2ry6TV2uNAOXniwH+sNHR7904WfrvQFHSIS5ik26KXoOOUP6DbtlbQ0Nayfy41VlKAHk2vCVAXvorg6zKHJf3Qlh6kH7lqEEvtoMJjvwYWEXYZ7TDLLvLFgYSvIDv5590gXVK/9/kKWZQieCuBXxiFQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=b4m5mJxC; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=RVpv5YJ5; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="b4m5mJxC"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="RVpv5YJ5" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074558; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ymPEj5IwoeEiVyTDVAlIcYp8+kC3Z0KCzQGCWXoVM90=; b=b4m5mJxCSmiRBhVdGUux+CWtR1rOrSIwR81M8v1r6WHylrWxP2m6ZqDoIYOzFeb5OGOZ2m e1tKd/WUtzXonzqmp03KGv7oSr1Ls7O+G76QXqmz1hfafxBgz8pKfC+Z64UIXlAyLQ3ogo CiHYct5R3YOcrkqYX5w6Yv/LwfTVPuD0avIP4ruJa4cGUSOoZwKjV7466BdPr6ckRaapxp zXKGIlp1fQzu1CVBRolzkDdHNggycNfHQuLqCjDOZCuVvzVEIniYmE4inJe1P3ZgxtlcxV 1YhdU0R+z+RwzYbczp55SXQLV+V9gKAGjgdUc+3IrTAv8tlG/nUvRdOjCXhpxQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074558; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ymPEj5IwoeEiVyTDVAlIcYp8+kC3Z0KCzQGCWXoVM90=; b=RVpv5YJ5nn4Kgtm/hK88YaYxOEvzVDheqZa10ZUcG0Uf6DYcQKH4vmpzcRj4n6VJu/t6yb xKSH9Lj84j5I3CAQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 12/35] x86/cpuid: Parse CPUID(0x80000000) Date: Fri, 5 Sep 2025 14:14:52 +0200 Message-ID: <20250905121515.192792-13-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add CPUID parser logic for CPUID(0x80000000). Verify the query output beforehand, since legacy 32-bit Intel machines without an extended range will just repeat the output of the highest standard CPUID leaf available. This is similar to what is done at arch/x86/kernel/head_32.S and arch/x86/kernel/cpu/common.c. References: 8a50e5135af0 ("x86-32: Use symbolic constants, safer CPUID when= enabling EFER.NX") References: 67ad24e6d39c ("- pre5: - Rasmus Andersen: add proper...") #= Historical git Signed-off-by: Ahmed S. Darwish Cc: "H. Peter Anvin" Link: https://lore.kernel.org/r/d4fcfd91-cc92-4b3c-9dd2-56ecd754cecc@citrix= .com --- arch/x86/include/asm/cpuid/types.h | 7 ++++++- arch/x86/kernel/cpu/cpuid_parser.c | 22 +++++++++++++++++++++- arch/x86/kernel/cpu/cpuid_parser.h | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index 9b8bd6b22ff3..e57245ca6419 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -33,7 +33,11 @@ enum cpuid_regs_idx { #define CPUID_LEAF_TILE 0x1d =20 #define CPUID_BASE_START 0x0 -#define CPUID_BASE_END (CPUID_BASE_START + 0xffff) +#define CPUID_EXT_START 0x80000000 + +#define __CPUID_RANGE_END(idx) ((idx) + 0xffff) +#define CPUID_BASE_END __CPUID_RANGE_END(CPUID_BASE_START) +#define CPUID_EXT_END __CPUID_RANGE_END(CPUID_EXT_START) =20 /* * Types for CPUID(0x2) parsing: @@ -232,6 +236,7 @@ struct cpuid_leaves { /* Leaf Subleaf number (or max number of dynamic subleaves) */ CPUID_LEAF ( 0x0, 0 ); CPUID_LEAF ( 0x1, 0 ); + CPUID_LEAF ( 0x80000000, 0 ); }; =20 /* diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c index 15264696eaad..9c40c180e3d4 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -27,6 +27,23 @@ static void cpuid_read_generic(const struct cpuid_parse_= entry *e, struct cpuid_r cpuid_read_subleaf(e->leaf, e->subleaf + i, output->regs); } =20 +static void cpuid_read_0x80000000(const struct cpuid_parse_entry *e, struc= t cpuid_read_output *output) +{ + struct leaf_0x80000000_0 *el0 =3D (struct leaf_0x80000000_0 *)output->reg= s; + + cpuid_read_subleaf(e->leaf, e->subleaf, el0); + + /* + * Protect against Intel 32-bit CPUs lacking an extended CPUID range. A + * CPUID(0x80000000) query on such machines will just repeat the output + * of the highest standard CPUID leaf. + */ + if ((el0->max_ext_leaf & 0xffff0000) !=3D 0x80000000) + return; + + output->info->nr_entries =3D 1; +} + /* * CPUID parser tables: * @@ -45,9 +62,11 @@ static const struct cpuid_parse_entry cpuid_parse_entrie= s[] =3D { static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsi= gned int range) { const struct leaf_0x0_0 *l0 =3D __cpuid_table_subleaf(t, 0x0, 0); + const struct leaf_0x80000000_0 *el0 =3D __cpuid_table_subleaf(t, 0x800000= 00, 0); =20 switch (range) { case CPUID_BASE_START: return l0 ? l0->max_std_leaf : 0; + case CPUID_EXT_START: return el0 ? el0->max_ext_leaf : 0; default: return 0; } } @@ -63,7 +82,8 @@ cpuid_range_valid(const struct cpuid_table *t, unsigned i= nt leaf, unsigned int s =20 static bool cpuid_leaf_in_range(const struct cpuid_table *t, unsigned int = leaf) { - return cpuid_range_valid(t, leaf, CPUID_BASE_START, CPUID_BASE_END); + return cpuid_range_valid(t, leaf, CPUID_BASE_START, CPUID_BASE_END) || + cpuid_range_valid(t, leaf, CPUID_EXT_START, CPUID_EXT_END); } =20 static void diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index acddcbc9bd06..39a361eed7ce 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -111,5 +111,6 @@ struct cpuid_parse_entry { /* Leaf Subleaf Reader function */ \ CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ =20 #endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C897F350D7B for ; Fri, 5 Sep 2025 12:16:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074564; cv=none; b=ibWUVUW660izs74GwnZchwnzYLDh7Pa5hWkMZOrJl4VavCdP344f1Ipbmas9aBPZy1zth625mSnADmT3BjTPEevujfU2YpO46aMr33ccoxy43TcUuv+nmTT6QTMc3UkmMwmmXVgsClYdl4kLiWbMPuyPxN9ve89GwOKkWN9lYVc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074564; c=relaxed/simple; bh=YE1zP9F3PJBAVUw+8cemB4kXR3Y9cKoz3JRrv1dxu68=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ke1ILSozuEUeqoYoTC62x3uxRPjt5N45AYEZKIefh/7Yz6uoo+ff7KD0trfOw4d6D4uX1jM48u7nrog+gJBbIHtfvUm0D+B45wyFlqg7snSazzl73Xsb0/ysNH+PDYyjMXN3lNoebUfhZV0Tn0tEldMiJxh2MsXEYvj3Ryb8BeI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=RPxaDtPU; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=gpgHbB7x; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="RPxaDtPU"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="gpgHbB7x" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074561; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FVtzqcPzX3LElgpViGnnRqDbJ6yW0GrL6GmMecTYiO4=; b=RPxaDtPUJoAJBFyjSCiO2js7uiShxpE3hZwQsR5y0eukUnPOysGBQzg34CRBACKUkhiIqq IZIJu5YCpNmbIM+Cbst5dVPc3PQG1Rd9pnNot658x5s34PxiVXpp3ntiULGWDnVcVoCxds ZED8a0Qn1lpvn7ha4LZ17hEf17uzcBKQ8WS8RQOSR2W11TMeRFtDsIw/Rl6Xx4KETaTLFz n2mX/5DJJ2yAoOxigkcs//OiR2FiD+NlyKEULaU1S7MnjNg2OhvOVwTmtU7fnKfHLUxGRi ectnMh2Zo7xLA3XOriYEg6lE5P0Oj+GrsuWTiTxYF34J0jMtsPT9hvN49LZrYQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074561; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FVtzqcPzX3LElgpViGnnRqDbJ6yW0GrL6GmMecTYiO4=; b=gpgHbB7xEokD//dMTmkFk3eV5DI0j0/rGsJm8S4z6MIqlt6K9DfNRS7G20Y3MxhhjaA291 QA7d7xIJfNHj68CQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 13/35] x86/cpu: Use parsed CPUID(0x80000000) Date: Fri, 5 Sep 2025 14:14:53 +0200 Message-ID: <20250905121515.192792-14-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the early boot code, use parsed CPUID(0x80000000) access instead of a direct CPUID query. Note that the modified code has the check: extended_cpuid_level =3D ((eax & 0xffff0000) =3D=3D 0x80000000) ? eax := 0; to protect against Intel 32-bit machines without an extended range, where a CPUID(0x80000000) query will repeat the max-valid standard CPUID leaf output. A similar check is already done at the CPUID parser's own CPUID(0x80000000) code: if ((l->max_ext_leaf & 0xffff0000) !=3D 0x80000000) { // Handle error } Thus, for the modified call-site code, the parsed CPUID access NULL check: el0 =3D cpuid_leaf(c, 0x80000000); extended_cpuid_level =3D el0 ? el0->max_ext_leaf : 0; is sufficient. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/common.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f989c8099490..0a0340a7ac1c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -971,6 +971,7 @@ static void init_speculation_control(struct cpuinfo_x86= *c) =20 void get_cpu_cap(struct cpuinfo_x86 *c) { + const struct leaf_0x80000000_0 *el0; u32 eax, ebx, ecx, edx; =20 /* Intel-defined flags: level 0x00000001 */ @@ -1006,12 +1007,8 @@ void get_cpu_cap(struct cpuinfo_x86 *c) c->x86_capability[CPUID_D_1_EAX] =3D eax; } =20 - /* - * Check if extended CPUID leaves are implemented: Max extended - * CPUID leaf must be in the 0x80000001-0x8000ffff range. - */ - eax =3D cpuid_eax(0x80000000); - c->extended_cpuid_level =3D ((eax & 0xffff0000) =3D=3D 0x80000000) ? eax = : 0; + el0 =3D cpuid_leaf(c, 0x80000000); + c->extended_cpuid_level =3D el0 ? el0->max_ext_leaf : 0; =20 if (c->extended_cpuid_level >=3D 0x80000001) { cpuid(0x80000001, &eax, &ebx, &ecx, &edx); --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 932F3352FC4 for ; Fri, 5 Sep 2025 12:16:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074567; cv=none; b=czD+eXhmR4cKgER8UbJlKoKmmutj2NvDZ8FInUir48cDVkQyXFb0lPokRR9BqGj554wBTR7dAlk7zfAMy+76SvyOfzgnu6YCk8oAblM2IuCSWn3M4Poii/BpjvV5S2+EDwFXPJeHAMUjTPX1zH1nuZEJ1JMRJnSgA7hN02Xukoc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074567; c=relaxed/simple; bh=wxRYS1wSWfVVXGDRY/WxGTafHuX3koQQP4WL7Xm05Z4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ci4VD5p7LL3g7CwtqH135KhF1bJpSGqJtq9Yl31ZNp3BovyK1RzwZ4OIE1XGOpPSllU1Oa7BpDvwo4MuKgIX3+NUg5dObyd17grdCmrWS2lY1a76x8KiAGABCv3tPAzb+leOtN3AEgZr5dvaLzmpt9tIEpqC8I3F9b4lt/P20N8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=0KuzPDdg; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=E6iSZp6e; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="0KuzPDdg"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="E6iSZp6e" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074564; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gIy4/xYKlSbEAWwZB7LbxZ9FECOWkxRxcaIrnJxGy2U=; b=0KuzPDdgkiITsWB0SO50RDoovlgl4She+dIzmIMBzTF5kQ66lVNF1ZJt8VhdugZrNwiu5C opDyfJFJmepT5g73OR3e/jQsmg8RZeAsJ7XBaNADq3MG4hkQAmcTMvorjoLAsj9W98RuDN DqFhAlV6fV5IYsOimHXT+ZOzDM8KfaO6oocOnnW38lsU7EKh3DUQY8FsOWBGPR61XlFdDv whAuREqJ3YFSJDLdDMj+yl4FRLMpaHfqNFv7bQRf4ovj9BsyBKYNocbGxeXUHB2B8brlJL aGzleTlm0NpIXYbmwsBwWrdBKpyOf7JhXgr5xfOz7BUB/6SiSsLwrlJTjMmK9Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074564; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gIy4/xYKlSbEAWwZB7LbxZ9FECOWkxRxcaIrnJxGy2U=; b=E6iSZp6e5TMVZrZTudWzUqkC1Dup7GbjwGm85O7EEzohJprdwq4fW1OlevsU2bpEgQBXua RfCjv+LOw+mLuiCQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 14/35] x86/cpuid: Parse CPUID(0x80000002) to CPUID(0x80000004) Date: Fri, 5 Sep 2025 14:14:54 +0200 Message-ID: <20250905121515.192792-15-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add CPUID(0x80000002)->CPUID(0x80000004) support to the CPUID parser. This allows converting their call site to the new CPUID parser API next. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/types.h | 3 +++ arch/x86/kernel/cpu/cpuid_parser.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index e57245ca6419..6f4da51126b3 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -237,6 +237,9 @@ struct cpuid_leaves { CPUID_LEAF ( 0x0, 0 ); CPUID_LEAF ( 0x1, 0 ); CPUID_LEAF ( 0x80000000, 0 ); + CPUID_LEAF ( 0x80000002, 0 ); + CPUID_LEAF ( 0x80000003, 0 ); + CPUID_LEAF ( 0x80000004, 0 ); }; =20 /* diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index 39a361eed7ce..c56c3dbe39e1 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -112,5 +112,8 @@ struct cpuid_parse_entry { CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ + CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \ =20 #endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2A7E352FEF for ; Fri, 5 Sep 2025 12:16:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074570; cv=none; b=rmoqJPnYgtFEf2nCcEeShKxWbE5G7ABeJpG2MxSjWkmR96iA5hXTLssNItQoKc0ABZc5HgbxpKPZSzlvjJvZmVQcx+yzLFyhA4vhYkpUZsgdh+KdKdV4PVQOw2VutFVkQi+lC2VZZJhnp5QWW2RKnExLsSIv4kkG4+DA7/nALPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074570; c=relaxed/simple; bh=pU/luzQBHwvhqb7dLeNckRcAmDp6BWrUgIWG/nq96CQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kh+VxUlK96JZxTpWGGUsQ4D4pIgsjO6GbDbM9WzQV16Kysljj7v3GY5dYliAlT9ccO5zsVQOqrGF84h0fbRCJYyQ3TlCMEat0TZvah4VQ1nkQrmQ7U3zEEYzywmY32w9FicNSMyH3/rv42wwxb73a0PsU1FNWxQG4iUB+KkfjKA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=rlxJQhgG; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=vqsGq0Ug; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="rlxJQhgG"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="vqsGq0Ug" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074567; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Su531WO3n0s4MwXJfjSCSav6UVBxpZNRYIumkWYWlb4=; b=rlxJQhgGuxJK2x2N5W+CFEkcKhGLN+w1H6a5b1/G63WBf7XnqfwlLBesUj6A3OR2z1gxdT D66UvJW3s/Ay8HGCkxmRlbckldGtimxJykv2Yph45riPyOnZicQfwyTEfAqMaQQZiBfglx /GuWKNy7//ExCk6h1u4rsOVdpkgOFZimDso4M/Goy7dLg9mYYMn9kf022o0QtfHxFX2VUO 29fMr/N3Yyp+nDoftTqR07zypy1xGNCa+GhMO4OAwW9t33G54SNozOgM3AJavOOPGyZmGF 4gzJZTt2GzinfNzEpp4b34QgGkgwQUuGGBV3ExsF747ubLfJ3dvTvclefJDDpA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074567; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Su531WO3n0s4MwXJfjSCSav6UVBxpZNRYIumkWYWlb4=; b=vqsGq0Ugbqzc+dp4UcZDS7lObw+K1lpAdiavdOHiBl7KjFykxUyYdkLO1Y3dbxVPOiJVeq xMniOdck/EQ1IoAg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 15/35] x86/cpu: Use parsed CPUID(0x80000002)..CPUID(0x80000004) Date: Fri, 5 Sep 2025 14:14:55 +0200 Message-ID: <20250905121515.192792-16-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For CPU brand string enumeration, use parsed CPUID(0x80000002) to CPUID(0x80000004) access instead of directly invoking CPUID queries. This allows centralizing CPUID queries, and the access of their cached data output, to one place in the kernel. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/common.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0a0340a7ac1c..1d45dbdd0e05 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -780,16 +780,19 @@ static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM]= =3D {}; =20 static void get_model_name(struct cpuinfo_x86 *c) { - unsigned int *v; + const struct cpuid_regs *leaf[] =3D { + cpuid_leaf_raw(c, 0x80000002), + cpuid_leaf_raw(c, 0x80000003), + cpuid_leaf_raw(c, 0x80000004), + }; char *p, *q, *s; =20 - if (c->extended_cpuid_level < 0x80000004) + if (!leaf[0] || !leaf[1] || !leaf[2]) return; =20 - v =3D (unsigned int *)c->x86_model_id; - cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); - cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); - cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); + for (int i =3D 0; i < ARRAY_SIZE(leaf); i++) + *(struct cpuid_regs *)&c->x86_model_id[16 * i] =3D *leaf[i]; + c->x86_model_id[48] =3D 0; =20 /* Trim whitespace */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C966A352FE4 for ; Fri, 5 Sep 2025 12:16:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074573; cv=none; b=qDQ4sQJa05ZAmjeRxHZSyK7u1O2aVtiuY1Dxb6ofuGmBUs3PVrLP49QcF6Pr5jOP2PJMI2n/4CVG7OQHtJTZwez5WFH2w5GxSmAnA0bCGyNKpEdNTp/xHcUvs/dofMWW8RQNobF7O2a16s/RVsTFLsW640HJsSWcrYag2Q7ZFKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074573; c=relaxed/simple; bh=URUnSTDb5haa4fYYLd6+D3Jje7Qu7hOkj6v/yO7YtOA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p5z+DbLt1RLK5dQelnYEr9CfSbmNGXOsU3OBPiw7LxTMbC1J0MOV2Kxb8hTfdujY/wUfmqn5M4rszbh9aam0ezKvG7OUOIfIo9VcKoq3kDhJh++zx6VKYysvDhQwBqG1F0Hu2XqndAx3GmGMYrQn6c0MIKZD4B1UyOodeg/OmmI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=gD3T2kL4; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=gY+x5cOU; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="gD3T2kL4"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="gY+x5cOU" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074570; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uY6TErsVte9LDQFAFTRgaU7CERMqfx2fDXfyQukGbhM=; b=gD3T2kL4mnfnVcLc7Hz2eMJFIXHACWglBsg2Qgy/lDxhB4MdL7/wVGbsBNRyUaiQTF+4k+ x3qrJmQyAVpelNI5sMy9CDoh9ZDRHCWZn8UctWoY83VS7fOqtsuVjvGNq7BHIBaYriFkNJ Go1t19nSNE7yiKa9VXZCn0oeEJ6rsggzmQtKVmYPGI6Xq7wqq9bhmigOE3lYdw5xeXiI2N iJqnP1XpblaIhAzZZ6WPGm5VIicjnVzidp6gv6p0RxQ6adpPCf653Ss1j2mlsmT4a5d0RM zh7Gvn2dyDFjpYE+Clr7a4xUdkuWXUp1QW9zkxWMYKmm6E2PSyqI8Pk8heEklQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074570; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uY6TErsVte9LDQFAFTRgaU7CERMqfx2fDXfyQukGbhM=; b=gY+x5cOU6K71WUKjUn9xQtOvfcx+A3WcBKozqax7z5uKv0BsbCo+ztRj3UE4Q4drmpGYSE 962NVrj+Sgpgh1BQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 16/35] x86/cpuid: Introduce a parser leaf x86 vendor table Date: Fri, 5 Sep 2025 14:14:56 +0200 Message-ID: <20250905121515.192792-17-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For the CPUID parser, introduce a table listing vendor-specific CPUID leaves. Not all CPUID leaves should be queried on all x86 vendors, so the parser will only enumerate such leaves if the boot machine's x86 vendor is listed as supported. This provides the following benefits: (a) Even when a CPUID leaf falls within the CPU's standard or extended maximum leaf range, querying architecturally unsupported and reserved CPUID leaves may trigger new kernel boot behaviors or subtle bugs, especially on legacy machines. (b) Associating x86 vendor information with CPUID leaves will enable the CPUID parser to emit (lightweight) error messages when malformed CPUID leaf output is detected. This is due to the parser now being more certain that the queried leaf is valid on the machine. (c) Attaching x86 vendor information to CPUID leaves will relieve call-sites, especially drivers, from ugly x86 vendor checks before querying a CPUID leaf. If the CPUID parsers API like cpuid_leaf() or cpuid_subleaf() return NULL, it willy simply implies the leaf is simply unavailable (or should not be queried) on the current machine. Split the CPUID parsing table into an "early boot" table and a standard one. The early boot phase parses only CPUID(0x0) and CPUID(0x1), where they will be needed to identify the CPU's x86 vendor. Once the kernel saves the vendor info to the CPU's capability structure, invoke the CPUID parser again to parse the rest of the CPUID leaves. In that second phase, the parser assumes that "boot_cpu_data.x86_vendor" is valid and uses it for CPUID leaf x86 vendor validity checks. For each vendor-specific CPUID leaf, build its list of matching x86 vendors using CPP varargs. Encoding this as bitflags was not doable, since the x86 vendor IDs are just raw monotonic numbers from 0 (Intel) to 11 (Vortex). Keep the CPUID parser's vendor-specific leaf table empty for now. Leaves like CPUID(0x2), CPUID(0x4), CPUID(0x16), and CPUID(0x8000001d) will be added to the vendor table once their support is actually added to the parser. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/common.c | 3 +- arch/x86/kernel/cpu/cpuid_parser.c | 100 +++++++++++++++++++++++++---- arch/x86/kernel/cpu/cpuid_parser.h | 50 ++++++++++++++- 3 files changed, 138 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 1d45dbdd0e05..b439f7cd0931 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1728,9 +1728,10 @@ static void __init early_identify_cpu(struct cpuinfo= _x86 *c) =20 /* cyrix could have cpuid enabled via c_identify()*/ if (cpuid_feature()) { - cpuid_parser_scan_cpu(c); + cpuid_parser_early_scan_cpu(c); cpu_detect(c); get_cpu_vendor(c); + cpuid_parser_scan_cpu(c); intel_unlock_cpuid_leafs(c); get_cpu_cap(c); setup_force_cpu_cap(X86_FEATURE_CPUID); diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c index 9c40c180e3d4..df73fd9286b8 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -12,6 +12,10 @@ =20 #include "cpuid_parser.h" =20 +static const struct cpuid_vendor_entry cpuid_vendor_entries[] =3D { + CPUID_VENDOR_ENTRIES +}; + /* * Leaf read functions: */ @@ -49,10 +53,24 @@ static void cpuid_read_0x80000000(const struct cpuid_pa= rse_entry *e, struct cpui * * Since these tables reference the leaf read functions above, they must be * defined afterwards. + * + * At early boot, only leaves at CPUID_EARLY_PARSE_ENTRIES should be parse= d. */ =20 -static const struct cpuid_parse_entry cpuid_parse_entries[] =3D { - CPUID_PARSE_ENTRIES +static const struct cpuid_parse_entry cpuid_early_parse_entries[] =3D { + CPUID_EARLY_PARSE_ENTRIES +}; + +static const struct cpuid_parse_entry cpuid_common_parse_entries[] =3D { + CPUID_COMMON_PARSE_ENTRIES +}; + +static const struct { + const struct cpuid_parse_entry *table; + int nr_entries; +} cpuid_parser_phases[] =3D { + { cpuid_early_parse_entries, ARRAY_SIZE(cpuid_early_parse_entries) }, + { cpuid_common_parse_entries, ARRAY_SIZE(cpuid_common_parse_entries) }, }; =20 /* @@ -86,6 +104,32 @@ static bool cpuid_leaf_in_range(const struct cpuid_tabl= e *t, unsigned int leaf) cpuid_range_valid(t, leaf, CPUID_EXT_START, CPUID_EXT_END); } =20 +static bool cpuid_leaf_matches_vendor(unsigned int leaf, u8 cpu_vendor) +{ + const struct cpuid_parse_entry *p =3D cpuid_early_parse_entries; + const struct cpuid_vendor_entry *v =3D cpuid_vendor_entries; + + /* Leaves in the early boot parser table are vendor agnostic */ + for (int i =3D 0; i < ARRAY_SIZE(cpuid_early_parse_entries); i++, p++) + if (p->leaf =3D=3D leaf) + return true; + + /* Leaves in the vendor table must pass a CPU vendor check */ + for (int i =3D 0; i < ARRAY_SIZE(cpuid_vendor_entries); i++, v++) { + if (v->leaf !=3D leaf) + continue; + + for (unsigned int j =3D 0; j < v->nvendors; j++) + if (cpu_vendor =3D=3D v->vendors[j]) + return true; + + return false; + } + + /* Remaining leaves are vendor agnostic */ + return true; +} + static void cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry ent= ries[], unsigned int nr_entries) { @@ -100,6 +144,9 @@ cpuid_fill_table(struct cpuid_table *t, const struct cp= uid_parse_entry entries[] if (!cpuid_leaf_in_range(t, entry->leaf)) continue; =20 + if (!cpuid_leaf_matches_vendor(entry->leaf, boot_cpu_data.x86_vendor)) + continue; + WARN_ON_ONCE(output.info->nr_entries !=3D 0); entry->read(entry, &output); } @@ -109,19 +156,13 @@ cpuid_fill_table(struct cpuid_table *t, const struct = cpuid_parse_entry entries[] * Exported APIs: */ =20 -/** - * cpuid_parser_scan_cpu() - Populate current CPU's CPUID table - * @c: CPU capability structure associated with the current CPU - * - * Populate the CPUID table embedded within @c with parsed CPUID data. Si= nce all CPUID - * instructions are invoked locally, this must be called on the CPU associ= ated with @c. - */ -void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c) +static void __cpuid_parser_scan_cpu(struct cpuinfo_x86 *c, bool early_boot) { + int nphases =3D early_boot ? 1 : ARRAY_SIZE(cpuid_parser_phases); struct cpuid_table *table =3D &c->cpuid; =20 /* - * For correctness, clear the CPUID table first. + * After early boot, clear the CPUID table first. * * This is due to the CPUID parser APIs at using leaf->= nr_entries * as a leaf validity check: non-zero means that the CPUID leaf's cached = output is @@ -137,7 +178,40 @@ void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c) * parsed (leaving stale leaf "nr_entries" fields behind.) The table mus= t thus be * also cleared. */ - memset(table, 0, sizeof(*table)); + if (!early_boot) + memset(table, 0, sizeof(*table)); + + for (int i =3D 0; i < nphases; i++) + cpuid_fill_table(table, cpuid_parser_phases[i].table, cpuid_parser_phase= s[i].nr_entries); +} =20 - cpuid_fill_table(table, cpuid_parse_entries, ARRAY_SIZE(cpuid_parse_entri= es)); +/** + * cpuid_parser_scan_cpu() - Populate the current CPU's CPUID table + * @c: CPU capability structure for the current CPU + * + * Populate the CPUID table embedded within @c with parsed CPUID data. Sin= ce all CPUID + * instructions are invoked locally, this must be run on the CPU associate= d with @c. + * + * cpuid_parser_early_scan_cpu() must've been called, at least once, befor= ehand. + */ +void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c) +{ + __cpuid_parser_scan_cpu(c, false); +} + +/** + * cpuid_parser_early_scan_cpu() - Populate primary CPU's CPUID table on e= arly boot + * @c: CPU capability structure associated with the current CPU + * + * Populate the CPUID table embedded within @c with parsed CPUID data. + * + * This must be called at early boot, so that the boot code can identify t= he CPU's + * x86 vendor. Only CPUID(0x0) and CPUID(0x1) are parsed. + * + * After saving the x86 vendor info in the boot CPU's capability structure, + * cpuid_parser_scan_cpu() must be called to complete the CPU's CPUID tabl= e. + */ +void __init cpuid_parser_early_scan_cpu(struct cpuinfo_x86 *c) +{ + __cpuid_parser_scan_cpu(c, true); } diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index c56c3dbe39e1..6adcbde62e1a 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -2,6 +2,7 @@ #ifndef _ARCH_X86_CPUID_PARSER_H #define _ARCH_X86_CPUID_PARSER_H =20 +#include #include =20 /* @@ -107,13 +108,60 @@ struct cpuid_parse_entry { * CPUID parser tables: */ =20 -#define CPUID_PARSE_ENTRIES \ +/* + * Early-boot CPUID leaves (to be parsed before x86 vendor detection) + * + * These leaves must be parsed at early boot to identify the x86 vendor. T= he + * parser treats them as universally valid across all vendors. + * + * At early boot, only leaves in this table must be parsed. For all other + * leaves, the CPUID parser will assume that "boot_cpu_data.x86_vendor" is + * properly set beforehand. + * + * Note: If these entries are to be modified, please adapt the kernel-doc = of + * cpuid_parser_early_scan_cpu() accordingly. + */ +#define CPUID_EARLY_PARSE_ENTRIES \ /* Leaf Subleaf Reader function */ \ CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \ + +/* + * Common CPUID leaves + * + * These leaves can be parsed once basic x86 vendor detection is in place. + * Further vendor-agnostic leaves, which are not needed at early boot, are= also + * listed here. + * + * For vendor-specific leaves, a matching entry must be added to the CPUID= leaf + * vendor table later defined. Leaves which are here, but without a match= ing + * vendor entry, are treated by the CPUID parser as valid for all x86 vend= ors. + */ +#define CPUID_COMMON_PARSE_ENTRIES \ + /* Leaf Subleaf Reader function */ \ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \ =20 +/* + * CPUID leaf vendor table: + */ + +struct cpuid_vendor_entry { + unsigned int leaf; + u8 vendors[X86_VENDOR_NUM]; + u8 nvendors; +}; + +#define CPUID_VENDOR_ENTRY(_leaf, ...) \ + { \ + .leaf =3D _leaf, \ + .vendors =3D { __VA_ARGS__ }, \ + .nvendors =3D (sizeof((u8[]){__VA_ARGS__})/sizeof(u8)), \ + } + +#define CPUID_VENDOR_ENTRIES \ + /* Leaf Vendor list */ \ + #endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ACC5E352FCE for ; Fri, 5 Sep 2025 12:16:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074576; cv=none; b=RsnLTe7tN8ThKZ5prRBvn9N8fnSBhPxxmOldNc2sT9HehzqmiqQi6T5TQQorFJzyf04TvJqKscey+/5elrvbAimFtSqmSEBM7IT5RCgjYpD86SD2jm2e11YB0hNU9TM1KxkjADGAIjiLywZ+mN6rT+MVnMtBkQqbCvYgaKJ5f+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074576; c=relaxed/simple; bh=4NEneCiEgxxGaIJsT7MTow4tmHAc6pWDZwG745EIVjs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ian91GAyizTRHy7xoq6Mt8/xhW9qUlISbpxPujkKHcozLagdcOrYVvrPT+UIOlhJHJVtUviLjxgwgMQ6iMsKbwjdKQPthCw4D1E6HjZgTKirHOeRdOlxcWIqnXKTvRQzVzhzq3WcBjvw5lzRkUpfIjUREc1YfVqV+QcFbzECw5Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=QZRig2nV; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=3DlSznJ/; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="QZRig2nV"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="3DlSznJ/" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074573; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JzXbKC+Xkp8wK2E0EC7Ptuhvcf12P91pDxR/m2KBA9c=; b=QZRig2nVtF6qJYCIxJFwna1+FYi4umdL9uC/crWaeqlJSXyYGCRLLzM/hCKpc1wr21h2Y2 1aRRL7swkjc86h2SC+E5NyXHr2l/OpLe/ZB/5jdXAW4RUvB36wQOVz+jpTDnghIob4YiDX +HZFVnmQclYdXJ0SGof83U7GhmjBGtIBSexA9dPJ+zcBuERUUTu3EIWNWttnJywQuqk28u 20XAKTduqS6/CLAujlO7/hfRj679SCkUKuTmdJMGZD0l7vJZcqZ5SNpCorcth6G1ePRvak NYeUmpRI1vAsgTNhdy3dP9TFbCz6BjoYGcWGjHKEmz/ZeiaVGNFagWe+4Lp7JQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074573; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JzXbKC+Xkp8wK2E0EC7Ptuhvcf12P91pDxR/m2KBA9c=; b=3DlSznJ/mBe+D6gsxi8CrqQDy6aGL54fyzgbXlCj6FGeZ4xAwcga4UartYJHzGT+m+2TaL SnpXeHBuyL6HaIAg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 17/35] x86/cpuid: Introduce a parser debugfs interface Date: Fri, 5 Sep 2025 14:14:57 +0200 Message-ID: <20250905121515.192792-18-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce the debugfs files 'x86/cpuid/[0-ncpus]' to dump each CPU's cached CPUID table. For each cached CPUID leaf/subleaf, invoke the CPUID instruction on the target CPU and compare the hardware result against the cached values. Mark any mismatched cached CPUID output value with an asterisk. This should help with tricky bug reports in the future, if/when the cached CPUID tables get unexpectedly out of sync with actual hardware state. It also simplifies the development and testing of adding new CPUID leaves to the CPUID parser. Note, expose cpuid_parse_phases[] via "cpuid_parser.h" to allow the debugfs code to traverse and dump the parsed CPUID data. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/cpuid_debugfs.c | 108 ++++++++++++++++++++++++++++ arch/x86/kernel/cpu/cpuid_parser.c | 9 ++- arch/x86/kernel/cpu/cpuid_parser.h | 12 ++++ 4 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 arch/x86/kernel/cpu/cpuid_debugfs.c diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index b2421cfb59ed..4e032ad851c7 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -61,7 +61,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) +=3D perfctr-watchdog.o obj-$(CONFIG_HYPERVISOR_GUEST) +=3D vmware.o hypervisor.o mshyperv.o obj-$(CONFIG_ACRN_GUEST) +=3D acrn.o =20 -obj-$(CONFIG_DEBUG_FS) +=3D debugfs.o +obj-$(CONFIG_DEBUG_FS) +=3D debugfs.o cpuid_debugfs.o =20 obj-$(CONFIG_X86_BUS_LOCK_DETECT) +=3D bus_lock.o =20 diff --git a/arch/x86/kernel/cpu/cpuid_debugfs.c b/arch/x86/kernel/cpu/cpui= d_debugfs.c new file mode 100644 index 000000000000..62aa92f7d226 --- /dev/null +++ b/arch/x86/kernel/cpu/cpuid_debugfs.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CPUID parser debugfs entries: x86/cpuid/[0-ncpus] + * + * Dump each CPU's cached CPUID table and compare its values against curre= nt + * CPUID output on that CPU. Mark changed entries with an asterisk. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "cpuid_parser.h" + +static void cpuid_this_cpu(void *info) +{ + struct cpuid_regs *regs =3D info; + + __cpuid(®s->eax, ®s->ebx, ®s->ecx, ®s->edx); +} + +static void +cpuid_show_leaf(struct seq_file *m, uintptr_t cpu_id, const struct cpuid_p= arse_entry *entry, + const struct leaf_query_info *info, const struct cpuid_regs *cached) +{ + for (int j =3D 0; j < info->nr_entries; j++) { + u32 subleaf =3D entry->subleaf + j; + struct cpuid_regs regs =3D { + .eax =3D entry->leaf, + .ecx =3D subleaf, + }; + int ret; + + seq_printf(m, "Leaf 0x%08x, subleaf %u:\n", entry->leaf, subleaf); + + ret =3D smp_call_function_single(cpu_id, cpuid_this_cpu, ®s, true); + if (ret) { + seq_printf(m, "Failed to invoke CPUID on CPU %lu: %d\n\n", cpu_id, ret); + continue; + } + + seq_printf(m, " cached: %cEAX=3D0x%08x %cEBX=3D0x%08x %cECX=3D0x%= 08x %cEDX=3D0x%08x\n", + cached[j].eax =3D=3D regs.eax ? ' ' : '*', cached[j].eax, + cached[j].ebx =3D=3D regs.ebx ? ' ' : '*', cached[j].ebx, + cached[j].ecx =3D=3D regs.ecx ? ' ' : '*', cached[j].ecx, + cached[j].edx =3D=3D regs.edx ? ' ' : '*', cached[j].edx); + seq_printf(m, " actual: EAX=3D0x%08x EBX=3D0x%08x ECX=3D0x%08x= EDX=3D0x%08x\n", + regs.eax, regs.ebx, regs.ecx, regs.edx); + } +} + +static void __cpuid_debug_show(struct seq_file *m, uintptr_t cpu_id, + const struct cpuid_parse_entry *entry, int nr_entries) +{ + const struct cpuinfo_x86 *c =3D per_cpu_ptr(&cpu_info, cpu_id); + const struct cpuid_table *t =3D &c->cpuid; + + for (int i =3D 0; i < nr_entries; i++, entry++) { + const struct leaf_query_info *qi =3D cpuid_table_query_info_p(t, entry->= info_offs); + const struct cpuid_regs *qr =3D cpuid_table_query_regs_p(t, entry->regs_= offs); + + cpuid_show_leaf(m, cpu_id, entry, qi, qr); + } +} + +static int cpuid_debug_show(struct seq_file *m, void *p) +{ + uintptr_t cpu_id =3D (uintptr_t)m->private; + + for (int i =3D 0; i < cpuid_parser_nphases; i++) + __cpuid_debug_show(m, cpu_id, cpuid_parser_phases[i].table, cpuid_parser= _phases[i].nr_entries); + + return 0; +} + +static int cpuid_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, cpuid_debug_show, inode->i_private); +} + +static const struct file_operations cpuid_ops =3D { + .open =3D cpuid_debug_open, + .read =3D seq_read, + .llseek =3D seq_lseek, + .release =3D single_release, +}; + +static __init int cpuid_init_debugfs(void) +{ + struct dentry *dir; + uintptr_t cpu_id; + char cpu_name[24]; + + dir =3D debugfs_create_dir("cpuid", arch_debugfs_dir); + + for_each_possible_cpu(cpu_id) { + scnprintf(cpu_name, sizeof(cpu_name), "%lu", cpu_id); + debugfs_create_file(cpu_name, 0444, dir, (void *)cpu_id, &cpuid_ops); + } + + return 0; +} +late_initcall(cpuid_init_debugfs); diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c index df73fd9286b8..a176722672ba 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -65,14 +65,13 @@ static const struct cpuid_parse_entry cpuid_common_pars= e_entries[] =3D { CPUID_COMMON_PARSE_ENTRIES }; =20 -static const struct { - const struct cpuid_parse_entry *table; - int nr_entries; -} cpuid_parser_phases[] =3D { +const struct cpuid_parser_phase cpuid_parser_phases[] =3D { { cpuid_early_parse_entries, ARRAY_SIZE(cpuid_early_parse_entries) }, { cpuid_common_parse_entries, ARRAY_SIZE(cpuid_common_parse_entries) }, }; =20 +const int cpuid_parser_nphases =3D ARRAY_SIZE(cpuid_parser_phases); + /* * Leaf-independent parser code: */ @@ -158,7 +157,7 @@ cpuid_fill_table(struct cpuid_table *t, const struct cp= uid_parse_entry entries[] =20 static void __cpuid_parser_scan_cpu(struct cpuinfo_x86 *c, bool early_boot) { - int nphases =3D early_boot ? 1 : ARRAY_SIZE(cpuid_parser_phases); + int nphases =3D early_boot ? 1 : cpuid_parser_nphases; struct cpuid_table *table =3D &c->cpuid; =20 /* diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index 6adcbde62e1a..066d4d60bf59 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -144,6 +144,18 @@ struct cpuid_parse_entry { CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \ =20 +/* + * CPUID parser tables repository: + */ + +struct cpuid_parser_phase { + const struct cpuid_parse_entry *table; + int nr_entries; +}; + +extern const struct cpuid_parser_phase cpuid_parser_phases[]; +extern const int cpuid_parser_nphases; + /* * CPUID leaf vendor table: */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 871CA353360 for ; Fri, 5 Sep 2025 12:16:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074579; cv=none; b=dMN7xaRbH6YQ7G2rqrxiAa9kUirv4mXyslDSyPW/J85VhLGWgogK9lfXLigeyMJZ1qTbaRYc2aEhn96Bo7imL4dzFkFhCj1KppSm6LSZB3Qh/6QxnVu7mfcLtfUljD7L8K5p6bSGlV+8hJJcfUxvZcN4g9KR3KtCDrd1Z5XJKmA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074579; c=relaxed/simple; bh=xVqoHGuwZYp0oVe1N6Tc0h9taOAqtIoYB7l4Ck/j0eY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C4XmM+uASsfojc0frH4kql/Cvsi6t+qWGCRHlwxe4ghKaaLuoFKa/NbbvxbnUuCONyQZEk5vNT3eXEoBeVVTfApmME8Ds0X5oGDfDfDdpZl8XEM9E0oDrnEtqKlTt0gArW9c4rByhmDpopXN6GCSxrHF76h0wpx3Xe7BZES3VlI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=gmHLEOTj; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=hq/Tj+c6; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="gmHLEOTj"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="hq/Tj+c6" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074576; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Vna62liQ3pVm5VyCtMFSOLzwHagCpxK9YGKs/jyMQks=; b=gmHLEOTjb11NGH+lroyzuaFIjJCpRg2CzkvA+QhY1FyLH56xk73NGh5dZcwlnu9rcKhheL 7BS0a9tEls5j4c8+8IDDdStl9HHyXwdTSKw6FR3Amu0lvtA2sjYjFsBWYB9Ip3AVusRY61 4PCy+/KWJhrd6FNzyg47HSWg2bM7FibZlTBtG+je3f1gPTk8VWLmjQg/BYMgS/BREeIpHd 1rLlNfKy6u/iyNFMrP0Vuwzp/Smb3L6IJKW/1zhfg3m6uVuHEqkldsXlnZXED+u532tgZM OK8moFCNsV2+MjRqRJ59hpOXa8/4nsuI4NTOxdeAoWowmkemr+VRtWax9BzVeA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074576; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Vna62liQ3pVm5VyCtMFSOLzwHagCpxK9YGKs/jyMQks=; b=hq/Tj+c6sXIT15j6u831ArZlmXtqUOYr1SXVQi3JmPvNSrDViQJiryoBJq9JlyLhadeuKf bgPSB1l3I3DbYwAw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 18/35] x86/cpuid: Parse CPUID(0x2) Date: Fri, 5 Sep 2025 14:14:58 +0200 Message-ID: <20250905121515.192792-19-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add CPUID(0x2) support to the CPUID parser. Query CPUID(0x2) only for Intel, Centaur, and Zhaoxin. Such vendor information was extracted from the kernel's boot code, given that kernel/cpu/cacheinfo.c :: init_intel_cacheinfo() is called by kernel/cpu/intel.c cpu_dev.c_x86_vendor =3D X86_VENDOR_INTEL kernel/cpu/centaur.c cpu_dev.c_x86_vendor =3D X86_VENDOR_CENTAUR kernel/cpu/zhaoxin.c cpu_dev.c_x86_vendor =3D X86_VENDOR_ZHAOXIN At the CPUID leaf output table, keep CPUID(0x2) marked as invalidif the whole leaf, or all of its output registers separately, were malformed. Note, the cpuid_leaf_0x2() logic at will be removed once all CPUID(0x2) call sites are transformed to the new CPUID model. References: fe78079ec07f ("x86/cpu: Introduce and use CPUID leaf 0x2 parsin= g helpers") Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/types.h | 1 + arch/x86/kernel/cpu/cpuid_parser.c | 35 ++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/cpuid_parser.h | 2 ++ 3 files changed, 38 insertions(+) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index 6f4da51126b3..b54080066084 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -236,6 +236,7 @@ struct cpuid_leaves { /* Leaf Subleaf number (or max number of dynamic subleaves) */ CPUID_LEAF ( 0x0, 0 ); CPUID_LEAF ( 0x1, 0 ); + CPUID_LEAF ( 0x2, 0 ); CPUID_LEAF ( 0x80000000, 0 ); CPUID_LEAF ( 0x80000002, 0 ); CPUID_LEAF ( 0x80000003, 0 ); diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c index a176722672ba..6efe594b9f2b 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -31,6 +31,41 @@ static void cpuid_read_generic(const struct cpuid_parse_= entry *e, struct cpuid_r cpuid_read_subleaf(e->leaf, e->subleaf + i, output->regs); } =20 +static void cpuid_read_0x2(const struct cpuid_parse_entry *e, struct cpuid= _read_output *output) +{ + union leaf_0x2_regs *regs =3D (union leaf_0x2_regs *)output->regs; + struct leaf_0x2_0 *l =3D (struct leaf_0x2_0 *)output->regs; + int invalid_regs =3D 0; + + /* + * All Intel CPUs must report an iteration count of 1. For broken hardwa= re, + * keep the leaf marked as invalid at the CPUID table. + */ + cpuid_read_subleaf(e->leaf, e->subleaf, l); + if (l->iteration_count !=3D 0x01) + return; + + /* + * The most significant bit (MSB) of each CPUID(0x2) register must be cle= ar. + * If a register is malformed, replace its 1-byte descriptors with NULL. + */ + for (int i =3D 0; i < 4; i++) { + if (regs->reg[i].invalid) { + regs->regv[i] =3D 0; + invalid_regs++; + } + } + + /* + * If all of the CPUID(0x2) output registers were malformed, keep the leaf + * marked as invalid at the CPUID table. + */ + if (invalid_regs =3D=3D 4) + return; + + output->info->nr_entries =3D 1; +} + static void cpuid_read_0x80000000(const struct cpuid_parse_entry *e, struc= t cpuid_read_output *output) { struct leaf_0x80000000_0 *el0 =3D (struct leaf_0x80000000_0 *)output->reg= s; diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index 066d4d60bf59..7366e8468116 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -139,6 +139,7 @@ struct cpuid_parse_entry { */ #define CPUID_COMMON_PARSE_ENTRIES \ /* Leaf Subleaf Reader function */ \ + CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ @@ -175,5 +176,6 @@ struct cpuid_vendor_entry { =20 #define CPUID_VENDOR_ENTRIES \ /* Leaf Vendor list */ \ + CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR= _ZHAOXIN),\ =20 #endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C66235335C for ; Fri, 5 Sep 2025 12:16:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074582; cv=none; b=Qc5z0kHtbMeXCWceuNzGL86ngfhtP2zNSBif2agM6EyF13PTmrMhPzvbAWTfCHy2vVOKEOT43LyG3bdqIRDjxO7Uke6GlQqO8G+vdavPPlF2cL8j+jxe7pRSsBksb4Dm37dvSDfZm2TN7/6bHHK+jrDfkGfUBJ6V5Hz+dEgpfTw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074582; c=relaxed/simple; bh=qMdf1jyQL5UirNvEw2ynQa1R8TT/nSoa8qDmigWq32Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HRJ4E02LNMUpIzLRgJ9cVZI1xZkM/Q7bPYOjCVHTP7RwmnC9gWo5phpC8ZEjaiIo4/qOVyq2dP5CAeFzAAHo5Rkz/SCqQ4/bh1JTQ/xTsG66v5aqoUSYUy5sqHVio7EMeuwTajyq/wgDv8KkGROQh+YzBn3qNm7Sqg47KEueCO4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=NuYZb7Kx; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=w8saUylo; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="NuYZb7Kx"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="w8saUylo" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074579; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WDI4umHATVRZl01ao44nBPkXLxRk1y7+6juPw2qjVBQ=; b=NuYZb7KxuHCOYdDywJVM6B2fLz/G1Lo5XEAe5iey2ezti6i1Cl3fNYJtGxCPVWU65y88wO YD4cooJjctbffQmkRfzI4dL0G9A2e/6UhPj9cMSjZZigfvft/sZ5/nrTFSg6uS8/ZaPxQn rfwbjBjjVkYOt2yBgKTl1FrVSgTXNhdQ3lRIcErK4b5vABIxvkfSNOf6nsXhT6rpIjGYaA U+guEBBQLmpOZeA8pHJfXpctZ6WW9w0YqZFbi0GZvtk/THLz5TkcKW/d1hLHrLy8vcgjhg pZmqHSQxmuTCZx0MqDSmUsJ9vQazn8xT4O9bTqRESKpRzLkB/6wzfwGHuhy8gw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074579; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WDI4umHATVRZl01ao44nBPkXLxRk1y7+6juPw2qjVBQ=; b=w8saUylo52W004kLpRqMVxS2Q4oRp8yLjicwpCFL5M2gGj+GE3wYRTyhprobet4Jh5pNr4 fiqHUw7bZ+U2dOAg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 19/35] x86/cpuid: Warn once on invalid CPUID(0x2) iteration count Date: Fri, 5 Sep 2025 14:14:59 +0200 Message-ID: <20250905121515.192792-20-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The CPUID(0x2) output includes a "query count" byte. That byte was supposed to specify the number of repeated CPUID(0x2) subleaf 0 queries needed to extract all of the CPU's cache and TLB descriptors. Per current Intel manuals, all CPUs supporting this leaf "will always" return an iteration count of 1. Since the CPUID parser ignores any CPUID(0x2) output with an invalid iteration count, lightly warn once about this in the kernel log. Do not emit a warning if any of the CPUID(0x2) output registers EAX->EDX, or even all of them, are invalid; i.e., their most significant bit is set. Such a case is both architecturally defined and legitimate. References: b5969494c8d8 ("x86/cpu: Remove CPUID leaf 0x2 parsing loop") Suggested-by: Ingo Molnar Signed-off-by: Ahmed S. Darwish Link: https://lore.kernel.org/lkml/aBnmy_Bmf-H0wxqz@gmail.com --- arch/x86/kernel/cpu/cpuid_parser.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c index 6efe594b9f2b..f7dc5c78b06b 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -3,6 +3,8 @@ * Centralized CPUID parser (for populating the system's CPUID tables.) */ =20 +#define pr_fmt(fmt) "x86/cpuid: " fmt + #include #include =20 @@ -42,8 +44,11 @@ static void cpuid_read_0x2(const struct cpuid_parse_entr= y *e, struct cpuid_read_ * keep the leaf marked as invalid at the CPUID table. */ cpuid_read_subleaf(e->leaf, e->subleaf, l); - if (l->iteration_count !=3D 0x01) + if (l->iteration_count !=3D 0x01) { + pr_warn_once("Ignoring CPUID(0x2) due to invalid iteration count =3D %d", + l->iteration_count); return; + } =20 /* * The most significant bit (MSB) of each CPUID(0x2) register must be cle= ar. --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C10013568ED for ; Fri, 5 Sep 2025 12:16:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074586; cv=none; b=alo/RM6JotfyybxagK5CtVrECDF693VT3WdRNqVpiOi5EKA9IFEQzGVb3jErLjviwjHMw3fC9ucrvtpwRazmxuY+3W/NP6/7RLzdu6tzT6/TnVN4jEpY+6igHHKWvpWBei3yZTtoKQf2vqf7UJ4/7JqWCW1FXIhDoF3ZLXnubpo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074586; c=relaxed/simple; bh=ntlPdb1E3VZGfmXTiGStFiSqlOoOUklABk5cqk2+URI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JhardyzsHA6aBhCIbdno67qJtI+LgjQ259OkaDTrBiC+ZVRHHUEB7UjtvYNV+XqxdzMdhs6v9bcHsbrMjo2gRRB/QDABiRRiCmqvvinVg3GzpQRM9bOEtyifcBcY25nd/Ep4hy8gJh+eoLWC7nqVWg6NwHQ/p+1/Y470kHmDiOU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=4nbc6ioh; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ZWiK/MJZ; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="4nbc6ioh"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ZWiK/MJZ" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=csEnnuoXzERtOr+dUZDPP1TtOCri68TRb5ODyXiAXxA=; b=4nbc6iohucjxeAKAKxPqO2j3cxCuUPFLCrAT1XpEutPUjLUcOSUrCe6PWlgoRkwS/uwivm 7beD1eInnnVhK5vr2yB8bjMY+CFKoH4KhIclCo5G2Xm+s6ZUe0zlwCe0b55HnWV4un0xH2 QsBVtKag365JeUdYXfLwfSbkiubJtuXRDnmcuPGANg8QXFpzWDs0TlqTC9bN2hg3m61Zse sISpVkJUm/UkEHOcuLo36jCdwcViaXYBmVHr8yZsZttuxD9VC5g2iDKDAAKdpryzFZQoY/ Ug/r+fAl4e80yojrKnqIZ+Lz2BvOjXxMMieD725mf0NaV9BzGysORpp6zqAzAQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=csEnnuoXzERtOr+dUZDPP1TtOCri68TRb5ODyXiAXxA=; b=ZWiK/MJZshNWKRSxjImkhiKy1ApCFjAnKkzA9tmMC1JuSRbgL1ij21+2cKVTNNMIerbpdB 3f6jNYUMV94novAA== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 20/35] x86/cpuid: Introduce parsed CPUID(0x2) API Date: Fri, 5 Sep 2025 14:15:00 +0200 Message-ID: <20250905121515.192792-21-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new iterator macro, for_each_parsed_cpuid_0x2_desc(), for retrieving parsed CPUID(0x2) entries as 1-byte descriptors. Unlike the existing for_each_cpuid_0x2_desc() macro, which operates on directly retrieved CPUID data, the new one takes its input from the centralized CPUID parser. That is, it is expected to be used as: const struct leaf_0x2_table *desc; const struct cpuid_regs *regs; u8 *ptr; regs =3D cpuid_leaf_raw(c, 0x2); // Parsed CPUID access for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) { ... } which should replace the older method: const struct leaf_0x2_table *desc; union leaf_0x2_regs regs; u8 *ptr; cpuid_leaf_0x2(®s); // Direct CPUID access for_each_leaf_0x2_desc(regs, ptr, desc) { ... } In the new macro, assert that the passed 'regs' is the same size as a 'union leaf_0x2_regs'. This is necessary since the macro internally casts 'regs' to that union in order to iterate over the CPUID(0x2) output as a 1-byte array. A size equivalence assert is used, instead of a typeof() check, to give callers the freedom to either pass a 'struct cpuid_regs' pointer or a 'struct leaf_0x2_0' pointer, both as returned by the parsed CPUID API at . That size comparison matches what other kernel CPUID APIs do; e.g. cpuid_read() and cpuid_read_subleaf() at . Note, put the size equivalence check inside a GNU statement expression, ({..}), so that it can be placed inside the macro's loop initialization. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/api.h | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/= api.h index 7b7951b28105..58f922033ff9 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -564,6 +564,49 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) __cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n); \ }) =20 +/* + * Convenience leaf-specific functions (using parsed CPUID data): + */ + +/* + * CPUID(0x2) + */ + +/** + * for_each_parsed_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descr= iptors + * @_regs: Leaf 0x2 register output, as returned by cpuid_leaf_raw() + * @_ptr: u8 pointer, for macro internal use only + * @_desc: Pointer to parsed descriptor information at each iteration + * + * Loop over the 1-byte descriptors in the passed CPUID(0x2) output regist= ers + * @_regs. Provide the parsed information for each descriptor through @_d= esc. + * + * To handle cache-specific descriptors, switch on @_desc->c_type. For TLB + * descriptors, switch on @_desc->t_type. + * + * Example usage for cache descriptors:: + * + * const struct leaf_0x2_table *desc; + * struct cpuid_regs *regs; + * u8 *ptr; + * + * regs =3D cpuid_leaf_raw(c, 0x2); + * if (!regs) { + * // Handle error + * } + * + * for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) { + * switch (desc->c_type) { + * ... + * } + * } + */ +#define for_each_parsed_cpuid_0x2_desc(_regs, _ptr, _desc) \ + for (({ static_assert(sizeof(*_regs) =3D=3D sizeof(union leaf_0x2_regs));= }), \ + _ptr =3D &((union leaf_0x2_regs *)(_regs))->desc[1]; \ + _ptr < &((union leaf_0x2_regs *)(_regs))->desc[16] && (_desc =3D &cp= uid_0x2_table[*_ptr]);\ + _ptr++) + /* * CPUID parser exported APIs: */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 004C5356909 for ; Fri, 5 Sep 2025 12:16:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074590; cv=none; b=JSBe4UoEvQWj9JgpNgnSZNqWFVcYw8bsSNIyx0XskDGiCtAA+obkd3g8hxmo4+nNuj2ZF9sepMmd0GgQUZrDutBnu+GbWhnQ40mGHaLIA9EK4gaOiIo2m2HC76AGHO0DTWB9zGsqyvcK6uXt/99BTyX38EK8epwV0NmWD4iyXks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074590; c=relaxed/simple; bh=jNgEx2eDog9agelm0hZ1d2Hksj0ecKsAQbeVdX6jQcw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GSzvxQELIZSLoIeSGeZZKX/5l352qkP9umli+tY+QlOo4QKPbIJBD5BavJGoHLW0hHmVJmppfOZgBWXCYpxEffQVaM2Tqfgo+6Ef/VStnxM3v4QlRhwN+8zZBY3DvR1hCdzbTL8ffb2pdlkQyJMjc1s4jp48/9bMceij0Rra0to= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=YSS6XjTk; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=VuUY4Ebw; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="YSS6XjTk"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="VuUY4Ebw" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UtKNAecyTmIQEvsVids3IFeQilSYo0cBXCC3LBkklLc=; b=YSS6XjTk/fqWbAswF9vdydJiw0IOncAxCRw99zdHTKDl1eg0jqfnEDum5bEufX+rPhWiMp znhJxyQawUVj4AyFR2Gk+/KHfmvn/sul4l/TEbRYQG/pvpn8ODWQReGhJ/QbFUYK5VWXvo Ag6cqnAg/4rnnN7y+c6OqElkzuLQCcES9UEo9Uy/OvrRGvmueB01nTF4pVSpHj+BQWM3FL T7nYUAuYc0k5DtmbgrtR/FO2/G4FXsSXxid3rufspDrTiwoDDH209O9nxP7u8sMbAMqY/s yKJwRoB9KQv2+awpbaLwRXnzOXNTbvFutSNpdJbdlo+nAVvnqHo2w3dRaaF1Ew== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UtKNAecyTmIQEvsVids3IFeQilSYo0cBXCC3LBkklLc=; b=VuUY4Ebww20rmu/VDBW6IvEafbuv0+Gs1lzIQcb8Xf99P9b5SxFZefwtFsvnlcXu3FCdJg 1t1Bw7p9/MMaUPDg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 21/35] x86/cpu: Use parsed CPUID(0x2) Date: Fri, 5 Sep 2025 14:15:01 +0200 Message-ID: <20250905121515.192792-22-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the Intel cacheinfo code, use parsed CPUID(0x2) access instead of a direct CPUID query. Remove the "maximum standard CPUID level >=3D 0x2" check as the parsed CPUID API output NULL check is equivalent. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/intel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 98ae4c37c93e..7078b4264294 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -710,14 +710,14 @@ static void intel_tlb_lookup(const struct leaf_0x2_ta= ble *desc) static void intel_detect_tlb(struct cpuinfo_x86 *c) { const struct leaf_0x2_table *desc; - union leaf_0x2_regs regs; + const struct cpuid_regs *regs; u8 *ptr; =20 - if (c->cpuid_level < 2) + regs =3D cpuid_leaf_raw(c, 0x2); + if (!regs) return; =20 - cpuid_leaf_0x2(®s); - for_each_cpuid_0x2_desc(regs, ptr, desc) + for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) intel_tlb_lookup(desc); } =20 --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CCFAC350850 for ; Fri, 5 Sep 2025 12:16:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074601; cv=none; b=dTn4mNAXRsjKgMXnme+2SMSPwdN6Wetaj0EbwmsR8dj9t2bjjq+KqPtKB/lr1CXK1m7I7jdzq9iS8FHKmGLbzssivm9oSL5LkuA9nCxAbzyjPoc1e1w1DK53DqzLxleyrV2DseY2Mp9G1SFJXRVT6eJR3WkO/FVxe685Tk5rJq4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074601; c=relaxed/simple; bh=vrilB8Pp2o05wrxQDrd+PviVOlyflql/qEV4JyceAE4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S0pTk5yqpK/njx37cleJuUYJJj+Kc3RlsYBPoaCyoMWGc4zBcbSfPIRLnkfVGEZo+da+DPj5b7/IpDHSXswQXzpP+sAyMZ0ANWzerS9fTb2K31sU3n36YhJJcFFoUwkF6XjNiS7wOSwGV0lz7SdGZawDOk4Ko11ZeuBf/oTTIbY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=2vXCPdK/; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=GZ0uzxc8; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="2vXCPdK/"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="GZ0uzxc8" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vnhfp7RG9+kQXAh3FHU78TA6UXd+wPzE4jdCgJfYuRU=; b=2vXCPdK/cDM/fFaCVa7+M/HEZCFqCrdX3V26yelvqpDZg+Ktm6eM+RelgwYd3rITUYtQPA qB2pyQtvxryyfXbwFLeXPOn7KSYuSu3PpEhMaaZNvjEVL5dsL+i9l+sIjttTFYmZ1qKhsX VR73HrL15rvNcIG6pidUgAacp4TUsYbaXTO6haqrvVAOL9R0x/kJOB2RJs737ygAeaVzo0 uG/RDYlQXvqRkZxPhUt6BO32iUaJ+sKN3WfecYjpQhxbNKoUhbGxXuhTmKx0mpzNfLfYqk kcYWTHPw01ganVjKXdOOqkNXDVwa4n9pWc4WDnY85xNMHC+NsX+V/M6oo+CpQg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vnhfp7RG9+kQXAh3FHU78TA6UXd+wPzE4jdCgJfYuRU=; b=GZ0uzxc8oZF987oRDh1i/2wt8uFNiMa4UVH2bXKNxLsPQxWI3vHoUK8/UYF+KnfMaJPz9c CHq9u20r61/6mqCA== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 22/35] x86/cacheinfo: Use parsed CPUID(0x2) Date: Fri, 5 Sep 2025 14:15:02 +0200 Message-ID: <20250905121515.192792-23-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use parsed CPUID(0x2) access instead of direct CPUID queries. Remove the max standard CPUID level check since the NULL check of cpuid_leaf_raw()'s result is equivalent. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/cacheinfo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index 51a95b07831f..4c3a08593ec4 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -391,14 +391,14 @@ static void intel_cacheinfo_0x2(struct cpuinfo_x86 *c) { unsigned int l1i =3D 0, l1d =3D 0, l2 =3D 0, l3 =3D 0; const struct leaf_0x2_table *desc; - union leaf_0x2_regs regs; + const struct cpuid_regs *regs; u8 *ptr; =20 - if (c->cpuid_level < 2) + regs =3D cpuid_leaf_raw(c, 0x2); + if (!regs) return; =20 - cpuid_leaf_0x2(®s); - for_each_cpuid_0x2_desc(regs, ptr, desc) { + for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) { switch (desc->c_type) { case CACHE_L1_INST: l1i +=3D desc->c_size; break; case CACHE_L1_DATA: l1d +=3D desc->c_size; break; --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E491350852 for ; Fri, 5 Sep 2025 12:16:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074603; cv=none; b=Sp7XAI4B8/LcB1wJlO0k6euuEg9NuS24AMim5+26Kc7JFP0cEJ7nBuHZKQ+Bs+G4sfLPqjJeUCYVKUIE7GSQ7jMzlMj51fN+thBbe6lTI1bf9JbJg1eO+jlWaRmFamtdWyMb6L7JnwX2tmtWYdbK4StZaq+XSyN7W4aT8WPMv0A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074603; c=relaxed/simple; bh=Km8SluEKC3BfiGEv6HzPDip26WWAmy8YrLWnrUVjars=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=saISPLYOhraFLTK4NO+ZZ2o6F32D/iAOViDU/TMeUIteG7xkmcLA9R4dhQExg3wzhiqPgvl8fR+YXijiKz9l7cQL4W0/rfGTsVd/qsyJSG5zOTBOnkCJBof+/HZAJgoxK/ARTTPmWSU0DYiKQdUMY+RSHRngytWpf08V2XJP4+o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=NY1QI/K4; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=r8l1Actm; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="NY1QI/K4"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="r8l1Actm" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074600; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VGDOjFyJkzFa4GVWlavjul7328JM5Y0vHx2XO7awrGc=; b=NY1QI/K4qN3v90BeW8RlL8TgdYATGCjPOFbKKYg8BjHJQv+vuStCkH54wIQqN+cipgZgys FQnruftXdGGbhSz1PlM2e8Dw09pyb+cuNSwVHU932zaOmxnGpafR7g1+K2xBC3kzJ07M8G 35xQFFsU4OwbkqS7b6yXHI+UexmazKZhWESl7gEPuoqYI/fFS4g2agHwHgEvdXr9neyOx2 opCrjrC3/b1P8owNrSqMI9Ez971tQBdTH13+63O8P3MgcmE1bMX6hf6lzN5izf/Il9y6g3 7hUgCSxUJH7SBciJ6n/FhlLVd8+6ItCy6B9fJnjf7/EiqfOr4Cd1HVnkl2aSfg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074600; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VGDOjFyJkzFa4GVWlavjul7328JM5Y0vHx2XO7awrGc=; b=r8l1Actm2du2FAfRobRA6fiMBf4ee5I2Iti1UckQcSus9nk4adNVrz4FYQSVC0UIZaj4YO pnhBpLPUr/9lsLBg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 23/35] x86/cpuid: Remove direct CPUID(0x2) query API Date: Fri, 5 Sep 2025 14:15:03 +0200 Message-ID: <20250905121515.192792-24-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" All call sites at x86/cpu and x86/cacheinfo has been switched from direct CPUID(0x2) access to parsed CPUID access. Remove the direct CPUID(0x2) query APIs at : cpuid_leaf_0x2() for_each_cpuid_0x2_desc() Rename the iterator macro: for_each_parsed_cpuid_0x2_desc() back to: for_each_cpuid_0x2_desc() since the "for_each_parsed_.." name and was just chosen to accommodate the transition from direct CPUID(0x2) access to parsed access. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/api.h | 75 ++------------------------------ arch/x86/kernel/cpu/cacheinfo.c | 2 +- arch/x86/kernel/cpu/intel.c | 2 +- 3 files changed, 5 insertions(+), 74 deletions(-) diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/= api.h index 58f922033ff9..2989a0c83ab0 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -213,75 +213,6 @@ static inline u32 cpuid_base_hypervisor(const char *si= g, u32 leaves) return 0; } =20 -/* - * CPUID(0x2) parsing: - */ - -/** - * cpuid_leaf_0x2() - Return sanitized CPUID(0x2) register output - * @regs: Output parameter - * - * Query CPUID(0x2) and store its output in @regs. Force set any - * invalid 1-byte descriptor returned by the hardware to zero (the NULL - * cache/TLB descriptor) before returning it to the caller. - * - * Use for_each_cpuid_0x2_desc() to iterate over the register output in - * parsed form. - */ -static inline void cpuid_leaf_0x2(union leaf_0x2_regs *regs) -{ - cpuid_read(0x2, regs); - - /* - * All Intel CPUs must report an iteration count of 1. In case - * of bogus hardware, treat all returned descriptors as NULL. - */ - if (regs->desc[0] !=3D 0x01) { - for (int i =3D 0; i < 4; i++) - regs->regv[i] =3D 0; - return; - } - - /* - * The most significant bit (MSB) of each register must be clear. - * If a register is invalid, replace its descriptors with NULL. - */ - for (int i =3D 0; i < 4; i++) { - if (regs->reg[i].invalid) - regs->regv[i] =3D 0; - } -} - -/** - * for_each_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors - * @_regs: CPUID(0x2) register output, as returned by cpuid_leaf_0x2() - * @_ptr: u8 pointer, for macro internal use only - * @_desc: Pointer to the parsed CPUID(0x2) descriptor at each iteration - * - * Loop over the 1-byte descriptors in the passed CPUID(0x2) output regist= ers - * @_regs. Provide the parsed information for each descriptor through @_d= esc. - * - * To handle cache-specific descriptors, switch on @_desc->c_type. For TLB - * descriptors, switch on @_desc->t_type. - * - * Example usage for cache descriptors:: - * - * const struct leaf_0x2_table *desc; - * union leaf_0x2_regs regs; - * u8 *ptr; - * - * cpuid_leaf_0x2(®s); - * for_each_cpuid_0x2_desc(regs, ptr, desc) { - * switch (desc->c_type) { - * ... - * } - * } - */ -#define for_each_cpuid_0x2_desc(_regs, _ptr, _desc) \ - for (_ptr =3D &(_regs).desc[1]; \ - _ptr < &(_regs).desc[16] && (_desc =3D &cpuid_0x2_table[*_ptr]); \ - _ptr++) - /* * CPUID(0x80000006) parsing: */ @@ -573,7 +504,7 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) */ =20 /** - * for_each_parsed_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descr= iptors + * for_each_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors * @_regs: Leaf 0x2 register output, as returned by cpuid_leaf_raw() * @_ptr: u8 pointer, for macro internal use only * @_desc: Pointer to parsed descriptor information at each iteration @@ -595,13 +526,13 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) * // Handle error * } * - * for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) { + * for_each_cpuid_0x2_desc(regs, ptr, desc) { * switch (desc->c_type) { * ... * } * } */ -#define for_each_parsed_cpuid_0x2_desc(_regs, _ptr, _desc) \ +#define for_each_cpuid_0x2_desc(_regs, _ptr, _desc) \ for (({ static_assert(sizeof(*_regs) =3D=3D sizeof(union leaf_0x2_regs));= }), \ _ptr =3D &((union leaf_0x2_regs *)(_regs))->desc[1]; \ _ptr < &((union leaf_0x2_regs *)(_regs))->desc[16] && (_desc =3D &cp= uid_0x2_table[*_ptr]);\ diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index 4c3a08593ec4..c09e7f96fa77 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -398,7 +398,7 @@ static void intel_cacheinfo_0x2(struct cpuinfo_x86 *c) if (!regs) return; =20 - for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) { + for_each_cpuid_0x2_desc(regs, ptr, desc) { switch (desc->c_type) { case CACHE_L1_INST: l1i +=3D desc->c_size; break; case CACHE_L1_DATA: l1d +=3D desc->c_size; break; diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 7078b4264294..dd284ece0de0 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -717,7 +717,7 @@ static void intel_detect_tlb(struct cpuinfo_x86 *c) if (!regs) return; =20 - for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) + for_each_cpuid_0x2_desc(regs, ptr, desc) intel_tlb_lookup(desc); } =20 --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A22E835690A for ; Fri, 5 Sep 2025 12:16:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074607; cv=none; b=eAb6U9tBQTpDCCSgzC0Vb2fDUWzm72wXFr++wLyrZvtllmWm3h/JFZaHJ39hlr3wuFiTuQfuWVD3NkThHlmYHgJt6qklYQmoGAGfRRu3Oh+j6UFJcFVD1mQeHBfb3J7u+Nr3TCKfySNDUs7cuzN1PI1qsnlg037Ibv8vcCOMEas= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074607; c=relaxed/simple; bh=zHGfdATx2CbM80sSBFShaRQR46slZRAipaOxYzCj5mw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bGpw/PrfPXAqUHYtAKJpPG1HaVh8EtF0G+1b9mWYNdWrVaM7aVfyT8qi6xTTGnR+c57EH0c8Sw9cPVrmbUeprOuW/9STvnSeiOKG9Gi1mCpA85hJDSaT3G32yr/oQLSIxhNmyIcd+5UTIfLCMQlustM6ruwT6gMqr927X8TcA1g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ZTeGvr8j; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=b+BrGIv/; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ZTeGvr8j"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="b+BrGIv/" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074603; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=J2o1gQPsOlt6+EV7FAqZn/kp7f8rsb9zroA5aANr7Go=; b=ZTeGvr8jFO7FgPrpGpD+zVI/iN7FrFeKrfR9yewnsmgHA70L/oefs//7IrU90Em6KUA8nw ELibTaT2gI27k0+HadbIiFzo6Q0Wxy9jX0cA0vgaA+kLZhlEnQ0yY9uXfhRkx5Go1ODeDC s/xt5AuClatOGbBK6Y2UbnkertBYJ1oRtqzXa6Y7De8x/x/4/3QZ5g1xFZhmYHbZJdVNHy dATuH7aJcYIgHGnk1A9Puj/I4IxYYwi59cUtx+yr8Hnl4nnOXisSCaYtnsAaVmtqRvsknh f00CkL3VwXNAKYlYHG4TUckhmhOYEZt8Bxk87g4bA1mOcaLl/o0wEI4Hnj9TAA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074603; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=J2o1gQPsOlt6+EV7FAqZn/kp7f8rsb9zroA5aANr7Go=; b=b+BrGIv/vdOmlQ6ELZdX9iKxqAa2WmVtA3HnRXTbny9lOZcoVsG81rUUPx8fPkipzF2yC9 RQFI2csxWiL6OYAg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 24/35] x86/cpuid: Parse 'deterministic cache parameters' CPUID leaves Date: Fri, 5 Sep 2025 14:15:04 +0200 Message-ID: <20250905121515.192792-25-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add CPUID(0x4) and CPUID(0x8000001d) support to the CPUID parser. Query CPUID(0x4) only for Intel, Centaur, and Zhaoxin as these are the only x86 vendors where it is supported. Query CPUID(0x8000001d) only for AMD and Hygon. Define a single output parsing function for both CPUID leaves, as both have the same subleaf cache enumeration logic. Introduce the macro __define_cpuid_read_function() to avoid code duplication between the CPUID parser default read function, cpuid_read_generic(), and the new CPUID(0x4)/CPUID(0x8000001d) parsing logic. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/types.h | 2 ++ arch/x86/kernel/cpu/cpuid_parser.c | 37 +++++++++++++++++++++++++----- arch/x86/kernel/cpu/cpuid_parser.h | 6 ++++- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index b54080066084..411a2a96e3ed 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -237,10 +237,12 @@ struct cpuid_leaves { CPUID_LEAF ( 0x0, 0 ); CPUID_LEAF ( 0x1, 0 ); CPUID_LEAF ( 0x2, 0 ); + CPUID_LEAF_N ( 0x4, 8 ); CPUID_LEAF ( 0x80000000, 0 ); CPUID_LEAF ( 0x80000002, 0 ); CPUID_LEAF ( 0x80000003, 0 ); CPUID_LEAF ( 0x80000004, 0 ); + CPUID_LEAF_N ( 0x8000001d, 8 ); }; =20 /* diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid= _parser.c index f7dc5c78b06b..6d1dc56f11f2 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -22,17 +22,36 @@ static const struct cpuid_vendor_entry cpuid_vendor_ent= ries[] =3D { * Leaf read functions: */ =20 -/* - * Default CPUID parser read function +/** + * __define_cpuid_parser_read_function() - Generate a CPUID parser leaf re= ad function + * @suffix: Generated function name suffix (full name becomes: cpuid_read_= @suffix()) + * @_leaf_t: Type to cast the CPUID query output storage pointer + * @_leaf: Name of the CPUID query storage pointer + * @_break_c: Condition to break the CPUID parsing loop, which may referen= ce @_leaf, and + * where @_leaf stores each iteration's CPUID query output. * * Satisfies the requirements stated at 'struct cpuid_parse_entry'->read(). + * Define a CPUID parser read function according to the requirements state= d at + * 'struct cpuid_parse_entry'->read(). */ -static void cpuid_read_generic(const struct cpuid_parse_entry *e, struct c= puid_read_output *output) -{ - for (int i =3D 0; i < e->maxcnt; i++, output->regs++, output->info->nr_en= tries++) - cpuid_read_subleaf(e->leaf, e->subleaf + i, output->regs); +#define __define_cpuid_parser_read_function(suffix, _leaf_t, _leaf, _break= _c) \ +static void \ +cpuid_read_##suffix(const struct cpuid_parse_entry *e, struct cpuid_read_o= utput *output) \ +{ \ + struct _leaf_t *_leaf =3D (struct _leaf_t *)output->regs; \ + \ + for (int i =3D 0; i < e->maxcnt; i++, _leaf++, output->info->nr_entries++= ) { \ + cpuid_read_subleaf(e->leaf, e->subleaf + i, _leaf); \ + if (_break_c) \ + break; \ + } \ } =20 +/* + * Default CPUID parser read function + */ +__define_cpuid_parser_read_function(generic, cpuid_regs, ignored, false); + static void cpuid_read_0x2(const struct cpuid_parse_entry *e, struct cpuid= _read_output *output) { union leaf_0x2_regs *regs =3D (union leaf_0x2_regs *)output->regs; @@ -71,6 +90,12 @@ static void cpuid_read_0x2(const struct cpuid_parse_entr= y *e, struct cpuid_read_ output->info->nr_entries =3D 1; } =20 +/* + * Shared read function for Intel CPUID(0x4) and AMD CPUID(0x8000001d), as= both have + * the same subleaf enumeration logic and register output format. + */ +__define_cpuid_parser_read_function(deterministic_cache, leaf_0x4_n, l, l-= >cache_type =3D=3D 0); + static void cpuid_read_0x80000000(const struct cpuid_parse_entry *e, struc= t cpuid_read_output *output) { struct leaf_0x80000000_0 *el0 =3D (struct leaf_0x80000000_0 *)output->reg= s; diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index 7366e8468116..227ffac6b297 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -138,12 +138,14 @@ struct cpuid_parse_entry { * vendor entry, are treated by the CPUID parser as valid for all x86 vend= ors. */ #define CPUID_COMMON_PARSE_ENTRIES \ - /* Leaf Subleaf Reader function */ \ + /* Leaf Static subleaf Reader function */ \ CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \ + CPUID_PARSE_ENTRY_N ( 0x4, deterministic_cache ), \ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \ + CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \ =20 /* * CPUID parser tables repository: @@ -177,5 +179,7 @@ struct cpuid_vendor_entry { #define CPUID_VENDOR_ENTRIES \ /* Leaf Vendor list */ \ CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR= _ZHAOXIN),\ + CPUID_VENDOR_ENTRY(0x4, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR= _ZHAOXIN),\ + CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \ =20 #endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 863413570BE for ; Fri, 5 Sep 2025 12:16:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074610; cv=none; b=G24ZfyfqCdbB8R5oxOHIQ0545F0hGDjrn2cWGatGwpbTtr25A71Pbxco+d+NvWVPWbUu61+MObXmSf7jWRNAPvLpDNMupp/RpzzylkclLWF8kdf1Hjkh6EQzw8TrzrrX86XgktGRgk5FslZ9Egkqlc2JxjL6QAOb+V7HODMtxfE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074610; c=relaxed/simple; bh=yNpYB8ZWbb+KQniL0ZjgQ/fa4iKBtyPmfBP0wwNfaj8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LTcUAS+Iz6ciNZmWNAfo66iUp9r2kzy42Zo3myrqP/8AIrClZ9vR/Jlbn2VdrldmLjeOPRCxQ+o2l61vP2OxBOdb/2+HcsvT0e4Sm1EKKmVRi7ZbN12lj3dyLe0NtBJyaN6emaUEhmxDmhF1VRW7uTELxpbDuWc68dw2SOGRCco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=hhUYr5VZ; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=nI5KapsW; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="hhUYr5VZ"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="nI5KapsW" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074607; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qs37mBil5a1SU5iV5EX5mmOXYYZ7JEI/2oUycDoeqOI=; b=hhUYr5VZCTE+u1nYiJsIi1G1uw74k1+Iij6dvGUyJbd1HRye9llNzpgcDW3JfZB3IRh5wx i3kvG4UeAO+SOfZi5ogAKy14hhvqxmy84xMSYZ8SuJxKsESihYSU9TCHCoy3uwixi8XqH6 ajEo4BGd5Y9BlkAl3bkp+G21RaIu6FYJg79e4fk4+2IJGI+n3e3vvkOqQh2X5iv6TlYwuq FZszPmQ6j/kSVafwYGnSHSePbh/zxCs6jLxJN33wQ5p2IT9isPcHPlLBg13PY0RROIMCov iyuIZQL7oOOT9631JFgNGVTOeCYX7/3UyqRdXSh7ShiIv3G3SI5eQ0Y82ix2YA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074607; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qs37mBil5a1SU5iV5EX5mmOXYYZ7JEI/2oUycDoeqOI=; b=nI5KapsW9/tkpPt5pKRyxhoWA6LhI44HfJnbO83cJSekRDIzGUNjHfPV1BdkiF9pj30yWj RmMBhJftuJ6AcFDg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 25/35] x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code Date: Fri, 5 Sep 2025 14:15:05 +0200 Message-ID: <20250905121515.192792-26-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prepare the CPUID(0x4) cache topology code for using parsed CPUID APIs instead of invoking direct CPUID queries. Since such an API requires a 'struct cpuinfo_x86' reference, trickle it from the 's populate_cache_leaves() x86 implementation down to fill_cpuid4_info() and its Intel-specific CPUID(0x4) code. No functional change intended. Suggested-by: Ingo Molnar Signed-off-by: Ahmed S. Darwish Link: https://lore.kernel.org/lkml/aBnEBbDATdE2LTGU@gmail.com --- arch/x86/kernel/cpu/cacheinfo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index c09e7f96fa77..f6b093dd8416 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -252,7 +252,7 @@ static int amd_fill_cpuid4_info(int index, struct _cpui= d4_info *id4) return cpuid4_info_fill_done(id4, eax, ebx, ecx); } =20 -static int intel_fill_cpuid4_info(int index, struct _cpuid4_info *id4) +static int intel_fill_cpuid4_info(struct cpuinfo_x86 *unused, int index, s= truct _cpuid4_info *id4) { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; @@ -264,13 +264,13 @@ static int intel_fill_cpuid4_info(int index, struct _= cpuid4_info *id4) return cpuid4_info_fill_done(id4, eax, ebx, ecx); } =20 -static int fill_cpuid4_info(int index, struct _cpuid4_info *id4) +static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpui= d4_info *id4) { u8 cpu_vendor =3D boot_cpu_data.x86_vendor; =20 return (cpu_vendor =3D=3D X86_VENDOR_AMD || cpu_vendor =3D=3D X86_VENDOR_= HYGON) ? amd_fill_cpuid4_info(index, id4) : - intel_fill_cpuid4_info(index, id4); + intel_fill_cpuid4_info(c, index, id4); } =20 static int find_num_cache_leaves(struct cpuinfo_x86 *c) @@ -443,7 +443,7 @@ static bool intel_cacheinfo_0x4(struct cpuinfo_x86 *c) struct _cpuid4_info id4 =3D {}; int ret; =20 - ret =3D intel_fill_cpuid4_info(i, &id4); + ret =3D intel_fill_cpuid4_info(c, i, &id4); if (ret < 0) continue; =20 @@ -612,17 +612,17 @@ int populate_cache_leaves(unsigned int cpu) struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); struct cacheinfo *ci =3D this_cpu_ci->info_list; u8 cpu_vendor =3D boot_cpu_data.x86_vendor; - u32 apicid =3D cpu_data(cpu).topo.apicid; + struct cpuinfo_x86 *c =3D &cpu_data(cpu); struct amd_northbridge *nb =3D NULL; struct _cpuid4_info id4 =3D {}; int idx, ret; =20 for (idx =3D 0; idx < this_cpu_ci->num_leaves; idx++) { - ret =3D fill_cpuid4_info(idx, &id4); + ret =3D fill_cpuid4_info(c, idx, &id4); if (ret) return ret; =20 - id4.id =3D get_cache_id(apicid, &id4); + id4.id =3D get_cache_id(c->topo.apicid, &id4); =20 if (cpu_vendor =3D=3D X86_VENDOR_AMD || cpu_vendor =3D=3D X86_VENDOR_HYG= ON) nb =3D amd_init_l3_cache(idx); --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DA793570DF for ; Fri, 5 Sep 2025 12:16:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074613; cv=none; b=EULbyqibz6Ki+ZDhMbOc2LJBVldSkbaP8OKUEcty9Wad97Z6iLemHWazLr5DV6lTWBgVKz4rP/RqPt2wcgz1/eZlvZ/zCLYEOGkbo3HVT4B+1XbTtvuDMatbVvWjMeITJ4vb62O+ENHWlWxm7JnrMmdsFLbxbT7w9PayHgf5XeI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074613; c=relaxed/simple; bh=O5cAbpiI+Tjmr4wDFGGhia3hX/6l83QzjiYacPX5AVY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fQ+BqDGOQJjrDlzZXhKKVKjbTezF08XVvXgXXIckvOiakVU0aS1ksnWEiIMKpU3a2wAJOxmb1JuFnZ2XoNtlJ6r8A9tBWu31U3sjhw2Z+eMzenfY2klQugRx0Cc6HpqcSfpddD/2TgQeqnrG6mea0dAuX8KF7bynoCQLtzwM2/c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ujxhTLcm; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=IlBGgObC; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ujxhTLcm"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="IlBGgObC" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074610; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cQoSw1nvlRzPsTiSlFXd+9t8QVcHNs1P2S1dYlYV6PQ=; b=ujxhTLcmZpFU3mTnbTnUoUZtVs02mmiudGxi9IVAMZoOK7EAmdbZ6/vOmWK+gws2nwBsdk s5T8fFZ8Dsf1SXrnVbIT6co8S/EzSFhfkpd5W2zFunH3BkjkOsPqhuYuR95Jcw1Ml0RuCt AHiN2hf/9FtsHQH/SjFv8ej0VPk78mKLjlJKpSnbf6K3C3cFtxvZPRBSVwl5xVK/WiaX9B M088P4l96N1Zj18mkZVE67OlXbWhnCF1lfr0l55B50xlhMp2bY+KUjmT+gztO55Bp9fpHD neNqyzJOCUYTXdoCTUbhjI3GZOltWS7MHmmcL9DCPxW71FKYA7Ahd7j1FfC1dw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074610; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cQoSw1nvlRzPsTiSlFXd+9t8QVcHNs1P2S1dYlYV6PQ=; b=IlBGgObC4G10J1mwyAFMQkwZqfPLKf9tf4bC2w/mfbbt8rVzJ/YjTTqJexJT14xTzV5Gly /NV3mh8NzxOyEFDQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 26/35] x86/cacheinfo: Use parsed CPUID(0x4) Date: Fri, 5 Sep 2025 14:15:06 +0200 Message-ID: <20250905121515.192792-27-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For the Intel cacheinfo code, use parsed CPUID(0x4) access instead of a direct CPUID query. Use the parsed CPUID API: cpuid_subleaf_count(c, 0x4) to determine the number of CPUID(0x4) cache subleaves instead of calling find_num_cache_leaves(), which uses direct CPUID(0x4) queries. Since find_num_cache_leaves() is no longer needed for Intel code paths, make it AMD-specific: - Rename it to amd_find_num_cache_leaves() - Remove its Intel CPUID(0x4) logic Adjust the AMD code paths accordingly. At intel_cacheinfo_0x4(), remove the max CPUID level check since cpuid_subleaf_count(c, 0x4) will safely return zero if CPUID(0x4) is not supported by the CPU. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/cacheinfo.c | 40 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index f6b093dd8416..76fa3a01a34b 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -252,16 +252,17 @@ static int amd_fill_cpuid4_info(int index, struct _cp= uid4_info *id4) return cpuid4_info_fill_done(id4, eax, ebx, ecx); } =20 -static int intel_fill_cpuid4_info(struct cpuinfo_x86 *unused, int index, s= truct _cpuid4_info *id4) +static int intel_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct= _cpuid4_info *id4) { - union _cpuid4_leaf_eax eax; - union _cpuid4_leaf_ebx ebx; - union _cpuid4_leaf_ecx ecx; - u32 ignored; + const struct cpuid_regs *regs =3D cpuid_subleaf_n_raw(c, 0x4, index); =20 - cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &ignored); + if (!regs) + return -EIO; =20 - return cpuid4_info_fill_done(id4, eax, ebx, ecx); + return cpuid4_info_fill_done(id4, + (union _cpuid4_leaf_eax)(regs->eax), + (union _cpuid4_leaf_ebx)(regs->ebx), + (union _cpuid4_leaf_ecx)(regs->ecx)); } =20 static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpui= d4_info *id4) @@ -273,17 +274,16 @@ static int fill_cpuid4_info(struct cpuinfo_x86 *c, in= t index, struct _cpuid4_inf intel_fill_cpuid4_info(c, index, id4); } =20 -static int find_num_cache_leaves(struct cpuinfo_x86 *c) +static int amd_find_num_cache_leaves(struct cpuinfo_x86 *c) { - unsigned int eax, ebx, ecx, edx, op; union _cpuid4_leaf_eax cache_eax; + unsigned int eax, ebx, ecx, edx; int i =3D -1; =20 - /* Do a CPUID(op) loop to calculate num_cache_leaves */ - op =3D (c->x86_vendor =3D=3D X86_VENDOR_AMD || c->x86_vendor =3D=3D X86_V= ENDOR_HYGON) ? 0x8000001d : 4; + /* Do a CPUID(0x8000001d) loop to calculate num_cache_leaves */ do { ++i; - cpuid_count(op, i, &eax, &ebx, &ecx, &edx); + cpuid_count(0x8000001d, i, &eax, &ebx, &ecx, &edx); cache_eax.full =3D eax; } while (cache_eax.split.type !=3D CTYPE_NULL); return i; @@ -328,7 +328,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u= 16 die_id) * Newer families: LLC ID is calculated from the number * of threads sharing the L3 cache. */ - u32 llc_index =3D find_num_cache_leaves(c) - 1; + u32 llc_index =3D amd_find_num_cache_leaves(c) - 1; struct _cpuid4_info id4 =3D {}; =20 if (!amd_fill_cpuid4_info(llc_index, &id4)) @@ -353,7 +353,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c) struct cpu_cacheinfo *ci =3D get_cpu_cacheinfo(c->cpu_index); =20 if (boot_cpu_has(X86_FEATURE_TOPOEXT)) - ci->num_leaves =3D find_num_cache_leaves(c); + ci->num_leaves =3D amd_find_num_cache_leaves(c); else if (c->extended_cpuid_level >=3D 0x80000006) ci->num_leaves =3D (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3; } @@ -362,7 +362,7 @@ void init_hygon_cacheinfo(struct cpuinfo_x86 *c) { struct cpu_cacheinfo *ci =3D get_cpu_cacheinfo(c->cpu_index); =20 - ci->num_leaves =3D find_num_cache_leaves(c); + ci->num_leaves =3D amd_find_num_cache_leaves(c); } =20 static void intel_cacheinfo_done(struct cpuinfo_x86 *c, unsigned int l3, @@ -426,15 +426,9 @@ static bool intel_cacheinfo_0x4(struct cpuinfo_x86 *c) unsigned int l2_id =3D BAD_APICID, l3_id =3D BAD_APICID; unsigned int l1d =3D 0, l1i =3D 0, l2 =3D 0, l3 =3D 0; =20 - if (c->cpuid_level < 4) - return false; - - /* - * There should be at least one leaf. A non-zero value means - * that the number of leaves has been previously initialized. - */ + /* Non-zero means that it has been previously initialized */ if (!ci->num_leaves) - ci->num_leaves =3D find_num_cache_leaves(c); + ci->num_leaves =3D cpuid_subleaf_count(c, 0x4); =20 if (!ci->num_leaves) return false; --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77A5A35A292 for ; Fri, 5 Sep 2025 12:16:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074616; cv=none; b=UpA4kjfOgBrIZZhzJ66ja5ZVdkeksAiwWx8/MxyRMVHYPctvez+JWtpP6MZ094SsuzorqxUFDF35nUObMRyOF4/vfKLbSjk05Y/rl/qhote/w+6t6jJ9vFoDqtPz5qOdRR+BQDNYaY5MLnT7Dpf4hOwoNh0SgSUntwtLwcA0LtQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074616; c=relaxed/simple; bh=rl+gbmlu1pyJb67mFYgrlr5iqNCPYrnKVRwsxOXXLyc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CA8EjueZdu8O+Ev9IL6Ry0OydFwyC5YNDUCXfEFaPSAlEAnpkV3GegUOHLYRUM27GnW6sGqyjMLW7R2ct4fQ+/3FMbOer6jhT7kJSkSInm9bO7d35ncvMEUdFof5OkKWXA3AzZwi7q7bazQEvTzlM+pH48j9jhtXoBvcVYVM8Rs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=qbkCzjYh; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=Z5zpEl1+; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="qbkCzjYh"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="Z5zpEl1+" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LVDTwm7Ah9FpA/qSB7MLWK6yLm0D5mM1+yK2R8vnyDs=; b=qbkCzjYhVkIgyms/ETYOqRcPJGxHYtPP//5+pcT3B4pqPiz/vv4TBLcsEUkZAGQJDMmhUC mR0le1Qtam6ABGSOFXRfrtJFLWqe/cGWNGY7lawiCH3O1MvIvxe9RCQvQX80tAMP+XgR4Y WSFDyZBDRN40SEqNst5ggfIqxcAnPjqaFRCPGrWuKCdiEjfMpYXRavU2LxvRo1fZAf3lg9 vi+gmjExOaRONaz/J+LNwpheW4k/nSiEHsvFo0NSVFZ3HTS1lr55rpPw2B52Oj3QNmuMCS AV4CIF2sLXJdErnGoOQG0rUM8RRfrm6ALVTjVCEPHZKzsxrGwd+8uypzApAIlw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LVDTwm7Ah9FpA/qSB7MLWK6yLm0D5mM1+yK2R8vnyDs=; b=Z5zpEl1+eIxie4ScE4+ki0QH8Q+x7iejJdlG1Tv61V8XOExwXRA0LvF8Ycoo3hwGHCZ4Pn ROQ/Be5D1+Y9RaDg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 27/35] x86/cacheinfo: Use parsed CPUID(0x8000001d) Date: Fri, 5 Sep 2025 14:15:07 +0200 Message-ID: <20250905121515.192792-28-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the AMD cacheinfo code, use parsed CPUID(0x8000001d) access instead of issuing direct CPUID queries. Beside the CPUID parser centralization benefits, this allows using the auto-generated data types, and their full C99 bitfields, instead of doing ugly bitwise operations on CPUID register output. Since parsed CPUID access requires a 'struct cpuinfo_x86' reference, trickle it down to relevant functions. Use the parsed CPUID API: cpuid_subleaf_count(c, 0x8000001d) to find the number of cache leaves, replacing amd_find_num_cache_leaves() and its direct CPUID queries. Drop that function completely as it is no longer needed. For now, keep using the 'union _cpuid4_leaf_eax/ebx/ecx' structures as they are required by the AMD CPUID(0x4) emulation code paths. A follow up commit will replace them with their auto-generated equivalents. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/cacheinfo.c | 41 +++++++++++++-------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index 76fa3a01a34b..3e1ccab56e4c 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -237,16 +237,22 @@ static int cpuid4_info_fill_done(struct _cpuid4_info = *id4, union _cpuid4_leaf_ea return 0; } =20 -static int amd_fill_cpuid4_info(int index, struct _cpuid4_info *id4) +static int amd_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _= cpuid4_info *id4) { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; union _cpuid4_leaf_ecx ecx; - u32 ignored; =20 - if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor =3D=3D = X86_VENDOR_HYGON) - cpuid_count(0x8000001d, index, &eax.full, &ebx.full, &ecx.full, &ignored= ); - else + if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor =3D=3D = X86_VENDOR_HYGON) { + const struct cpuid_regs *regs =3D cpuid_subleaf_n_raw(c, 0x8000001d, ind= ex); + + if (!regs) + return -EIO; + + eax.full =3D regs->eax; + ebx.full =3D regs->ebx; + ecx.full =3D regs->ecx; + } else legacy_amd_cpuid4(index, &eax, &ebx, &ecx); =20 return cpuid4_info_fill_done(id4, eax, ebx, ecx); @@ -270,25 +276,10 @@ static int fill_cpuid4_info(struct cpuinfo_x86 *c, in= t index, struct _cpuid4_inf u8 cpu_vendor =3D boot_cpu_data.x86_vendor; =20 return (cpu_vendor =3D=3D X86_VENDOR_AMD || cpu_vendor =3D=3D X86_VENDOR_= HYGON) ? - amd_fill_cpuid4_info(index, id4) : + amd_fill_cpuid4_info(c, index, id4) : intel_fill_cpuid4_info(c, index, id4); } =20 -static int amd_find_num_cache_leaves(struct cpuinfo_x86 *c) -{ - union _cpuid4_leaf_eax cache_eax; - unsigned int eax, ebx, ecx, edx; - int i =3D -1; - - /* Do a CPUID(0x8000001d) loop to calculate num_cache_leaves */ - do { - ++i; - cpuid_count(0x8000001d, i, &eax, &ebx, &ecx, &edx); - cache_eax.full =3D eax; - } while (cache_eax.split.type !=3D CTYPE_NULL); - return i; -} - /* * The max shared threads number comes from CPUID(0x4) EAX[25-14] with inp= ut * ECX as cache index. Then right shift apicid by the number's order to get @@ -328,10 +319,10 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c,= u16 die_id) * Newer families: LLC ID is calculated from the number * of threads sharing the L3 cache. */ - u32 llc_index =3D amd_find_num_cache_leaves(c) - 1; + u32 llc_index =3D cpuid_subleaf_count(c, 0x8000001d) - 1; struct _cpuid4_info id4 =3D {}; =20 - if (!amd_fill_cpuid4_info(llc_index, &id4)) + if (!amd_fill_cpuid4_info(c, llc_index, &id4)) c->topo.llc_id =3D get_cache_id(c->topo.apicid, &id4); } } @@ -353,7 +344,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c) struct cpu_cacheinfo *ci =3D get_cpu_cacheinfo(c->cpu_index); =20 if (boot_cpu_has(X86_FEATURE_TOPOEXT)) - ci->num_leaves =3D amd_find_num_cache_leaves(c); + ci->num_leaves =3D cpuid_subleaf_count(c, 0x8000001d); else if (c->extended_cpuid_level >=3D 0x80000006) ci->num_leaves =3D (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3; } @@ -362,7 +353,7 @@ void init_hygon_cacheinfo(struct cpuinfo_x86 *c) { struct cpu_cacheinfo *ci =3D get_cpu_cacheinfo(c->cpu_index); =20 - ci->num_leaves =3D amd_find_num_cache_leaves(c); + ci->num_leaves =3D cpuid_subleaf_count(c, 0x8000001d); } =20 static void intel_cacheinfo_done(struct cpuinfo_x86 *c, unsigned int l3, --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E04B35A2B0 for ; Fri, 5 Sep 2025 12:16:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074619; cv=none; b=ERwLZWiPk2OFNvHS4EnC+Pp26nOrY1jAzb3XYI3RrtWsVfDbuWHYdHAUdS2pMghI2FoU+tFmfnKCO611mTaAEjVjkLT4zyRZ/Uy1a1cFZuXSGHRcakzPO3SV/iEEt8c2nWO02l1U3sDGH1I3EFk4GWb9HrLZYUE/LNsONLY1Fd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074619; c=relaxed/simple; bh=yyoLGJdIQJ+uteloafTm4myva2llzw52/YQZvjzHUsI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aq598PFA+g/9rmapXHy90keS5+Ut5EP2ubwiX0oYrjhBl2WW/XBJrcgCTjnenjgDi8qDbh/CKY/2ncwWVD/fL18J/B3mVI8tLTFWAsIlJDnVE2yje8f4x/eOVD5QfnDTxAn2aMsppsCzeX8sI4tWEN/fLAIFliBOGNaAdTB1wz4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=rRzLLUjh; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=2Onh9cHH; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="rRzLLUjh"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="2Onh9cHH" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074616; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+3DaCaEgbHSXI0dlH4MV/dgs7FEd82F2fVqQWxZutv4=; b=rRzLLUjhu0OdiJ64w5jfGeVPDxrFCYxglax1bBYNm6OT0Fhuew7SegmPOAdgZMmQEmgTmZ +2kVXl2WSpEWOLgYVbE4mlMEDq9pz0fPAvmFzY6DiwT9LfZMkxTCxDk/WrWu7gEfBfSclz hRh+vXzenRmmuUu4HENxPuDwXTZL78ywqvHh/NsTafkHWPEON8kbeLMCuQ9c/tkAPl9pJp t60d7CEYZ4/CUksgoopZNGzgSxCli5ypch5mJOfyF0mO3JIJUVmOS3HjBDwb0JZ/NZDPfm jVEAsgmv+9sqG/TMuaYqpg2EzSKmeqjYhqnQZS4jXGksdC3HQsWwLbhGbDRK4w== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074616; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+3DaCaEgbHSXI0dlH4MV/dgs7FEd82F2fVqQWxZutv4=; b=2Onh9cHHfGbR8cQcTjzjkhrorB+h8AN11CzdSoSp9KCN5w5ozFrgznV9Vdq/xmlgn24zbL ZKpht4Id3AOkKaAA== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 28/35] x86/cpuid: Parse CPUID(0x80000005) and CPUID(0x80000006) Date: Fri, 5 Sep 2025 14:15:08 +0200 Message-ID: <20250905121515.192792-29-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Parse AMD cacheinfo CPUID(0x80000005) and CPUID(0x80000006), if available, using the generic CPUID parser read function cpuid_read_generic(). The x86/cacheinfo AMD CPUID(0x4)-emulation logic will be swithced next to the parsed CPUID table APIs instead of invoking direct CPUID queries. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/types.h | 2 ++ arch/x86/kernel/cpu/cpuid_parser.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index 411a2a96e3ed..5a3a365044ce 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -242,6 +242,8 @@ struct cpuid_leaves { CPUID_LEAF ( 0x80000002, 0 ); CPUID_LEAF ( 0x80000003, 0 ); CPUID_LEAF ( 0x80000004, 0 ); + CPUID_LEAF ( 0x80000005, 0 ); + CPUID_LEAF ( 0x80000006, 0 ); CPUID_LEAF_N ( 0x8000001d, 8 ); }; =20 diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index 227ffac6b297..44a056a5a321 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -145,6 +145,8 @@ struct cpuid_parse_entry { CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x80000005, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x80000006, 0, generic ), \ CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \ =20 /* --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6DA3735AAAF for ; Fri, 5 Sep 2025 12:17:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074622; cv=none; b=c5VWkMo61HwI2DSJVeV+63PSqwxsRVKnaX1B9Ls3KUmOvtL59X2qoClfISDBfTZvcujMc4o01xD5I/HqK6tTZN1quqEkXnXLRKPe9WuptAzhNNzKUjzVE/NOkOF3N1Kt9pkAE5/PlhQZEf46aJFXaeg55wwA+uKXFeRZ3RS9CWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074622; c=relaxed/simple; bh=7anxj/W4ZTI/3qrsbFCOcCPIVBbKWTXedcy9YL2aHH8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TUF+6SvGFBLuNrltK2FgNCQYZXD7BaHnU5Z8jS1S0mw0Z8PTZQdtaJ/p6aelQ97G252W2AAeBjYirPpZl1jS6OWU3d0YtiXisW0dL3J//CKPbTA65w08cGUcDf6jMLW/gkYMtFD1mSgrjv16Odpdn7FlzKiqHHlQVk8FU1kyxms= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=Zg1FJTkO; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=E8FxgQeM; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="Zg1FJTkO"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="E8FxgQeM" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074619; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sx4DffFKwZOMaQlBwx3uZ7KClJAls5rI47TU/h7xf5U=; b=Zg1FJTkOfyI7eHGp8ZIUJEcyJtN9kGs7mXOjInuVQn6fDgTJXqstcHfd9kf+GtWXDTpapE W+sv+voOXn9Z++mdR3Yt6OUXP3O/i08vv3/zNvCxbTpUnqh+aPXEoCzfLStArTvZ8kJmjR KtdnmvknyX2Hj/esz+rMfPG5k0opDSisg2t6VAgjbXSxoeNFLtCnGwMjqibG/baWKhAsit 8YTZSc+UNqRxD82d2wzvTX5Z6EuSUdNtf9RVGb6X9adENXZ2kcLMSGMMuaPNTcnuiKj/jZ +3iEQr5fvWJc32HxCfQb6UDaTNU13rlvUCklnuqPyAwz4xxc7adGkSpRqI/IDA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074619; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sx4DffFKwZOMaQlBwx3uZ7KClJAls5rI47TU/h7xf5U=; b=E8FxgQeM+AZH1wphj+h0fgpTyKjw7LXRkKXM4ilFoNvzeCnDYs9xqsdi3fu0kxnBfIkPom 4aPWxWvP1jhyrnBQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 29/35] x86/cacheinfo: Use auto-generated data types Date: Fri, 5 Sep 2025 14:15:09 +0200 Message-ID: <20250905121515.192792-30-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For the AMD CPUID(0x4) emulation logic, use the auto-generated data type: struct leaf_0x4_n instead of the manually-defined: union _cpuid4_leaf_{eax,ebx,ecx} ones. Remove such unions entirely as they are no longer used. Signed-off-by: Ahmed S. Darwish Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db --- arch/x86/kernel/cpu/cacheinfo.c | 127 +++++++++++--------------------- 1 file changed, 42 insertions(+), 85 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index 3e1ccab56e4c..8474d9047bad 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -41,39 +41,8 @@ enum _cache_type { CTYPE_UNIFIED =3D 3 }; =20 -union _cpuid4_leaf_eax { - struct { - enum _cache_type type :5; - unsigned int level :3; - unsigned int is_self_initializing :1; - unsigned int is_fully_associative :1; - unsigned int reserved :4; - unsigned int num_threads_sharing :12; - unsigned int num_cores_on_die :6; - } split; - u32 full; -}; - -union _cpuid4_leaf_ebx { - struct { - unsigned int coherency_line_size :12; - unsigned int physical_line_partition :10; - unsigned int ways_of_associativity :10; - } split; - u32 full; -}; - -union _cpuid4_leaf_ecx { - struct { - unsigned int number_of_sets :32; - } split; - u32 full; -}; - struct _cpuid4_info { - union _cpuid4_leaf_eax eax; - union _cpuid4_leaf_ebx ebx; - union _cpuid4_leaf_ecx ecx; + struct leaf_0x4_n regs; unsigned int id; unsigned long size; }; @@ -148,17 +117,14 @@ static const unsigned short assocs[] =3D { static const unsigned char levels[] =3D { 1, 1, 2, 3 }; static const unsigned char types[] =3D { 1, 2, 3, 3 }; =20 -static void legacy_amd_cpuid4(int index, union _cpuid4_leaf_eax *eax, - union _cpuid4_leaf_ebx *ebx, union _cpuid4_leaf_ecx *ecx) +static void legacy_amd_cpuid4(int index, struct leaf_0x4_n *regs) { unsigned int dummy, line_size, lines_per_tag, assoc, size_in_kb; union l1_cache l1i, l1d, *l1; union l2_cache l2; union l3_cache l3; =20 - eax->full =3D 0; - ebx->full =3D 0; - ecx->full =3D 0; + *regs =3D (struct leaf_0x4_n){ }; =20 cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val); cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val); @@ -204,71 +170,62 @@ static void legacy_amd_cpuid4(int index, union _cpuid= 4_leaf_eax *eax, return; } =20 - eax->split.is_self_initializing =3D 1; - eax->split.type =3D types[index]; - eax->split.level =3D levels[index]; - eax->split.num_threads_sharing =3D 0; - eax->split.num_cores_on_die =3D topology_num_cores_per_package(); + regs->cache_self_init =3D 1; + regs->cache_type =3D types[index]; + regs->cache_level =3D levels[index]; + regs->num_threads_sharing =3D 0; + regs->num_cores_on_die =3D topology_num_cores_per_package(); =20 if (assoc =3D=3D AMD_CPUID4_FULLY_ASSOCIATIVE) - eax->split.is_fully_associative =3D 1; + regs->fully_associative =3D 1; =20 - ebx->split.coherency_line_size =3D line_size - 1; - ebx->split.ways_of_associativity =3D assoc - 1; - ebx->split.physical_line_partition =3D lines_per_tag - 1; - ecx->split.number_of_sets =3D (size_in_kb * 1024) / line_size / - (ebx->split.ways_of_associativity + 1) - 1; + regs->cache_linesize =3D line_size - 1; + regs->cache_nways =3D assoc - 1; + regs->cache_npartitions =3D lines_per_tag - 1; + regs->cache_nsets =3D (size_in_kb * 1024) / line_size / + (regs->cache_nways + 1) - 1; } =20 -static int cpuid4_info_fill_done(struct _cpuid4_info *id4, union _cpuid4_l= eaf_eax eax, - union _cpuid4_leaf_ebx ebx, union _cpuid4_leaf_ecx ecx) +static int cpuid4_info_fill_done(struct _cpuid4_info *id4, const struct le= af_0x4_n *regs) { - if (eax.split.type =3D=3D CTYPE_NULL) + if (regs->cache_type =3D=3D CTYPE_NULL) return -EIO; =20 - id4->eax =3D eax; - id4->ebx =3D ebx; - id4->ecx =3D ecx; - id4->size =3D (ecx.split.number_of_sets + 1) * - (ebx.split.coherency_line_size + 1) * - (ebx.split.physical_line_partition + 1) * - (ebx.split.ways_of_associativity + 1); + id4->regs =3D *regs; + id4->size =3D (regs->cache_nsets + 1) * + (regs->cache_linesize + 1) * + (regs->cache_npartitions + 1) * + (regs->cache_nways + 1); =20 return 0; } =20 static int amd_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _= cpuid4_info *id4) { - union _cpuid4_leaf_eax eax; - union _cpuid4_leaf_ebx ebx; - union _cpuid4_leaf_ecx ecx; + struct leaf_0x4_n l_0x4_regs; =20 if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor =3D=3D = X86_VENDOR_HYGON) { - const struct cpuid_regs *regs =3D cpuid_subleaf_n_raw(c, 0x8000001d, ind= ex); + const struct leaf_0x8000001d_n *regs =3D cpuid_subleaf_n(c, 0x8000001d, = index); =20 if (!regs) return -EIO; =20 - eax.full =3D regs->eax; - ebx.full =3D regs->ebx; - ecx.full =3D regs->ecx; + /* CPUID(0x8000001d) and CPUID(0x4) have the same bitfields */ + l_0x4_regs =3D *(struct leaf_0x4_n *)regs; } else - legacy_amd_cpuid4(index, &eax, &ebx, &ecx); + legacy_amd_cpuid4(index, &l_0x4_regs); =20 - return cpuid4_info_fill_done(id4, eax, ebx, ecx); + return cpuid4_info_fill_done(id4, &l_0x4_regs); } =20 static int intel_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct= _cpuid4_info *id4) { - const struct cpuid_regs *regs =3D cpuid_subleaf_n_raw(c, 0x4, index); + const struct leaf_0x4_n *regs =3D cpuid_subleaf_n(c, 0x4, index); =20 if (!regs) return -EIO; =20 - return cpuid4_info_fill_done(id4, - (union _cpuid4_leaf_eax)(regs->eax), - (union _cpuid4_leaf_ebx)(regs->ebx), - (union _cpuid4_leaf_ecx)(regs->ecx)); + return cpuid4_info_fill_done(id4, regs); } =20 static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpui= d4_info *id4) @@ -290,7 +247,7 @@ static unsigned int get_cache_id(u32 apicid, const stru= ct _cpuid4_info *id4) unsigned long num_threads_sharing; int index_msb; =20 - num_threads_sharing =3D 1 + id4->eax.split.num_threads_sharing; + num_threads_sharing =3D 1 + id4->regs.num_threads_sharing; index_msb =3D get_count_order(num_threads_sharing); =20 return apicid >> index_msb; @@ -406,7 +363,7 @@ static unsigned int calc_cache_topo_id(struct cpuinfo_x= 86 *c, const struct _cpui unsigned int num_threads_sharing; int index_msb; =20 - num_threads_sharing =3D 1 + id4->eax.split.num_threads_sharing; + num_threads_sharing =3D 1 + id4->regs.num_threads_sharing; index_msb =3D get_count_order(num_threads_sharing); return c->topo.apicid & ~((1 << index_msb) - 1); } @@ -432,11 +389,11 @@ static bool intel_cacheinfo_0x4(struct cpuinfo_x86 *c) if (ret < 0) continue; =20 - switch (id4.eax.split.level) { + switch (id4.regs.cache_level) { case 1: - if (id4.eax.split.type =3D=3D CTYPE_DATA) + if (id4.regs.cache_type =3D=3D CTYPE_DATA) l1d =3D id4.size / 1024; - else if (id4.eax.split.type =3D=3D CTYPE_INST) + else if (id4.regs.cache_type =3D=3D CTYPE_INST) l1i =3D id4.size / 1024; break; case 2: @@ -497,7 +454,7 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, i= nt index, } else if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { unsigned int apicid, nshared, first, last; =20 - nshared =3D id4->eax.split.num_threads_sharing + 1; + nshared =3D id4->regs.num_threads_sharing + 1; apicid =3D cpu_data(cpu).topo.apicid; first =3D apicid - (apicid % nshared); last =3D first + nshared - 1; @@ -544,7 +501,7 @@ static void __cache_cpumap_setup(unsigned int cpu, int = index, } =20 ci =3D this_cpu_ci->info_list + index; - num_threads_sharing =3D 1 + id4->eax.split.num_threads_sharing; + num_threads_sharing =3D 1 + id4->regs.num_threads_sharing; =20 cpumask_set_cpu(cpu, &ci->shared_cpu_map); if (num_threads_sharing =3D=3D 1) @@ -571,13 +528,13 @@ static void ci_info_init(struct cacheinfo *ci, const = struct _cpuid4_info *id4, { ci->id =3D id4->id; ci->attributes =3D CACHE_ID; - ci->level =3D id4->eax.split.level; - ci->type =3D cache_type_map[id4->eax.split.type]; - ci->coherency_line_size =3D id4->ebx.split.coherency_line_size + 1; - ci->ways_of_associativity =3D id4->ebx.split.ways_of_associativity + 1; + ci->level =3D id4->regs.cache_level; + ci->type =3D cache_type_map[id4->regs.cache_type]; + ci->coherency_line_size =3D id4->regs.cache_linesize + 1; + ci->ways_of_associativity =3D id4->regs.cache_nways + 1; ci->size =3D id4->size; - ci->number_of_sets =3D id4->ecx.split.number_of_sets + 1; - ci->physical_line_partition =3D id4->ebx.split.physical_line_partition + = 1; + ci->number_of_sets =3D id4->regs.cache_nsets + 1; + ci->physical_line_partition =3D id4->regs.cache_npartitions + 1; ci->priv =3D nb; } =20 --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1AF8B35AAC6 for ; Fri, 5 Sep 2025 12:17:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074626; cv=none; b=SwubXb5nZP4/Vu6oE4cG50zvdAt42MudJYcqbRzPiOuREDgQ8pmMdupZ8DfsDkC/O3tMc1NFQk74rwteVHfYfm2uWn2adjQ0x6rQK58a30gf8629QY3bgMUdqNnsOYn2IEvCtfS0ldRmq5TVZxDNLoqseawwLUcoVsR0L76eWuk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074626; c=relaxed/simple; bh=TixfzEjwVGymqAeR1NCwoKWxkWvqqQZodbSVGE+G/bs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eN5a/OQEASNRDNUvzPZlNIdAKJuHWKiPA9jQf+JfqJUl6+KOh2SsW/sxFwZfjTmWJUvtzcOLeS/Bj7reJhjfXo3tSNSP+tFpCaGuHKXgCZgchou+IEOTR/eOfGW+yVrkq1xdTIT6rlrlSOFGaXNgYXSfulmgAHwTv0wpIwXx7N8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=w4bVxAFc; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=BdrimERf; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="w4bVxAFc"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="BdrimERf" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074622; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Jfr/B42lVlCz5r7cAgzfO7jsPmMcbv0EUY9kOUd9L/M=; b=w4bVxAFc8UmzZ/8f2f5DEsM+oESbcdOmtgL8kxWkRXS4v3/8CiZvN4od10twhESiSq3GDi 1RuqlCnzPLXP1qWS6hxAlsAu1XpXEbuZqMJQdJ6Z07YiXM3MbqubsWNvRXrd5QTwDSvbCP kbq2uaL6vHmNKS8gM/is+DAx5CfOBVy3MwTK9kyXBr6u3bAOHSc/9EYQKuVaFViMxFmOu9 6bTUKveOwGfjBKGKB92ppeeqo+1MAGjoA3FI58HLXMuLy01+yZz/PLDmHtvO5aCbeLgBPT dS+AIDcxZUB5rbaGCe+cC/GZGfOhFTKt8PG9YJj+ry+DyjUgcE0V/LNQGU9uwg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074622; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Jfr/B42lVlCz5r7cAgzfO7jsPmMcbv0EUY9kOUd9L/M=; b=BdrimERfRtS6FmsKg1JAPqqZt8jyDO7epwM7KNpi5MjH0OcLa66BB/kBR2KtMSYC/vu0iZ u4sHTvA0vUrPTeDw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 30/35] x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Date: Fri, 5 Sep 2025 14:15:10 +0200 Message-ID: <20250905121515.192792-31-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the AMD CPUID(0x4)-emulation logic, use parsed CPUID(0x80000005) and CPUID(0x80000006) access instead of direct CPUID queries. Beside the CPUID parser centralization benefits, this allows using the auto-generated data types, and their full C99 bitfields, instead of doing ugly bitwise operations or defining custom data types at call sites. Remove the 'union {l1,l2,l3}_cache' data types as they are no longer needed. Replace the expression: ci->num_leaves =3D (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3; with: ci->num_leaves =3D cpuid_leaf(c, 0x80000006)->l3_assoc ? 4 : 3; since per AMD manuals, an L3 associativity level of zero implies the absence of an L3 cache on the CPU. The CPUID(0x80000006) l3_assoc bitfield above is 4 bits wide at EDX offset 12. While at it, separate the 'Fallback AMD CPUID(0x4) emulation' comment from the '@AMD_L2_L3_INVALID_ASSOC' one, since the former acts as a source code section header. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/cacheinfo.c | 105 ++++++++++++-------------------- 1 file changed, 40 insertions(+), 65 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index 8474d9047bad..7033baa94276 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -56,47 +56,17 @@ static const enum cache_type cache_type_map[] =3D { }; =20 /* - * Fallback AMD CPUID(0x4) emulation + * Fallback AMD CPUID(0x4) emulation: * AMD CPUs with TOPOEXT can just use CPUID(0x8000001d) - * + */ + +/* * @AMD_L2_L3_INVALID_ASSOC: cache info for the respective L2/L3 cache sho= uld * be determined from CPUID(0x8000001d) instead of CPUID(0x80000006). */ - #define AMD_CPUID4_FULLY_ASSOCIATIVE 0xffff #define AMD_L2_L3_INVALID_ASSOC 0x9 =20 -union l1_cache { - struct { - unsigned line_size :8; - unsigned lines_per_tag :8; - unsigned assoc :8; - unsigned size_in_kb :8; - }; - unsigned int val; -}; - -union l2_cache { - struct { - unsigned line_size :8; - unsigned lines_per_tag :4; - unsigned assoc :4; - unsigned size_in_kb :16; - }; - unsigned int val; -}; - -union l3_cache { - struct { - unsigned line_size :8; - unsigned lines_per_tag :4; - unsigned assoc :4; - unsigned res :2; - unsigned size_encoded :14; - }; - unsigned int val; -}; - /* L2/L3 associativity mapping */ static const unsigned short assocs[] =3D { [1] =3D 1, @@ -117,50 +87,52 @@ static const unsigned short assocs[] =3D { static const unsigned char levels[] =3D { 1, 1, 2, 3 }; static const unsigned char types[] =3D { 1, 2, 3, 3 }; =20 -static void legacy_amd_cpuid4(int index, struct leaf_0x4_n *regs) +static void legacy_amd_cpuid4(struct cpuinfo_x86 *c, int index, struct lea= f_0x4_n *regs) { - unsigned int dummy, line_size, lines_per_tag, assoc, size_in_kb; - union l1_cache l1i, l1d, *l1; - union l2_cache l2; - union l3_cache l3; + const struct leaf_0x80000005_0 *el5 =3D cpuid_leaf(c, 0x80000005); + const struct leaf_0x80000006_0 *el6 =3D cpuid_leaf(c, 0x80000006); + const struct cpuid_regs *el5_raw =3D cpuid_leaf_raw(c, 0x80000005); + unsigned int line_size, lines_per_tag, assoc, size_in_kb; =20 *regs =3D (struct leaf_0x4_n){ }; =20 - cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val); - cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val); - - l1 =3D &l1d; switch (index) { - case 1: - l1 =3D &l1i; - fallthrough; case 0: - if (!l1->val) + if (!el5 || !el5_raw->ecx) return; =20 - assoc =3D (l1->assoc =3D=3D 0xff) ? AMD_CPUID4_FULLY_ASSOCIATIVE : l1->= assoc; - line_size =3D l1->line_size; - lines_per_tag =3D l1->lines_per_tag; - size_in_kb =3D l1->size_in_kb; + assoc =3D el5->l1_dcache_assoc; + line_size =3D el5->l1_dcache_line_size; + lines_per_tag =3D el5->l1_dcache_nlines; + size_in_kb =3D el5->l1_dcache_size_kb; + break; + case 1: + if (!el5 || !el5_raw->edx) + return; + + assoc =3D el5->l1_icache_assoc; + line_size =3D el5->l1_icache_line_size; + lines_per_tag =3D el5->l1_icache_nlines; + size_in_kb =3D el5->l1_icache_size_kb; break; case 2: - if (!l2.assoc || l2.assoc =3D=3D AMD_L2_L3_INVALID_ASSOC) + if (!el6 || !el6->l2_assoc || el6->l2_assoc =3D=3D AMD_L2_L3_INVALID_ASS= OC) return; =20 /* Use x86_cache_size as it might have K7 errata fixes */ - assoc =3D assocs[l2.assoc]; - line_size =3D l2.line_size; - lines_per_tag =3D l2.lines_per_tag; + assoc =3D assocs[el6->l2_assoc]; + line_size =3D el6->l2_line_size; + lines_per_tag =3D el6->l2_nlines; size_in_kb =3D __this_cpu_read(cpu_info.x86_cache_size); break; case 3: - if (!l3.assoc || l3.assoc =3D=3D AMD_L2_L3_INVALID_ASSOC) + if (!el6 || !el6->l3_assoc || el6->l3_assoc =3D=3D AMD_L2_L3_INVALID_ASS= OC) return; =20 - assoc =3D assocs[l3.assoc]; - line_size =3D l3.line_size; - lines_per_tag =3D l3.lines_per_tag; - size_in_kb =3D l3.size_encoded * 512; + assoc =3D assocs[el6->l3_assoc]; + line_size =3D el6->l3_line_size; + lines_per_tag =3D el6->l3_nlines; + size_in_kb =3D el6->l3_size_range * 512; if (boot_cpu_has(X86_FEATURE_AMD_DCM)) { size_in_kb =3D size_in_kb >> 1; assoc =3D assoc >> 1; @@ -170,6 +142,10 @@ static void legacy_amd_cpuid4(int index, struct leaf_0= x4_n *regs) return; } =20 + /* For L1d and L1i caches, 0xff is the full associativity marker */ + if ((index =3D=3D 0 || index =3D=3D 1) && assoc =3D=3D 0xff) + assoc =3D AMD_CPUID4_FULLY_ASSOCIATIVE; + regs->cache_self_init =3D 1; regs->cache_type =3D types[index]; regs->cache_level =3D levels[index]; @@ -213,7 +189,7 @@ static int amd_fill_cpuid4_info(struct cpuinfo_x86 *c, = int index, struct _cpuid4 /* CPUID(0x8000001d) and CPUID(0x4) have the same bitfields */ l_0x4_regs =3D *(struct leaf_0x4_n *)regs; } else - legacy_amd_cpuid4(index, &l_0x4_regs); + legacy_amd_cpuid4(c, index, &l_0x4_regs); =20 return cpuid4_info_fill_done(id4, &l_0x4_regs); } @@ -300,10 +276,9 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c) { struct cpu_cacheinfo *ci =3D get_cpu_cacheinfo(c->cpu_index); =20 - if (boot_cpu_has(X86_FEATURE_TOPOEXT)) - ci->num_leaves =3D cpuid_subleaf_count(c, 0x8000001d); - else if (c->extended_cpuid_level >=3D 0x80000006) - ci->num_leaves =3D (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3; + ci->num_leaves =3D boot_cpu_has(X86_FEATURE_TOPOEXT) ? + cpuid_subleaf_count(c, 0x8000001d) : + cpuid_leaf(c, 0x80000006)->l3_assoc ? 4 : 3; } =20 void init_hygon_cacheinfo(struct cpuinfo_x86 *c) --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0BF0635CEA6 for ; Fri, 5 Sep 2025 12:17:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074628; cv=none; b=qCK98tSyiEOHg7YEZrLG18nx/fgWVoa01Syg6wqTiwpWX2YjYFWG4GNcxmsuvRvMeu/fUF5EvVk8BFxopXxwsb8psAL+SaQZL+MrYwcgKalhWwGFO2088jbuz3Kb/wMGPCag018DQffIYDPtgh1GR1vcODFDl3DDU9Ai3JF4UBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074628; c=relaxed/simple; bh=pBJyRvgNQt474dIEuzA+OkD8yRjaAJyG8hxAgB4pNug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ipd7tScFUpDBUu6np9svzgkxJ0AFt0rD3gITR5WBFHCBI0VZpcVwYojKF4BH4SEH7TSohoocxHa9Jsmt3lvM85JPLr5EqRN+6lLYtbnYCYe+ymjsB3IX4+syjTLmU/UJvTDndaUNnDk0tOfEj4UHh0HjVpFhnwFGzueNoNB+6Ao= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=dqTViZY5; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=WrRW7DsB; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="dqTViZY5"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="WrRW7DsB" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074625; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7UH1ADx+oQa8Ha42YGFE8ArA8CIpjZUSmClZmRcsp1s=; b=dqTViZY5Rhg+4dxm6j6eTDrDRZxJobGKPEC5f6m105ViKQk5ihdBxBOVGZS+wnV/nnlJnq HlU8nooKUrlDLbtRN4x0YlRxsqIc1PsMXurE8hNPEozddY1FDkiDvRZIXZSOvEgoVZKaDT K9UTh1Hwz7rkkmXo0q/CbhmYfoeY/Sm0AwdEMVFCfFLALXH3uU6/V5K7FBUBQ+VO/nbN4z W13C99vHEmbJcpJOMLhRSEsAqTo1FTM1skZdAAhBW3HFX+KnadSl4CZRjGWHKZ2css3bUO jBxnnhqOGxXfDfDNODB7YOKUSbFIwza1b5DXU4/0Uch3Lej5HPBJxY1JQTd1zA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074625; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7UH1ADx+oQa8Ha42YGFE8ArA8CIpjZUSmClZmRcsp1s=; b=WrRW7DsBgKI+GwACfML25UaaF/wj1wMrn4TtUBR8T68yGei/KbPg6AHdkJAf/9ZNnQe/Jy Uk6vDXlfoNnR+jCg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 31/35] x86/cacheinfo: Use parsed CPUID(0x80000006) Date: Fri, 5 Sep 2025 14:15:11 +0200 Message-ID: <20250905121515.192792-32-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For the AMD cacheinfo logic, use parsed CPUID(0x80000006) access instead of a direct CPUID query. Beside the CPUID parser centralization benefits, this allows using the auto-generated data types, and their full C99 bitfields, instead of doing ugly bitwise operations on CPUID register output. For testing L3 cache availability, just check if CPUID(0x80000006) EDX l3_assoc output is not zero. Per AMD manuals, an L3 associativity of zero implies the absence of an L3 cache on the CPU. Since cpuid_amd_hygon_has_l3_cache() is now using the CPUID parser API, move its definition under the header file section: "Convenience leaf specific functions (using parsed CPUID data)" Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/api.h | 18 +++++++++--------- arch/x86/kernel/amd_nb.c | 3 ++- arch/x86/kernel/cpu/cacheinfo.c | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/= api.h index 2989a0c83ab0..c8efbd013504 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -213,15 +213,6 @@ static inline u32 cpuid_base_hypervisor(const char *si= g, u32 leaves) return 0; } =20 -/* - * CPUID(0x80000006) parsing: - */ - -static inline bool cpuid_amd_hygon_has_l3_cache(void) -{ - return cpuid_edx(0x80000006); -} - /* * 'struct cpuid_leaves' accessors (without sanity checks): * @@ -538,6 +529,15 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) _ptr < &((union leaf_0x2_regs *)(_regs))->desc[16] && (_desc =3D &cp= uid_0x2_table[*_ptr]);\ _ptr++) =20 +/* + * CPUID(0x80000006) + */ + +static inline bool cpuid_amd_hygon_has_l3_cache(struct cpuinfo_x86 *c) +{ + return cpuid_leaf(c, 0x80000006)->l3_assoc; +} + /* * CPUID parser exported APIs: */ diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index c1acead6227a..04a1965f10fe 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -16,6 +16,7 @@ =20 #include #include +#include =20 static u32 *flush_words; =20 @@ -93,7 +94,7 @@ static int amd_cache_northbridges(void) if (amd_gart_present()) amd_northbridges.flags |=3D AMD_NB_GART; =20 - if (!cpuid_amd_hygon_has_l3_cache()) + if (!cpuid_amd_hygon_has_l3_cache(&boot_cpu_data)) return 0; =20 /* diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index 7033baa94276..c5c6b0740e0d 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -235,7 +235,7 @@ static unsigned int get_cache_id(u32 apicid, const stru= ct _cpuid4_info *id4) =20 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id) { - if (!cpuid_amd_hygon_has_l3_cache()) + if (!cpuid_amd_hygon_has_l3_cache(c)) return; =20 if (c->x86 < 0x17) { @@ -262,7 +262,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u= 16 die_id) =20 void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c) { - if (!cpuid_amd_hygon_has_l3_cache()) + if (!cpuid_amd_hygon_has_l3_cache(c)) return; =20 /* @@ -278,7 +278,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c) =20 ci->num_leaves =3D boot_cpu_has(X86_FEATURE_TOPOEXT) ? cpuid_subleaf_count(c, 0x8000001d) : - cpuid_leaf(c, 0x80000006)->l3_assoc ? 4 : 3; + cpuid_amd_hygon_has_l3_cache(c) ? 4 : 3; } =20 void init_hygon_cacheinfo(struct cpuinfo_x86 *c) --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0973A35CEB8 for ; Fri, 5 Sep 2025 12:17:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074631; cv=none; b=Ij/IqCaX7umUD1C+iOEyhwudjeQf6WPjRF5XDxKKI606yyLfpWNEUnSSorzPPrAm922zWfgzESd7O00qIq9Ky2o9LGq7Gb+K+iUJwVy6p2n3V5AsdPft7JPX2C8drQEBsSwdfYJLSK/MhBtTRz9P1rBxx8i4CkPmU6qUvrz6tg8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074631; c=relaxed/simple; bh=g+3E6nDj5KS1CrR0tozgVXmymJ5NVXDPP0PSmHwU7uo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HutfdajJGaf994fUbyA+E8Aibid2GIfUksCRLSPahDtovjLl1SalHiF3n8/ubZQ+eSEJXdK39XtTz/ZoTof43IqAM5F9Mln4yUsbzk2zVqmI44J+R31+O0YOJgKmqGsSSRW1VksRFa4eiPbdBOWtOYLVx1BkHhf3TimTySD+rJg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=FKm6tFG5; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ltWo3yiN; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="FKm6tFG5"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ltWo3yiN" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074628; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iO/bLlHOMbYL2N9P2uJRmHVZGJlxMv6LsNM4sHKXhzg=; b=FKm6tFG5qxy2u5MQvZmwb05xQnkMS+J67+9q6yen1+RpY5u41NWhVP9thfYMaS9vQwXzf2 13+DTYY1IGZ5JXhiD4uooShYjnl3S7SDRiAew+zKHqBMZ5T9KQASPfBDlovpEMkhuxqp6j wAntSB3CRnc+rnP5ukn5R11gtN3yZFsbj+8JweNyf5/qOX9T42PV7wwD6MFUpVKcV/0tSi MIAQYZGaUfwlTQJ9gayIcOzxg+Eyvu3x9Z+1sikm+QXCCnXCfj2SINaXbC5uo2qsDec5MS /SbWanFqwAyA0ubsfBvsKeiqV0/yveRzbgEGCotnvG2CjBbC2vMaml1YxaAbaQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074628; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iO/bLlHOMbYL2N9P2uJRmHVZGJlxMv6LsNM4sHKXhzg=; b=ltWo3yiN6JMk7mBT3LL/qPoUmXzHt5NTCd2MsU90qvD4MObJGmfNwSXOfdDPv5hHIFbeVu 1x6i9cSdIlQ0feDw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 32/35] x86/cpu: Rescan CPUID table after PSN disable Date: Fri, 5 Sep 2025 14:15:12 +0200 Message-ID: <20250905121515.192792-33-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" On Pentium-III and Transmeta CPUs, disabling the CPUID(0x3) Processor Serial Number (PSN) can affect the maximum valid CPUID standard leaf. Rescan the CPU's CPUID table in that case, not to have stale cached data. Use parsed CPUID(0x0) access, instead of direct CPUID query, afterwards. Rename squash_the_stupid_serial_number() to disable_cpu_serial_number() and explain the rational for disabling the CPU's PSN. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/common.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b439f7cd0931..2867111ae40b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -328,15 +328,17 @@ bool cpuid_feature(void) return flag_is_changeable_p(X86_EFLAGS_ID); } =20 -static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +/* + * For privacy concerns, disable legacy Intel and Transmeta CPUID(0x3) + * feature, Processor Serial Number, by default. + */ +static void disable_cpu_serial_number(struct cpuinfo_x86 *c) { unsigned long lo, hi; =20 if (!cpu_has(c, X86_FEATURE_PN) || !disable_x86_serial_nr) return; =20 - /* Disable processor serial number: */ - rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi); lo |=3D 0x200000; wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); @@ -344,8 +346,12 @@ static void squash_the_stupid_serial_number(struct cpu= info_x86 *c) pr_notice("CPU serial number disabled.\n"); clear_cpu_cap(c, X86_FEATURE_PN); =20 - /* Disabling the serial number may affect the cpuid level */ - c->cpuid_level =3D cpuid_eax(0); + /* + * Disabling CPUID(0x3) might have affected the maximum standard + * CPUID level. Rescan the CPU's CPUID table afterwards. + */ + cpuid_parser_scan_cpu(c); + c->cpuid_level =3D cpuid_leaf(c, 0x0)->max_std_leaf; } =20 static int __init x86_serial_nr_setup(char *s) @@ -355,7 +361,7 @@ static int __init x86_serial_nr_setup(char *s) } __setup("serialnumber", x86_serial_nr_setup); #else -static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +static inline void disable_cpu_serial_number(struct cpuinfo_x86 *c) { } #endif @@ -1985,7 +1991,7 @@ static void identify_cpu(struct cpuinfo_x86 *c) bus_lock_init(); =20 /* Disable the PN if appropriate */ - squash_the_stupid_serial_number(c); + disable_cpu_serial_number(c); =20 /* Set up SMEP/SMAP/UMIP */ setup_smep(c); --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E934735CECD for ; Fri, 5 Sep 2025 12:17:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074634; cv=none; b=N7XnKSt6IBRMVeezIJamAeVOABzJdKfWer6rbez2jk1DKryPXgfGxbHC7bJTYRUQ4yrWa2rP0cJKjV+vtmenpy0bqSivpQp0cn8UcL0wKiPTbWLsVsIIJ4y4hlgCGJC3zCHUfGOnwVq0u0SILfkcOEga9q4fHQOjUe7uaYKMwNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074634; c=relaxed/simple; bh=5fdcoPUvdlD524keF9ij+kOFiFaEcRqH8n3QFhInQ70=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n1/Ura77ENItUlUzqNdCGRSrRnJzKGPBAHWgapemK5uaJvpLTJVPxaVIYx+9hSFM23mQ/BuYJnKygnzxUaLLIDm6dZDuKM8u4rLVvGMXpYTScIVjobAU4hjjc696QwsadRAhA4hcKV0FW4W9HUcjoyiIce2SM/FVd/hpxwrEXHE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ocVNo+6h; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=dpPzO952; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ocVNo+6h"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="dpPzO952" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074631; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KGhLRPv3T2ZfPDukdKO031Z+Va1drrHlEhRJWLjPwzM=; b=ocVNo+6hk/Pj5iuH9R6lSi4kzrzJxE5SZItx+LEw6h/QfvvYPyysNXJ3MzoYYHRWlajOuT jQRiBmIsi8VBLmRz3/GNB+chmdcr+d0g2LpuBCphH9l+10J5bhie8O+ZLnRNY6clH4v9om VZq5pFsziBEZFlJHgfJfNqlcF0F3pqWhamz2fdd8Zvf3aCzAWclOeTh08r3MHY72IV05Q4 8+9rfN/Aw4c87pe7Ojizp3P2RnYXhTocGm1U3xf7vdrvrY+yJGsHy9d62HO+Iwx+T4qbin e7rEhx+7DTyHZ1T6EO6V39Zi9lIxId3I27no3/g3x4wwCmFzQBZmbGI3OyTpoQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074631; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KGhLRPv3T2ZfPDukdKO031Z+Va1drrHlEhRJWLjPwzM=; b=dpPzO952CuExUeI21UhLjUOdiZxQFpvdzRVwC+HRK1Sw6LaCwQqKA+40Cf42LmK0Nmev5f Ldh4pK+JPT3b25CQ== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 33/35] x86/cpu: Rescan CPUID table after unlocking full CPUID range Date: Fri, 5 Sep 2025 14:15:13 +0200 Message-ID: <20250905121515.192792-34-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Intel CPUs have an MSR bit to limit CPUID enumeration to leaf two, which can be set by old BIOSen before booting Linux. Rescan the CPUID table after unlocking the CPU's full CPUID range. Use parsed CPUID(0x0) access, instead of a direct CPUID query, afterwards. References: 066941bd4eeb ("x86: unmask CPUID levels on Intel CPUs") References: 0c2f6d04619e ("x86/topology/intel: Unlock CPUID before evaluati= ng anything") Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/cpu/intel.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index dd284ece0de0..ffaba5a378f5 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -192,11 +192,14 @@ void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c) return; =20 /* - * The BIOS can have limited CPUID to leaf 2, which breaks feature - * enumeration. Unlock it and update the maximum leaf info. + * Intel CPUs have an MSR bit to limit CPUID enumeration to CPUID(0x2), + * which can be set by old BIOSes before booting Linux. If enabled, + * unlock the CPU's full CPUID range and rescan its CPUID table. */ - if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_= BIT) > 0) - c->cpuid_level =3D cpuid_eax(0); + if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_= BIT) > 0) { + cpuid_parser_scan_cpu(c); + c->cpuid_level =3D cpuid_leaf(c, 0x0)->max_std_leaf; + } } =20 static void early_init_intel(struct cpuinfo_x86 *c) --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0772035CEC7 for ; Fri, 5 Sep 2025 12:17:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074637; cv=none; b=uvhvb/TnR9o2NmYe3wA12PfGgWIUEIcoipEVbe4JcSXm2wX9tbC8dkFSoBJ6+MfCxGtjHIi5iZLL96/HxUlZGejU/RihEG7hXl9kJ3oKcjAfXVIWEzy2+VmiOu5hDBEcYZxsXmLFu0WxRXkxY0cBLO+Hoij3796VofH+pOyWcgo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074637; c=relaxed/simple; bh=B3ZOlRo5fFMzuD6Qx3/JQeHJfzMqR2rUoUm1Q5YXFnA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mJ/XWI35CEUq4G7pqjBgK3MvDOhQG9bqWcMeAKxqCbumxZN9KpreaRW8+j+LQLAHvPZ+NmSX8YmfJPnkRYCJ7f4an3+W/2pcLnyIMY2OFcHUwuxQVyjufzABGbk+a6EpPgRMOF/FiR4+XTVSwgbqIobL0IyvQeNZ9fXwRDJD78k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=c8SLcA2V; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=L1RCRtHz; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="c8SLcA2V"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="L1RCRtHz" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074634; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vFQOkiSbm6SnH6/fp3VlStcp8A1xYIN8Z2bDzSRzyo4=; b=c8SLcA2Vn9yihbdUw60SyqeJlr1JqXU93P990YRorlQUH6x/PEP5cl9f6QRAjJQ7LV3Nij O/sfVfFhb1A/IGex0xLpeIjzaruPghA7bBMRUQCM0ux/cAjfQYJ/PR5/gnnrPL4WgfQV0n 6GLP71TCMchXOkzEQciO0SIdqDnWQ/FxPKMUc4dB8epby1GqRl2p6xCZp8ZrEXozTTxEeW MWG6hHrxHJ6iLEv1VCo7LAu43VokWg2q0VMvBLzV8cndGB4VKo6a9HG1b6K9dMxZfa8Y9d ULxsf4do12dNVWBzqeG8oBIHg+AnVw0a8mXX7Pb7yIX5e4tuAhw8eXIKSApepw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074634; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vFQOkiSbm6SnH6/fp3VlStcp8A1xYIN8Z2bDzSRzyo4=; b=L1RCRtHzyW3JS7gfq28BtVFfhOQwiQw+G6r+jsC+R2nAyuVRJJVKlCss0chC811ZcsxqR0 i4k+ecvkbGjgMaCw== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 34/35] x86/cpuid: Parse CPUID(0x16) Date: Fri, 5 Sep 2025 14:15:14 +0200 Message-ID: <20250905121515.192792-35-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add CPUID(0x16) support to the CPUID parser. It enumerates processor frequency information. Query the leaf only for Intel machines, as this is where it is supported. This allows converting CPUID(0x16) call sites to the new CPUID parser APIs next. Signed-off-by: Ahmed S. Darwish --- arch/x86/include/asm/cpuid/types.h | 1 + arch/x86/kernel/cpu/cpuid_parser.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpui= d/types.h index 5a3a365044ce..00aca54ff293 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -238,6 +238,7 @@ struct cpuid_leaves { CPUID_LEAF ( 0x1, 0 ); CPUID_LEAF ( 0x2, 0 ); CPUID_LEAF_N ( 0x4, 8 ); + CPUID_LEAF ( 0x16, 0 ); CPUID_LEAF ( 0x80000000, 0 ); CPUID_LEAF ( 0x80000002, 0 ); CPUID_LEAF ( 0x80000003, 0 ); diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid= _parser.h index 44a056a5a321..e64ff57e08be 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -141,6 +141,7 @@ struct cpuid_parse_entry { /* Leaf Static subleaf Reader function */ \ CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \ CPUID_PARSE_ENTRY_N ( 0x4, deterministic_cache ), \ + CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ @@ -182,6 +183,7 @@ struct cpuid_vendor_entry { /* Leaf Vendor list */ \ CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR= _ZHAOXIN),\ CPUID_VENDOR_ENTRY(0x4, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR= _ZHAOXIN),\ + CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \ CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \ =20 #endif /* _ARCH_X86_CPUID_PARSER_H */ --=20 2.50.1 From nobody Sun Feb 8 21:56:19 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D90AE35E4DE for ; Fri, 5 Sep 2025 12:17:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074640; cv=none; b=VBouV4D0cwyyw5jIhij8bpKKZcSqpMlS/hCDseboJzaMwMRNs1jUmt8TOSsr2/pwiiSBhJvB3MG/Tqen378phOMLOnVQYfeWLeaWOPScChiAVAsU37eqEjZAtU2LtaIMjvPm7qOdFtdwQUlEF4HBYgxLrnB3cYzd2JfoUjJoliw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757074640; c=relaxed/simple; bh=SpgDp4laY3Pb0mMhApX77JkuC/iMBdEU5Th067+K1MU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=D30Fgg4l4VMKEmXDVanOTQfPHhuTuuCBHSGzVVnLYH/oW17iC9IbEt8SZO8pMtmrBIdIAM5uwDiV1BK93T6Brp1mqlTzmRDHPJhzuo5SdWj11KjclMRC1oHvRM0WUXpxvPWveYqf0XzPzu1eCwiec0NIFAFS+PvYgcXepCVOY9Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=gRbBN8D0; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=4Bky2rvM; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="gRbBN8D0"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="4Bky2rvM" From: "Ahmed S. Darwish" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1757074637; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NvgIjikOWlsZNf2y+C+TbxciQN2DYhSOt1mMUIat88w=; b=gRbBN8D0BT86EDvmDy2uOirdkjS90R0KWnFyQbHANe9oHQz/cIdAlAM/QRI5AxF9mkBNwB 4iQ+j+dLkOAlt7qXAJERUY1si8NFhMn2RWnVigEUeMUQZIA9gARdAVCOweTUVQJ/Vaoing tdhh84uCn+bMEoDmnbKwbsMyzVnfDLVQurPHgVtUBgnyRmiJeqd0PuSmCm4kYhJM02Uwhp CWD32TyU0+1rPuFTLluiHBNhGC3XznoFAfk8xpCeEbMWLlF/WRiQyT/TPybBzwALtjuxLu XebLf6UUzY5AabBW19Vo+R239ySs3b6oAQEtN2zkCgZqRZhnO967E44mAazMGw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1757074637; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NvgIjikOWlsZNf2y+C+TbxciQN2DYhSOt1mMUIat88w=; b=4Bky2rvMAtr0ehqV4LepPMwgz+hZLjP2pR8fC2+5RaxAKvk+POm3Jo3KI6TrxZqIjXBZtk Zvv3ek2z+tCOGdBg== To: Borislav Petkov , Ingo Molnar , Dave Hansen Cc: Thomas Gleixner , Andrew Cooper , Sean Christopherson , David Woodhouse , "H. Peter Anvin" , Peter Zijlstra , Sohil Mehta , John Ogness , x86@kernel.org, x86-cpuid@lists.linux.dev, LKML , "Ahmed S. Darwish" Subject: [PATCH v5 35/35] x86/tsc: Use parsed CPUID(0x16) Date: Fri, 5 Sep 2025 14:15:15 +0200 Message-ID: <20250905121515.192792-36-darwi@linutronix.de> In-Reply-To: <20250905121515.192792-1-darwi@linutronix.de> References: <20250905121515.192792-1-darwi@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the x86 time stamp counter counter code, use parsed CPUID(0x16) access instead of a direct CPUID query. Beside the CPUID parser centralization benefits, this allows using the auto-generated data types, and their full C99 bitfields, instead of doing ugly bitwise operations on CPUID register output. Remove the "max standard level >=3D CPUID_LEVEL_FREQ" check since the CPUID parser API's NULL check is equivalent. Remove the Intel vendor check since the CPUID parser does a similar check before caching CPUID(0x16) output. Thus the CPUID parser API's NULL check is also equivalent. Signed-off-by: Ahmed S. Darwish --- arch/x86/kernel/tsc.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 87e749106dda..34da49d45d85 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -662,6 +662,7 @@ static unsigned long quick_pit_calibrate(void) */ unsigned long native_calibrate_tsc(void) { + const struct leaf_0x16_0 *l16 =3D cpuid_leaf(&boot_cpu_data, 0x16); unsigned int eax_denominator, ebx_numerator, ecx_hz, edx; unsigned int crystal_khz; =20 @@ -703,13 +704,8 @@ unsigned long native_calibrate_tsc(void) * clock, but we can easily calculate it to a high degree of accuracy * by considering the crystal ratio and the CPU speed. */ - if (crystal_khz =3D=3D 0 && boot_cpu_data.cpuid_level >=3D CPUID_LEAF_FRE= Q) { - unsigned int eax_base_mhz, ebx, ecx, edx; - - cpuid(CPUID_LEAF_FREQ, &eax_base_mhz, &ebx, &ecx, &edx); - crystal_khz =3D eax_base_mhz * 1000 * - eax_denominator / ebx_numerator; - } + if (crystal_khz =3D=3D 0 && l16) + crystal_khz =3D l16->cpu_base_mhz * 1000 * eax_denominator / ebx_numerat= or; =20 if (crystal_khz =3D=3D 0) return 0; @@ -736,19 +732,9 @@ unsigned long native_calibrate_tsc(void) =20 static unsigned long cpu_khz_from_cpuid(void) { - unsigned int eax_base_mhz, ebx_max_mhz, ecx_bus_mhz, edx; - - if (boot_cpu_data.x86_vendor !=3D X86_VENDOR_INTEL) - return 0; - - if (boot_cpu_data.cpuid_level < CPUID_LEAF_FREQ) - return 0; - - eax_base_mhz =3D ebx_max_mhz =3D ecx_bus_mhz =3D edx =3D 0; - - cpuid(CPUID_LEAF_FREQ, &eax_base_mhz, &ebx_max_mhz, &ecx_bus_mhz, &edx); + const struct leaf_0x16_0 *l16 =3D cpuid_leaf(&boot_cpu_data, 0x16); =20 - return eax_base_mhz * 1000; + return l16 ? (l16->cpu_base_mhz * 1000) : 0; } =20 /* --=20 2.50.1