From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linutronix.de (193.142.43.55:993) by crypto-ml.lab.linutronix.de with IMAP4-SSL for ; 25 Feb 2020 21:46:40 -0000 Received: from mga14.intel.com ([192.55.52.115]) by Galois.linutronix.de with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1j6i2J-0003LZ-AE for speck@linutronix.de; Tue, 25 Feb 2020 22:46:39 +0100 Received: from mtg-dev (mtg-dev.jf.intel.com [10.54.74.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.ostc.intel.com (Postfix) with ESMTPS id 858496367 for ; Tue, 25 Feb 2020 21:46:35 +0000 (UTC) Received: from mgross by mtg-dev with local (Exim 4.90_1) (envelope-from ) id 1j6i2G-000TC0-5D for speck@linutronix.de; Tue, 25 Feb 2020 13:46:36 -0800 Message-Id: =?utf-8?q?=3C0e637bd8b28bb3f53c278b0dee8219c3bdda40db=2E158258?= =?utf-8?q?0710=2Egit=2Emgross=40linux=2Eintel=2Ecom=3E?= In-Reply-To: References: From: mark gross Date: Thu, 6 Feb 2020 14:11:02 -0800 Subject: [MODERATED] [PATCH v2 1/2] v2: more sampling fun 1 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit MIME-Version: 1.0 To: speck@linutronix.de List-ID: From: mark gross Subject: [PATCH v2 1/2] Add capability to specify a range of steppings in the vulnerability white list structure. From: mark gross Subject: [PATCH v2 1/2] Add capability to specify a range of steppings in the Intel has produced processors with the same CPUID family+model. Code may need to check the stepping when programming model specific behavior. Add an API to allow easy specification of stepping or range of steppings with a 16 bit bitmask. Update cpu_vuln_whitelist using this new API. I implemented this in the way I did to avoid modifying x86_cpu_id as that structure is an exported ABI and any change would impact user mode code using the structure. Signed-off-by: mark gross Reviewed-by: tony luck --- arch/x86/include/asm/cpu_device_id.h | 12 ++++++++++++ arch/x86/kernel/cpu/common.c | 28 ++++++++++++++-------------- arch/x86/kernel/cpu/match.c | 26 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h index 31c379c1da41..e9de5f6d784a 100644 --- a/arch/x86/include/asm/cpu_device_id.h +++ b/arch/x86/include/asm/cpu_device_id.h @@ -35,7 +35,19 @@ struct x86_cpu_desc { .x86_microcode_rev = (revision), \ } +/* + * Match a range of steppings + */ + +struct x86_cpu_id_ext { + struct x86_cpu_id id; + __u16 steppings; /* bit map of steppings to match against */ +}; + +#define X86_STEPPING_ANY GENMASK(15,0) + extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match); +const struct x86_cpu_id_ext *x86_match_cpu_ext(const struct x86_cpu_id_ext *match); extern bool x86_cpu_has_min_microcode_rev(const struct x86_cpu_desc *table); #endif /* _ASM_X86_CPU_DEVICE_ID */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 52c9bfbbdb2a..c0519be5f563 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1008,23 +1008,23 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) #define NO_ITLB_MULTIHIT BIT(7) #define NO_SPECTRE_V2 BIT(8) -#define VULNWL(_vendor, _family, _model, _whitelist) \ - { X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist } +#define VULNWL(_vendor, _family, _model, __stepping, _whitelist) \ + {{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }, __stepping} #define VULNWL_INTEL(model, whitelist) \ - VULNWL(INTEL, 6, INTEL_FAM6_##model, whitelist) + VULNWL(INTEL, 6, INTEL_FAM6_##model, X86_STEPPING_ANY, whitelist) #define VULNWL_AMD(family, whitelist) \ - VULNWL(AMD, family, X86_MODEL_ANY, whitelist) + VULNWL(AMD, family, X86_MODEL_ANY, X86_STEPPING_ANY, whitelist) #define VULNWL_HYGON(family, whitelist) \ - VULNWL(HYGON, family, X86_MODEL_ANY, whitelist) + VULNWL(HYGON, family, X86_MODEL_ANY, X86_STEPPING_ANY, whitelist) -static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { - VULNWL(ANY, 4, X86_MODEL_ANY, NO_SPECULATION), - VULNWL(CENTAUR, 5, X86_MODEL_ANY, NO_SPECULATION), - VULNWL(INTEL, 5, X86_MODEL_ANY, NO_SPECULATION), - VULNWL(NSC, 5, X86_MODEL_ANY, NO_SPECULATION), +static const struct x86_cpu_id_ext cpu_vuln_whitelist[] __initconst = { + VULNWL(ANY, 4, X86_MODEL_ANY, X86_STEPPING_ANY, NO_SPECULATION), + VULNWL(CENTAUR, 5, X86_MODEL_ANY, X86_STEPPING_ANY, NO_SPECULATION), + VULNWL(INTEL, 5, X86_MODEL_ANY, X86_STEPPING_ANY, NO_SPECULATION), + VULNWL(NSC, 5, X86_MODEL_ANY, X86_STEPPING_ANY, NO_SPECULATION), /* Intel Family 6 */ VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION | NO_ITLB_MULTIHIT), @@ -1070,16 +1070,16 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT), /* Zhaoxin Family 7 */ - VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS), - VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS), + VULNWL(CENTAUR, 7, X86_MODEL_ANY, X86_STEPPING_ANY, NO_SPECTRE_V2 | NO_SWAPGS), + VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, X86_STEPPING_ANY, NO_SPECTRE_V2 | NO_SWAPGS), {} }; static bool __init cpu_matches(unsigned long which) { - const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist); + const struct x86_cpu_id_ext *m = x86_match_cpu_ext(cpu_vuln_whitelist); - return m && !!(m->driver_data & which); + return m && !!(m->id.driver_data & which); } u64 x86_read_arch_cap_msr(void) diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index 6dd78d8235e4..118c503b1c36 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c @@ -49,6 +49,32 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) } EXPORT_SYMBOL(x86_match_cpu); +/* + * Extend x86_match_cpu to support matching a range of steppings. + */ +const struct x86_cpu_id_ext *x86_match_cpu_ext(const struct x86_cpu_id_ext *match) +{ + const struct x86_cpu_id_ext *m; + struct cpuinfo_x86 *c = &boot_cpu_data; + + for (m = match; m->id.vendor | m->id.family | m->id.model | m->id.feature; m++) { + if (m->id.vendor != X86_VENDOR_ANY && c->x86_vendor != m->id.vendor) + continue; + if (m->id.family != X86_FAMILY_ANY && c->x86 != m->id.family) + continue; + if (m->id.model != X86_MODEL_ANY && c->x86_model != m->id.model) + continue; + if (m->steppings != X86_STEPPING_ANY && + !(BIT(c->x86_stepping) & m->steppings)) + continue; + if (m->id.feature != X86_FEATURE_ANY && !cpu_has(c, m->id.feature)) + continue; + return m; + } + return NULL; +} +EXPORT_SYMBOL(x86_match_cpu_ext); + static const struct x86_cpu_desc * x86_match_cpu_with_stepping(const struct x86_cpu_desc *match) { -- 2.17.1