From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90977C43219 for ; Tue, 1 Mar 2022 19:56:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237381AbiCAT4m (ORCPT ); Tue, 1 Mar 2022 14:56:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231738AbiCAT4f (ORCPT ); Tue, 1 Mar 2022 14:56:35 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19AC16CA4F; Tue, 1 Mar 2022 11:55:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164554; x=1677700554; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=dD5vgT47K/7ze5uYlH7rkWVlSTm7dGQOtKM9I4Tl4yk=; b=XqtrboGDAuCJsIrMAO1os/Hn/6qPO0aHZzm6DQotgXZNmpStDZLXLtKH yZzbKSGDl5JV+tcLyInYpaeMS+672IAUxEakoqDtuaiagRJjNYwaqjkCJ +CraijzEuLFlkWSRQo+wZ+hs/NWFdyUgJSYDsrwGOtBfGvqo6Gqtnp2Y7 P4FnxkCA1kxz1uaNQ18RAbZiCwMqCFbRI6SxVf7rnK5S1iVf7DX/S6Zod LgrR7O6i3bsjx7Xx5PgZO1gjCDI8/ZE3+SwF+xziLeayNW7M6pWCFBP5f v52UN/GY/4T6ccpNA/JyXpcVuxhCRgxQWGdRxuKxk5i48z5CzBkGQPQD0 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194889" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194889" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133155" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS Date: Tue, 1 Mar 2022 11:54:48 -0800 Message-Id: <20220301195457.21152-2-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" IFS uses a image provided by Intel that can be regarded as firmware. IFS image carries the Processor Signature such as family/model/stepping similar to what we find in the microcode header. Expose collect_cpu_info_early() and cpu_signatures_match() for IFS image sanity check. No functional change. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- arch/x86/include/asm/microcode_intel.h | 6 ++++++ arch/x86/kernel/cpu/microcode/intel.c | 8 +++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/= microcode_intel.h index d85a07d7154f..ec19eeac535b 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -74,12 +74,18 @@ extern void load_ucode_intel_ap(void); extern void show_ucode_info_early(void); extern int __init save_microcode_in_initrd_intel(void); void reload_ucode_intel(void); +int collect_cpu_info_early(struct ucode_cpu_info *uci); +bool cpu_signatures_match(unsigned int s1, unsigned int p1, + unsigned int s2, unsigned int p2); #else static inline __init void load_ucode_intel_bsp(void) {} static inline void load_ucode_intel_ap(void) {} static inline void show_ucode_info_early(void) {} static inline int __init save_microcode_in_initrd_intel(void) { return -EI= NVAL; } static inline void reload_ucode_intel(void) {} +static inline void collect_cpu_info_early(struct ucode_cpu_info *uci) {} +static inline void cpu_signatures_match(unsigned int s1, unsigned int p1, + unsigned int s2, unsigned int p2) {} #endif =20 #endif /* _ASM_X86_MICROCODE_INTEL_H */ diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index d28a9f8f3fec..360ec06eec1e 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -45,8 +45,8 @@ static struct microcode_intel *intel_ucode_patch; /* last level cache size per core */ static int llc_size_per_core; =20 -static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1, - unsigned int s2, unsigned int p2) +bool cpu_signatures_match(unsigned int s1, unsigned int p1, + unsigned int s2, unsigned int p2) { if (s1 !=3D s2) return false; @@ -58,6 +58,7 @@ static inline bool cpu_signatures_match(unsigned int s1, = unsigned int p1, /* ... or they intersect. */ return p1 & p2; } +EXPORT_SYMBOL_GPL(cpu_signatures_match); =20 /* * Returns 1 if update has been found, 0 otherwise. @@ -342,7 +343,7 @@ scan_microcode(void *data, size_t size, struct ucode_cp= u_info *uci, bool save) return patch; } =20 -static int collect_cpu_info_early(struct ucode_cpu_info *uci) +int collect_cpu_info_early(struct ucode_cpu_info *uci) { unsigned int val[2]; unsigned int family, model; @@ -372,6 +373,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info= *uci) =20 return 0; } +EXPORT_SYMBOL_GPL(collect_cpu_info_early); =20 static void show_saved_mc(void) { --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2DDEC433F5 for ; Tue, 1 Mar 2022 19:56:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237469AbiCAT4q (ORCPT ); Tue, 1 Mar 2022 14:56:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56148 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233672AbiCAT4f (ORCPT ); Tue, 1 Mar 2022 14:56:35 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 760B76CA59; Tue, 1 Mar 2022 11:55:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164554; x=1677700554; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=1grK952Uv/mTeG41VPRB/n4tgViBRWh0iu2ugzI+fQ4=; b=SB2H0qP1XFWL2Jfjs+LumAP3fa1rqTIguPeyx9PQtdf9RPKH4PMy1elI jbLnyvTcS+qROcRzF1WVAKxHWlDvNFN4hrj/9GjNbKTaOo42xgQB+R5Mf Jg0glAF1blQ6H+jY3uBe+8KcYvwdEo7EM7YwxaNzFae6eNqDG4V3GgZ4/ x74MxCmWgF9JSv6c6jqYleCU1OSSgGa/SWGAoKHrIJUWtBFRhN3zms7Gr SvVx65L6/NViuCa0xOb/4pTOm+yoVw0p9R+ahrJzlcQMIIELx+aM+RXUE S89MI+ocvoJdifJ5HJuvnDlg9oi/xSBhZKWKbo+5bDx72U/xbBsDbsoz4 g==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194891" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194891" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133158" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 02/10] Documentation: In-Field Scan Date: Tue, 1 Mar 2022 11:54:49 -0800 Message-Id: <20220301195457.21152-3-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Tony Luck Add documentation for In-Field Scan (IFS). This documentation describes the basics of IFS, the loading IFS image, chunk authentication, running scan and how to check result via sysfs as well as tunable parameters. The CORE_CAPABILITIES MSR enumerates whether IFS is supported. Signed-off-by: Tony Luck Reviewed-by: Ashok Raj --- Documentation/x86/ifs.rst | 108 ++++++++++++++++++++++++++++++++++++ Documentation/x86/index.rst | 1 + 2 files changed, 109 insertions(+) create mode 100644 Documentation/x86/ifs.rst diff --git a/Documentation/x86/ifs.rst b/Documentation/x86/ifs.rst new file mode 100644 index 000000000000..fa77639f52dd --- /dev/null +++ b/Documentation/x86/ifs.rst @@ -0,0 +1,108 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +In-Field Scan +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Introduction +------------ + +In Field Scan (IFS) is a hardware feature to run circuit level tests on +a CPU core to detect problems that are not caught by parity or ECC checks. + +IFS Image +--------- + +Intel will provide a firmware file containing the scan tests via +github [#f1]_. Similar to microcode there is a separate file for each +family-model-stepping. The tests in the file are divided into some number +of "chunks" that can be run individually. + +IFS Image Loading +----------------- + +The driver loads the tests into memory reserved BIOS local to each CPU +socket in a two step process using writes to MSRs to first load the +SHA hashes for the test. Then the tests themselves. Status MSRs provide +feedback on the success/failure of these steps. When a new test file +is installed it can be loaded with:: + + # echo 1 > /sys/devices/system/cpu/ifs/reload + +Triggering tests +---------------- + +Tests are run by synchronizing execution of all threads on a core and then +writing to the ACTIVATE_SCAN MSR on all threads. Instruction execution +continues when: + +1) All tests have completed. +2) Execution was interrupted. +3) A test detected a problem. + +In all cases reading the SCAN_STATUS MSR provides details on what +happened. Interrupted tests may be restarted. + +The IFS driver provides interfaces from /sys to control execution: + +Run tests on all cores:: + + # echo 1 > /sys/devices/system/cpu/ifs/run_test + +Scans run on each core sequentially by logical CPU number (when HT is +enabled this only runs the tests once for each core). + +Test a single core:: + + # echo 1 > /sys/devices/system/cpu/cpu#/ifs/run_test + +Results of the tests are also provided in /sys:: + + $ cat /sys/devices/system/cpu/ifs/status + pass + +global status. Shows the most serious status across +all cores (fail > untested > pass) + +There are files showing which CPUs are in each of the +pass/untested/fail states:: + + $ cat /sys/devices/system/cpu/ifs/cpu_fail_list + $ cat /sys/devices/system/cpu/ifs/cpu_untested_list + $ cat /sys/devices/system/cpu/ifs/cpu_pass_list + 0-127 + +Also files in the per-CPU directories showing the status +of the most recent test on that core:: + + $ cat /sys/devices/system/cpu/cpu#/ifs/status + pass + $ cat /sys/devices/system/cpu/cpu#/ifs/details + 8081 + +The details file reports the hex value of the SCAN_STATUS MSR. Note that +the error_code field may contain driver defined software code not defined +in the Intel SDM. + +Current driver limitations +-------------------------- + +1) The ACTIVATE_SCAN MSR allows for running any consecutive subrange or +available tests. But the driver always tries to run all tests and only +uses the subrange feature to restart an interrupted test. + +2) Hardware allows for some number of cores to be tested in parallel. +The driver does not make use of this, it only tests one core at a time. + +Tunable Parameters +------------------ + +This module accepts two tunable parameters. These could be provided at +load time or can be modified at runtime through module parameter. +(/sys/module/ifs/parameters/). The parameters are as +described below. + +1. noint: When set, system interrupts are not allowed to interrupt an ifs. +2. retry: Maximum retry counter when the test is not executed due to an ev= ent such as interrupt. + +.. [#f1] https://github.com/intel diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst index f498f1d36cd3..be58b7638d9e 100644 --- a/Documentation/x86/index.rst +++ b/Documentation/x86/index.rst @@ -33,6 +33,7 @@ x86-specific Documentation usb-legacy-support i386/index x86_64/index + ifs sva sgx features --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C559AC433F5 for ; Tue, 1 Mar 2022 19:56:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237475AbiCAT4u (ORCPT ); Tue, 1 Mar 2022 14:56:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56164 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234210AbiCAT4g (ORCPT ); Tue, 1 Mar 2022 14:56:36 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A01DD6CA6F; Tue, 1 Mar 2022 11:55:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164554; x=1677700554; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=IX9RbOmrBoZoGdoaea4eD/8Uj1Ve7FBJwYQ9q6QGXdw=; b=XiOTmf2upM7Pw3Yu/YhYxVt1aaL3Y8nT/jDE9Vl314hloHI+89oFoNkd BvFi0WkGb/4XmguXmOo2zO2r0LOuVN2bqHPRSOVQRTaffO4Krdar+Tzvx 4XU0sFPoK8t+DstfSKixi05tei7LXEhBI+ft1L27/0ep4j8TPQEgmCaQ7 F5O0VlPoLadKl5KpGK9uDI8n7XTJS6kbsO3vaaNL4WrM9tbBBayN5LQlG T7fuK1D0aHPqcjObJfsSW7IpU6gZoEfdMa2Y6oDXszcN6pSRhyhLofOV4 siQybq429pVRpLoDjs7eJZLHzPbqelXoESGklOofh7ZKdebinNNUsldie Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194892" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194892" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133161" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 03/10] platform/x86/intel/ifs: Add driver for In-Field Scan Date: Tue, 1 Mar 2022 11:54:50 -0800 Message-Id: <20220301195457.21152-4-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In-Field Scan (IFS) provides hardware hooks to perform core tests and report failures for portions of silicon that lack error detection capabilities, which will be available in some server SKUs starting with Sapphire Rapids. It offers infrastructure to specific users such as cloud providers or OEMs to schedule tests and find in-field failures due to aging in silicon that might not necessarily be reported with normal machine checks. Add basic parts of the IFS module (initialization and check IFS capability support in a processor). MSR IA32_CORE_CAPABILITY is a feature-enumerating MSR, bit 2 of which reports MSR_INTEGRITY_CAPABILITIES. Processor that supports IFS should reports the MSR_INTEGRITY_CAPABILITIES enabled. Please check the latest Intel 64 and IA-32 Architectures Software Developer's Manual for more detailed information on the MSR and the MSR_INTEGRITY_CAPABILITIES. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- MAINTAINERS | 7 ++++ drivers/platform/x86/intel/Kconfig | 1 + drivers/platform/x86/intel/Makefile | 1 + drivers/platform/x86/intel/ifs/Kconfig | 9 +++++ drivers/platform/x86/intel/ifs/Makefile | 7 ++++ drivers/platform/x86/intel/ifs/core.c | 49 +++++++++++++++++++++++++ drivers/platform/x86/intel/ifs/ifs.h | 14 +++++++ 7 files changed, 88 insertions(+) create mode 100644 drivers/platform/x86/intel/ifs/Kconfig create mode 100644 drivers/platform/x86/intel/ifs/Makefile create mode 100644 drivers/platform/x86/intel/ifs/core.c create mode 100644 drivers/platform/x86/intel/ifs/ifs.h diff --git a/MAINTAINERS b/MAINTAINERS index 777cd6fa2b3d..4c9912c0d725 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9685,6 +9685,13 @@ B: https://bugzilla.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git F: drivers/idle/intel_idle.c =20 +INTEL IN FIELD SCAN (IFS) DRIVER +M: Jithu Joseph +R: Ashok Raj +R: Tony Luck +S: Maintained +F: drivers/platform/x86/intel/ifs + INTEL INTEGRATED SENSOR HUB DRIVER M: Srinivas Pandruvada M: Jiri Kosina diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/inte= l/Kconfig index 8e65086bb6c8..7339e7daf0a1 100644 --- a/drivers/platform/x86/intel/Kconfig +++ b/drivers/platform/x86/intel/Kconfig @@ -4,6 +4,7 @@ # =20 source "drivers/platform/x86/intel/atomisp2/Kconfig" +source "drivers/platform/x86/intel/ifs/Kconfig" source "drivers/platform/x86/intel/int1092/Kconfig" source "drivers/platform/x86/intel/int33fe/Kconfig" source "drivers/platform/x86/intel/int3472/Kconfig" diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/int= el/Makefile index 35f2066578b2..bd7f2ef5e767 100644 --- a/drivers/platform/x86/intel/Makefile +++ b/drivers/platform/x86/intel/Makefile @@ -5,6 +5,7 @@ # =20 obj-$(CONFIG_INTEL_ATOMISP2_PDX86) +=3D atomisp2/ +obj-$(CONFIG_INTEL_IFS) +=3D ifs/ obj-$(CONFIG_INTEL_SAR_INT1092) +=3D int1092/ obj-$(CONFIG_INTEL_CHT_INT33FE) +=3D int33fe/ obj-$(CONFIG_INTEL_SKL_INT3472) +=3D int3472/ diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/= intel/ifs/Kconfig new file mode 100644 index 000000000000..88e3d4fa1759 --- /dev/null +++ b/drivers/platform/x86/intel/ifs/Kconfig @@ -0,0 +1,9 @@ +config INTEL_IFS + tristate "Intel In Field Scan" + depends on X86 && 64BIT && SMP + help + Enable support for In Field Scan in Intel CPU to perform core + logic test in the field. To compile this driver as a module, choose + M here. The module will be called intel_ifs. + + If unsure, say N. diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86= /intel/ifs/Makefile new file mode 100644 index 000000000000..05b4925402b4 --- /dev/null +++ b/drivers/platform/x86/intel/ifs/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the In-Field Scan driver +# + +obj-$(CONFIG_INTEL_IFS) +=3D intel_ifs.o + +intel_ifs-objs :=3D core.o diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/i= ntel/ifs/core.c new file mode 100644 index 000000000000..fb3c864d3085 --- /dev/null +++ b/drivers/platform/x86/intel/ifs/core.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2021 Intel Corporation. + * + * Author: Jithu Joseph + */ + +#include +#include + +#include "ifs.h" + +#define X86_MATCH(model) \ + X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, \ + INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL) + +static const struct x86_cpu_id ifs_cpu_ids[] __initconst =3D { + X86_MATCH(SAPPHIRERAPIDS_X), + {} +}; + +MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids); + +static int __init ifs_init(void) +{ + const struct x86_cpu_id *m; + u64 ia32_core_caps; + + /* ifs capability check */ + m =3D x86_match_cpu(ifs_cpu_ids); + if (!m) + return -ENODEV; + if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &ia32_core_caps)) + return -ENODEV; + if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_INTEGRITY)) + return -ENODEV; + + return 0; +} + +static void __exit ifs_exit(void) +{ + pr_info("unloaded 'In-Field Scan' module\n"); +} + +MODULE_LICENSE("GPL"); +MODULE_INFO(name, "ifs"); +MODULE_DESCRIPTION("ifs"); +module_init(ifs_init); +module_exit(ifs_exit); diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/in= tel/ifs/ifs.h new file mode 100644 index 000000000000..f3f924fced06 --- /dev/null +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2021 Intel Corporation. + * + * Author: Jithu Joseph + */ + +#ifndef _IFS_H_ +#define _IFS_H_ + +/* These bits are in the IA32_CORE_CAPABILITIES MSR */ +#define MSR_IA32_CORE_CAPS_INTEGRITY_BIT 2 +#define MSR_IA32_CORE_CAPS_INTEGRITY BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT) + +#endif --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 800DCC433EF for ; Tue, 1 Mar 2022 19:56:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237500AbiCAT4y (ORCPT ); Tue, 1 Mar 2022 14:56:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56174 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235686AbiCAT4g (ORCPT ); Tue, 1 Mar 2022 14:56:36 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 51A936D392; Tue, 1 Mar 2022 11:55:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164555; x=1677700555; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=NL3tmVP6e7ebwMaEfzotOOpoe8/22/j35aqUXMTqY4w=; b=WdNJLTpNvXPjgKetOZoitJYeFuw2FKy6WQk6tDlzZ7fLF3yxDufBBHjr U8zTTagGls0sZ4qHLZwvDGLqVgtChwo3Nth88FBxnqMYjzy3tjhHts0RL F80O6fbGWtVsGyXv8Zs0FFQWhSxms/NnN5DBxHjkioIUbYc3UKxPx3prR iReCXGEVk1emO7yLeRAvNMGOYvO++bTCLtGlLn2zVDFWymrUTMbb5SHbX ENznMKc88E5hdlUybOuYWt5yZIQjaYaeynWkopRJ5n0giBbgLbq+UETK+ +FILxr60deDnOkuMPdO4FTfqKe1WsdtoA4zK9EjAs1GJsbr5VZ7KsBhBn A==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194893" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194893" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133164" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 04/10] platform/x86/intel/ifs: Load IFS Image Date: Tue, 1 Mar 2022 11:54:51 -0800 Message-Id: <20220301195457.21152-5-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" IFS uses a test image that can be regarded as firmware. The image is specific to a processor family, model and stepping. IFS requires that a test image be loaded before any ifs test is initiated. Load the image that matches processor signature. The IFS image is signed by Intel. The IFS image file follows a similar naming convention as used for Intel CPU microcode files. The file must be located in the firmware directory where the microcode files are placed and named as {family/model /stepping}.scan as below: /lib/firmware/intel/ifs/{ff-mm-ss}.scan Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- drivers/platform/x86/intel/ifs/Makefile | 2 +- drivers/platform/x86/intel/ifs/core.c | 8 +++ drivers/platform/x86/intel/ifs/ifs.h | 13 ++++ drivers/platform/x86/intel/ifs/load.c | 95 +++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 drivers/platform/x86/intel/ifs/load.c diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86= /intel/ifs/Makefile index 05b4925402b4..105b377de410 100644 --- a/drivers/platform/x86/intel/ifs/Makefile +++ b/drivers/platform/x86/intel/ifs/Makefile @@ -4,4 +4,4 @@ =20 obj-$(CONFIG_INTEL_IFS) +=3D intel_ifs.o =20 -intel_ifs-objs :=3D core.o +intel_ifs-objs :=3D core.o load.o diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/i= ntel/ifs/core.c index fb3c864d3085..765d9a2c4683 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -8,6 +8,7 @@ #include =20 #include "ifs.h" +struct ifs_params ifs_params; =20 #define X86_MATCH(model) \ X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, \ @@ -24,6 +25,7 @@ static int __init ifs_init(void) { const struct x86_cpu_id *m; u64 ia32_core_caps; + int ret; =20 /* ifs capability check */ m =3D x86_match_cpu(ifs_cpu_ids); @@ -34,6 +36,12 @@ static int __init ifs_init(void) if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_INTEGRITY)) return -ENODEV; =20 + ret =3D load_ifs_binary(); + if (ret) { + pr_err("loading ifs binaries failed\n"); + return ret; + } + return 0; } =20 diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/in= tel/ifs/ifs.h index f3f924fced06..f2daf2cfd3e6 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -7,8 +7,21 @@ #ifndef _IFS_H_ #define _IFS_H_ =20 +#undef pr_fmt +#define pr_fmt(fmt) "ifs: " fmt + /* These bits are in the IA32_CORE_CAPABILITIES MSR */ #define MSR_IA32_CORE_CAPS_INTEGRITY_BIT 2 #define MSR_IA32_CORE_CAPS_INTEGRITY BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT) =20 +/** + * struct ifs_params - global ifs parameter for all cpus. + * @loaded_version: stores the currently loaded ifs image version. + */ +struct ifs_params { + int loaded_version; +}; + +int load_ifs_binary(void); +extern struct ifs_params ifs_params; #endif diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/i= ntel/ifs/load.c new file mode 100644 index 000000000000..1a5e906c51af --- /dev/null +++ b/drivers/platform/x86/intel/ifs/load.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2021 Intel Corporation. + * + * Author: Jithu Joseph + */ + +#include +#include + +#include "ifs.h" +static const char *ifs_path =3D "intel/ifs/"; + +struct ifs_header { + u32 header_ver; + u32 blob_revision; + u32 date; + u32 processor_sig; + u32 check_sum; + u32 loader_rev; + u32 processor_flags; + u32 metadata_size; + u32 total_size; + u32 fusa_info; + u64 reserved; +}; + +#define IFS_HEADER_SIZE (sizeof(struct ifs_header)) +static struct ifs_header *ifs_header_ptr; /* pointer to the ifs image head= er */ +static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */ + +static const struct firmware *load_binary(const char *path) +{ + struct platform_device *ifs_pdev; + const struct firmware *fw; + int err; + + ifs_pdev =3D platform_device_register_simple("ifs", -1, NULL, 0); + if (IS_ERR(ifs_pdev)) { + pr_err("platform device register failed\n"); + return NULL; + } + err =3D request_firmware_direct(&fw, path, &ifs_pdev->dev); + if (err) { + pr_err("ifs file %s load failed\n", path); + goto out; + } + +out: + platform_device_unregister(ifs_pdev); + + return fw; +} + +/* + * Compare the image version whenever loading a new image. + * Load the new image only if it is later or equal than the current versio= n. + */ +static bool is_newer_binary(int current_loaded_version, struct ifs_header = *new_image_ptr) +{ + return current_loaded_version <=3D new_image_ptr->blob_revision; +} + +/* + * Load ifs image. Before loading ifs module, the ifs image must be located + * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testna= me}. + */ +int load_ifs_binary(void) +{ + const struct firmware *scan_fw; + char scan_path[256]; + int ret; + + snprintf(scan_path, sizeof(scan_path), "%s%02x-%02x-%02x.scan", ifs_path, + boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping); + + scan_fw =3D load_binary(scan_path); + if (!scan_fw) + return -ENOENT; + + /* only reload new scan image for later version than currently loaded */ + if (!is_newer_binary(ifs_params.loaded_version, (struct ifs_header *)scan= _fw->data)) { + pr_warn("Refusing to load older binary"); + ret =3D -EINVAL; + goto out; + } + + ifs_header_ptr =3D (struct ifs_header *)scan_fw->data; + ifs_hash_ptr =3D (u64)(ifs_header_ptr + 1); + + ret =3D 0; +out: + release_firmware(scan_fw); + + return ret; +} --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC7C2C433F5 for ; Tue, 1 Mar 2022 19:56:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237427AbiCAT45 (ORCPT ); Tue, 1 Mar 2022 14:56:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235995AbiCAT4h (ORCPT ); Tue, 1 Mar 2022 14:56:37 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B25266CA4F; Tue, 1 Mar 2022 11:55:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164555; x=1677700555; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=uC5rspVyubKHGiV6BlR4gnoUFKw65v33QJn3OEQqbkU=; b=IOoZOGRRikwdpzSswMurQR0EKwqWDL8VJRRQVBZmjCtGZvHeIS6JJ9li 3J8ccSQa+qQHiQ+z19v1Yli5khrRcKZFRcSUa3H8jOSxVVN55u4IaIiZs inYT3mO2y0f3wMiLcvUBstwn+I3gv3tiZQeQd1spvKJtvw8ZleDyMi5EH XII0u7Bu6wd3ui9aoWCtY3KVfRGNLzI+Jb4VAfgg8gD/oS0wVngxYo8ep ZICGZsmUtrsPP20ch2g/57T4CWWtPQM1b5d+ZbGd7ZhZ0oCXlrZjuqKq3 1UosNvEabEX2Bkn2mwEQfAGiAwMqtBo1NEzIP1U1XvvYHjmta2ky4RRww g==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194894" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194894" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133167" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 05/10] platform/x86/intel/ifs: Check IFS Image sanity Date: Tue, 1 Mar 2022 11:54:52 -0800 Message-Id: <20220301195457.21152-6-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" IFS image is designed specifically for a given family, model and stepping of the processor. Like Intel microcode header, the IFS image has the Processor Signature, Checksum and Processor Flags that must be matched with the information returned by the CPUID. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- drivers/platform/x86/intel/ifs/load.c | 67 +++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/i= ntel/ifs/load.c index 1a5e906c51af..b40f70258f8e 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -6,6 +6,7 @@ =20 #include #include +#include =20 #include "ifs.h" static const char *ifs_path =3D "intel/ifs/"; @@ -27,6 +28,67 @@ struct ifs_header { #define IFS_HEADER_SIZE (sizeof(struct ifs_header)) static struct ifs_header *ifs_header_ptr; /* pointer to the ifs image head= er */ static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */ +static int ifs_sanity_check(void *mc) +{ + struct microcode_header_intel *mc_header =3D mc; + unsigned long total_size, data_size; + u32 sum, i; + + total_size =3D get_totalsize(mc_header); + data_size =3D get_datasize(mc_header); + + if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32= ))) { + pr_err("bad ifs data file size.\n"); + return -EINVAL; + } + + if (mc_header->ldrver !=3D 1 || mc_header->hdrver !=3D 1) { + pr_err("invalid/unknown ifs update format.\n"); + return -EINVAL; + } + + sum =3D 0; + i =3D total_size / sizeof(u32); + while (i--) + sum +=3D ((u32 *)mc)[i]; + + if (sum) { + pr_err("bad ifs data checksum, aborting.\n"); + return -EINVAL; + } + + return 0; +} + +static bool find_ifs_matching_signature(struct ucode_cpu_info *uci, void *= mc) +{ + struct microcode_header_intel *shdr; + unsigned int mc_size; + + shdr =3D (struct microcode_header_intel *)mc; + mc_size =3D get_totalsize(shdr); + + if (!mc_size || ifs_sanity_check(shdr) < 0) { + pr_err("ifs sanity check failure\n"); + return false; + } + + if (!cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, s= hdr->pf)) { + pr_err("ifs signature, pf not matching\n"); + return false; + } + + return true; +} + +static bool ifs_image_sanity_check(void *data) +{ + struct ucode_cpu_info uci; + + collect_cpu_info_early(&uci); + + return find_ifs_matching_signature(&uci, data); +} =20 static const struct firmware *load_binary(const char *path) { @@ -45,6 +107,11 @@ static const struct firmware *load_binary(const char *p= ath) goto out; } =20 + if (!ifs_image_sanity_check((void *)fw->data)) { + pr_err("ifs header sanity check failed\n"); + release_firmware(fw); + fw =3D NULL; + } out: platform_device_unregister(ifs_pdev); =20 --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F1F2C433EF for ; Tue, 1 Mar 2022 19:56:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237556AbiCAT5A (ORCPT ); Tue, 1 Mar 2022 14:57:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236227AbiCAT4h (ORCPT ); Tue, 1 Mar 2022 14:56:37 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C78E66CA59; Tue, 1 Mar 2022 11:55:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164555; x=1677700555; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=LXBIKDOPHycxgjU3B8bcgxSuOd2mkT56pNavGwV7x9k=; b=KDuugjEVAkwSBbJPWUZerFw1NtziKBMVM+h4fllw8X63/JLkAEpQ3yoL 1XB/xG+8WI/5+vEVB/yxEUsVElhdRa/7DTapzDJN4Fg2dwm6u7ZPBBMR3 uBbJqMgR+rB3Suf01Q78z1bxUzL1Bn14clgP/qmOMAv3oOIbhK50PcrSU 36wlnur6V699t/5XkRfJ5wvUX5OW6MnSXlLKx9qpP8cHO1ms+DF0NGlZQ EJjqmRQOssdAsTBtaaM/Rlt0tnR9EGGHaPqWO0fBTpoQLRR19+5GE3yGU SuMv6mvmOzS6iU2E3Bvek2ipQp17PEIZOk4r/FXtD+zRPr2mTvhmNhS0X A==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194896" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194896" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133170" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Date: Tue, 1 Mar 2022 11:54:53 -0800 Message-Id: <20220301195457.21152-7-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The IFS image contains hashes that will be used to authenticate the ifs test chunks. First, use WRMSR to copy the hashes and enumerate the number of test chunks, chunk size and the maximum number of cores that can run scan test simultaneously. Next, use WRMSR to authenticate each and every scan test chunk which is also stored in the IFS image. The CPU will check if the test chunks match the hashes, otherwise failure is indicated to system software. If the test chunk is authenticated, it is automatically copied to secured memory. The ifs hash copy and authentication only needs to be done on the first logical cpu of each socket. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- drivers/platform/x86/intel/ifs/ifs.h | 33 ++++++ drivers/platform/x86/intel/ifs/load.c | 139 +++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/in= tel/ifs/ifs.h index f2daf2cfd3e6..8f9abdb304b0 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -14,12 +14,45 @@ #define MSR_IA32_CORE_CAPS_INTEGRITY_BIT 2 #define MSR_IA32_CORE_CAPS_INTEGRITY BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT) =20 +#define MSR_COPY_SCAN_HASHES 0x000002c2 +#define MSR_SCAN_HASHES_STATUS 0x000002c3 +#define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4 +#define MSR_CHUNKS_AUTHENTICATION_STATUS 0x000002c5 + +/* MSR_SCAN_HASHES_STATUS bit fields */ +union ifs_scan_hashes_status { + u64 data; + struct { + u64 chunk_size :16; + u64 num_chunks :8; + u64 rsvd1 :8; + u64 error_code :8; + u64 rsvd2 :11; + u64 max_core_limit :12; + u64 valid :1; + }; +}; + +/* MSR_CHUNKS_AUTH_STATUS bit fields */ +union ifs_chunks_auth_status { + u64 data; + struct { + u64 valid_chunks :8; + u64 total_chunks :8; + u64 rsvd1 :16; + u64 error_code :8; + u64 rsvd2 :24; + }; +}; + /** * struct ifs_params - global ifs parameter for all cpus. * @loaded_version: stores the currently loaded ifs image version. + * @valid_chunks: number of chunks which could be validated. */ struct ifs_params { int loaded_version; + int valid_chunks; }; =20 int load_ifs_binary(void); diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/i= ntel/ifs/load.c index b40f70258f8e..a0cb0e1718bc 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -6,10 +6,13 @@ =20 #include #include +#include #include =20 #include "ifs.h" + static const char *ifs_path =3D "intel/ifs/"; +static bool ifs_loading_error; /* error occurred during ifs hashes/chunk a= uthentication.*/ =20 struct ifs_header { u32 header_ver; @@ -28,6 +31,140 @@ struct ifs_header { #define IFS_HEADER_SIZE (sizeof(struct ifs_header)) static struct ifs_header *ifs_header_ptr; /* pointer to the ifs image head= er */ static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */ +static u64 ifs_test_image_ptr; /* 256B aligned address of test pattern */ + +static const char * const scan_hash_status[] =3D { + "Reserved", + "Attempt to copy scan hashes when copy already in progress", + "Secure Memory not set up correctly", + "FuSaInfo.ProgramID does not match or ff-mm-ss does not match", + "Reserved", + "Integrity check failed", + "Scan test is in progress" +}; + +static const char * const scan_authentication_status[] =3D { + "No error reported", + "Attempt to authenticate a chunk which is already marked as authentic", + "Chunk authentication error. The hash of chunk did not match expected val= ue" +}; + +/* + * To copy scan hashes and authenticate test chunks, the initiating cpu mu= st point + * to the EDX:EAX to the test image in linear address. + * Run wrmsr(MSR_COPY_SCAN_HASHES) for scan hash copy and run wrmsr(MSR_AU= THENTICATE_AND_COPY_CHUNK) + * for scan hash copy and test chunk authentication. + */ +static int copy_hashes_authenticate_chunks(void *arg) +{ + union ifs_scan_hashes_status hashes_status; + union ifs_chunks_auth_status chunk_status; + int i, num_chunks, chunk_size; + u64 linear_addr, base; + u32 err_code; + + /* run scan hash copy */ + wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr); + rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data); + + /* enumerate the scan image information */ + num_chunks =3D hashes_status.num_chunks; + chunk_size =3D hashes_status.chunk_size * 1024; + err_code =3D hashes_status.error_code; + + if (!hashes_status.valid) { + ifs_loading_error =3D true; + if (err_code >=3D ARRAY_SIZE(scan_hash_status)) { + pr_err("invalid error code 0x%x for hash copy\n", err_code); + return -EINVAL; + } + pr_err("ifs: %s", scan_hash_status[err_code]); + return -ENODEV; + } + pr_info("the total chunk number: %d\n", num_chunks); + + /* base linear address to the scan data */ + base =3D ifs_test_image_ptr; + + /* scan data authentication and copy chunks to secured memory */ + for (i =3D 0; i < num_chunks; i++) { + linear_addr =3D base + i * chunk_size; + linear_addr |=3D i; + + wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr); + rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data); + + ifs_params.valid_chunks =3D chunk_status.valid_chunks; + err_code =3D chunk_status.error_code; + + if (err_code) { + ifs_loading_error =3D true; + if (err_code >=3D ARRAY_SIZE(scan_authentication_status)) { + pr_err("invalid error code 0x%x for authentication\n", err_code); + return -EINVAL; + } + pr_err("%s\n", scan_authentication_status[err_code]); + return -ENODEV; + } + } + + return 0; +} + +/* + * IFS requires scan chunks authenticated per each socket in the platform. + * Once the test chunk is authenticated, it is automatically copied to sec= ured memory + * and proceed the authentication for the next chunk. + */ +static int scan_chunks_sanity_check(void) +{ + int metadata_size, curr_pkg, cpu, ret =3D -ENOMEM; + bool *package_authenticated; + char *test_ptr; + + package_authenticated =3D kcalloc(topology_max_packages(), sizeof(bool), = GFP_KERNEL); + if (!package_authenticated) + return ret; + + metadata_size =3D ifs_header_ptr->metadata_size; + + /* Spec says that if the Meta Data Size =3D 0 then it should be treated a= s 2000 */ + if (metadata_size =3D=3D 0) + metadata_size =3D 2000; + + /* Scan chunk start must be 256 byte aligned */ + if ((metadata_size + IFS_HEADER_SIZE) % 256) { + pr_err("Scan pattern offset within the binary is not 256 byte aligned\n"= ); + return -EINVAL; + } + + test_ptr =3D (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size; + + ifs_test_image_ptr =3D (u64)test_ptr; + ifs_params.loaded_version =3D ifs_header_ptr->blob_revision; + + /* copy the scan hash and authenticate per package */ + cpus_read_lock(); + for_each_online_cpu(cpu) { + curr_pkg =3D topology_physical_package_id(cpu); + if (package_authenticated[curr_pkg]) + continue; + package_authenticated[curr_pkg] =3D 1; + ret =3D smp_call_function_single(cpu, (void *)copy_hashes_authenticate_c= hunks, + NULL, 1); + if (ret || ifs_loading_error) { + ret =3D ifs_loading_error ? -ENOMEM : ret; + goto out; + } + } + +out: + cpus_read_unlock(); + kfree(package_authenticated); + + return ret; +} + static int ifs_sanity_check(void *mc) { struct microcode_header_intel *mc_header =3D mc; @@ -154,7 +291,7 @@ int load_ifs_binary(void) ifs_header_ptr =3D (struct ifs_header *)scan_fw->data; ifs_hash_ptr =3D (u64)(ifs_header_ptr + 1); =20 - ret =3D 0; + ret =3D scan_chunks_sanity_check(); out: release_firmware(scan_fw); =20 --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCB7BC433F5 for ; Tue, 1 Mar 2022 19:56:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237545AbiCAT5R (ORCPT ); Tue, 1 Mar 2022 14:57:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236718AbiCAT4i (ORCPT ); Tue, 1 Mar 2022 14:56:38 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 31F586D4D7; Tue, 1 Mar 2022 11:55:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164556; x=1677700556; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=lJyla5FagWFCwraH51W1efpjORCyrwBuUXLYfAA9vgM=; b=nS6x7XPj2zheOug8jrw2+H9ru/GkF+ogXmZ6L1CpLY3Oc9RaV6s1DwY1 yyuP+K6Q3k4qiHAWD/6M1CRIPYh9Lo4M47wa7W5OvH5W/dTETygn4T6zi 1PKKShbNs5lVEDaVvsihnP08bar3E6XJOroKypdNeYCNTFK4c8wmSXR7k MCpx+0AMLIKKtR9+07bv/jvJNNYlAzV3Q9iaXjj7jv7iHP+CDyFNL4knj kT6JLXQJOMGNH2MLOoQrUmIdW21g9GM/knu/WtDb+t3hnYV7HCkhaiQ2O rbzrRuyV8GSdXpRKnhL/tgpugY//JO9h5AGOcloYMkW/NIFwL2jSVzG2F A==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194898" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194898" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133173" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:53 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 07/10] platform/x86/intel/ifs: Create kthreads for online cpus for scan test Date: Tue, 1 Mar 2022 11:54:54 -0800 Message-Id: <20220301195457.21152-8-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Create scan kthreads for online logical cpus. Once scan test is triggered, it wakes up the corresponding thread and its sibling threads to execute the test. Once the scan test is done, the threads go back to thread wait for next signal to start a new scan. In a core, the scan engine is shared between siblings. When a scan test is triggered on a core, all the siblings rendezvous before the test executi= on. The scan results are same for all siblings. Scan may be aborted by some reasons. Scan test will be aborted in certain circumstances such as when interrupt occurred or cpu does not have enough power budget for scan. In this case, the kernel restart scan from the chunk where it stopped. Scan will also be aborted when the test is failed. In this case, the test is immediately stopped without retry. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- drivers/platform/x86/intel/ifs/core.c | 317 ++++++++++++++++++++++++++ drivers/platform/x86/intel/ifs/ifs.h | 91 ++++++++ 2 files changed, 408 insertions(+) diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/i= ntel/ifs/core.c index 765d9a2c4683..6747b523587a 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -4,11 +4,38 @@ * Author: Jithu Joseph */ =20 +#include +#include +#include #include +#include #include =20 #include "ifs.h" + +static enum cpuhp_state cpuhp_scan_state; struct ifs_params ifs_params; +int cpu_sibl_ct; +atomic_t siblings_in; /* sibling count for joining rendezvous.*/ +atomic_t siblings_out; /* sibling count for exiting rendezvous.*/ +struct completion test_thread_done; /* set when scan are done for all sibl= ings threads.*/ + +DEFINE_PER_CPU(struct ifs_state, ifs_state); + +static int ifs_retry_set(const char *val, const struct kernel_param *kp); +static const struct kernel_param_ops ifs_retry_ops =3D { + .set =3D ifs_retry_set, + .get =3D param_get_int, +}; + +static int retry =3D 5; +module_param_cb(retry, &ifs_retry_ops, &retry, 0644); + +MODULE_PARM_DESC(retry, "Maximum retry count when the test is not executed= "); + +static bool noint =3D 1; +module_param(noint, bool, 0644); +MODULE_PARM_DESC(noint, "Option to enable/disable interrupt during test"); =20 #define X86_MATCH(model) \ X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, \ @@ -21,6 +48,273 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initcons= t =3D { =20 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids); =20 +static int ifs_retry_set(const char *val, const struct kernel_param *kp) +{ + int var =3D 0; + + if (kstrtoint(val, 0, &var)) { + pr_err("unable to parse retry\n"); + return -EINVAL; + } + + /* validate retry value for sanity */ + if (var < 1 || var > 20) { + pr_err("retry parameter should be between 1 and 20\n"); + return -EINVAL; + } + + return param_set_int(val, kp); +} + +static unsigned long msec_to_tsc(unsigned long msec) +{ + return tsc_khz * 1000 * msec / MSEC_PER_SEC; +} + +static const char * const scan_test_status[] =3D { + "SCAN no error", + "Other thread could not join.", + "Interrupt occurred prior to SCAN coordination.", + "Core Abort SCAN Response due to power management condition.", + "Non valid chunks in the range", + "Mismatch in arguments between threads T0/T1.", + "Core not capable of performing SCAN currently", + "Unassigned error code 0x7", + "Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field = concurrently", + "Interrupt occurred prior to SCAN start", +}; + +static void message_not_tested(int cpu, union ifs_status status) +{ + if (status.error_code < ARRAY_SIZE(scan_test_status)) + pr_warn("CPU %d: SCAN operation did not start. %s\n", cpu, + scan_test_status[status.error_code]); + else if (status.error_code =3D=3D IFS_SW_TIMEOUT) + pr_warn("CPU %d: software timeout during scan\n", cpu); + else if (status.error_code =3D=3D IFS_SW_PARTIAL_COMPLETION) + pr_warn("CPU %d: %s\n", cpu, + "Not all scan chunks were executed. Maximum forward progress retries ex= ceeded"); + else + pr_warn("CPU %d: SCAN unknown status %llx\n", cpu, status.data); +} + +static void message_fail(int cpu, union ifs_status status) +{ + if (status.control_error) { + pr_err("CPU %d: scan failed. %s\n", cpu, + "Suggest reload scan file: # echo 1 > /sys/devices/system/cpu/ifs= /reload"); + } + if (status.signature_error) { + pr_err("CPU %d: test signature incorrect. %s\n", cpu, + "Suggest retry scan to check if problem is transient"); + } +} + +static bool can_restart(union ifs_status status) +{ + /* Signature for chunk is bad, or scan test failed */ + if (status.signature_error || status.control_error) + return false; + + switch (status.error_code) { + case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN: + mdelay(1); + fallthrough; + case IFS_NO_ERROR: + case IFS_OTHER_THREAD_DID_NOT_JOIN: + case IFS_INTERRUPTED_BEFORE_RENDEZVOUS: + case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT: + case IFS_INTERRUPTED_DURING_EXECUTION: + return true; + } + return false; +} + +static bool wait_for_siblings(atomic_t *t, long long timeout) +{ + atomic_inc(t); + while (atomic_read(t) < cpu_sibl_ct) { + if (timeout < SPINUNIT) { + pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n", + cpu_sibl_ct - atomic_read(t)); + return false; + } + + ndelay(SPINUNIT); + timeout -=3D SPINUNIT; + + touch_nmi_watchdog(); + } + + return true; +} + +/* + * Scan test kthreads bound with each logical cpu. + * Wait for the sibling thread to join before the execution. + * Execute the scan test by running wrmsr(MSR_ACTIVATE_SCAN). + */ +static int scan_test_worker(void *info) +{ + int cpu =3D smp_processor_id(); + union ifs_scan activate; + union ifs_status status; + unsigned long timeout; + int retries; + u32 first; + + activate.rsvd =3D 0; + activate.delay =3D msec_to_tsc(THREAD_WAIT); + activate.sigmce =3D 0; + + while (1) { + /* wait event until cpumask set from user */ + wait_event_interruptible(per_cpu(ifs_state, cpu).scan_wq, + (cpumask_test_cpu(cpu, &per_cpu(ifs_state, cpu).mask) || + kthread_should_stop())); + + if (kthread_should_stop()) + break; + + /* + * Need to get (and keep) the threads on this core executing close toget= her + * so that the writes to MSR_ACTIVATE_SCAN below will succeed in entering + * IFS test mode on this core. Interrupts on each thread are expected to= be + * brief. But preemption would be a problem. + */ + preempt_disable(); + + /* wait for the sibling threads to join */ + first =3D cpumask_first(topology_sibling_cpumask(cpu)); + if (!wait_for_siblings(&siblings_in, NSEC_PER_SEC)) { + preempt_enable(); + return -1; + } + + activate.start =3D 0; + activate.stop =3D ifs_params.valid_chunks - 1; + timeout =3D jiffies + HZ / 2; + retries =3D retry; + + while (activate.start <=3D activate.stop) { + if (time_after(jiffies, timeout)) { + status.error_code =3D IFS_SW_TIMEOUT; + break; + } + + if (noint) + local_irq_disable(); + /* scan start */ + wrmsrl(MSR_ACTIVATE_SCAN, activate.data); + + if (noint) + local_irq_enable(); + + /* + * All logical CPUs on this core are now running IFS test. When it comp= letes + * execution or is interrupted, the following RDMSR gets the scan statu= s. + */ + + rdmsrl(MSR_SCAN_STATUS, status.data); + + /* Some cases can be retried, give up for others */ + if (!can_restart(status)) + break; + + if (status.chunk_num =3D=3D activate.start) { + /* Check for forward progress */ + if (retries-- =3D=3D 0) { + if (status.error_code =3D=3D IFS_NO_ERROR) + status.error_code =3D IFS_SW_PARTIAL_COMPLETION; + break; + } + } else { + retries =3D retry; + activate.start =3D status.chunk_num; + } + } + + preempt_enable(); + + /* Update status for this core */ + per_cpu(ifs_state, cpu).scan_details =3D status.data; + + if (status.control_error || status.signature_error) { + per_cpu(ifs_state, cpu).status =3D SCAN_TEST_FAIL; + cpumask_set_cpu(cpu, &ifs_params.fail_mask); + cpumask_clear_cpu(cpu, &ifs_params.not_tested_mask); + cpumask_clear_cpu(cpu, &ifs_params.pass_mask); + message_fail(cpu, status); + } else if (status.error_code) { + per_cpu(ifs_state, cpu).status =3D SCAN_NOT_TESTED; + cpumask_set_cpu(cpu, &ifs_params.not_tested_mask); + cpumask_clear_cpu(cpu, &ifs_params.fail_mask); + cpumask_clear_cpu(cpu, &ifs_params.pass_mask); + message_not_tested(cpu, status); + } else { + per_cpu(ifs_state, cpu).status =3D SCAN_TEST_PASS; + cpumask_set_cpu(cpu, &ifs_params.pass_mask); + cpumask_clear_cpu(cpu, &ifs_params.not_tested_mask); + cpumask_clear_cpu(cpu, &ifs_params.fail_mask); + } + + cpumask_clear_cpu(cpu, &per_cpu(ifs_state, cpu).mask); + + if (!wait_for_siblings(&siblings_out, NSEC_PER_SEC)) + return -1; + + if (cpu =3D=3D first) + complete(&test_thread_done); + } + + return 0; +} + +static void ifs_first_time(unsigned int cpu) +{ + init_waitqueue_head(&(per_cpu(ifs_state, cpu).scan_wq)); + + per_cpu(ifs_state, cpu).first_time =3D 1; + per_cpu(ifs_state, cpu).status =3D SCAN_NOT_TESTED; + cpumask_set_cpu(cpu, &ifs_params.not_tested_mask); + cpumask_clear_cpu(cpu, &ifs_params.fail_mask); + cpumask_clear_cpu(cpu, &ifs_params.pass_mask); +} + +static int ifs_online_cpu(unsigned int cpu) +{ + /* If the CPU is coming online for the first time*/ + if (per_cpu(ifs_state, cpu).first_time =3D=3D 0) + ifs_first_time(cpu); + + cpumask_clear_cpu(cpu, &(per_cpu(ifs_state, cpu).mask)); + + per_cpu(ifs_state, cpu).scan_task =3D kthread_create_on_node(scan_test_wo= rker, (void *)&cpu, + cpu_to_node(cpu), "ifsCpu/%u", + cpu); + if (IS_ERR(per_cpu(ifs_state, cpu).scan_task)) { + pr_err("scan_test_worker task create failed\n"); + return PTR_ERR(per_cpu(ifs_state, cpu).scan_task); + } + kthread_bind(per_cpu(ifs_state, cpu).scan_task, cpu); + wake_up_process(per_cpu(ifs_state, cpu).scan_task); + + return 0; +} + +static int ifs_offline_cpu(unsigned int cpu) +{ + struct task_struct *thread; + + thread =3D per_cpu(ifs_state, cpu).scan_task; + per_cpu(ifs_state, cpu).scan_task =3D NULL; + + if (thread) + kthread_stop(thread); + + return 0; +} + static int __init ifs_init(void) { const struct x86_cpu_id *m; @@ -42,11 +336,34 @@ static int __init ifs_init(void) return ret; } =20 + init_completion(&test_thread_done); + ret =3D cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/ifs:online", + ifs_online_cpu, ifs_offline_cpu); + + if (ret < 0) { + pr_err("cpuhp_setup_failed\n"); + return ret; + } + cpuhp_scan_state =3D ret; + return 0; } =20 static void __exit ifs_exit(void) { + struct task_struct *thread; + int cpu; + + cpus_read_lock(); + for_each_online_cpu(cpu) { + thread =3D per_cpu(ifs_state, cpu).scan_task; + per_cpu(ifs_state, cpu).scan_task =3D NULL; + if (thread) + kthread_stop(thread); + } + cpus_read_unlock(); + cpuhp_remove_state(cpuhp_scan_state); + pr_info("unloaded 'In-Field Scan' module\n"); } =20 diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/in= tel/ifs/ifs.h index 8f9abdb304b0..fcbbb49faa19 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -18,6 +18,13 @@ #define MSR_SCAN_HASHES_STATUS 0x000002c3 #define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4 #define MSR_CHUNKS_AUTHENTICATION_STATUS 0x000002c5 +#define MSR_ACTIVATE_SCAN 0x000002c6 +#define MSR_SCAN_STATUS 0x000002c7 +#define SCAN_TEST_PASS 0 +#define SCAN_TEST_FAIL 1 +#define SCAN_NOT_TESTED 2 +#define SPINUNIT 100 +#define THREAD_WAIT 5 =20 /* MSR_SCAN_HASHES_STATUS bit fields */ union ifs_scan_hashes_status { @@ -45,16 +52,100 @@ union ifs_chunks_auth_status { }; }; =20 +/* MSR_ACTIVATE_SCAN bit fields */ +union ifs_scan { + u64 data; + struct { + u64 start :8; + u64 stop :8; + u64 rsvd :16; + u64 delay :31; + u64 sigmce :1; + }; +}; + +/* MSR_SCAN_STATUS bit fields */ +union ifs_status { + u64 data; + struct { + u64 chunk_num :8; + u64 chunk_stop_index :8; + u64 rsvd1 :16; + u64 error_code :8; + u64 rsvd2 :22; + u64 control_error :1; + u64 signature_error :1; + }; +}; + +/* + * ifs_status.error_code values after rdmsr(SCAN_STATUS) + * 0x0: no error. + * 0x1: scan did not start because all sibling threads did not join. + * 0x2: scan did not start because interrupt occurred prior to threads ren= dezvous + * 0x3: scan did not start because power management conditions are inadequ= ate. + * 0x4: scan did not start because non-valid chunks in range stop_index:st= art_index. + * 0x5: scan did not start because of mismatches in arguments between sibl= ing threads. + * 0x6: scan did not start because core is not capable of performing scan = currently. + * 0x7: not assigned. + * 0x8: scan did not start because of exceed number of concurrent CPUs att= empt to run scan. + * 0x9: interrupt occurred. Scan operation aborted prematurely. Not all ch= unks executed. + * 0xFE: not all scan chunks were executed. Maximum forward progress retri= es exceeded. + * This is a driver populated error-code as hardware returns success in t= his scenario. + */ +#define IFS_NO_ERROR 0x0 +#define IFS_OTHER_THREAD_DID_NOT_JOIN 0x1 +#define IFS_INTERRUPTED_BEFORE_RENDEZVOUS 0x2 +#define IFS_POWER_MGMT_INADEQUATE_FOR_SCAN 0x3 +#define IFS_INVALID_CHUNK_RANGE 0x4 +#define IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS 0x5 +#define IFS_CORE_NOT_CAPABLE_CURRENTLY 0x6 +/* Code 0x7 not assigned */ +#define IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT 0x8 +#define IFS_INTERRUPTED_DURING_EXECUTION 0x9 + +#define IFS_SW_TIMEOUT 0xFD +#define IFS_SW_PARTIAL_COMPLETION 0xFE + /** * struct ifs_params - global ifs parameter for all cpus. * @loaded_version: stores the currently loaded ifs image version. * @valid_chunks: number of chunks which could be validated. + * @fail_mask: stores the cpus which failed the scan. + * @not_tested_mask: stores the cpus which have not been tested. */ struct ifs_params { int loaded_version; int valid_chunks; + struct cpumask fail_mask; + struct cpumask pass_mask; + struct cpumask not_tested_mask; }; =20 +/** + * struct ifs_state - per-cpu ifs parameter. + * @scan_task: scan_task for kthread to run scan test on each cpu. + * @first_time: to track if cpu is coming online for the first time. + * @status: it holds simple status pass/fail/untested. + * @scan_details: opaque scan status code from h/w. + * @scan_wq: kthread task wait queue. + * @mask: triggering the test by setting the mask. + */ +struct ifs_state { + struct task_struct *scan_task; + int first_time; + int status; + u64 scan_details; + wait_queue_head_t scan_wq; + struct cpumask mask; +}; + +DECLARE_PER_CPU(struct ifs_state, ifs_state); + int load_ifs_binary(void); extern struct ifs_params ifs_params; +extern atomic_t siblings_in; +extern atomic_t siblings_out; +extern struct completion test_thread_done; +extern int cpu_sibl_ct; #endif --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA644C433F5 for ; Tue, 1 Mar 2022 19:56:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231386AbiCAT5N (ORCPT ); Tue, 1 Mar 2022 14:57:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237187AbiCAT4i (ORCPT ); Tue, 1 Mar 2022 14:56:38 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5078C5D188; Tue, 1 Mar 2022 11:55:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164556; x=1677700556; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=l9+0JdtN9wgdVgpsIysnTaRpfpOxummB1ggACJktejk=; b=Zj/t1xPCbTrti82C4gbk7omPYyddapjbIIVRgBpFBaWqJiEJQgivrfCH 2bWQecL55uYwA1BcVCqD4bacA9eEqbNpe1w5wsZBRLTD5bQKiG2KMOBO7 TYEHf25SdWw5gn4Q0fiZzzNi9mdjs88lVlCZj8Terkg+QeHpEV9Dhz4Wx Y7BD1EP3sS5yziFZRToKDZ18OPkiTMA6D3gw4EFuJR8zix6v1pHEgeWhz PatpaNssxH/iePTXRzklvwoFs0b7N8+XYOmSL2eqVFc0XBcu7lx/CNeho vLZRklKOII3ViSQWjgzZaRtJekt4Lm5VmWIlqM3lnlBhXf2XQfYoXL3kz A==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194900" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194900" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133176" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Date: Tue, 1 Mar 2022 11:54:55 -0800 Message-Id: <20220301195457.21152-9-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Implement sysfs interface to trigger ifs test for a targeted core or all cores. For all core testing, the kernel will start testing from core 0 and proceed to the next core one after another. After the ifs test on the last core, the test stops until the administrator starts another round of tests. A "targeted core" test runs a single ifs on a single core. The kernel will only test the target core. The basic usage is as below. 1. For all cores testing: echo 1 > /sys/devices/system/cpu/ifs/run_test cat /sys/devices/system/cpu/ifs/status 2. For "targeted core" testing: To start test, for example, cpu0: echo 1 > /sys/devices/system/cpu/cpu#/ifs/run_test cat /sys/devices/system/cpu/cpu#/ifs/status 3. For reloading IFS image: (e.g, when new IFS image is released) - copy the new image to /lib/firmware/intel/ifs/ - rename it as {family/model/stepping}.{testname} - echo 1 > /sys/devices/system/cpu/ifs/reload This module accepts two tunable parameters. Defaults could be overridden by passing appropriate values during load time. The parameters are as described below. 1. noint: When set, system interrupts are not allowed to interrupt a scan. 2. retry: Maximum retry counter when the test is not executed due to an event such as interrupt. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- drivers/platform/x86/intel/ifs/Makefile | 2 +- drivers/platform/x86/intel/ifs/core.c | 8 + drivers/platform/x86/intel/ifs/ifs.h | 4 + drivers/platform/x86/intel/ifs/sysfs.c | 394 ++++++++++++++++++++++++ 4 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86= /intel/ifs/Makefile index 105b377de410..a2e05bf78c3e 100644 --- a/drivers/platform/x86/intel/ifs/Makefile +++ b/drivers/platform/x86/intel/ifs/Makefile @@ -4,4 +4,4 @@ =20 obj-$(CONFIG_INTEL_IFS) +=3D intel_ifs.o =20 -intel_ifs-objs :=3D core.o load.o +intel_ifs-objs :=3D core.o load.o sysfs.o diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/i= ntel/ifs/core.c index 6747b523587a..c9ca385082e9 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -283,11 +283,16 @@ static void ifs_first_time(unsigned int cpu) =20 static int ifs_online_cpu(unsigned int cpu) { + int ret; + /* If the CPU is coming online for the first time*/ if (per_cpu(ifs_state, cpu).first_time =3D=3D 0) ifs_first_time(cpu); =20 cpumask_clear_cpu(cpu, &(per_cpu(ifs_state, cpu).mask)); + ret =3D ifs_sysfs_create(cpu); + if (ret) + return ret; =20 per_cpu(ifs_state, cpu).scan_task =3D kthread_create_on_node(scan_test_wo= rker, (void *)&cpu, cpu_to_node(cpu), "ifsCpu/%u", @@ -311,6 +316,7 @@ static int ifs_offline_cpu(unsigned int cpu) =20 if (thread) kthread_stop(thread); + ifs_sysfs_remove(cpu); =20 return 0; } @@ -336,6 +342,7 @@ static int __init ifs_init(void) return ret; } =20 + cpu_ifs_init(); init_completion(&test_thread_done); ret =3D cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/ifs:online", ifs_online_cpu, ifs_offline_cpu); @@ -361,6 +368,7 @@ static void __exit ifs_exit(void) if (thread) kthread_stop(thread); } + cpu_ifs_exit(); cpus_read_unlock(); cpuhp_remove_state(cpuhp_scan_state); =20 diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/in= tel/ifs/ifs.h index fcbbb49faa19..4442ccd626c6 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -143,6 +143,10 @@ struct ifs_state { DECLARE_PER_CPU(struct ifs_state, ifs_state); =20 int load_ifs_binary(void); +void cpu_ifs_init(void); +void cpu_ifs_exit(void); +int ifs_sysfs_create(unsigned int cpu); +void ifs_sysfs_remove(unsigned int cpu); extern struct ifs_params ifs_params; extern atomic_t siblings_in; extern atomic_t siblings_out; diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/= intel/ifs/sysfs.c new file mode 100644 index 000000000000..f441968de642 --- /dev/null +++ b/drivers/platform/x86/intel/ifs/sysfs.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2021 Intel Corporation. + * + * Author: Jithu Joseph + */ + +#include +#include +#include +#include + +#include "ifs.h" + +static DEFINE_SEMAPHORE(ifs_sem); +static int core_delay =3D 1; +static bool ifs_disabled; + +/* + * Initiate per core test. It wakes up all sibling threads that belongs to= the + * target cpu. Once all sibling threads wake up, the scan test gets execut= ed and + * wait for all sibling threads to finish the scan test. + */ +static void do_core_test(int cpu) +{ + int sibling; + + reinit_completion(&test_thread_done); + atomic_set(&siblings_in, 0); + atomic_set(&siblings_out, 0); + + cpu_sibl_ct =3D cpumask_weight(topology_sibling_cpumask(cpu)); + + for_each_cpu(sibling, topology_sibling_cpumask(cpu)) + cpumask_set_cpu(sibling, &per_cpu(ifs_state, sibling).mask); + + for_each_cpu(sibling, topology_sibling_cpumask(cpu)) + wake_up_interruptible(&per_cpu(ifs_state, sibling).scan_wq); + + if (wait_for_completion_timeout(&test_thread_done, HZ) =3D=3D 0) { + pr_err("Core locked up during IFS test? IFS disabled\n"); + ifs_disabled =3D true; + } +} + +/* + * The sysfs interface to check the test status: + * To check the result, for example, cpu0 + * cat /sys/devices/system/cpu/cpu0/ifs/details + */ +static ssize_t details_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + unsigned int cpu =3D dev->id; + int ret; + + if (down_trylock(&ifs_sem)) + return -EBUSY; + + ret =3D sprintf(buf, "%llx\n", per_cpu(ifs_state, cpu).scan_details); + up(&ifs_sem); + + return ret; +} + +static DEVICE_ATTR_RO(details); + +/* + * The sysfs interface to check the test status: + * To check the status, for example, cpu0 + * cat /sys/devices/system/cpu/cpu0/ifs/status + */ +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + unsigned int cpu =3D dev->id; + u32 scan_result; + int ret; + + if (down_trylock(&ifs_sem)) + return -EBUSY; + + scan_result =3D per_cpu(ifs_state, cpu).status; + + if (scan_result =3D=3D SCAN_TEST_FAIL) + ret =3D sprintf(buf, "fail\n"); + else if (scan_result =3D=3D SCAN_NOT_TESTED) + ret =3D sprintf(buf, "untested\n"); + else + ret =3D sprintf(buf, "pass\n"); + + up(&ifs_sem); + + return ret; +} + +static DEVICE_ATTR_RO(status); + +/* + * The sysfs interface for single core testing + * To start test, for example, cpu0 + * echo 1 > /sys/devices/system/cpu/cpu0/ifs/run_test + * To check the result: + * cat /sys/devices/system/cpu/cpu0/ifs/result + * The sibling core gets tested at the same time. + */ +static ssize_t run_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int cpu =3D dev->id; + bool var; + int rc; + + if (ifs_disabled) + return -ENXIO; + + rc =3D kstrtobool(buf, &var); + if (rc < 0 || var !=3D 1) + return -EINVAL; + + if (down_trylock(&ifs_sem)) { + pr_info("another instance in progress.\n"); + return -EBUSY; + } + cpu_hotplug_disable(); + do_core_test(cpu); + cpu_hotplug_enable(); + up(&ifs_sem); + + return count; +} + +static DEVICE_ATTR_WO(run_test); + +/* per-cpu scan sysfs attributes */ +static struct attribute *ifs_attrs[] =3D { + &dev_attr_run_test.attr, + &dev_attr_status.attr, + &dev_attr_details.attr, + NULL +}; + +const struct attribute_group ifs_attr_group =3D { + .attrs =3D ifs_attrs, + .name =3D "ifs", +}; + +/* Creates the sysfs files under /sys/devices/system/cpu/cpuX/ifs */ +int ifs_sysfs_create(unsigned int cpu) +{ + struct device *dev; + int ret; + + dev =3D get_cpu_device(cpu); + ret =3D sysfs_create_group(&dev->kobj, &ifs_attr_group); + if (ret) { + pr_err("failed to create sysfs group\n"); + return ret; + } + + return 0; +} + +/* Removes the sysfs files under /sys/devices/system/cpu/cpuX/ifs */ +void ifs_sysfs_remove(unsigned int cpu) +{ + struct device *dev; + + dev =3D get_cpu_device(cpu); + sysfs_remove_group(&dev->kobj, &ifs_attr_group); +} + +/* + * Reload the IFS image. When user wants to install new IFS image + * image, reloading must be done. + */ +static ssize_t reload_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + bool var; + int rc; + + if (ifs_disabled) + return -ENXIO; + + rc =3D kstrtobool(buf, &var); + if (rc < 0 || var !=3D 1) + return -EINVAL; + + down(&ifs_sem); + rc =3D load_ifs_binary(); + up(&ifs_sem); + if (rc < 0) { + pr_info("failed to reload ifs hash and test\n"); + return rc; + } + + return count; +} + +static DEVICE_ATTR_WO(reload); + +static int run_allcpu_scan_test(void) +{ + int cpu; + + if (down_trylock(&ifs_sem)) { + pr_info("another instance in progress.\n"); + return -EBUSY; + } + + cpu_hotplug_disable(); + for_each_cpu(cpu, cpu_online_mask) { + /* Only execute test on the first thread on each core */ + if (cpumask_first(topology_sibling_cpumask(cpu)) !=3D cpu) + continue; + do_core_test(cpu); + mdelay(core_delay); + } + cpu_hotplug_enable(); + + up(&ifs_sem); + return 0; +} + +/* + * The sysfs interface to execute scan test for all online cpus. + * The test can be triggered as below: + * echo 1 > /sys/devices/system/cpu/ifs/run_test + */ +static ssize_t allcpu_run_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + bool var; + int rc; + + if (ifs_disabled) + return -ENXIO; + + rc =3D kstrtobool(buf, &var); + if (rc < 0 || var !=3D 1) + return -EINVAL; + + rc =3D run_allcpu_scan_test(); + if (rc < 0) + return rc; + + return count; +} + +/* + * Percpu and allcpu ifs have attributes named "run_test". + * Since the former is defined in this same file using DEVICE_ATTR_WO() + * the latter is defined directly. + */ +static struct device_attribute dev_attr_allcpu_run_test =3D { + .attr =3D { .name =3D "run_test", .mode =3D 0200 }, + .store =3D allcpu_run_test_store, +}; + +/* + * Currently loaded IFS image version. + */ +static ssize_t image_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%x\n", ifs_params.loaded_version); +} + +static DEVICE_ATTR_RO(image_version); + +/* + * Currently loaded IFS image version. + */ +static ssize_t cpu_fail_list_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + + if (down_trylock(&ifs_sem)) + return -EBUSY; + + ret =3D sprintf(buf, "%*pbl\n", cpumask_pr_args(&ifs_params.fail_mask)); + up(&ifs_sem); + return ret; +} + +static DEVICE_ATTR_RO(cpu_fail_list); + +static ssize_t cpu_untested_list_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + + if (down_trylock(&ifs_sem)) + return -EBUSY; + + ret =3D sprintf(buf, "%*pbl\n", cpumask_pr_args(&ifs_params.not_tested_ma= sk)); + up(&ifs_sem); + + return ret; +} + +static DEVICE_ATTR_RO(cpu_untested_list); + +static ssize_t cpu_pass_list_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + + if (down_trylock(&ifs_sem)) + return -EBUSY; + + ret =3D sprintf(buf, "%*pbl\n", cpumask_pr_args(&ifs_params.pass_mask)); + up(&ifs_sem); + + return ret; +} + +static DEVICE_ATTR_RO(cpu_pass_list); + +/* + * Status for global ifs test + */ +static ssize_t allcpu_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + + if (down_trylock(&ifs_sem)) + return -EBUSY; + + if (!cpumask_empty(&ifs_params.fail_mask)) + ret =3D sprintf(buf, "fail\n"); + else if (!cpumask_empty(&ifs_params.not_tested_mask)) + ret =3D sprintf(buf, "untested\n"); + else + ret =3D sprintf(buf, "pass\n"); + + up(&ifs_sem); + + return ret; +} + +/* + * Percpu and allcpu ifs have attributes named "status". + * Since the former is defined in this same file using DEVICE_ATTR_RO() + * the latter is defined directly. + */ +static struct device_attribute dev_attr_allcpu_status =3D { + .attr =3D { .name =3D "status", .mode =3D 0444 }, + .show =3D allcpu_status_show, +}; + +/* global scan sysfs attributes */ +static struct attribute *cpu_ifs_attrs[] =3D { + &dev_attr_reload.attr, + &dev_attr_allcpu_run_test.attr, + &dev_attr_image_version.attr, + &dev_attr_cpu_fail_list.attr, + &dev_attr_cpu_untested_list.attr, + &dev_attr_cpu_pass_list.attr, + &dev_attr_allcpu_status.attr, + NULL +}; + +const struct attribute_group cpu_ifs_attr_group =3D { + .attrs =3D cpu_ifs_attrs, +}; + +const struct attribute_group *cpu_ifs_attr_groups[] =3D { + &cpu_ifs_attr_group, + NULL, +}; + +static struct device *cpu_scan_device; + +/* Creates the sysfs files under /sys/devices/system/cpu/ifs */ +void cpu_ifs_init(void) +{ + struct device *root; + + root =3D cpu_subsys.dev_root; + cpu_scan_device =3D cpu_device_create(root, NULL, cpu_ifs_attr_groups, "i= fs"); +} + +void cpu_ifs_exit(void) +{ + device_unregister(cpu_scan_device); +} --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86BB7C433EF for ; Tue, 1 Mar 2022 19:56:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233599AbiCAT5G (ORCPT ); Tue, 1 Mar 2022 14:57:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56210 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236985AbiCAT4i (ORCPT ); Tue, 1 Mar 2022 14:56:38 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA1966D4EA; Tue, 1 Mar 2022 11:55:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164556; x=1677700556; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=XLKybxN7zciO2WXoGtuDgQD2mqkuZlXQf8E59ZXt5Es=; b=PNSan40XMbcMUS7buMvRb+LugAbSQgBBlcc0mn3U2YHeaPhca+D64DCe Tx3YNDnCbKhRBSI6ekOQb9nwcA48HpOnR/G8LwSVJ8OTMCf6BB2yenNlV Jd2brfRTA2+1F4WG+XpbAfnZBV/x1r21Tz2H2TXDD5CCk16UKwb8IqPQm FF3zTN84msu71q1pVLFmxo1hJr8XYtqRAA3u+O9ndYyMrEwkHIgQ0q2wd ShOwgshPXoVUKwthfNzvKONwzeAFMB/WIrMQ07++xq5v0FUVo/sgc6tq6 m5GHSeHLCoaS4vVXJtEtq498z/ZhGuIFk/4uHBRiiI3qUvUdmN0soroK/ Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194903" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194903" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133180" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 09/10] platform/x86/intel/ifs: add ABI documentation for IFS Date: Tue, 1 Mar 2022 11:54:56 -0800 Message-Id: <20220301195457.21152-10-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add the sysfs attributes in ABI/stable for In-Field Scan. Originally-by: Kyung Min Park Signed-off-by: Jithu Joseph Reviewed-by: Ashok Raj Reviewed-by: Tony Luck --- Documentation/ABI/stable/sysfs-driver-ifs | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/ABI/stable/sysfs-driver-ifs diff --git a/Documentation/ABI/stable/sysfs-driver-ifs b/Documentation/ABI/= stable/sysfs-driver-ifs new file mode 100644 index 000000000000..8b6b9472f57e --- /dev/null +++ b/Documentation/ABI/stable/sysfs-driver-ifs @@ -0,0 +1,85 @@ +What: /sys/devices/system/cpu/ifs/run_test +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: echo 1 to trigger ifs test for all online cores. + +What: /sys/devices/system/cpu/ifs/status +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: Global status. Shows the most serious status across + all cores (fail > untested > pass) + +What: /sys/devices/system/cpu/ifs/image_version +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: Version of loaded IFS binary image. + +What: /sys/devices/system/cpu/ifs/reload +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: echo 1 to reload IFS image. + +What: /sys/devices/system/cpu/ifs/cpu_pass_list +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: List of cpus which passed the IFS test. + +What: /sys/devices/system/cpu/ifs/cpu_fail_list +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: List of cpus which failed the IFS test. + +What: /sys/devices/system/cpu/ifs/cpu_untested_list +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: List of cpus which could not be tested. + +What: /sys/module/intel_ifs/parameters/noint +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: SAF tunable parameter that user can modify before + the scan run if they wish to override default value. + + When set, system interrupts are not allowed to interrupt an IFS. The + default state for this parameter is set. + +What: /sys/module/intel_ifs/parameters/retry +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: SAF tunable parameter that user can modify at + load time if they wish to override default value. + + Maximum retry counter when the test is not executed due to an + event such as interrupt. The default value is 5, it can be set to any + value from 1 to 20. + +What: /sys/devices/system/cpu/cpu#/ifs/run_test +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: IFS target core testing. echo 1 to trigger scan test on cpu#. + +What: /sys/devices/system/cpu/cpu#/ifs/status +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: The status of IFS test on a specific cpu#. It can be one of "= pass", "fail" + or "untested". + +What: /sys/devices/system/cpu/cpu#/ifs/details +Date: Feb 28, 2022 +KernelVersion: 5.18.0 +Contact: linux-kernel@vger.kernel.org +Description: The details file reports the hex value of the SCAN_STATUS MSR= . Note that + the error_code field may contain driver defined software code not defined + in the Intel SDM. + --=20 2.17.1 From nobody Tue Jun 23 17:20:52 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C4EAC433EF for ; Tue, 1 Mar 2022 19:56:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237548AbiCAT5W (ORCPT ); Tue, 1 Mar 2022 14:57:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237251AbiCAT4i (ORCPT ); Tue, 1 Mar 2022 14:56:38 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A26EC6CA59; Tue, 1 Mar 2022 11:55:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646164557; x=1677700557; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Fl34ROTLcd+eMllC9hzRVku13lC3x4b2npFrIe2SmFc=; b=dP3MGgq4pFzAEn5dJbLWWQmKXi4RCFGcDybzALGcz0OLyo2xBhVP08zI Xn6OTFKcjx9aWsdhMzztqnaXfL7y6CQfpJPnSfig20gJK6AoH7oMunKrV Bl2ZldRkmPJ3QuLLGSsX+SJ5QC9H+ZQBiG3XFxF4qSQ42ZZ06bdgLJkmQ Ib0F9gbvEJcY0jS7e/zL2kBD8tNd3Q6QgSge9Cy/7zHBkqJyY0xjcy8r0 KZyQuosQYn40gLr/rJeLFgcAlmtYHqNbkVPD71ppGsd/1pNeMrQZyp4VZ SlYoju/DY2cBeR4Oy2i4CPEMTHDWDVBfHrLtQA/tSPxlVF6jQGte0uuUr g==; X-IronPort-AV: E=McAfee;i="6200,9189,10273"; a="233194906" X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="233194906" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 X-IronPort-AV: E=Sophos;i="5.90,146,1643702400"; d="scan'208";a="630133183" Received: from coffy.sc.intel.com ([10.3.79.166]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2022 11:55:54 -0800 From: Jithu Joseph To: hdegoede@redhat.com, markgross@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, corbet@lwn.net, gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com, jithu.joseph@intel.com, ashok.raj@intel.com, tony.luck@intel.com, rostedt@goodmis.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org, patches@lists.linux.dev, ravi.v.shankar@intel.com Subject: [RFC 10/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Date: Tue, 1 Mar 2022 11:54:57 -0800 Message-Id: <20220301195457.21152-11-jithu.joseph@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220301195457.21152-1-jithu.joseph@intel.com> References: <20220301195457.21152-1-jithu.joseph@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Tony Luck Add tracing support which may be useful for debugging systems that fail to = complete In Field Scan tests. Signed-off-by: Tony Luck --- drivers/platform/x86/intel/ifs/core.c | 5 ++++ include/trace/events/ifs.h | 38 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 include/trace/events/ifs.h diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/i= ntel/ifs/core.c index c9ca385082e9..dec2a72eb95a 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -13,6 +13,9 @@ =20 #include "ifs.h" =20 +#define CREATE_TRACE_POINTS +#include + static enum cpuhp_state cpuhp_scan_state; struct ifs_params ifs_params; int cpu_sibl_ct; @@ -217,6 +220,8 @@ static int scan_test_worker(void *info) =20 rdmsrl(MSR_SCAN_STATUS, status.data); =20 + trace_ifs_status(activate, status); + /* Some cases can be retried, give up for others */ if (!can_restart(status)) break; diff --git a/include/trace/events/ifs.h b/include/trace/events/ifs.h new file mode 100644 index 000000000000..3c6ef33c7b3b --- /dev/null +++ b/include/trace/events/ifs.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ifs + +#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_IFS_H + +#include +#include + +TRACE_EVENT(ifs_status, + + TP_PROTO(union ifs_scan activate, union ifs_status status), + + TP_ARGS(activate, status), + + TP_STRUCT__entry( + __field( u8, start ) + __field( u8, stop ) + __field( u64, status ) + ), + + TP_fast_assign( + __entry->start =3D activate.start; + __entry->stop =3D activate.stop; + __entry->status =3D status.data; + ), + + TP_printk("start: %.2x, stop: %.2x, status: %llx", + __entry->start, + __entry->stop, + __entry->status) +); + +#endif /* _TRACE_IFS_H */ + +/* This part must be outside protection */ +#include --=20 2.17.1