All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/10] Introduce In Field Scan driver
@ 2022-04-07 19:13 Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS Jithu Joseph
                   ` (10 more replies)
  0 siblings, 11 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Note to Maintainers:
Requesting x86 Maintainers to take a look at patch1 as it
touches arch/x86 portion of the kernel.

Patch 2/10 - Adds Documentation. Requesting Documentation maintainer to review it.

Requesting Greg KH to review the sysfs changes added by patch8 (note that in
this revision we no longer touch /sys/devices/system/cpu as in previous version
and limit ourselves to only /sys/devices/platform/intel_ifs)

Patch10 - adds tracing support, requesting Steven Rostedt to review that.

Rest of the patches adds the IFS platform driver, requesting Platform driver maintainers
to review them.

This is the v2 version incorporating the review feedback from the RFC version [1]

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.
See References section to understand more about CPU core errors and how
and when they are encountered.

Intel will provide a firmware file containing the scan tests.  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.

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.

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:

/sys/devices/platform/intel_ifs/run_test
  Writing <cpu#> to this file will trigger a scan on that core
  e.g echo 5 > sys/devices/platform/intel_ifs/run_test will trigger
  scan on the core containing cpu5

Results of the tests are also provided in /sys:

/sys/devices/platform/intel_ifs/status
  Status (pass/fail/untested) for the last test

/sys/devices/platform/intel_ifs/details
  Hex value of the SCAN_STATUS MSR for the most recent test.
  Note that the error_code field may contain driver
  defined software code not defined in the Intel SDM.

Driver design choices:

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.

References
Links to a few articles, papers, presentation  [2] [3] [4] [5] which
talk about cpu core errors encountered in the wild which could be
relevant to this work.

[1] https://lore.kernel.org/lkml/20220301195457.21152-1-jithu.joseph@intel.com/
[2] https://sigops.org/s/conferences/hotos/2021/papers/hotos21-s01-hochschild.pdf
[3] https://www.youtube.com/watch?v=QMF3rqhjYuM
[4] https://engineering.fb.com/2021/02/23/data-infrastructure/silent-data-corruption/
[5] https://www.theregister.com/2021/06/04/google_chip_flaws/

Changes since RFC:
 - Renamed collect_cpu_info_early() - >cpu_collect_info_early() (Patch 1; GregKH)
 - Refactored collect_cpu_info_early(), cpu_signatures_match() from
    microcode specific file to intel-generic file (Patch 1; Borislav Petkov)
 - Keep the same platform driver object through-out the life-time of
   the driver (patch 4; Dan Wiliiams)
 - Replace platform_device_register_simple() with platform_device_alloc/add()
   so that sysfs files are available instantateously (patch 4;  Dan Wiliiams)
 - Move IFS binary loading to driver_probe context from module_init
   context (patch4;  Dan Wiliiams)
 - Remove the version check during scan image load so as to allow user
   to move to any IFS binary (Patch 4)
 - Replace pr_* macros with dev_* macros (Patches 3-9;  Dan Wiliiams)
 - Replace percpu kthreads with work_queue worker threads  (Patch 7; Dan Wiliiams)
 - Remove hotplug callbacks which are no longer required due to above
   change (Patch 7;  Dan Wiliiams)
 - Remove percpu ifs_state data structure as it is no longer needed (Patch 7)
 - Refactored test logic into a separate runtest.c file (Patch 7, Tony Luck)
 - Moved sysfs interface from /sys/devices/system/cpu/ifs and
   /sys/devices/system/cpu/cpu#/ifs to /sys/devices/platform/intel_ifs
 - Done away with global/percpu testing interfaces. To trigger a test,
   there is a single run_test file which takes cpu_number as input.
   This hugely reduces the number of sysfs file needed. Userspace can iterate
   over all the cpus to achevie global testing (Patch8;  Dan Wiliiams)
 - Remove the reload sysfs interface for IFS binary loading. Since binary loading
   is done from the probe context, reloading can be acheieved using driver
   bind sysfs interface (Patch 8; Dan Williams)
 - Updated the Documentation/ ABI files to reflect the sysfs changes
 - Change trace event structure field ordering (patch 10; Steven Rostedt)
 - misc changes
     - adding enum type for ifs_status_err_code
     - replace sprintf with sysfs_emit in sysfs.c

Jithu Joseph (8):
  x86/microcode/intel: expose collect_cpu_info_early() for IFS
  platform/x86/intel/ifs: Add driver for In-Field Scan
  platform/x86/intel/ifs: Load IFS Image
  platform/x86/intel/ifs: Check IFS Image sanity
  platform/x86/intel/ifs: Authenticate and copy to secured memory
  platform/x86/intel/ifs: Add scan test support
  platform/x86/intel/ifs: Add IFS sysfs interface
  platform/x86/intel/ifs: add ABI documentation for IFS

Tony Luck (2):
  Documentation: In-Field Scan
  trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
    operations

 .../ABI/testing/sysfs-platform-intel-ifs      |  54 ++++
 Documentation/x86/ifs.rst                     | 114 +++++++
 Documentation/x86/index.rst                   |   1 +
 MAINTAINERS                                   |   7 +
 arch/x86/include/asm/microcode_intel.h        |   4 +
 arch/x86/kernel/cpu/intel.c                   |  47 +++
 arch/x86/kernel/cpu/microcode/intel.c         |  55 +---
 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       |   3 +
 drivers/platform/x86/intel/ifs/core.c         | 121 +++++++
 drivers/platform/x86/intel/ifs/ifs.h          | 137 ++++++++
 drivers/platform/x86/intel/ifs/load.c         | 285 +++++++++++++++++
 drivers/platform/x86/intel/ifs/runtest.c      | 300 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/sysfs.c        | 139 ++++++++
 include/trace/events/intel_ifs.h              |  38 +++
 17 files changed, 1266 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
 create mode 100644 Documentation/x86/ifs.rst
 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
 create mode 100644 drivers/platform/x86/intel/ifs/load.c
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
 create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
 create mode 100644 include/trace/events/intel_ifs.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-08  8:34   ` Borislav Petkov
  2022-04-07 19:13 ` [PATCH v2 02/10] Documentation: In-Field Scan Jithu Joseph
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs. In support of an IFS driver to trigger loading, validation, and
running of these tests blobs, export cpu_signatures_match() and
collect_cpu_info_early().

Rename collect_cpu_info_early() to cpu_collect_info_early()
to keep a more appropriate prefix.

Per Boris [1], move these helpers to a generic location.

No functional change intended.

Link: https://lore.kernel.org/lkml/Yh9HKhESkcUIYzSr@nazgul.tnic/ [1]

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 arch/x86/include/asm/microcode_intel.h |  4 ++
 arch/x86/kernel/cpu/intel.c            | 47 ++++++++++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c  | 55 +++-----------------------
 3 files changed, 56 insertions(+), 50 deletions(-)

diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h
index d85a07d7154f..cf0fd1d712b4 100644
--- a/arch/x86/include/asm/microcode_intel.h
+++ b/arch/x86/include/asm/microcode_intel.h
@@ -68,6 +68,10 @@ static inline u32 intel_get_microcode_revision(void)
 	return rev;
 }
 
+int cpu_collect_info_early(struct ucode_cpu_info *uci);
+bool cpu_signatures_match(unsigned int s1, unsigned int p1,
+			  unsigned int s2, unsigned int p2);
+
 #ifdef CONFIG_MICROCODE_INTEL
 extern void __init load_ucode_intel_bsp(void);
 extern void load_ucode_intel_ap(void);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 8321c43554a1..2008c8267fd3 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,6 +181,53 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 	return false;
 }
 
+bool cpu_signatures_match(unsigned int s1, unsigned int p1,
+			  unsigned int s2, unsigned int p2)
+{
+	if (s1 != s2)
+		return false;
+
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
+
+	/* ... or they intersect. */
+	return p1 & p2;
+}
+EXPORT_SYMBOL_GPL(cpu_signatures_match);
+
+int cpu_collect_info_early(struct ucode_cpu_info *uci)
+{
+	unsigned int val[2];
+	unsigned int family, model;
+	struct cpu_signature csig = { 0 };
+	unsigned int eax, ebx, ecx, edx;
+
+	memset(uci, 0, sizeof(*uci));
+
+	eax = 0x00000001;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	csig.sig = eax;
+
+	family = x86_family(eax);
+	model  = x86_model(eax);
+
+	if ((model >= 5) || (family > 6)) {
+		/* get processor flags from MSR 0x17 */
+		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		csig.pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	csig.rev = intel_get_microcode_revision();
+
+	uci->cpu_sig = csig;
+	uci->valid = 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpu_collect_info_early);
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index d28a9f8f3fec..7220327a6b1f 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 	return patch;
 }
 
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-	unsigned int val[2];
-	unsigned int family, model;
-	struct cpu_signature csig = { 0 };
-	unsigned int eax, ebx, ecx, edx;
-
-	memset(uci, 0, sizeof(*uci));
-
-	eax = 0x00000001;
-	ecx = 0;
-	native_cpuid(&eax, &ebx, &ecx, &edx);
-	csig.sig = eax;
-
-	family = x86_family(eax);
-	model  = x86_model(eax);
-
-	if ((model >= 5) || (family > 6)) {
-		/* get processor flags from MSR 0x17 */
-		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		csig.pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	csig.rev = intel_get_microcode_revision();
-
-	uci->cpu_sig = csig;
-	uci->valid = 1;
-
-	return 0;
-}
-
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
 		return;
 	}
 
-	collect_cpu_info_early(&uci);
+	cpu_collect_info_early(&uci);
 
 	sig	= uci.cpu_sig.sig;
 	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
 	struct ucode_cpu_info uci;
 
 	if (delay_ucode_info) {
-		collect_cpu_info_early(&uci);
+		cpu_collect_info_early(&uci);
 		print_ucode_info(&uci, current_mc_date);
 		delay_ucode_info = 0;
 	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
 	if (!(cp.data && cp.size))
 		return 0;
 
-	collect_cpu_info_early(&uci);
+	cpu_collect_info_early(&uci);
 
 	scan_microcode(cp.data, cp.size, &uci, true);
 
@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 	if (!(cp.data && cp.size))
 		return NULL;
 
-	collect_cpu_info_early(uci);
+	cpu_collect_info_early(uci);
 
 	return scan_microcode(cp.data, cp.size, uci, false);
 }
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
 	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
 
-	collect_cpu_info_early(&uci);
+	cpu_collect_info_early(&uci);
 
 	p = find_patch(&uci);
 	if (!p)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 02/10] Documentation: In-Field Scan
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 03/10] platform/x86/intel/ifs: Add driver for " Jithu Joseph
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Tony Luck <tony.luck@intel.com>

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.

The full  github location for distributing the IFS images is
still being decided. So just a placeholder included for now
in the documentation.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 Documentation/x86/ifs.rst   | 114 ++++++++++++++++++++++++++++++++++++
 Documentation/x86/index.rst |   1 +
 2 files changed, 115 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..f8a1b1f57de8
--- /dev/null
+++ b/Documentation/x86/ifs.rst
@@ -0,0 +1,114 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+In-Field Scan
+=============
+
+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 provides a firmware file containing the scan tests via
+github [#f1]_.  Similar to microcode there is a separate file for each
+family-model-stepping.
+
+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 by triggering a driver bind as below::
+
+  # echo "intel_ifs" > /sys/bus/platform/drivers/intel_ifs/unbind
+  # echo "intel_ifs" > /sys/bus/platform/drivers/intel_ifs/bind
+
+Similar to microcode, the current version of the scan tests is stored
+in a fixed location: /lib/firmware/intel/ifs/family-model-stepping.scan
+
+Triggering tests
+----------------
+
+Tests are run by the driver 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. The driver makes the value of this MSR visible to applications
+via the "details" file (see below). Interrupted tests may be restarted.
+
+The IFS driver provides sysfs interfaces via /sys/devices/platform/intel_ifs/
+to control execution:
+
+Test a specific core::
+
+  # echo <cpu#> > /sys/devices/platform/intel_ifs/run_test
+
+when HT is enabled any of the sibling cpu# can be specified to test its
+corresponding physical core. Since the tests are per physical core, the
+result of testing any thread is same. It is only necessary to test one
+thread.
+
+For e.g. to test core corresponding to cpu5
+
+  # echo 5 > /sys/devices/platform/intel_ifs/run_test
+
+Results of the last test is provided in /sys::
+
+  $ cat /sys/devices/platform/intel_ifs/status
+  pass
+
+Status can be one of pass, fail, untested
+
+Additional details of the last test is provided by the details file::
+
+  $ cat /sys/devices/platform/intel_ifs/details
+  0x8081
+
+The details file reports the hex value of the SCAN_STATUS MSR.
+Hardware defined error codes are documented in volume 4 of the Intel
+Software Developer's Manual but the error_code field may contain one of
+the following driver defined software codes:
+
++------+--------------------+
+| 0xFD | Software timeout   |
++------+--------------------+
+| 0xFE | Partial completion |
++------+--------------------+
+
+Driver design choices
+---------------------
+
+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/<parameter_name>). The parameters are as
+described below.
+
+1. noirq: When set (default), system interrupts are not allowed to interrupt an ifs scan.
+Unsetting this might be helpful to improve the irq latency during the test.
+
+2. retry: Maximum retry counter when the test chunk is not executed due to an event such as
+interrupt. The default value for this parameter is 5, it accepts a value between 1 and 20.
+If test status continuously reports as "untested", increasing the value might help.
+
+.. [#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
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 03/10] platform/x86/intel/ifs: Add driver for In-Field Scan
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 02/10] Documentation: In-Field Scan Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image Jithu Joseph
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Cloud Service Providers that operate fleets of servers have reported
[1] occasions where they can detect that a CPU has gone bad due to
effects like electromigration, or isolated manufacturing defects.
However, that detection method is A/B testing seemingly random
application failures looking for a pattern. In-Field Scan (IFS) is
a driver for a platform capability to load a crafted 'scan image'
to run targeted low level diagnostics outside of the CPU's architectural
error detection capabilities.

[1]: https://www.youtube.com/watch?v=QMF3rqhjYuM

IFS will be available in some server SKUs starting with Sapphire Rapids.

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.

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 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 |  3 ++
 drivers/platform/x86/intel/ifs/core.c   | 44 +++++++++++++++++++++++++
 drivers/platform/x86/intel/ifs/ifs.h    | 11 +++++++
 7 files changed, 76 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
 
+INTEL IN FIELD SCAN (IFS) DRIVER
+M:	Jithu Joseph <jithu.joseph@intel.com>
+R:	Ashok Raj <ashok.raj@intel.com>
+R:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+F:	drivers/platform/x86/intel/ifs
+
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 8e65086bb6c8..7339e7daf0a1 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -4,6 +4,7 @@
 #
 
 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/intel/Makefile
index 35f2066578b2..bd7f2ef5e767 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
+obj-$(CONFIG_INTEL_IFS)			+= ifs/
 obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
 obj-$(CONFIG_INTEL_CHT_INT33FE)		+= int33fe/
 obj-$(CONFIG_INTEL_SKL_INT3472)		+= 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..c44305dff542
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_IFS)			+= intel_ifs.o
+
+intel_ifs-objs				:= core.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
new file mode 100644
index 000000000000..87956623208f
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/module.h>
+#include <asm/cpu_device_id.h>
+
+#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 = {
+	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 = 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)
+{
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel In Field Scan (IFS) driver");
+module_init(ifs_init);
+module_exit(ifs_exit);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
new file mode 100644
index 000000000000..bb25a4cd3af6
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Intel Corporation. */
+
+#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
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (2 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 03/10] platform/x86/intel/ifs: Add driver for " Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-08  5:02   ` Greg KH
  2022-04-08  5:04   ` Greg KH
  2022-04-07 19:13 ` [PATCH v2 05/10] platform/x86/intel/ifs: Check IFS Image sanity Jithu Joseph
                   ` (6 subsequent siblings)
  10 siblings, 2 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

IFS uses a scan image format that shares the same header as
microcode updates and deployment approach for these images mirrors
that of microcode update. Specifically, enable images to be deployed
relative to a static symlink in /lib/firmware and then load
into kernel memory via request_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

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |  2 +-
 drivers/platform/x86/intel/ifs/core.c   | 62 ++++++++++++++++++++
 drivers/platform/x86/intel/ifs/ifs.h    | 15 +++++
 drivers/platform/x86/intel/ifs/load.c   | 76 +++++++++++++++++++++++++
 4 files changed, 154 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 c44305dff542..b69d026ca9da 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)			+= intel_ifs.o
 
-intel_ifs-objs				:= core.o
+intel_ifs-objs				:= core.o load.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 87956623208f..716f333a064b 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -2,10 +2,14 @@
 /* Copyright(c) 2022 Intel Corporation. */
 
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <asm/cpu_device_id.h>
 
 #include "ifs.h"
 
+struct platform_device *ifs_pdev;
+struct ifs_binary ifs_binary;
+
 #define X86_MATCH(model)					\
 	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6,		\
 		INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL)
@@ -17,10 +21,39 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
 
 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 
+static int ifs_probe(struct platform_device *pdev)
+{
+	/* Load IFS binary to BIOS reserved memory area */
+	if (load_ifs_binary()) {
+		ifs_binary.loaded = false;
+		dev_err(&ifs_pdev->dev, "Failed to Load IFS binary. Try reloading.\n");
+		return -EPERM;
+	}
+	ifs_binary.loaded = true;
+	return 0;
+}
+
+static int ifs_remove(struct platform_device *pdev)
+{
+	ifs_binary.loaded = false;
+	ifs_binary.loaded_version = 0;
+	/* No OS managed memory to free */
+	return 0;
+}
+
+static struct platform_driver ifs_driver = {
+	.probe = ifs_probe,
+	.remove = ifs_remove,
+	.driver = {
+		.name = "intel_ifs",
+	},
+};
+
 static int __init ifs_init(void)
 {
 	const struct x86_cpu_id *m;
 	u64 ia32_core_caps;
+	int ret;
 
 	/* ifs capability check */
 	m = x86_match_cpu(ifs_cpu_ids);
@@ -31,11 +64,40 @@ static int __init ifs_init(void)
 	if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_INTEGRITY))
 		return -ENODEV;
 
+	ifs_binary.loaded = false;
+
+	ret = platform_driver_register(&ifs_driver);
+	if (ret) {
+		pr_err("intel_ifs: platform driver register failed\n");
+		return ret;
+	}
+
+	ifs_pdev = platform_device_alloc("intel_ifs", -1);
+	if (!ifs_pdev) {
+		pr_err("intel_ifs: platform device allocation failed\n");
+		ret = -ENOMEM;
+		goto drv_unreg;
+	}
+
+	ret = platform_device_add(ifs_pdev);
+	if (ret) {
+		pr_err("intel_ifs: platform device add failed\n");
+		platform_device_put(ifs_pdev);
+		goto drv_unreg;
+	}
+
 	return 0;
+
+drv_unreg:
+	platform_driver_unregister(&ifs_driver);
+	return ret;
+
 }
 
 static void __exit ifs_exit(void)
 {
+	platform_device_unregister(ifs_pdev);
+	platform_driver_unregister(&ifs_driver);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index bb25a4cd3af6..e1c9c16cbadb 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -8,4 +8,19 @@
 #define MSR_IA32_CORE_CAPS_INTEGRITY_BIT	2
 #define MSR_IA32_CORE_CAPS_INTEGRITY		BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT)
 
+#define IFS_BLOB_REV_ERR_INJ			BIT(30)
+#define IFS_BLOB_REV_DEBUG			BIT(31)
+/**
+ * struct ifs_binary - attributes related to test binary
+ * @loaded_version: stores the currently loaded ifs image version.
+ * @loaded: If a valid test binary has been loaded into the memory
+ */
+struct ifs_binary {
+	int loaded_version;
+	bool loaded;
+};
+
+int load_ifs_binary(void);
+extern struct platform_device *ifs_pdev;
+extern struct ifs_binary ifs_binary;
 #endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
new file mode 100644
index 000000000000..a1be4d6558a1
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+
+#include "ifs.h"
+static const char *ifs_path = "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 header */
+static u64 ifs_hash_ptr;			/* Address of ifs metadata (hash) */
+
+static const struct firmware *load_binary(const char *path)
+{
+	const struct firmware *fw;
+	int err;
+
+	err = request_firmware_direct(&fw, path, &ifs_pdev->dev);
+	if (err) {
+		dev_err(&ifs_pdev->dev, "ifs file %s load failed\n", path);
+		goto out;
+	}
+
+out:
+
+	return fw;
+}
+
+static void check_binary_flags(struct ifs_header *new_image_ptr)
+{
+	if (new_image_ptr->blob_revision & IFS_BLOB_REV_DEBUG)
+		dev_warn(&ifs_pdev->dev, "Debug flag is set in the binary loaded\n");
+	if (new_image_ptr->blob_revision & IFS_BLOB_REV_ERR_INJ)
+		dev_warn(&ifs_pdev->dev, "Error Injection flag is set in the binary loaded\n");
+}
+
+/*
+ * Load ifs image. Before loading ifs module, the ifs image must be located
+ * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
+ */
+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 = load_binary(scan_path);
+	if (!scan_fw)
+		return -ENOENT;
+
+	ifs_header_ptr = (struct ifs_header *)scan_fw->data;
+	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
+
+	check_binary_flags(ifs_header_ptr);
+	release_firmware(scan_fw);
+
+	return ret;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 05/10] platform/x86/intel/ifs: Check IFS Image sanity
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (3 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Jithu Joseph
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

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.

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 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/intel/ifs/load.c
index a1be4d6558a1..8f2735775f5b 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,6 +3,7 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <asm/microcode_intel.h>
 
 #include "ifs.h"
 static const char *ifs_path = "intel/ifs/";
@@ -24,6 +25,67 @@ struct ifs_header {
 #define IFS_HEADER_SIZE	(sizeof(struct ifs_header))
 static struct ifs_header *ifs_header_ptr;	/* pointer to the ifs image header */
 static u64 ifs_hash_ptr;			/* Address of ifs metadata (hash) */
+static int ifs_sanity_check(void *mc)
+{
+	struct microcode_header_intel *mc_header = mc;
+	unsigned long total_size, data_size;
+	u32 sum, i;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+
+	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
+		dev_err(&ifs_pdev->dev, "bad ifs data file size.\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		dev_err(&ifs_pdev->dev, "invalid/unknown ifs update format.\n");
+		return -EINVAL;
+	}
+
+	sum = 0;
+	i = total_size / sizeof(u32);
+	while (i--)
+		sum += ((u32 *)mc)[i];
+
+	if (sum) {
+		dev_err(&ifs_pdev->dev, "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 = (struct microcode_header_intel *)mc;
+	mc_size = get_totalsize(shdr);
+
+	if (!mc_size || ifs_sanity_check(shdr) < 0) {
+		dev_err(&ifs_pdev->dev, "ifs sanity check failure\n");
+		return false;
+	}
+
+	if (!cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
+		dev_err(&ifs_pdev->dev, "ifs signature, pf not matching\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool ifs_image_sanity_check(void *data)
+{
+	struct ucode_cpu_info uci;
+
+	cpu_collect_info_early(&uci);
+
+	return find_ifs_matching_signature(&uci, data);
+}
 
 static const struct firmware *load_binary(const char *path)
 {
@@ -36,6 +98,11 @@ static const struct firmware *load_binary(const char *path)
 		goto out;
 	}
 
+	if (!ifs_image_sanity_check((void *)fw->data)) {
+		dev_err(&ifs_pdev->dev, "ifs header sanity check failed\n");
+		release_firmware(fw);
+		fw = NULL;
+	}
 out:
 
 	return fw;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (4 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 05/10] platform/x86/intel/ifs: Check IFS Image sanity Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 07/10] platform/x86/intel/ifs: Add scan test support Jithu Joseph
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

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.

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 drivers/platform/x86/intel/ifs/ifs.h  |  33 ++++++
 drivers/platform/x86/intel/ifs/load.c | 142 ++++++++++++++++++++++++++
 2 files changed, 175 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index e1c9c16cbadb..4d12f8e71c67 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -10,13 +10,46 @@
 
 #define IFS_BLOB_REV_ERR_INJ			BIT(30)
 #define IFS_BLOB_REV_DEBUG			BIT(31)
+#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_binary - attributes related to test binary
  * @loaded_version: stores the currently loaded ifs image version.
+ * @valid_chunks: number of chunks which could be validated.
  * @loaded: If a valid test binary has been loaded into the memory
  */
 struct ifs_binary {
 	int loaded_version;
+	int valid_chunks;
 	bool loaded;
 };
 
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index 8f2735775f5b..8778be87fee6 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,10 +3,13 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <asm/microcode_intel.h>
 
 #include "ifs.h"
+
 static const char *ifs_path = "intel/ifs/";
+static bool ifs_loading_error;	/* error occurred during ifs hashes/chunk authentication.*/
 
 struct ifs_header {
 	u32 header_ver;
@@ -25,6 +28,144 @@ struct ifs_header {
 #define IFS_HEADER_SIZE	(sizeof(struct ifs_header))
 static struct ifs_header *ifs_header_ptr;	/* pointer to the ifs image header */
 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[] = {
+	"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[] = {
+	"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 value"
+};
+
+/*
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must 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_AUTHENTICATE_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 = hashes_status.num_chunks;
+	chunk_size = hashes_status.chunk_size * 1024;
+	err_code = hashes_status.error_code;
+
+	if (!hashes_status.valid) {
+		ifs_loading_error = true;
+		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
+			dev_err(&ifs_pdev->dev,
+				"invalid error code 0x%x for hash copy\n", err_code);
+			return -EINVAL;
+		}
+		dev_err(&ifs_pdev->dev, "Hash copy error : %s", scan_hash_status[err_code]);
+		return -ENODEV;
+	}
+	dev_info(&ifs_pdev->dev, "the total chunk number: %d\n", num_chunks);
+
+	/* base linear address to the scan data */
+	base = ifs_test_image_ptr;
+
+	/* scan data authentication and copy chunks to secured memory */
+	for (i = 0; i < num_chunks; i++) {
+		linear_addr = base + i * chunk_size;
+		linear_addr |= i;
+
+		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
+		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
+
+		ifs_binary.valid_chunks = chunk_status.valid_chunks;
+		err_code = chunk_status.error_code;
+
+		if (err_code) {
+			ifs_loading_error = true;
+			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
+				dev_err(&ifs_pdev->dev,
+					"invalid error code 0x%x for authentication\n", err_code);
+				return -EINVAL;
+			}
+			dev_err(&ifs_pdev->dev, "Chunk authentication error %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 secured memory
+ * and proceed the authentication for the next chunk.
+ */
+static int scan_chunks_sanity_check(void)
+{
+	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
+	bool *package_authenticated;
+	char *test_ptr;
+
+	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
+	if (!package_authenticated)
+		return ret;
+
+	metadata_size = ifs_header_ptr->metadata_size;
+
+	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
+	if (metadata_size == 0)
+		metadata_size = 2000;
+
+	/* Scan chunk start must be 256 byte aligned */
+	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
+		dev_err(&ifs_pdev->dev,
+			"Scan pattern offset within the binary is not 256 byte aligned\n");
+		return -EINVAL;
+	}
+
+	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
+
+	ifs_test_image_ptr = (u64)test_ptr;
+	ifs_binary.loaded_version = ifs_header_ptr->blob_revision;
+
+	/* copy the scan hash and authenticate per package */
+	cpus_read_lock();
+	for_each_online_cpu(cpu) {
+		curr_pkg = topology_physical_package_id(cpu);
+		if (package_authenticated[curr_pkg])
+			continue;
+		package_authenticated[curr_pkg] = 1;
+		ret = smp_call_function_single(cpu, (void *)copy_hashes_authenticate_chunks,
+					       NULL, 1);
+		if (ret || ifs_loading_error) {
+			ret = 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 = mc;
@@ -137,6 +278,7 @@ int load_ifs_binary(void)
 	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
 
 	check_binary_flags(ifs_header_ptr);
+	ret = scan_chunks_sanity_check();
 	release_firmware(scan_fw);
 
 	return ret;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 07/10] platform/x86/intel/ifs: Add scan test support
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (5 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-07 19:13 ` [PATCH v2 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Jithu Joseph
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

In a core, the scan engine is shared between sibling cpus.

When a Scan test (for a particular core) is triggered by the user,
worker threads for each sibling cpus(belonging to that core) are
queued to execute the scan test function in the Workqueue context.

All the siblings rendezvous before the test execution. 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.

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/core.c    |  14 ++
 drivers/platform/x86/intel/ifs/ifs.h     |  76 ++++++
 drivers/platform/x86/intel/ifs/runtest.c | 295 +++++++++++++++++++++++
 4 files changed, 386 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c

diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
index b69d026ca9da..d5905e5d2de8 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)			+= intel_ifs.o
 
-intel_ifs-objs				:= core.o load.o
+intel_ifs-objs				:= core.o load.o runtest.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 716f333a064b..95847e00038b 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -9,6 +9,9 @@
 
 struct platform_device *ifs_pdev;
 struct ifs_binary ifs_binary;
+struct ifs_test ifs_test;
+
+struct workqueue_struct *ifs_wq;
 
 #define X86_MATCH(model)					\
 	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6,		\
@@ -86,6 +89,15 @@ static int __init ifs_init(void)
 		goto drv_unreg;
 	}
 
+	/* Flags are to keep all the sibling cpu worker threads (of a core) in close sync */
+	ifs_wq = alloc_workqueue("intel_ifs", (WQ_HIGHPRI | WQ_CPU_INTENSIVE), 1);
+	if (!ifs_wq) {
+		dev_err(&ifs_pdev->dev, "Failed to create work queue\n");
+		platform_device_unregister(ifs_pdev);
+		ret = -ENOMEM;
+		goto drv_unreg;
+	}
+	init_completion(&ifs_test.test_thread_done);
 	return 0;
 
 drv_unreg:
@@ -96,6 +108,8 @@ static int __init ifs_init(void)
 
 static void __exit ifs_exit(void)
 {
+	flush_workqueue(ifs_wq);
+	destroy_workqueue(ifs_wq);
 	platform_device_unregister(ifs_pdev);
 	platform_driver_unregister(&ifs_driver);
 }
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 4d12f8e71c67..93cc1af4aea0 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -14,6 +14,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_NOT_TESTED				0
+#define SCAN_TEST_PASS				1
+#define SCAN_TEST_FAIL				2
+#define SPINUNIT				100
+#define THREAD_WAIT				5
 
 /* MSR_SCAN_HASHES_STATUS bit fields */
 union ifs_scan_hashes_status {
@@ -41,6 +48,53 @@ union ifs_chunks_auth_status {
 	};
 };
 
+/* 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;
+	};
+};
+
+enum ifs_status_err_code {
+	IFS_NO_ERROR = 0,
+	IFS_OTHER_THREAD_COULD_NOT_JOIN,
+	IFS_INTERRUPTED_BEFORE_RENDEZVOUS,
+	IFS_POWER_MGMT_INADEQUATE_FOR_SCAN,
+	IFS_INVALID_CHUNK_RANGE,
+	IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS,
+	IFS_CORE_NOT_CAPABLE_CURRENTLY,
+	IFS_UNASSIGNED_ERROR_CODE,
+	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT,
+	IFS_INTERRUPTED_DURING_EXECUTION,
+};
+
+/*
+ * Driver populated error-codes
+ * 0xFD: Test timed out before completing all the chunks.
+ * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
+ */
+#define IFS_SW_TIMEOUT				0xFD
+#define IFS_SW_PARTIAL_COMPLETION		0xFE
+
 /**
  * struct ifs_binary - attributes related to test binary
  * @loaded_version: stores the currently loaded ifs image version.
@@ -53,7 +107,29 @@ struct ifs_binary {
 	bool loaded;
 };
 
+/**
+ * struct ifs_test - various parameters pertaining to a test
+ * @status: it holds simple status pass/fail/untested
+ * @cpu_sibl_ct: number of h/w sibling threads for the test cpu
+ * @siblings_in: sibling count for joining rendezvous
+ * @siblings_out: sibling count for exiting rendezvous
+ * @scan_details: opaque scan status code from h/w
+ * @test_thread_done: set when scan are done for all siblings threads
+ */
+struct ifs_test {
+	int status;
+	int cpu_sibl_ct;
+	atomic_t siblings_in;
+	atomic_t siblings_out;
+	u64 scan_details;
+	struct completion test_thread_done;
+};
+
 int load_ifs_binary(void);
+int do_core_test(int cpu);
 extern struct platform_device *ifs_pdev;
 extern struct ifs_binary ifs_binary;
+extern struct ifs_test ifs_test;
+extern struct workqueue_struct *ifs_wq;
+extern bool ifs_disabled;
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
new file mode 100644
index 000000000000..f9c98d84183f
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/nmi.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+bool ifs_disabled;
+
+static int ifs_retry_set(const char *val, const struct kernel_param *kp);
+static const struct kernel_param_ops ifs_retry_ops = {
+	.set = ifs_retry_set,
+	.get = param_get_int,
+};
+
+static int retry = 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 noirq = 1;
+module_param(noirq, bool, 0644);
+MODULE_PARM_DESC(noirq, "Option to enable/disable interrupt during test");
+
+static int ifs_retry_set(const char *val, const struct kernel_param *kp)
+{
+	int var = 0;
+
+	if (kstrtoint(val, 0, &var)) {
+		dev_warn(&ifs_pdev->dev, "unable to parse retry\n");
+		return -EINVAL;
+	}
+
+	/* validate retry value for sanity */
+	if (var < 1 || var > 20) {
+		dev_warn(&ifs_pdev->dev, "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[] = {
+	[IFS_NO_ERROR] = "SCAN no error",
+	[IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.",
+	[IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.",
+	[IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] =
+	"Core Abort SCAN Response due to power management condition.",
+	[IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range",
+	[IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.",
+	[IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently",
+	[IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7",
+	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
+	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
+	[IFS_INTERRUPTED_DURING_EXECUTION] = "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))
+		dev_info(&ifs_pdev->dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 scan_test_status[status.error_code]);
+	else if (status.error_code == IFS_SW_TIMEOUT)
+		dev_info(&ifs_pdev->dev, "CPU(s) %*pbl: software timeout during scan\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	else if (status.error_code == IFS_SW_PARTIAL_COMPLETION)
+		dev_info(&ifs_pdev->dev, "CPU(s) %*pbl: %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 "Not all scan chunks were executed. Maximum forward progress retries exceeded");
+	else
+		dev_info(&ifs_pdev->dev, "CPU(s) %*pbl: SCAN unknown status %llx\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)), status.data);
+}
+
+static void message_fail(int cpu, union ifs_status status)
+{
+	if (status.control_error) {
+		dev_err(&ifs_pdev->dev, "CPU(s) %*pbl: scan failed. %s\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			"Suggest reload scan file: # echo 1 > /sys/devices/platform/intel_ifs/reload");
+	}
+	if (status.signature_error) {
+		dev_err(&ifs_pdev->dev, "CPU(s) %*pbl: test signature incorrect. %s\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			"Retry once to check if problem is transient");
+	}
+}
+
+static bool can_restart(union ifs_status status)
+{
+	enum ifs_status_err_code err_code = status.error_code;
+
+	/* Signature for chunk is bad, or scan test failed */
+	if (status.signature_error || status.control_error)
+		return false;
+
+	switch (err_code) {
+	case IFS_NO_ERROR:
+	case IFS_OTHER_THREAD_COULD_NOT_JOIN:
+	case IFS_INTERRUPTED_BEFORE_RENDEZVOUS:
+	case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN:
+	case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT:
+	case IFS_INTERRUPTED_DURING_EXECUTION:
+		return true;
+	case IFS_INVALID_CHUNK_RANGE:
+	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
+	case IFS_CORE_NOT_CAPABLE_CURRENTLY:
+	case IFS_UNASSIGNED_ERROR_CODE:
+		break;
+	}
+	return false;
+}
+
+static bool wait_for_siblings(atomic_t *t, long long timeout)
+{
+	atomic_inc(t);
+	while (atomic_read(t) < ifs_test.cpu_sibl_ct) {
+		if (timeout < SPINUNIT) {
+			dev_err(&ifs_pdev->dev,
+				"Timeout while waiting for CPUs rendezvous, remaining: %d\n",
+				ifs_test.cpu_sibl_ct - atomic_read(t));
+			return false;
+		}
+
+		ndelay(SPINUNIT);
+		timeout -= SPINUNIT;
+
+		touch_nmi_watchdog();
+	}
+
+	return true;
+}
+
+/*
+ * When a Scan test (for a particular core) is triggered by the user, worker threads
+ * for each sibling cpus(belonging to that core) are queued to execute this function in
+ * the Workqueue (ifs_wq) context.
+ * Wait for the sibling thread to join before the execution.
+ * Execute the scan test by running wrmsr(MSR_ACTIVATE_SCAN).
+ */
+static void ifs_work_func(struct work_struct *work)
+{
+	int cpu = smp_processor_id();
+	union ifs_scan activate;
+	union ifs_status status;
+	unsigned long timeout;
+	int retries;
+	u32 first;
+
+	activate.rsvd = 0;
+	activate.delay = msec_to_tsc(THREAD_WAIT);
+	activate.sigmce = 0;
+
+	/*
+	 * Need to get (and keep) the threads on this core executing close together
+	 * 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 = cpumask_first(topology_sibling_cpumask(cpu));
+	if (!wait_for_siblings(&ifs_test.siblings_in, NSEC_PER_SEC)) {
+		preempt_enable();
+		dev_err(&ifs_pdev->dev, "cpu %d sibling did not join rendezvous\n", cpu);
+		goto out;
+	}
+
+	activate.start = 0;
+	activate.stop = ifs_binary.valid_chunks - 1;
+	timeout = jiffies + HZ / 2;
+	retries = retry;
+
+	while (activate.start <= activate.stop) {
+		if (time_after(jiffies, timeout)) {
+			status.error_code = IFS_SW_TIMEOUT;
+			break;
+		}
+
+		if (noirq)
+			local_irq_disable();
+		/* scan start */
+		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
+
+		if (noirq)
+			local_irq_enable();
+
+		/*
+		 * All logical CPUs on this core are now running IFS test. When it completes
+		 * execution or is interrupted, the following RDMSR gets the scan status.
+		 */
+
+		rdmsrl(MSR_SCAN_STATUS, status.data);
+
+		/* Some cases can be retried, give up for others */
+		if (!can_restart(status))
+			break;
+
+		if (status.chunk_num == activate.start) {
+			/* Check for forward progress */
+			if (retries-- == 0) {
+				if (status.error_code == IFS_NO_ERROR)
+					status.error_code = IFS_SW_PARTIAL_COMPLETION;
+				break;
+			}
+		} else {
+			retries = retry;
+			activate.start = status.chunk_num;
+		}
+	}
+
+	preempt_enable();
+
+	if (cpu == first) {
+		/* Update status for this core */
+		ifs_test.scan_details = status.data;
+
+		if (status.control_error || status.signature_error) {
+			ifs_test.status = SCAN_TEST_FAIL;
+			message_fail(cpu, status);
+		} else if (status.error_code) {
+			ifs_test.status = SCAN_NOT_TESTED;
+			message_not_tested(cpu, status);
+		} else {
+			ifs_test.status = SCAN_TEST_PASS;
+		}
+	}
+
+	if (!wait_for_siblings(&ifs_test.siblings_out, NSEC_PER_SEC))
+		dev_err(&ifs_pdev->dev, "cpu %d sibling did not exit rendezvous\n", cpu);
+
+out:
+	if (cpu == first)
+		complete(&ifs_test.test_thread_done);
+}
+
+/*
+ * Initiate per core test. It wakes up work queue threads on the target cpu and
+ * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
+ * wait for all sibling threads to finish the scan test.
+ */
+int do_core_test(int cpu)
+{
+	struct work_struct *local_work;
+	int sibling;
+	int ret = 0;
+	int i = 0;
+
+	cpu_hotplug_disable();
+	if (!cpu_online(cpu)) {
+		dev_info(&ifs_pdev->dev, "cannot test on the offline cpu %d\n", cpu);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	reinit_completion(&ifs_test.test_thread_done);
+	atomic_set(&ifs_test.siblings_in, 0);
+	atomic_set(&ifs_test.siblings_out, 0);
+
+	ifs_test.cpu_sibl_ct = cpumask_weight(topology_sibling_cpumask(cpu));
+	local_work = kcalloc(ifs_test.cpu_sibl_ct, sizeof(struct work_struct), GFP_NOWAIT);
+	if (!local_work) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for_each_cpu(sibling, topology_sibling_cpumask(cpu)) {
+		INIT_WORK(&local_work[i], ifs_work_func);
+		queue_work_on(sibling, ifs_wq, &local_work[i]);
+		i++;
+	}
+
+	if (wait_for_completion_timeout(&ifs_test.test_thread_done, HZ) == 0) {
+		dev_err(&ifs_pdev->dev,
+			"cpu %d Core locked up during IFS test? IFS disabled\n", cpu);
+		ifs_disabled = true;
+	}
+
+	kfree(local_work);
+out:
+	cpu_hotplug_enable();
+	return ret;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 08/10] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (6 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 07/10] platform/x86/intel/ifs: Add scan test support Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-08  4:59   ` Greg KH
  2022-04-07 19:13 ` [PATCH v2 09/10] platform/x86/intel/ifs: add ABI documentation for IFS Jithu Joseph
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Implement sysfs interface to trigger ifs test for a specific cpu.
Additional interfaces related to checking the status of the
scan test and seeing the version of the loaded IFS binary
are also added.

The basic usage is as below.
   - To start test, for example on cpu5:
       echo 5 > /sys/devices/platform/intel_ifs/run_test
   - To see the status of the last test
       cat /sys/devices/platform/intel_ifs/status
   - To see the version of the loaded scan binary
       cat /sys/devices/platform/intel_ifs/image_version

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |   2 +-
 drivers/platform/x86/intel/ifs/core.c   |   1 +
 drivers/platform/x86/intel/ifs/ifs.h    |   2 +
 drivers/platform/x86/intel/ifs/sysfs.c  | 139 ++++++++++++++++++++++++
 4 files changed, 143 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 d5905e5d2de8..93745fcdf652 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)			+= intel_ifs.o
 
-intel_ifs-objs				:= core.o load.o runtest.o
+intel_ifs-objs				:= core.o load.o runtest.o sysfs.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 95847e00038b..85442953d0f5 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -82,6 +82,7 @@ static int __init ifs_init(void)
 		goto drv_unreg;
 	}
 
+	ifs_sysfs_add();
 	ret = platform_device_add(ifs_pdev);
 	if (ret) {
 		pr_err("intel_ifs: platform device add failed\n");
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 93cc1af4aea0..3200d9de4436 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -127,6 +127,8 @@ struct ifs_test {
 
 int load_ifs_binary(void);
 int do_core_test(int cpu);
+void ifs_sysfs_add(void);
+
 extern struct platform_device *ifs_pdev;
 extern struct ifs_binary ifs_binary;
 extern struct ifs_test ifs_test;
diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
new file mode 100644
index 000000000000..f6decebbeae9
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+static DEFINE_SEMAPHORE(ifs_sem);
+
+/*
+ * The sysfs interface to check additional details of last test
+ * cat /sys/devices/system/platform/ifs/details
+ */
+static ssize_t details_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	int ret;
+
+	if (down_trylock(&ifs_sem))
+		return -EBUSY;
+
+	ret = sysfs_emit(buf, "%#llx\n", ifs_test.scan_details);
+	up(&ifs_sem);
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(details);
+
+static const char * const status_msg[] = {
+	[SCAN_NOT_TESTED] = "untested",
+	[SCAN_TEST_PASS] = "pass",
+	[SCAN_TEST_FAIL] = "fail"
+};
+
+/*
+ * The sysfs interface to check the test status:
+ * To check the status of last test
+ * cat /sys/devices/platform/ifs/status
+ */
+static ssize_t status_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	int ret;
+
+	if (down_trylock(&ifs_sem))
+		return -EBUSY;
+
+	ret = sysfs_emit(buf, "%s\n", status_msg[ifs_test.status]);
+
+	up(&ifs_sem);
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(status);
+
+/*
+ * The sysfs interface for single core testing
+ * To start test, for example, cpu5
+ * echo 5 > /sys/devices/platform/ifs/run_test
+ * To check the result:
+ * cat /sys/devices/platform/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;
+	int ret = count;
+	int rc;
+
+	if (!ifs_binary.loaded) {
+		dev_info(&ifs_pdev->dev, "Load scan binary using driver bind interface\n");
+		return -EPERM;
+	}
+
+	if (ifs_disabled)
+		return -ENXIO;
+
+	rc = kstrtouint(buf, 0, &cpu);
+	if (rc < 0 || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	if (down_trylock(&ifs_sem))
+		return -EBUSY;
+
+	rc = do_core_test(cpu);
+	if (rc)
+		ret = rc;
+
+	up(&ifs_sem);
+
+	return ret;
+}
+
+static DEVICE_ATTR_WO(run_test);
+
+/*
+ * Currently loaded IFS image version.
+ */
+static ssize_t image_version_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "%#x\n", ifs_binary.loaded_version);
+}
+
+static DEVICE_ATTR_RO(image_version);
+
+/* global scan sysfs attributes */
+static struct attribute *plat_ifs_attrs[] = {
+	&dev_attr_image_version.attr,
+	&dev_attr_run_test.attr,
+	&dev_attr_status.attr,
+	&dev_attr_details.attr,
+	NULL
+};
+
+static const struct attribute_group plat_ifs_attr_group = {
+	.attrs = plat_ifs_attrs,
+};
+
+static const struct attribute_group *plat_ifs_groups[] = {
+	&plat_ifs_attr_group,
+	NULL
+};
+
+void ifs_sysfs_add(void)
+{
+	ifs_pdev->dev.groups = plat_ifs_groups;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 09/10] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (7 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-08  5:02   ` Greg KH
  2022-04-07 19:13 ` [PATCH v2 10/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Jithu Joseph
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
  10 siblings, 1 reply; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Add the sysfs attributes in ABI/testing for In-Field Scan.

Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 .../ABI/testing/sysfs-platform-intel-ifs      | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
new file mode 100644
index 000000000000..54dc6cd75484
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -0,0 +1,54 @@
+What:		/sys/devices/platform/intel_ifs/run_test
+Date:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	echo <cpu#> to trigger ifs test for all online cores.
+		For e.g to test cpu5 do echo 5 > /sys/devices/platform/intel_ifs/run_test
+
+What:		/sys/devices/platform/intel_ifs/status
+Date:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	The status of the last test. It can be one of "pass", "fail"
+		or "untested".
+
+What:		/sys/devices/system/cpu/cpu#/ifs/details
+Date:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Additional information regarding the last test. 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.
+
+What:		/sys/devices/platform/intel_ifs/image_version
+Date:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Version of loaded IFS binary image.
+
+What:		/sys/bus/platform/drivers/intel_ifs/bind
+Date:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	echo "intel_ifs" to reload IFS image.
+
+What:		/sys/module/intel_ifs/parameters/noirq
+Date:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	IFS 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:		April 07, 2022
+KernelVersion:	5.19.0
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	IFS tunable parameter that user can modify before scan run
+		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.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v2 10/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (8 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 09/10] platform/x86/intel/ifs: add ABI documentation for IFS Jithu Joseph
@ 2022-04-07 19:13 ` Jithu Joseph
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
  10 siblings, 0 replies; 152+ messages in thread
From: Jithu Joseph @ 2022-04-07 19:13 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Tony Luck <tony.luck@intel.com>

Add tracing support which may be useful for debugging systems that fail to complete
In Field Scan tests.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
---
 drivers/platform/x86/intel/ifs/runtest.c |  5 ++++
 include/trace/events/intel_ifs.h         | 38 ++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 include/trace/events/intel_ifs.h

diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index f9c98d84183f..b9fac2ac7107 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -10,6 +10,9 @@
 
 #include "ifs.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ifs.h>
+
 bool ifs_disabled;
 
 static int ifs_retry_set(const char *val, const struct kernel_param *kp);
@@ -204,6 +207,8 @@ static void ifs_work_func(struct work_struct *work)
 
 		rdmsrl(MSR_SCAN_STATUS, status.data);
 
+		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/intel_ifs.h b/include/trace/events/intel_ifs.h
new file mode 100644
index 000000000000..0611f370cb37
--- /dev/null
+++ b/include/trace/events/intel_ifs.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ifs
+
+#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IFS_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ifs_status,
+
+	TP_PROTO(union ifs_scan activate, union ifs_status status),
+
+	TP_ARGS(activate, status),
+
+	TP_STRUCT__entry(
+		__field(	u64,	status	)
+		__field(	u8,	start	)
+		__field(	u8,	stop	)
+	),
+
+	TP_fast_assign(
+		__entry->start	= activate.start;
+		__entry->stop	= activate.stop;
+		__entry->status	= 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 <trace/define_trace.h>
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v2 08/10] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-07 19:13 ` [PATCH v2 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Jithu Joseph
@ 2022-04-08  4:59   ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-08  4:59 UTC (permalink / raw)
  To: Jithu Joseph
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 07, 2022 at 12:13:45PM -0700, Jithu Joseph wrote:
> Implement sysfs interface to trigger ifs test for a specific cpu.
> Additional interfaces related to checking the status of the
> scan test and seeing the version of the loaded IFS binary
> are also added.
> 
> The basic usage is as below.
>    - To start test, for example on cpu5:
>        echo 5 > /sys/devices/platform/intel_ifs/run_test
>    - To see the status of the last test
>        cat /sys/devices/platform/intel_ifs/status
>    - To see the version of the loaded scan binary
>        cat /sys/devices/platform/intel_ifs/image_version
> 
> Reviewed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> ---
>  drivers/platform/x86/intel/ifs/Makefile |   2 +-
>  drivers/platform/x86/intel/ifs/core.c   |   1 +
>  drivers/platform/x86/intel/ifs/ifs.h    |   2 +
>  drivers/platform/x86/intel/ifs/sysfs.c  | 139 ++++++++++++++++++++++++
>  4 files changed, 143 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 d5905e5d2de8..93745fcdf652 100644
> --- a/drivers/platform/x86/intel/ifs/Makefile
> +++ b/drivers/platform/x86/intel/ifs/Makefile
> @@ -1,3 +1,3 @@
>  obj-$(CONFIG_INTEL_IFS)			+= intel_ifs.o
>  
> -intel_ifs-objs				:= core.o load.o runtest.o
> +intel_ifs-objs				:= core.o load.o runtest.o sysfs.o
> diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
> index 95847e00038b..85442953d0f5 100644
> --- a/drivers/platform/x86/intel/ifs/core.c
> +++ b/drivers/platform/x86/intel/ifs/core.c
> @@ -82,6 +82,7 @@ static int __init ifs_init(void)
>  		goto drv_unreg;
>  	}
>  
> +	ifs_sysfs_add();
>  	ret = platform_device_add(ifs_pdev);
>  	if (ret) {
>  		pr_err("intel_ifs: platform device add failed\n");
> diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
> index 93cc1af4aea0..3200d9de4436 100644
> --- a/drivers/platform/x86/intel/ifs/ifs.h
> +++ b/drivers/platform/x86/intel/ifs/ifs.h
> @@ -127,6 +127,8 @@ struct ifs_test {
>  
>  int load_ifs_binary(void);
>  int do_core_test(int cpu);
> +void ifs_sysfs_add(void);
> +
>  extern struct platform_device *ifs_pdev;
>  extern struct ifs_binary ifs_binary;
>  extern struct ifs_test ifs_test;
> diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
> new file mode 100644
> index 000000000000..f6decebbeae9
> --- /dev/null
> +++ b/drivers/platform/x86/intel/ifs/sysfs.c
> @@ -0,0 +1,139 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright(c) 2022 Intel Corporation. */
> +
> +#include <linux/cpu.h>
> +#include <linux/delay.h>
> +#include <linux/fs.h>
> +#include <linux/platform_device.h>
> +#include <linux/semaphore.h>
> +#include <linux/slab.h>
> +
> +#include "ifs.h"
> +
> +static DEFINE_SEMAPHORE(ifs_sem);
> +
> +/*
> + * The sysfs interface to check additional details of last test
> + * cat /sys/devices/system/platform/ifs/details
> + */
> +static ssize_t details_show(struct device *dev,
> +			    struct device_attribute *attr,
> +			    char *buf)
> +{
> +	int ret;
> +
> +	if (down_trylock(&ifs_sem))
> +		return -EBUSY;

Why do you care about locking here at all?

> +
> +	ret = sysfs_emit(buf, "%#llx\n", ifs_test.scan_details);
> +	up(&ifs_sem);

What are you protecting?  The value can change right after the lock is
released, so who cares?

> +
> +	return ret;
> +}
> +
> +static DEVICE_ATTR_RO(details);
> +
> +static const char * const status_msg[] = {
> +	[SCAN_NOT_TESTED] = "untested",
> +	[SCAN_TEST_PASS] = "pass",
> +	[SCAN_TEST_FAIL] = "fail"
> +};
> +
> +/*
> + * The sysfs interface to check the test status:
> + * To check the status of last test
> + * cat /sys/devices/platform/ifs/status
> + */
> +static ssize_t status_show(struct device *dev,
> +			   struct device_attribute *attr,
> +			   char *buf)
> +{
> +	int ret;
> +
> +	if (down_trylock(&ifs_sem))
> +		return -EBUSY;
> +
> +	ret = sysfs_emit(buf, "%s\n", status_msg[ifs_test.status]);
> +
> +	up(&ifs_sem);
> +
> +	return ret;
> +}
> +
> +static DEVICE_ATTR_RO(status);
> +
> +/*
> + * The sysfs interface for single core testing
> + * To start test, for example, cpu5
> + * echo 5 > /sys/devices/platform/ifs/run_test
> + * To check the result:
> + * cat /sys/devices/platform/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;
> +	int ret = count;
> +	int rc;
> +
> +	if (!ifs_binary.loaded) {
> +		dev_info(&ifs_pdev->dev, "Load scan binary using driver bind interface\n");

Do not allow userspace to spam kernel logs for no reason :(

sysfs files are not "help files" in the kernel.

> +		return -EPERM;
> +	}
> +
> +	if (ifs_disabled)
> +		return -ENXIO;
> +
> +	rc = kstrtouint(buf, 0, &cpu);
> +	if (rc < 0 || cpu >= nr_cpu_ids)
> +		return -EINVAL;
> +
> +	if (down_trylock(&ifs_sem))
> +		return -EBUSY;
> +
> +	rc = do_core_test(cpu);
> +	if (rc)
> +		ret = rc;
> +
> +	up(&ifs_sem);
> +
> +	return ret;
> +}
> +
> +static DEVICE_ATTR_WO(run_test);
> +
> +/*
> + * Currently loaded IFS image version.
> + */
> +static ssize_t image_version_show(struct device *dev,
> +				  struct device_attribute *attr, char *buf)
> +{
> +	return sysfs_emit(buf, "%#x\n", ifs_binary.loaded_version);
> +}
> +
> +static DEVICE_ATTR_RO(image_version);
> +
> +/* global scan sysfs attributes */
> +static struct attribute *plat_ifs_attrs[] = {
> +	&dev_attr_image_version.attr,
> +	&dev_attr_run_test.attr,
> +	&dev_attr_status.attr,
> +	&dev_attr_details.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group plat_ifs_attr_group = {
> +	.attrs = plat_ifs_attrs,
> +};
> +
> +static const struct attribute_group *plat_ifs_groups[] = {
> +	&plat_ifs_attr_group,
> +	NULL
> +};
> +
> +void ifs_sysfs_add(void)
> +{
> +	ifs_pdev->dev.groups = plat_ifs_groups;

Why do you have a single global structure?

{sigh}



^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v2 09/10] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-04-07 19:13 ` [PATCH v2 09/10] platform/x86/intel/ifs: add ABI documentation for IFS Jithu Joseph
@ 2022-04-08  5:02   ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-08  5:02 UTC (permalink / raw)
  To: Jithu Joseph
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 07, 2022 at 12:13:46PM -0700, Jithu Joseph wrote:
> Add the sysfs attributes in ABI/testing for In-Field Scan.
> 
> Reviewed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> ---
>  .../ABI/testing/sysfs-platform-intel-ifs      | 54 +++++++++++++++++++
>  1 file changed, 54 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
> 
> diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
> new file mode 100644
> index 000000000000..54dc6cd75484
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
> @@ -0,0 +1,54 @@
> +What:		/sys/devices/platform/intel_ifs/run_test
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0

No need for ".0"

> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	echo <cpu#> to trigger ifs test for all online cores.
> +		For e.g to test cpu5 do echo 5 > /sys/devices/platform/intel_ifs/run_test

So core numbers are different than cpu numbers here?  How are users
going to map them?

> +
> +What:		/sys/devices/platform/intel_ifs/status
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0
> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	The status of the last test. It can be one of "pass", "fail"
> +		or "untested".
> +
> +What:		/sys/devices/system/cpu/cpu#/ifs/details
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0
> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	Additional information regarding the last test. 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.
> +
> +What:		/sys/devices/platform/intel_ifs/image_version
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0
> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	Version of loaded IFS binary image.

In what format?

> +
> +What:		/sys/bus/platform/drivers/intel_ifs/bind
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0
> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	echo "intel_ifs" to reload IFS image.

Huh?  Why are you using a common sysfs file for this type of attribute?
Please do not do so, make it "reload" or something like that.

> +
> +What:		/sys/module/intel_ifs/parameters/noirq
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0
> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	IFS tunable parameter that user can modify before
> +		the scan run if they wish to override default value.

And where are those parameters documented?  What are valid values here?

> +		When set, system interrupts are not allowed to interrupt an IFS. The
> +		default state for this parameter is set.

set to what?

> +
> +What:		/sys/module/intel_ifs/parameters/retry
> +Date:		April 07, 2022
> +KernelVersion:	5.19.0
> +Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
> +Description:	IFS tunable parameter that user can modify before scan run
> +		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.

Why would anyone ever want to change this value?  Why doesn't it "just
work" without needing anything tuned?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image
  2022-04-07 19:13 ` [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image Jithu Joseph
@ 2022-04-08  5:02   ` Greg KH
  2022-04-08  5:04   ` Greg KH
  1 sibling, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-08  5:02 UTC (permalink / raw)
  To: Jithu Joseph
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 07, 2022 at 12:13:41PM -0700, Jithu Joseph wrote:
> IFS uses a scan image format that shares the same header as
> microcode updates and deployment approach for these images mirrors
> that of microcode update. Specifically, enable images to be deployed
> relative to a static symlink in /lib/firmware and then load
> into kernel memory via request_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

Is the firmware already submitted to the linux-firmware project for
inclusion there?

If not, where should a user get it from?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image
  2022-04-07 19:13 ` [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image Jithu Joseph
  2022-04-08  5:02   ` Greg KH
@ 2022-04-08  5:04   ` Greg KH
  1 sibling, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-08  5:04 UTC (permalink / raw)
  To: Jithu Joseph
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 07, 2022 at 12:13:41PM -0700, Jithu Joseph wrote:
> IFS uses a scan image format that shares the same header as
> microcode updates and deployment approach for these images mirrors
> that of microcode update. Specifically, enable images to be deployed
> relative to a static symlink in /lib/firmware and then load
> into kernel memory via request_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
> 
> Reviewed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> ---
>  drivers/platform/x86/intel/ifs/Makefile |  2 +-
>  drivers/platform/x86/intel/ifs/core.c   | 62 ++++++++++++++++++++
>  drivers/platform/x86/intel/ifs/ifs.h    | 15 +++++
>  drivers/platform/x86/intel/ifs/load.c   | 76 +++++++++++++++++++++++++
>  4 files changed, 154 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 c44305dff542..b69d026ca9da 100644
> --- a/drivers/platform/x86/intel/ifs/Makefile
> +++ b/drivers/platform/x86/intel/ifs/Makefile
> @@ -1,3 +1,3 @@
>  obj-$(CONFIG_INTEL_IFS)			+= intel_ifs.o
>  
> -intel_ifs-objs				:= core.o
> +intel_ifs-objs				:= core.o load.o
> diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
> index 87956623208f..716f333a064b 100644
> --- a/drivers/platform/x86/intel/ifs/core.c
> +++ b/drivers/platform/x86/intel/ifs/core.c
> @@ -2,10 +2,14 @@
>  /* Copyright(c) 2022 Intel Corporation. */
>  
>  #include <linux/module.h>
> +#include <linux/platform_device.h>
>  #include <asm/cpu_device_id.h>
>  
>  #include "ifs.h"
>  
> +struct platform_device *ifs_pdev;
> +struct ifs_binary ifs_binary;

Please no static memory.  Use the driver model properly which does not
want you to do this at all.

You should not need this at all.  If you do, something is wrong as you
are tying the lifecycle of the memory to the code, not to the device.

{sigh}

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS
  2022-04-07 19:13 ` [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS Jithu Joseph
@ 2022-04-08  8:34   ` Borislav Petkov
  2022-04-21 14:56     ` Thomas Gleixner
  0 siblings, 1 reply; 152+ messages in thread
From: Borislav Petkov @ 2022-04-08  8:34 UTC (permalink / raw)
  To: Jithu Joseph
  Cc: hdegoede, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 07, 2022 at 12:13:38PM -0700, Jithu Joseph wrote:
> diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h
> index d85a07d7154f..cf0fd1d712b4 100644
> --- a/arch/x86/include/asm/microcode_intel.h
> +++ b/arch/x86/include/asm/microcode_intel.h
> @@ -68,6 +68,10 @@ static inline u32 intel_get_microcode_revision(void)
>  	return rev;
>  }
>  
> +int cpu_collect_info_early(struct ucode_cpu_info *uci);
> +bool cpu_signatures_match(unsigned int s1, unsigned int p1,
> +			  unsigned int s2, unsigned int p2);
> +

So you can't move the functions to cpu/intel.c but put the
prototype declarations in the microcode header - they should go to
arch/x86/include/asm/cpu.h or so.


>  #ifdef CONFIG_MICROCODE_INTEL
>  extern void __init load_ucode_intel_bsp(void);
>  extern void load_ucode_intel_ap(void);
> diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
> index 8321c43554a1..2008c8267fd3 100644
> --- a/arch/x86/kernel/cpu/intel.c
> +++ b/arch/x86/kernel/cpu/intel.c
> @@ -181,6 +181,53 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
>  	return false;
>  }
>  
> +bool cpu_signatures_match(unsigned int s1, unsigned int p1,

That function is Intel-specific:

intel_cpu_signatures_match()

and it is small enough to stick it in the above header and make it an
inline without the need for an export.

> +			  unsigned int s2, unsigned int p2)
> +{
> +	if (s1 != s2)
> +		return false;
> +
> +	/* Processor flags are either both 0 ... */
> +	if (!p1 && !p2)
> +		return true;
> +
> +	/* ... or they intersect. */
> +	return p1 & p2;
> +}
> +EXPORT_SYMBOL_GPL(cpu_signatures_match);
> +
> +int cpu_collect_info_early(struct ucode_cpu_info *uci)

intel_collect_cpu_info_early()

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v3 00/11] Introduce In Field Scan driver
  2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
                   ` (9 preceding siblings ...)
  2022-04-07 19:13 ` [PATCH v2 10/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Jithu Joseph
@ 2022-04-19 16:38 ` Tony Luck
  2022-04-19 16:38   ` [PATCH v3 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
                     ` (11 more replies)
  10 siblings, 12 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Longer description of what this does, and why it is useful in the v2 cover
letter here:
  https://lore.kernel.org/all/20220407191347.9681-1-jithu.joseph@intel.com/

But the TL;DR version is this driver loads scan test files that can
check whether silicon in a CPU core is still running correctly. It
is expected that these tests would be run several times per day to
catch problems as silicon ages.

I'm posting this update because I missed many major issues when I added
my review tag. So I have a moral obligation to fix up the things that
I missed.

Changes since V2:

Dan Williams (offline):
----------------------
1) Provided the clue to split into a tiny driver that enumerates and
   registers the device. Then the IFS driver can attach to that an behave
   much more like a normal driver (original idea from Andy Lutomirski,
   used for pmem/nvdimms)

2 .. many) Lots more pointers, tips, and general good guidance to make both
   the code and commit comments better and easier to understand.

Boris:
-----
1) Add "intel_" prefixes to the two functions moving to wider scope.

Done.

2) Move the declarations from <asm/microcode_intel.h> to <asm/cpu.h>

Done.

3) intel_cpu_signatures_match() is small enough to be "inline".

Done.

Greg:
----
1) Is the firmware already submitted to the linux-firmware project for
   inclusion there?
   If not, where should a user get it from?

The scan files will be distributed by Intel on Github in much the
same way that microcode is distributed today.

2) > +struct ifs_binary ifs_binary;

   Please no static memory.  Use the driver model properly which does not
   want you to do this at all.

   You should not need this at all.  If you do, something is wrong as you
   are tying the lifecycle of the memory to the code, not to the device.

Moved this (and ifs_test) to dynamic allocation using devm_kzalloc()
and attaching the resulting pointer to the device with dev_set_drvdata().

3) > +static ssize_t details_show(struct device *dev,
   > +			    struct device_attribute *attr,
   > +			    char *buf)
   > +{
   > +	int ret;
   > +
   > +	if (down_trylock(&ifs_sem))
   > +		return -EBUSY;

   Why do you care about locking here at all?

   > +
   > +	ret = sysfs_emit(buf, "%#llx\n", ifs_test.scan_details);
   > +	up(&ifs_sem);

   What are you protecting?  The value can change right after the lock is
   released, so who cares?

Removed locking from status and details show() functions. Running a test
is synchronous. So:
  # echo 3 > run_test
  # cat status
  # cat details
will give the results of the core 3 test as expected. It is up to the user
to not do dumb things like reading status/details from another process in
parallel with running tests.

4) > +	if (!ifs_binary.loaded) {
   > +		dev_info(&ifs_pdev->dev, "Load scan binary using driver bind interface\n");

   Do not allow userspace to spam kernel logs for no reason :(

   sysfs files are not "help files" in the kernel.

Spam removed.

5) > +void ifs_sysfs_add(void)
   > +{
   > +	ifs_pdev->dev.groups = plat_ifs_groups;

   Why do you have a single global structure?

All instances of the driver for different tests can use the same files
and functions. They use "struct ifs_data *ifsd = dev_get_drvdata(dev);"
to operate on the correct driver instance.

6) > +KernelVersion:	5.19.0

   No need for ".0"

Removed.

7) > +		For e.g to test cpu5 do echo 5 > /sys/devices/platform/intel_ifs/run_test

   So core numbers are different than cpu numbers here?  How are users
   going to map them?

Added some extra text here to say that tests are per core, but any thread
on the core can be used to run the test. Should I also point people at
/sys/devices/system/cpu/cpu#/topology/thread_siblings_list? It seems
easy for users to get a list of cores with a script like:
$ cores=$(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | sed -e 's/,.*//' | sort -n | uniq)

8) > +Description:	Version of loaded IFS binary image.

   In what format?

Added "(hexadecimal)". Also added code (and Docs) to print "none" if the load
of the scan file failed.

9) > +Description:	echo "intel_ifs" to reload IFS image.

   Huh?  Why are you using a common sysfs file for this type of attribute?
   Please do not do so, make it "reload" or something like that.

Ok. Added a "reload" file like microcode. (Though using driver bind/unbind
also works).

10) > +Description:	IFS tunable parameter that user can modify before
   > +		the scan run if they wish to override default value.

   And where are those parameters documented?  What are valid values here?

Dropped both the "noirq" and "retry" parameters. I think they now have sane
defaults. If Jithu/Ashok have a good use case, they can send a patch to add
them back.

-Tony


Jithu Joseph (7):
  x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  platform/x86/intel/ifs: Read IFS firmware image
  platform/x86/intel/ifs: Check IFS Image sanity
  platform/x86/intel/ifs: Authenticate and copy to secured memory
  platform/x86/intel/ifs: Add scan test support
  platform/x86/intel/ifs: Add IFS sysfs interface
  platform/x86/intel/ifs: add ABI documentation for IFS

Tony Luck (4):
  Documentation: In-Field Scan
  platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  platform/x86/intel/ifs: Add stub driver for In-Field Scan
  trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
    operations

 .../ABI/testing/sysfs-platform-intel-ifs      |  39 ++
 Documentation/x86/ifs.rst                     | 101 ++++++
 Documentation/x86/index.rst                   |   1 +
 MAINTAINERS                                   |   8 +
 arch/x86/include/asm/cpu.h                    |  18 +
 arch/x86/kernel/cpu/intel.c                   |  32 ++
 arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
 drivers/platform/x86/intel/Kconfig            |   1 +
 drivers/platform/x86/intel/Makefile           |   1 +
 drivers/platform/x86/intel/ifs/Kconfig        |  16 +
 drivers/platform/x86/intel/ifs/Makefile       |   5 +
 drivers/platform/x86/intel/ifs/core.c         |  74 ++++
 drivers/platform/x86/intel/ifs/ifs.h          | 103 ++++++
 .../platform/x86/intel/ifs/intel_ifs_device.c |  50 +++
 drivers/platform/x86/intel/ifs/load.c         | 265 ++++++++++++++
 drivers/platform/x86/intel/ifs/runtest.c      | 333 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/sysfs.c        | 151 ++++++++
 include/trace/events/intel_ifs.h              |  38 ++
 18 files changed, 1243 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
 create mode 100644 Documentation/x86/ifs.rst
 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
 create mode 100644 drivers/platform/x86/intel/ifs/intel_ifs_device.c
 create mode 100644 drivers/platform/x86/intel/ifs/load.c
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
 create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
 create mode 100644 include/trace/events/intel_ifs.h


base-commit: b2d229d4ddb17db541098b83524d901257e93845
-- 
2.35.1


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v3 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 16:38   ` [PATCH v3 02/11] Documentation: In-Field Scan Tony Luck
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs.

In support of an IFS driver to trigger loading, validation, and running
of these tests blobs, make the functionality of cpu_signatures_match()
and collect_cpu_info_early() available outside of the microcode driver.

Rename collect_cpu_info_early() to intel_cpu_collect_info_early() and
EXPORT_SYMBOL_GPL() it. Add declaration to x86 <asm/cpu.h>

Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
and also give it an "intel_" prefix.

No functional change intended.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 arch/x86/include/asm/cpu.h            | 18 ++++++++
 arch/x86/kernel/cpu/intel.c           | 32 +++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c | 59 ++++-----------------------
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 86e5e4e26fcb..c245b2196657 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -76,4 +76,22 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
 
 extern __noendbr void cet_disable(void);
 
+struct ucode_cpu_info;
+
+int intel_cpu_collect_info_early(struct ucode_cpu_info *uci);
+
+static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+					      unsigned int s2, unsigned int p2)
+{
+	if (s1 != s2)
+		return false;
+
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
+
+	/* ... or they intersect. */
+	return p1 & p2;
+}
+
 #endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f7a5370a9b3b..bb717cd847b4 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,6 +181,38 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 	return false;
 }
 
+int intel_cpu_collect_info_early(struct ucode_cpu_info *uci)
+{
+	unsigned int val[2];
+	unsigned int family, model;
+	struct cpu_signature csig = { 0 };
+	unsigned int eax, ebx, ecx, edx;
+
+	memset(uci, 0, sizeof(*uci));
+
+	eax = 0x00000001;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	csig.sig = eax;
+
+	family = x86_family(eax);
+	model  = x86_model(eax);
+
+	if (model >= 5 || family > 6) {
+		/* get processor flags from MSR 0x17 */
+		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		csig.pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	csig.rev = intel_get_microcode_revision();
+
+	uci->cpu_sig = csig;
+	uci->valid = 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intel_cpu_collect_info_early);
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index d28a9f8f3fec..5184bd06416c 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */
@@ -69,7 +55,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	struct extended_signature *ext_sig;
 	int i;
 
-	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
 		return 1;
 
 	/* Look for ext. headers: */
@@ -80,7 +66,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
 
 	for (i = 0; i < ext_hdr->count; i++) {
-		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
 			return 1;
 		ext_sig++;
 	}
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 	return patch;
 }
 
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-	unsigned int val[2];
-	unsigned int family, model;
-	struct cpu_signature csig = { 0 };
-	unsigned int eax, ebx, ecx, edx;
-
-	memset(uci, 0, sizeof(*uci));
-
-	eax = 0x00000001;
-	ecx = 0;
-	native_cpuid(&eax, &ebx, &ecx, &edx);
-	csig.sig = eax;
-
-	family = x86_family(eax);
-	model  = x86_model(eax);
-
-	if ((model >= 5) || (family > 6)) {
-		/* get processor flags from MSR 0x17 */
-		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		csig.pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	csig.rev = intel_get_microcode_revision();
-
-	uci->cpu_sig = csig;
-	uci->valid = 1;
-
-	return 0;
-}
-
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
 		return;
 	}
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info_early(&uci);
 
 	sig	= uci.cpu_sig.sig;
 	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
 	struct ucode_cpu_info uci;
 
 	if (delay_ucode_info) {
-		collect_cpu_info_early(&uci);
+		intel_cpu_collect_info_early(&uci);
 		print_ucode_info(&uci, current_mc_date);
 		delay_ucode_info = 0;
 	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
 	if (!(cp.data && cp.size))
 		return 0;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info_early(&uci);
 
 	scan_microcode(cp.data, cp.size, &uci, true);
 
@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 	if (!(cp.data && cp.size))
 		return NULL;
 
-	collect_cpu_info_early(uci);
+	intel_cpu_collect_info_early(uci);
 
 	return scan_microcode(cp.data, cp.size, uci, false);
 }
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
 	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info_early(&uci);
 
 	p = find_patch(&uci);
 	if (!p)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 02/11] Documentation: In-Field Scan
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
  2022-04-19 16:38   ` [PATCH v3 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 16:48     ` Greg KH
  2022-04-19 16:38   ` [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan) Tony Luck
                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

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.

The full  github location for distributing the IFS images is
still being decided. So just a placeholder included for now
in the documentation.

Future CPUs will support more than one type of test. Plan for
that now by using a ".0" suffix on the ABI directory names.
Additional test types will use ".1", etc.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 Documentation/x86/ifs.rst   | 101 ++++++++++++++++++++++++++++++++++++
 Documentation/x86/index.rst |   1 +
 2 files changed, 102 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..62f3c07d433a
--- /dev/null
+++ b/Documentation/x86/ifs.rst
@@ -0,0 +1,101 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+In-Field Scan
+=============
+
+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.
+Future CPUs will support more than one type of test which will show up
+with a new platform-device instance-id, for now only .0 is exposed.
+
+
+IFS Image
+---------
+
+Intel provides a firmware file containing the scan tests via
+github [#f1]_.  Similar to microcode there is a separate file for each
+family-model-stepping.
+
+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 by writing to the driver reload file::
+
+  # echo 1 > /sys/bus/platform/drivers/intel_ifs.0/reload
+
+Similar to microcode, the current version of the scan tests is stored
+in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan
+
+Running tests
+-------------
+
+Tests are run by the driver 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. The driver makes the value of this MSR visible to applications
+via the "details" file (see below). Interrupted tests may be restarted.
+
+The IFS driver provides sysfs interfaces via /sys/devices/platform/intel_ifs.0/
+to control execution:
+
+Test a specific core::
+
+  # echo <cpu#> > /sys/devices/platform/intel_ifs.0/run_test
+
+when HT is enabled any of the sibling cpu# can be specified to test its
+corresponding physical core. Since the tests are per physical core, the
+result of testing any thread is same. It is only necessary to test one
+thread.
+
+For e.g. to test core corresponding to cpu5
+
+  # echo 5 > /sys/devices/platform/intel_ifs.0/run_test
+
+Results of the last test is provided in /sys::
+
+  $ cat /sys/devices/platform/intel_ifs.0/status
+  pass
+
+Status can be one of pass, fail, untested
+
+Additional details of the last test is provided by the details file::
+
+  $ cat /sys/devices/platform/intel_ifs.0/details
+  0x8081
+
+The details file reports the hex value of the SCAN_STATUS MSR.
+Hardware defined error codes are documented in volume 4 of the Intel
+Software Developer's Manual but the error_code field may contain one of
+the following driver defined software codes:
+
++------+--------------------+
+| 0xFD | Software timeout   |
++------+--------------------+
+| 0xFE | Partial completion |
++------+--------------------+
+
+Driver design choices
+---------------------
+
+1) The ACTIVATE_SCAN MSR allows for running any consecutive subrange of
+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.
+
+.. [#f1] https://github.com/intel/TBD
diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst
index 91b2fa456618..9d8e8a73d57b 100644
--- a/Documentation/x86/index.rst
+++ b/Documentation/x86/index.rst
@@ -35,6 +35,7 @@ x86-specific Documentation
    usb-legacy-support
    i386/index
    x86_64/index
+   ifs
    sva
    sgx
    features
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
  2022-04-19 16:38   ` [PATCH v3 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
  2022-04-19 16:38   ` [PATCH v3 02/11] Documentation: In-Field Scan Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 16:47     ` Greg KH
  2022-04-19 16:38   ` [PATCH v3 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
                     ` (8 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

The initial implementation of IFS is model specific. Enumeration is
via a combination of family-model-stepping and a check for a bit in the
CORE_CAPABILITIES MSR.

Linux has handled this lack of enumeration before with a code stub to
create a device.  See arch/x86/kernel/pmem.c. Use the same approach
here.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 MAINTAINERS                                   |  7 +++
 drivers/platform/x86/intel/Kconfig            |  1 +
 drivers/platform/x86/intel/Makefile           |  1 +
 drivers/platform/x86/intel/ifs/Kconfig        |  2 +
 drivers/platform/x86/intel/ifs/Makefile       |  1 +
 .../platform/x86/intel/ifs/intel_ifs_device.c | 50 +++++++++++++++++++
 6 files changed, 62 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/intel_ifs_device.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 40fa1955ca3f..9e372a960fa5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9861,6 +9861,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
 
+INTEL IN FIELD SCAN (IFS) DRIVER
+M:	Jithu Joseph <jithu.joseph@intel.com>
+R:	Ashok Raj <ashok.raj@intel.com>
+R:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+F:	drivers/platform/x86/intel/ifs
+
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 1f01a8a23c57..794968bda115 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -4,6 +4,7 @@
 #
 
 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/int3472/Kconfig"
 source "drivers/platform/x86/intel/pmc/Kconfig"
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index c61bc3e97121..10285d0fd16a 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
+obj-y					+= ifs/
 obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
 obj-$(CONFIG_INTEL_SKL_INT3472)		+= int3472/
 obj-$(CONFIG_INTEL_PMC_CORE)		+= pmc/
diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
new file mode 100644
index 000000000000..51325b699563
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Kconfig
@@ -0,0 +1,2 @@
+config INTEL_IFS_DEVICE
+	bool
diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
new file mode 100644
index 000000000000..12c2f5ce9925
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
diff --git a/drivers/platform/x86/intel/ifs/intel_ifs_device.c b/drivers/platform/x86/intel/ifs/intel_ifs_device.c
new file mode 100644
index 000000000000..64a143871d72
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/intel_ifs_device.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <asm/cpu_device_id.h>
+
+#define MSR_IA32_CORE_CAPS_INTEGRITY_BIT	2
+#define MSR_IA32_CORE_CAPS_INTEGRITY		BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT)
+
+#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 = {
+	X86_MATCH(SAPPHIRERAPIDS_X),
+	{}
+};
+
+static __init int register_ifs_device(void)
+{
+	struct platform_device *pdev;
+	const struct x86_cpu_id *m;
+	u64 ia32_core_caps;
+
+	m = 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) {
+		pdev = platform_device_alloc("intel_ifs", 0);
+		if (pdev) {
+			if (platform_device_add(pdev))
+				platform_device_put(pdev);
+		}
+	}
+
+	/*
+	 * Failure here will be visible by a missing device
+	 * in sysfs. Returning an error code would not make
+	 * that any easier to diagnose. Would also complicate
+	 * future implementations that may support a subset of
+	 * the types of tests.
+	 */
+	return 0;
+}
+device_initcall(register_ifs_device);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (2 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan) Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 16:38   ` [PATCH v3 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
                     ` (7 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Cloud Service Providers that operate fleets of servers have reported
[1] occasions where they can detect that a CPU has gone bad due to
effects like electromigration, or isolated manufacturing defects.
However, that detection method is A/B testing seemingly random
application failures looking for a pattern. In-Field Scan (IFS) is
a driver for a platform capability to load a crafted 'scan image'
to run targeted low level diagnostics outside of the CPU's architectural
error detection capabilities.

[1]: https://www.youtube.com/watch?v=QMF3rqhjYuM

Kconfig for this driver selects CONFIG_INTEL_IFS_DEVICE so the base
kernel will be built with code to create the device to which this driver
will attach.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

---
Not using module_platform_driver() for this simple stub because
later patches need to add init()/exit() functions.
---
 drivers/platform/x86/intel/ifs/Kconfig  | 14 ++++++++++++
 drivers/platform/x86/intel/ifs/Makefile |  4 ++++
 drivers/platform/x86/intel/ifs/core.c   | 29 +++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 drivers/platform/x86/intel/ifs/core.c

diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
index 51325b699563..0aa5ecc5ef42 100644
--- a/drivers/platform/x86/intel/ifs/Kconfig
+++ b/drivers/platform/x86/intel/ifs/Kconfig
@@ -1,2 +1,16 @@
 config INTEL_IFS_DEVICE
 	bool
+
+config INTEL_IFS
+	tristate "Intel In Field Scan"
+	depends on X86 && 64BIT && SMP
+	select INTEL_IFS_DEVICE
+	help
+	  Enable support for the In Field Scan capability in select
+	  CPUs. The capability allows for running low level tests via
+	  a scan image distributed by Intel via Github to validate CPU
+	  operation beyond baseline RAS capabilities. 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
index 12c2f5ce9925..bf8adc57892c 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1 +1,5 @@
 obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
+
+obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
+
+intel_ifs-objs			:= core.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
new file mode 100644
index 000000000000..eb34b877dac0
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static struct platform_driver intel_ifs_driver = {
+	.driver = {
+		.name = "intel_ifs",
+	},
+};
+
+static int __init ifs_init(void)
+{
+	return platform_driver_register(&intel_ifs_driver);
+}
+
+static void __exit ifs_exit(void)
+{
+	platform_driver_unregister(&intel_ifs_driver);
+}
+
+module_init(ifs_init);
+module_exit(ifs_exit);
+
+MODULE_ALIAS("platform:intel_ifs*");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel In Field Scan (IFS) driver");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 05/11] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (3 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 17:14     ` Greg KH
  2022-04-19 16:38   ` [PATCH v3 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
                     ` (6 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Driver probe routine allocates structure to communicate status
and parameters between functions in the driver. Also call
load_ifs_binary() to load the scan image file.

There is a separate scan image file for each processor family,
model, stepping combination. This is read from the static path:

  /lib/firmware/intel/ifs/{ff-mm-ss}.scan

Step 1 in loading is to generate the correct path and use
request_firmware_direct() to load into memory.

Subsequent patches will use the IFS MSR interfaces to copy
the image to BIOS reserved memory and validate the SHA256
checksums.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |  2 +-
 drivers/platform/x86/intel/ifs/core.c   | 23 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/ifs.h    | 19 +++++++++++++++
 drivers/platform/x86/intel/ifs/load.c   | 31 +++++++++++++++++++++++++
 4 files changed, 74 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/ifs.h
 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 bf8adc57892c..eab0cc81f38e 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -2,4 +2,4 @@ obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
 
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o
+intel_ifs-objs			:= core.o load.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index eb34b877dac0..139449f11a64 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -4,7 +4,30 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include "ifs.h"
+
+static int ifs_probe(struct platform_device *pdev)
+{
+	struct ifs_data *ifsd;
+
+	ifsd = devm_kzalloc(&pdev->dev, sizeof(*ifsd), GFP_KERNEL);
+	if (!ifsd)
+		return -ENOMEM;
+
+	dev_set_drvdata(&pdev->dev, ifsd);
+
+	switch (pdev->id) {
+	case 0:
+		/* Load IFS binary to BIOS reserved memory area */
+		ifsd->loaded = !load_ifs_binary(&pdev->dev);
+		break;
+	}
+
+	return 0;
+}
+
 static struct platform_driver intel_ifs_driver = {
+	.probe = ifs_probe,
 	.driver = {
 		.name = "intel_ifs",
 	},
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
new file mode 100644
index 000000000000..dacc8b6ce159
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Intel Corporation. */
+
+#ifndef _IFS_H_
+#define _IFS_H_
+
+/**
+ * struct ifs_data - attributes related to intel IFS driver
+ * @loaded_version: stores the currently loaded ifs image version.
+ * @loaded: If a valid test binary has been loaded into the memory
+ */
+struct ifs_data {
+	int loaded_version;
+	bool loaded;
+};
+
+int load_ifs_binary(struct device *dev);
+
+#endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
new file mode 100644
index 000000000000..fa6c64707a73
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+
+static const char *ifs_path = "intel/ifs/";
+
+/*
+ * Load ifs image. Before loading ifs module, the ifs image must be located
+ * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
+ */
+int load_ifs_binary(struct device *dev)
+{
+	const struct firmware *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);
+
+	ret = request_firmware_direct(&fw, scan_path, dev);
+	if (ret) {
+		dev_err(dev, "ifs file %s load failed\n", scan_path);
+		return ret;
+	}
+
+	release_firmware(fw);
+
+	return ret;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 06/11] platform/x86/intel/ifs: Check IFS Image sanity
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (4 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 17:16     ` Greg KH
  2022-04-19 16:38   ` [PATCH v3 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
                     ` (5 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/load.c | 69 +++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index fa6c64707a73..b05d9055c391 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,9 +3,73 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <asm/cpu.h>
+#include <asm/microcode_intel.h>
 
 static const char *ifs_path = "intel/ifs/";
 
+static int ifs_sanity_check(struct device *dev, void *mc)
+{
+	struct microcode_header_intel *mc_header = mc;
+	unsigned long total_size, data_size;
+	u32 sum, i;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+
+	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
+		dev_err(dev, "bad ifs data file size.\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		dev_err(dev, "invalid/unknown ifs update format.\n");
+		return -EINVAL;
+	}
+
+	sum = 0;
+	i = total_size / sizeof(u32);
+	while (i--)
+		sum += ((u32 *)mc)[i];
+
+	if (sum) {
+		dev_err(dev, "bad ifs data checksum, aborting.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci, void *mc)
+{
+	struct microcode_header_intel *shdr;
+	unsigned int mc_size;
+
+	shdr = (struct microcode_header_intel *)mc;
+	mc_size = get_totalsize(shdr);
+
+	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
+		dev_err(dev, "ifs sanity check failure\n");
+		return false;
+	}
+
+	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
+		dev_err(dev, "ifs signature, pf not matching\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool ifs_image_sanity_check(struct device *dev, void *data)
+{
+	struct ucode_cpu_info uci;
+
+	intel_cpu_collect_info_early(&uci);
+
+	return find_ifs_matching_signature(dev, &uci, data);
+}
+
 /*
  * Load ifs image. Before loading ifs module, the ifs image must be located
  * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
@@ -25,6 +89,11 @@ int load_ifs_binary(struct device *dev)
 		return ret;
 	}
 
+	if (!ifs_image_sanity_check(dev, (void *)fw->data)) {
+		dev_err(dev, "ifs header sanity check failed\n");
+		ret = -ENOENT;
+	}
+
 	release_firmware(fw);
 
 	return ret;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (5 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 16:38   ` [PATCH v3 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
                     ` (4 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/ifs.h  |  33 ++++++
 drivers/platform/x86/intel/ifs/load.c | 165 ++++++++++++++++++++++++++
 2 files changed, 198 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index dacc8b6ce159..c51e285fc7ba 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -4,14 +4,47 @@
 #ifndef _IFS_H_
 #define _IFS_H_
 
+#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 {
+		u32	chunk_size	:16;
+		u32	num_chunks	:8;
+		u32	rsvd1		:8;
+		u32	error_code	:8;
+		u32	rsvd2		:11;
+		u32	max_core_limit	:12;
+		u32	valid		:1;
+	};
+};
+
+/* MSR_CHUNKS_AUTH_STATUS bit fields */
+union ifs_chunks_auth_status {
+	u64	data;
+	struct {
+		u32	valid_chunks	:8;
+		u32	total_chunks	:8;
+		u32	rsvd1		:16;
+		u32	error_code	:8;
+		u32	rsvd2		:24;
+	};
+};
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @loaded_version: stores the currently loaded ifs image version.
  * @loaded: If a valid test binary has been loaded into the memory
+ * @valid_chunks: number of chunks which could be validated.
  */
 struct ifs_data {
 	int loaded_version;
 	bool loaded;
+	int valid_chunks;
 };
 
 int load_ifs_binary(struct device *dev);
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index b05d9055c391..04072ed84071 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,10 +3,169 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <asm/cpu.h>
 #include <asm/microcode_intel.h>
 
+#include "ifs.h"
+
 static const char *ifs_path = "intel/ifs/";
+static bool ifs_loading_error;	/* error occurred during ifs hashes/chunk authentication.*/
+
+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 header */
+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[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to copy scan hashes when copy already in progress",
+	[2] = "Secure Memory not set up correctly",
+	[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
+	[4] = "Reserved",
+	[5] = "Integrity check failed",
+	[6] = "Scan reload or test is in progress"
+};
+
+static const char * const scan_authentication_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to authenticate a chunk which is already marked as authentic",
+	[2] = "Chunk authentication error. The hash of chunk did not match expected value"
+};
+
+/*
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must 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_AUTHENTICATE_AND_COPY_CHUNK)
+ * for scan hash copy and test chunk authentication.
+ */
+static void 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;
+	struct device *dev = arg;
+	struct ifs_data *ifsd;
+	u64 linear_addr, base;
+	u32 err_code;
+
+	ifsd = dev_get_drvdata(dev);
+	/* 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 = hashes_status.num_chunks;
+	chunk_size = hashes_status.chunk_size * 1024;
+	err_code = hashes_status.error_code;
+
+	if (!hashes_status.valid) {
+		ifs_loading_error = true;
+		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
+			dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
+			return;
+		}
+		dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
+		return;
+	}
+
+	/* base linear address to the scan data */
+	base = ifs_test_image_ptr;
+
+	/* scan data authentication and copy chunks to secured memory */
+	for (i = 0; i < num_chunks; i++) {
+		linear_addr = base + i * chunk_size;
+		linear_addr |= i;
+
+		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
+		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
+
+		ifsd->valid_chunks = chunk_status.valid_chunks;
+		err_code = chunk_status.error_code;
+
+		if (err_code) {
+			ifs_loading_error = true;
+			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
+				dev_err(dev,
+					"invalid error code 0x%x for authentication\n", err_code);
+				return;
+			}
+			dev_err(dev, "Chunk authentication error %s\n",
+				scan_authentication_status[err_code]);
+			return;
+		}
+	}
+}
+
+/*
+ * IFS requires scan chunks authenticated per each socket in the platform.
+ * Once the test chunk is authenticated, it is automatically copied to secured memory
+ * and proceed the authentication for the next chunk.
+ */
+static int scan_chunks_sanity_check(struct device *dev)
+{
+	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
+	struct ifs_data *ifsd = dev_get_drvdata(dev);
+	bool *package_authenticated;
+	char *test_ptr;
+
+	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
+	if (!package_authenticated)
+		return ret;
+
+	metadata_size = ifs_header_ptr->metadata_size;
+
+	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
+	if (metadata_size == 0)
+		metadata_size = 2000;
+
+	/* Scan chunk start must be 256 byte aligned */
+	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
+		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
+		return -EINVAL;
+	}
+
+	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
+	ifs_loading_error = false;
+
+	ifs_test_image_ptr = (u64)test_ptr;
+	ifsd->loaded_version = ifs_header_ptr->blob_revision;
+
+	/* copy the scan hash and authenticate per package */
+	cpus_read_lock();
+	for_each_online_cpu(cpu) {
+		curr_pkg = topology_physical_package_id(cpu);
+		if (package_authenticated[curr_pkg])
+			continue;
+		package_authenticated[curr_pkg] = 1;
+		ret = smp_call_function_single(cpu, copy_hashes_authenticate_chunks,
+					       dev, 1);
+		if (ret || ifs_loading_error) {
+			ret = ifs_loading_error ? -ENOMEM : ret;
+			goto out;
+		}
+	}
+
+out:
+	cpus_read_unlock();
+	kfree(package_authenticated);
+
+	return ret;
+}
 
 static int ifs_sanity_check(struct device *dev, void *mc)
 {
@@ -92,8 +251,14 @@ int load_ifs_binary(struct device *dev)
 	if (!ifs_image_sanity_check(dev, (void *)fw->data)) {
 		dev_err(dev, "ifs header sanity check failed\n");
 		ret = -ENOENT;
+		goto release;
 	}
 
+	ifs_header_ptr = (struct ifs_header *)fw->data;
+	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
+
+	ret = scan_chunks_sanity_check(dev);
+release:
 	release_firmware(fw);
 
 	return ret;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 08/11] platform/x86/intel/ifs: Add scan test support
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (6 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 16:38   ` [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
                     ` (3 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

In a core, the scan engine is shared between sibling cpus.

When a Scan test (for a particular core) is triggered by the user,
worker threads for each sibling cpus(belonging to that core) are
queued to execute the scan test function in the Workqueue context.

All the siblings rendezvous before the test execution. 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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/core.c    |  15 +-
 drivers/platform/x86/intel/ifs/ifs.h     |  48 ++++
 drivers/platform/x86/intel/ifs/runtest.c | 321 +++++++++++++++++++++++
 4 files changed, 384 insertions(+), 2 deletions(-)
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c

diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
index eab0cc81f38e..7de27361b479 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -2,4 +2,4 @@ obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
 
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o
+intel_ifs-objs			:= core.o load.o runtest.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 139449f11a64..0dc4cdda35ff 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -35,11 +35,24 @@ static struct platform_driver intel_ifs_driver = {
 
 static int __init ifs_init(void)
 {
-	return platform_driver_register(&intel_ifs_driver);
+	int ret;
+
+	ret = platform_driver_register(&intel_ifs_driver);
+	if (ret)
+		return ret;
+
+	ret = ifs_setup_wq();
+	if (ret) {
+		platform_driver_unregister(&intel_ifs_driver);
+		return ret;
+	}
+
+	return 0;
 }
 
 static void __exit ifs_exit(void)
 {
+	ifs_destroy_wq();
 	platform_driver_unregister(&intel_ifs_driver);
 }
 
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index c51e285fc7ba..f5e3636d709f 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -8,6 +8,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_NOT_TESTED				0
+#define SCAN_TEST_PASS				1
+#define SCAN_TEST_FAIL				2
+#define SPINUNIT				100
+#define THREAD_WAIT				5
 
 /* MSR_SCAN_HASHES_STATUS bit fields */
 union ifs_scan_hashes_status {
@@ -35,18 +42,59 @@ union ifs_chunks_auth_status {
 	};
 };
 
+/* MSR_ACTIVATE_SCAN bit fields */
+union ifs_scan {
+	u64	data;
+	struct {
+		u32	start	:8;
+		u32	stop	:8;
+		u32	rsvd	:16;
+		u32	delay	:31;
+		u32	sigmce	:1;
+	};
+};
+
+/* MSR_SCAN_STATUS bit fields */
+union ifs_status {
+	u64	data;
+	struct {
+		u32	chunk_num		:8;
+		u32	chunk_stop_index	:8;
+		u32	rsvd1			:16;
+		u32	error_code		:8;
+		u32	rsvd2			:22;
+		u32	control_error		:1;
+		u32	signature_error		:1;
+	};
+};
+
+/*
+ * Driver populated error-codes
+ * 0xFD: Test timed out before completing all the chunks.
+ * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
+ */
+#define IFS_SW_TIMEOUT				0xFD
+#define IFS_SW_PARTIAL_COMPLETION		0xFE
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @loaded_version: stores the currently loaded ifs image version.
  * @loaded: If a valid test binary has been loaded into the memory
  * @valid_chunks: number of chunks which could be validated.
+ * @status: it holds simple status pass/fail/untested
+ * @scan_details: opaque scan status code from h/w
  */
 struct ifs_data {
 	int loaded_version;
 	bool loaded;
 	int valid_chunks;
+	int status;
+	u64 scan_details;
 };
 
 int load_ifs_binary(struct device *dev);
+int ifs_setup_wq(void);
+void ifs_destroy_wq(void);
+int do_core_test(int cpu, struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
new file mode 100644
index 000000000000..7793a01f7b94
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/nmi.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+static struct workqueue_struct *ifs_wq;
+static struct completion test_thread_done;
+static atomic_t siblings_in;
+static atomic_t siblings_out;
+static int cpu_sibl_ct;
+static bool scan_enabled = true;
+
+struct ifs_work {
+	struct work_struct w;
+	struct device *dev;
+};
+
+/* Max retries on the same chunk */
+#define MAX_IFS_RETRIES  5
+
+static unsigned long msec_to_tsc(unsigned long msec)
+{
+	return tsc_khz * 1000 * msec / MSEC_PER_SEC;
+}
+
+enum ifs_status_err_code {
+	IFS_NO_ERROR				= 0,
+	IFS_OTHER_THREAD_COULD_NOT_JOIN		= 1,
+	IFS_INTERRUPTED_BEFORE_RENDEZVOUS	= 2,
+	IFS_POWER_MGMT_INADEQUATE_FOR_SCAN	= 3,
+	IFS_INVALID_CHUNK_RANGE			= 4,
+	IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS	= 5,
+	IFS_CORE_NOT_CAPABLE_CURRENTLY		= 6,
+	IFS_UNASSIGNED_ERROR_CODE		= 7,
+	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT	= 8,
+	IFS_INTERRUPTED_DURING_EXECUTION	= 9,
+};
+
+static const char * const scan_test_status[] = {
+	[IFS_NO_ERROR] = "SCAN no error",
+	[IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.",
+	[IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.",
+	[IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] =
+	"Core Abort SCAN Response due to power management condition.",
+	[IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range",
+	[IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.",
+	[IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently",
+	[IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7",
+	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
+	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
+	[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start",
+};
+
+static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
+{
+	if (status.error_code < ARRAY_SIZE(scan_test_status))
+		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 scan_test_status[status.error_code]);
+	else if (status.error_code == IFS_SW_TIMEOUT)
+		dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	else if (status.error_code == IFS_SW_PARTIAL_COMPLETION)
+		dev_info(dev, "CPU(s) %*pbl: %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 "Not all scan chunks were executed. Maximum forward progress retries exceeded");
+	else
+		dev_info(dev, "CPU(s) %*pbl: SCAN unknown status %llx\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)), status.data);
+}
+
+static void message_fail(struct device *dev, int cpu, union ifs_status status)
+{
+	/*
+	 * control_error is set when the microcode runs into a problem
+	 * loading the image from the reserved BIOS memory, or it has
+	 * been corrupted. Reloading the image may fix this issue.
+	 */
+	if (status.control_error) {
+		dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+
+	/*
+	 * signature_error is set when the output from the scan chains does not
+	 * match the expected signature. This might be a transient problem (e.g.
+	 * due to a bit flip from an alpha particle or neutron). If the problem
+	 * repeats on a subsequent test, then it indicates an actual problem in
+	 * the core being tested.
+	 */
+	if (status.signature_error) {
+		dev_err(dev, "CPU(s) %*pbl: test signature incorrect.\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+}
+
+static bool can_restart(union ifs_status status)
+{
+	enum ifs_status_err_code err_code = status.error_code;
+
+	/* Signature for chunk is bad, or scan test failed */
+	if (status.signature_error || status.control_error)
+		return false;
+
+	switch (err_code) {
+	case IFS_NO_ERROR:
+	case IFS_OTHER_THREAD_COULD_NOT_JOIN:
+	case IFS_INTERRUPTED_BEFORE_RENDEZVOUS:
+	case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN:
+	case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT:
+	case IFS_INTERRUPTED_DURING_EXECUTION:
+		return true;
+	case IFS_INVALID_CHUNK_RANGE:
+	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
+	case IFS_CORE_NOT_CAPABLE_CURRENTLY:
+	case IFS_UNASSIGNED_ERROR_CODE:
+		break;
+	}
+	return false;
+}
+
+static bool wait_for_siblings(struct device *dev, struct ifs_data *ifsd, atomic_t *t, long long timeout)
+{
+	atomic_inc(t);
+	while (atomic_read(t) < cpu_sibl_ct) {
+		if (timeout < SPINUNIT) {
+			dev_err(dev,
+				"Timeout while waiting for CPUs rendezvous, remaining: %d\n",
+				cpu_sibl_ct - atomic_read(t));
+			return false;
+		}
+
+		ndelay(SPINUNIT);
+		timeout -= SPINUNIT;
+
+		touch_nmi_watchdog();
+	}
+
+	return true;
+}
+
+/*
+ * When a Scan test (for a particular core) is triggered by the user, worker threads
+ * for each sibling cpus(belonging to that core) are queued to execute this function in
+ * the Workqueue (ifs_wq) context.
+ * Wait for the sibling thread to join before the execution.
+ * Execute the scan test by running wrmsr(MSR_ACTIVATE_SCAN).
+ */
+static void ifs_work_func(struct work_struct *work)
+{
+	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
+	int cpu = smp_processor_id();
+	union ifs_scan activate;
+	union ifs_status status;
+	unsigned long timeout;
+	struct ifs_data *ifsd;
+	struct device *dev;
+	int retries;
+	u32 first;
+
+	dev = local_work->dev;
+	ifsd = dev_get_drvdata(dev);
+
+	activate.rsvd = 0;
+	activate.delay = msec_to_tsc(THREAD_WAIT);
+	activate.sigmce = 0;
+
+	/*
+	 * Need to get (and keep) the threads on this core executing close together
+	 * 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 = cpumask_first(topology_sibling_cpumask(cpu));
+	if (!wait_for_siblings(dev, ifsd, &siblings_in, NSEC_PER_SEC)) {
+		preempt_enable();
+		dev_err(dev, "cpu %d sibling did not join rendezvous\n", cpu);
+		goto out;
+	}
+
+	activate.start = 0;
+	activate.stop = ifsd->valid_chunks - 1;
+	timeout = jiffies + HZ / 2;
+	retries = MAX_IFS_RETRIES;
+
+	while (activate.start <= activate.stop) {
+		if (time_after(jiffies, timeout)) {
+			status.error_code = IFS_SW_TIMEOUT;
+			break;
+		}
+
+		local_irq_disable();
+		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
+		local_irq_enable();
+
+		/*
+		 * All logical CPUs on this core are now running IFS test. When it completes
+		 * execution or is interrupted, the following RDMSR gets the scan status.
+		 */
+
+		rdmsrl(MSR_SCAN_STATUS, status.data);
+
+		/* Some cases can be retried, give up for others */
+		if (!can_restart(status))
+			break;
+
+		if (status.chunk_num == activate.start) {
+			/* Check for forward progress */
+			if (retries-- == 0) {
+				if (status.error_code == IFS_NO_ERROR)
+					status.error_code = IFS_SW_PARTIAL_COMPLETION;
+				break;
+			}
+		} else {
+			retries = MAX_IFS_RETRIES;
+			activate.start = status.chunk_num;
+		}
+	}
+
+	preempt_enable();
+
+	if (cpu == first) {
+		/* Update status for this core */
+		ifsd->scan_details = status.data;
+
+		if (status.control_error || status.signature_error) {
+			ifsd->status = SCAN_TEST_FAIL;
+			message_fail(dev, cpu, status);
+		} else if (status.error_code) {
+			ifsd->status = SCAN_NOT_TESTED;
+			message_not_tested(dev, cpu, status);
+		} else {
+			ifsd->status = SCAN_TEST_PASS;
+		}
+	}
+
+	if (!wait_for_siblings(dev, ifsd, &siblings_out, NSEC_PER_SEC))
+		dev_err(dev, "cpu %d sibling did not exit rendezvous\n", cpu);
+
+out:
+	if (cpu == first)
+		complete(&test_thread_done);
+}
+
+/*
+ * Initiate per core test. It wakes up work queue threads on the target cpu and
+ * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
+ * wait for all sibling threads to finish the scan test.
+ */
+int do_core_test(int cpu, struct device *dev)
+{
+	struct ifs_work *local_work;
+	int sibling;
+	int ret = 0;
+	int i = 0;
+
+	if (!scan_enabled)
+		return -ENXIO;
+
+	cpu_hotplug_disable();
+	if (!cpu_online(cpu)) {
+		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	reinit_completion(&test_thread_done);
+	atomic_set(&siblings_in, 0);
+	atomic_set(&siblings_out, 0);
+
+	cpu_sibl_ct = cpumask_weight(topology_sibling_cpumask(cpu));
+	local_work = kcalloc(cpu_sibl_ct, sizeof(*local_work), GFP_NOWAIT);
+	if (!local_work) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for_each_cpu(sibling, topology_sibling_cpumask(cpu)) {
+		local_work[i].dev = dev;
+		INIT_WORK(&local_work[i].w, ifs_work_func);
+		queue_work_on(sibling, ifs_wq, &local_work[i].w);
+		i++;
+	}
+
+	if (wait_for_completion_timeout(&test_thread_done, HZ) == 0) {
+		dev_err(dev, "cpu %d Core locked up during IFS test? IFS disabled\n", cpu);
+		scan_enabled = false;
+	}
+
+	kfree(local_work);
+out:
+	cpu_hotplug_enable();
+	return ret;
+}
+
+int ifs_setup_wq(void)
+{
+	/* Flags are to keep all the sibling cpu worker threads (of a core) in close sync */
+	ifs_wq = alloc_workqueue("intel_ifs", (WQ_HIGHPRI | WQ_CPU_INTENSIVE), 1);
+	if (!ifs_wq)
+		return -ENOMEM;
+
+	init_completion(&test_thread_done);
+
+	return 0;
+}
+
+void ifs_destroy_wq(void)
+{
+	destroy_workqueue(ifs_wq);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (7 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-19 17:20     ` Greg KH
  2022-04-19 16:38   ` [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
                     ` (2 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Implement sysfs interface to trigger ifs test for a specific cpu.
Additional interfaces related to checking the status of the
scan test and seeing the version of the loaded IFS binary
are also added.

The basic usage is as below.
   - To start test, for example on cpu5:
       echo 5 > /sys/devices/platform/intel_ifs/run_test
   - To see the status of the last test
       cat /sys/devices/platform/intel_ifs/status
   - To see the version of the loaded scan binary
       cat /sys/devices/platform/intel_ifs/image_version

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/core.c    |   9 ++
 drivers/platform/x86/intel/ifs/ifs.h     |   3 +
 drivers/platform/x86/intel/ifs/runtest.c |   7 ++
 drivers/platform/x86/intel/ifs/sysfs.c   | 151 +++++++++++++++++++++++
 5 files changed, 171 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 7de27361b479..dbbe0bf66987 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -2,4 +2,4 @@ obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
 
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o runtest.o
+intel_ifs-objs			:= core.o load.o runtest.o sysfs.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 0dc4cdda35ff..f56cde0cdfd6 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -3,6 +3,7 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/semaphore.h>
 
 #include "ifs.h"
 
@@ -26,10 +27,18 @@ static int ifs_probe(struct platform_device *pdev)
 	return 0;
 }
 
+/*
+ * Note there is no need for a ->remove() call back. There isn't an
+ * "unload" operation to remove the scan binary from the BIOS reserved
+ * area. Also ".dev_groups" removal order will guarantee that any in
+ * flight tests have completed.
+ */
+
 static struct platform_driver intel_ifs_driver = {
 	.probe = ifs_probe,
 	.driver = {
 		.name = "intel_ifs",
+		.dev_groups = plat_ifs_groups,
 	},
 };
 
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index f5e3636d709f..4e6662f2d2f8 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -97,4 +97,7 @@ int ifs_setup_wq(void);
 void ifs_destroy_wq(void);
 int do_core_test(int cpu, struct device *dev);
 
+extern const struct attribute_group *plat_ifs_groups[];
+extern struct semaphore ifs_sem;
+
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index 7793a01f7b94..246eff250563 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -10,6 +10,13 @@
 
 #include "ifs.h"
 
+/*
+ * Note all code and data in this file is protected by
+ * ifs_sem. On HT systems all threads on a core will
+ * execute together, but only the first thread on the
+ * core will update results of the test and indicate
+ * completion.
+ */
 static struct workqueue_struct *ifs_wq;
 static struct completion test_thread_done;
 static atomic_t siblings_in;
diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
new file mode 100644
index 000000000000..41db2a12fbc8
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Protects against simultaneous tests on multiple cores, or
+ * reloading can file while a test is in progress
+ */
+DEFINE_SEMAPHORE(ifs_sem);
+
+/*
+ * The sysfs interface to check additional details of last test
+ * cat /sys/devices/system/platform/ifs/details
+ */
+static ssize_t details_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct ifs_data *ifsd = dev_get_drvdata(dev);
+
+	return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
+}
+
+static DEVICE_ATTR_RO(details);
+
+static const char * const status_msg[] = {
+	[SCAN_NOT_TESTED] = "untested",
+	[SCAN_TEST_PASS] = "pass",
+	[SCAN_TEST_FAIL] = "fail"
+};
+
+/*
+ * The sysfs interface to check the test status:
+ * To check the status of last test
+ * cat /sys/devices/platform/ifs/status
+ */
+static ssize_t status_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ifs_data *ifsd = dev_get_drvdata(dev);
+
+	return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
+}
+
+static DEVICE_ATTR_RO(status);
+
+/*
+ * The sysfs interface for single core testing
+ * To start test, for example, cpu5
+ * echo 5 > /sys/devices/platform/ifs/run_test
+ * To check the result:
+ * cat /sys/devices/platform/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)
+{
+	struct ifs_data *ifsd = dev_get_drvdata(dev);
+	unsigned int cpu;
+	int rc;
+
+	rc = kstrtouint(buf, 0, &cpu);
+	if (rc < 0 || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	if (!ifsd->loaded)
+		rc = -EPERM;
+	else
+		rc = do_core_test(cpu, dev);
+
+	up(&ifs_sem);
+
+	return rc ? rc : count;
+}
+
+static DEVICE_ATTR_WO(run_test);
+
+/*
+ * Reload the IFS image. When user wants to install new IFS image
+ */
+static ssize_t reload_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct ifs_data *ifsd = dev_get_drvdata(dev);
+	int rc;
+
+	if (!sysfs_streq(buf, "1"))
+		return -EINVAL;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	rc = load_ifs_binary(dev);
+
+	ifsd->loaded = (rc == 0);
+
+	up(&ifs_sem);
+
+	return rc ? rc : count;
+}
+
+static DEVICE_ATTR_WO(reload);
+
+/*
+ * Display currently loaded IFS image version.
+ */
+static ssize_t image_version_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct ifs_data *ifsd = dev_get_drvdata(dev);
+
+	if (!ifsd->loaded)
+		return sysfs_emit(buf, "%s\n", "none");
+	else
+		return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
+}
+
+static DEVICE_ATTR_RO(image_version);
+
+/* global scan sysfs attributes */
+static struct attribute *plat_ifs_attrs[] = {
+	&dev_attr_details.attr,
+	&dev_attr_status.attr,
+	&dev_attr_run_test.attr,
+	&dev_attr_reload.attr,
+	&dev_attr_image_version.attr,
+	NULL
+};
+
+static const struct attribute_group plat_ifs_attr_group = {
+	.attrs = plat_ifs_attrs,
+};
+
+const struct attribute_group *plat_ifs_groups[] = {
+	&plat_ifs_attr_group,
+	NULL
+};
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (8 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-20 23:38     ` Steven Rostedt
  2022-04-19 16:38   ` [PATCH v3 11/11] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Add tracing support which may be useful for debugging systems that fail to complete
In Field Scan tests.

Reviewed-by: Dan Williams <dan.j.williams@intel.com
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 MAINTAINERS                              |  1 +
 drivers/platform/x86/intel/ifs/runtest.c |  5 ++++
 include/trace/events/intel_ifs.h         | 38 ++++++++++++++++++++++++
 3 files changed, 44 insertions(+)
 create mode 100644 include/trace/events/intel_ifs.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e372a960fa5..b488ff628a43 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9867,6 +9867,7 @@ R:	Ashok Raj <ashok.raj@intel.com>
 R:	Tony Luck <tony.luck@intel.com>
 S:	Maintained
 F:	drivers/platform/x86/intel/ifs
+F:	include/trace/events/intel_ifs.h
 
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index 246eff250563..c6fa9385dda0 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -24,6 +24,9 @@ static atomic_t siblings_out;
 static int cpu_sibl_ct;
 static bool scan_enabled = true;
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ifs.h>
+
 struct ifs_work {
 	struct work_struct w;
 	struct device *dev;
@@ -217,6 +220,8 @@ static void ifs_work_func(struct work_struct *work)
 
 		rdmsrl(MSR_SCAN_STATUS, status.data);
 
+		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/intel_ifs.h b/include/trace/events/intel_ifs.h
new file mode 100644
index 000000000000..0611f370cb37
--- /dev/null
+++ b/include/trace/events/intel_ifs.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ifs
+
+#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IFS_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ifs_status,
+
+	TP_PROTO(union ifs_scan activate, union ifs_status status),
+
+	TP_ARGS(activate, status),
+
+	TP_STRUCT__entry(
+		__field(	u64,	status	)
+		__field(	u8,	start	)
+		__field(	u8,	stop	)
+	),
+
+	TP_fast_assign(
+		__entry->start	= activate.start;
+		__entry->stop	= activate.stop;
+		__entry->status	= 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 <trace/define_trace.h>
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v3 11/11] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (9 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-04-19 16:38   ` Tony Luck
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-19 16:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Add the sysfs attributes in ABI/testing for In-Field Scan.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 .../ABI/testing/sysfs-platform-intel-ifs      | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
new file mode 100644
index 000000000000..7a753c9f2dd7
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -0,0 +1,39 @@
+What:		/sys/devices/platform/intel_ifs.<N>/run_test
+Date:		April 13, 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write <cpu#> to trigger IFS test for one online core.
+		Note that the test is per core. The cpu# can be
+		for any thread on the core. Running on one thread
+		completes the test for the core containing that thread.
+		Example: to test the core containing cpu5: echo 5 >
+		/sys/devices/platform/intel_ifs.<N>/run_test
+
+What:		/sys/devices/platform/intel_ifs.<N>/status
+Date:		April 13, 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	The status of the last test. It can be one of "pass", "fail"
+		or "untested".
+
+What:		/sys/devices/system/cpu/cpu#/ifs.<N>/details
+Date:		April 13, 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Additional information regarding the last test. 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.
+
+What:		/sys/devices/platform/intel_ifs.<N>/image_version
+Date:		April 13, 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Version (hexadecimal) of loaded IFS binary image. If no scan image
+		is loaded reports "none".
+
+What:		/sys/bus/platform/drivers/intel_ifs.<N>/reload
+Date:		April 13, 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write "1" > reload to reload IFS image from
+		/lib/firmware/intel/ifs/ff-mm-ss.scan.
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-19 16:38   ` [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan) Tony Luck
@ 2022-04-19 16:47     ` Greg KH
  2022-04-19 18:09       ` Dan Williams
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-19 16:47 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 09:38:51AM -0700, Tony Luck wrote:
> The initial implementation of IFS is model specific. Enumeration is
> via a combination of family-model-stepping and a check for a bit in the
> CORE_CAPABILITIES MSR.
> 
> Linux has handled this lack of enumeration before with a code stub to
> create a device.  See arch/x86/kernel/pmem.c. Use the same approach
> here.

Ick, why?  Why not just create a simple virtual device and use that?  Do
you really want to bind a driver to this?  Or do you already "know" the
only driver that you have will bind to this?

pmem.c should not be used as a good example of anything, sorry.

greg k-h


> 
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  MAINTAINERS                                   |  7 +++
>  drivers/platform/x86/intel/Kconfig            |  1 +
>  drivers/platform/x86/intel/Makefile           |  1 +
>  drivers/platform/x86/intel/ifs/Kconfig        |  2 +
>  drivers/platform/x86/intel/ifs/Makefile       |  1 +
>  .../platform/x86/intel/ifs/intel_ifs_device.c | 50 +++++++++++++++++++
>  6 files changed, 62 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/intel_ifs_device.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 40fa1955ca3f..9e372a960fa5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9861,6 +9861,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
>  
> +INTEL IN FIELD SCAN (IFS) DRIVER
> +M:	Jithu Joseph <jithu.joseph@intel.com>
> +R:	Ashok Raj <ashok.raj@intel.com>
> +R:	Tony Luck <tony.luck@intel.com>
> +S:	Maintained
> +F:	drivers/platform/x86/intel/ifs
> +
>  INTEL INTEGRATED SENSOR HUB DRIVER
>  M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
>  M:	Jiri Kosina <jikos@kernel.org>
> diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
> index 1f01a8a23c57..794968bda115 100644
> --- a/drivers/platform/x86/intel/Kconfig
> +++ b/drivers/platform/x86/intel/Kconfig
> @@ -4,6 +4,7 @@
>  #
>  
>  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/int3472/Kconfig"
>  source "drivers/platform/x86/intel/pmc/Kconfig"
> diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
> index c61bc3e97121..10285d0fd16a 100644
> --- a/drivers/platform/x86/intel/Makefile
> +++ b/drivers/platform/x86/intel/Makefile
> @@ -5,6 +5,7 @@
>  #
>  
>  obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
> +obj-y					+= ifs/
>  obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
>  obj-$(CONFIG_INTEL_SKL_INT3472)		+= int3472/
>  obj-$(CONFIG_INTEL_PMC_CORE)		+= pmc/
> diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
> new file mode 100644
> index 000000000000..51325b699563
> --- /dev/null
> +++ b/drivers/platform/x86/intel/ifs/Kconfig
> @@ -0,0 +1,2 @@
> +config INTEL_IFS_DEVICE
> +	bool
> diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
> new file mode 100644
> index 000000000000..12c2f5ce9925
> --- /dev/null
> +++ b/drivers/platform/x86/intel/ifs/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
> diff --git a/drivers/platform/x86/intel/ifs/intel_ifs_device.c b/drivers/platform/x86/intel/ifs/intel_ifs_device.c
> new file mode 100644
> index 000000000000..64a143871d72
> --- /dev/null
> +++ b/drivers/platform/x86/intel/ifs/intel_ifs_device.c
> @@ -0,0 +1,50 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright(c) 2022 Intel Corporation. */
> +
> +#include <linux/platform_device.h>
> +#include <linux/init.h>
> +#include <asm/cpu_device_id.h>
> +
> +#define MSR_IA32_CORE_CAPS_INTEGRITY_BIT	2
> +#define MSR_IA32_CORE_CAPS_INTEGRITY		BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT)
> +
> +#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 = {
> +	X86_MATCH(SAPPHIRERAPIDS_X),
> +	{}
> +};
> +
> +static __init int register_ifs_device(void)
> +{
> +	struct platform_device *pdev;
> +	const struct x86_cpu_id *m;
> +	u64 ia32_core_caps;
> +
> +	m = 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) {
> +		pdev = platform_device_alloc("intel_ifs", 0);
> +		if (pdev) {
> +			if (platform_device_add(pdev))
> +				platform_device_put(pdev);
> +		}
> +	}
> +
> +	/*
> +	 * Failure here will be visible by a missing device
> +	 * in sysfs. Returning an error code would not make
> +	 * that any easier to diagnose. Would also complicate
> +	 * future implementations that may support a subset of
> +	 * the types of tests.
> +	 */
> +	return 0;

So even if everything fails, you succeed?  But you are failing above for
some cases, so why is creating the device somehow special here that you
should succeed no matter what?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 02/11] Documentation: In-Field Scan
  2022-04-19 16:38   ` [PATCH v3 02/11] Documentation: In-Field Scan Tony Luck
@ 2022-04-19 16:48     ` Greg KH
  2022-04-19 19:45       ` Dan Williams
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-19 16:48 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 09:38:50AM -0700, Tony Luck wrote:
> 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.
> 
> The full  github location for distributing the IFS images is
> still being decided. So just a placeholder included for now
> in the documentation.
> 
> Future CPUs will support more than one type of test. Plan for
> that now by using a ".0" suffix on the ABI directory names.
> Additional test types will use ".1", etc.
> 
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  Documentation/x86/ifs.rst   | 101 ++++++++++++++++++++++++++++++++++++
>  Documentation/x86/index.rst |   1 +
>  2 files changed, 102 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..62f3c07d433a
> --- /dev/null
> +++ b/Documentation/x86/ifs.rst
> @@ -0,0 +1,101 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +=============
> +In-Field Scan
> +=============
> +
> +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.
> +Future CPUs will support more than one type of test which will show up
> +with a new platform-device instance-id, for now only .0 is exposed.
> +
> +
> +IFS Image
> +---------
> +
> +Intel provides a firmware file containing the scan tests via
> +github [#f1]_.  Similar to microcode there is a separate file for each
> +family-model-stepping.
> +
> +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 by writing to the driver reload file::
> +
> +  # echo 1 > /sys/bus/platform/drivers/intel_ifs.0/reload
> +
> +Similar to microcode, the current version of the scan tests is stored
> +in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan
> +
> +Running tests
> +-------------
> +
> +Tests are run by the driver 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. The driver makes the value of this MSR visible to applications
> +via the "details" file (see below). Interrupted tests may be restarted.
> +
> +The IFS driver provides sysfs interfaces via /sys/devices/platform/intel_ifs.0/
> +to control execution:
> +
> +Test a specific core::
> +
> +  # echo <cpu#> > /sys/devices/platform/intel_ifs.0/run_test
> +
> +when HT is enabled any of the sibling cpu# can be specified to test its
> +corresponding physical core. Since the tests are per physical core, the
> +result of testing any thread is same. It is only necessary to test one
> +thread.
> +
> +For e.g. to test core corresponding to cpu5
> +
> +  # echo 5 > /sys/devices/platform/intel_ifs.0/run_test
> +
> +Results of the last test is provided in /sys::
> +
> +  $ cat /sys/devices/platform/intel_ifs.0/status
> +  pass

sysfs documentation belongs in Documentation/ABI/

And why not just include this whole thing in the driver itself and suck
the documentation out of that?  No need to have a separate file.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 05/11] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-19 16:38   ` [PATCH v3 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-04-19 17:14     ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-19 17:14 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 09:38:53AM -0700, Tony Luck wrote:
> +/*
> + * Load ifs image. Before loading ifs module, the ifs image must be located
> + * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
> + */
> +int load_ifs_binary(struct device *dev)

Shouldn't all of your global symbols start with "ifs_"?  Your other ones
seem to, what went wrong here?

Also, how about "ifs_load_firmware()" makes more sense.

thanks,

greg "naming is hard" k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 06/11] platform/x86/intel/ifs: Check IFS Image sanity
  2022-04-19 16:38   ` [PATCH v3 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-04-19 17:16     ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-19 17:16 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 09:38:54AM -0700, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
> 
> 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.
> 
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  drivers/platform/x86/intel/ifs/load.c | 69 +++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
> index fa6c64707a73..b05d9055c391 100644
> --- a/drivers/platform/x86/intel/ifs/load.c
> +++ b/drivers/platform/x86/intel/ifs/load.c
> @@ -3,9 +3,73 @@
>  
>  #include <linux/firmware.h>
>  #include <linux/platform_device.h>
> +#include <asm/cpu.h>
> +#include <asm/microcode_intel.h>
>  
>  static const char *ifs_path = "intel/ifs/";
>  
> +static int ifs_sanity_check(struct device *dev, void *mc)
> +{
> +	struct microcode_header_intel *mc_header = mc;
> +	unsigned long total_size, data_size;
> +	u32 sum, i;
> +
> +	total_size = get_totalsize(mc_header);
> +	data_size = get_datasize(mc_header);
> +
> +	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
> +		dev_err(dev, "bad ifs data file size.\n");
> +		return -EINVAL;
> +	}
> +
> +	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
> +		dev_err(dev, "invalid/unknown ifs update format.\n");
> +		return -EINVAL;
> +	}
> +
> +	sum = 0;
> +	i = total_size / sizeof(u32);
> +	while (i--)
> +		sum += ((u32 *)mc)[i];
> +
> +	if (sum) {
> +		dev_err(dev, "bad ifs data checksum, aborting.\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci, void *mc)
> +{
> +	struct microcode_header_intel *shdr;
> +	unsigned int mc_size;
> +
> +	shdr = (struct microcode_header_intel *)mc;
> +	mc_size = get_totalsize(shdr);
> +
> +	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
> +		dev_err(dev, "ifs sanity check failure\n");
> +		return false;
> +	}
> +
> +	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
> +		dev_err(dev, "ifs signature, pf not matching\n");
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +static bool ifs_image_sanity_check(struct device *dev, void *data)

u8 *data?

> +{
> +	struct ucode_cpu_info uci;
> +
> +	intel_cpu_collect_info_early(&uci);
> +
> +	return find_ifs_matching_signature(dev, &uci, data);
> +}
> +
>  /*
>   * Load ifs image. Before loading ifs module, the ifs image must be located
>   * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
> @@ -25,6 +89,11 @@ int load_ifs_binary(struct device *dev)
>  		return ret;
>  	}
>  
> +	if (!ifs_image_sanity_check(dev, (void *)fw->data)) {

It's not a void pointer, it's a pointer to u8.  Why cast it away?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-19 16:38   ` [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-04-19 17:20     ` Greg KH
  2022-04-19 17:35       ` Luck, Tony
  2022-04-19 18:24       ` Dan Williams
  0 siblings, 2 replies; 152+ messages in thread
From: Greg KH @ 2022-04-19 17:20 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 09:38:57AM -0700, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
> 
> Implement sysfs interface to trigger ifs test for a specific cpu.
> Additional interfaces related to checking the status of the
> scan test and seeing the version of the loaded IFS binary
> are also added.
> 
> The basic usage is as below.
>    - To start test, for example on cpu5:
>        echo 5 > /sys/devices/platform/intel_ifs/run_test
>    - To see the status of the last test
>        cat /sys/devices/platform/intel_ifs/status
>    - To see the version of the loaded scan binary
>        cat /sys/devices/platform/intel_ifs/image_version
> 
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  drivers/platform/x86/intel/ifs/Makefile  |   2 +-
>  drivers/platform/x86/intel/ifs/core.c    |   9 ++
>  drivers/platform/x86/intel/ifs/ifs.h     |   3 +
>  drivers/platform/x86/intel/ifs/runtest.c |   7 ++
>  drivers/platform/x86/intel/ifs/sysfs.c   | 151 +++++++++++++++++++++++
>  5 files changed, 171 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 7de27361b479..dbbe0bf66987 100644
> --- a/drivers/platform/x86/intel/ifs/Makefile
> +++ b/drivers/platform/x86/intel/ifs/Makefile
> @@ -2,4 +2,4 @@ obj-$(CONFIG_INTEL_IFS_DEVICE)	+= intel_ifs_device.o
>  
>  obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
>  
> -intel_ifs-objs			:= core.o load.o runtest.o
> +intel_ifs-objs			:= core.o load.o runtest.o sysfs.o
> diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
> index 0dc4cdda35ff..f56cde0cdfd6 100644
> --- a/drivers/platform/x86/intel/ifs/core.c
> +++ b/drivers/platform/x86/intel/ifs/core.c
> @@ -3,6 +3,7 @@
>  
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
> +#include <linux/semaphore.h>
>  
>  #include "ifs.h"
>  
> @@ -26,10 +27,18 @@ static int ifs_probe(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +/*
> + * Note there is no need for a ->remove() call back. There isn't an
> + * "unload" operation to remove the scan binary from the BIOS reserved
> + * area. Also ".dev_groups" removal order will guarantee that any in
> + * flight tests have completed.
> + */

So you are ok with the warning the kernel gives you when you unload the
driver?  That feels wrong :(

> +
>  static struct platform_driver intel_ifs_driver = {
>  	.probe = ifs_probe,
>  	.driver = {
>  		.name = "intel_ifs",
> +		.dev_groups = plat_ifs_groups,
>  	},
>  };
>  
> diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
> index f5e3636d709f..4e6662f2d2f8 100644
> --- a/drivers/platform/x86/intel/ifs/ifs.h
> +++ b/drivers/platform/x86/intel/ifs/ifs.h
> @@ -97,4 +97,7 @@ int ifs_setup_wq(void);
>  void ifs_destroy_wq(void);
>  int do_core_test(int cpu, struct device *dev);
>  
> +extern const struct attribute_group *plat_ifs_groups[];
> +extern struct semaphore ifs_sem;
> +
>  #endif
> diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
> index 7793a01f7b94..246eff250563 100644
> --- a/drivers/platform/x86/intel/ifs/runtest.c
> +++ b/drivers/platform/x86/intel/ifs/runtest.c
> @@ -10,6 +10,13 @@
>  
>  #include "ifs.h"
>  
> +/*
> + * Note all code and data in this file is protected by
> + * ifs_sem. On HT systems all threads on a core will
> + * execute together, but only the first thread on the
> + * core will update results of the test and indicate
> + * completion.
> + */
>  static struct workqueue_struct *ifs_wq;
>  static struct completion test_thread_done;
>  static atomic_t siblings_in;
> diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
> new file mode 100644
> index 000000000000..41db2a12fbc8
> --- /dev/null
> +++ b/drivers/platform/x86/intel/ifs/sysfs.c
> @@ -0,0 +1,151 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright(c) 2022 Intel Corporation. */
> +
> +#include <linux/cpu.h>
> +#include <linux/delay.h>
> +#include <linux/fs.h>
> +#include <linux/platform_device.h>
> +#include <linux/semaphore.h>
> +#include <linux/slab.h>
> +
> +#include "ifs.h"
> +
> +/*
> + * Protects against simultaneous tests on multiple cores, or
> + * reloading can file while a test is in progress
> + */
> +DEFINE_SEMAPHORE(ifs_sem);
> +
> +/*
> + * The sysfs interface to check additional details of last test
> + * cat /sys/devices/system/platform/ifs/details
> + */
> +static ssize_t details_show(struct device *dev,
> +			    struct device_attribute *attr,
> +			    char *buf)
> +{
> +	struct ifs_data *ifsd = dev_get_drvdata(dev);
> +
> +	return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
> +}
> +
> +static DEVICE_ATTR_RO(details);
> +
> +static const char * const status_msg[] = {
> +	[SCAN_NOT_TESTED] = "untested",
> +	[SCAN_TEST_PASS] = "pass",
> +	[SCAN_TEST_FAIL] = "fail"
> +};
> +
> +/*
> + * The sysfs interface to check the test status:
> + * To check the status of last test
> + * cat /sys/devices/platform/ifs/status
> + */
> +static ssize_t status_show(struct device *dev,
> +			   struct device_attribute *attr,
> +			   char *buf)
> +{
> +	struct ifs_data *ifsd = dev_get_drvdata(dev);
> +
> +	return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
> +}
> +
> +static DEVICE_ATTR_RO(status);
> +
> +/*
> + * The sysfs interface for single core testing
> + * To start test, for example, cpu5
> + * echo 5 > /sys/devices/platform/ifs/run_test
> + * To check the result:
> + * cat /sys/devices/platform/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)
> +{
> +	struct ifs_data *ifsd = dev_get_drvdata(dev);
> +	unsigned int cpu;
> +	int rc;
> +
> +	rc = kstrtouint(buf, 0, &cpu);
> +	if (rc < 0 || cpu >= nr_cpu_ids)
> +		return -EINVAL;
> +
> +	if (down_interruptible(&ifs_sem))
> +		return -EINTR;
> +
> +	if (!ifsd->loaded)
> +		rc = -EPERM;
> +	else
> +		rc = do_core_test(cpu, dev);
> +
> +	up(&ifs_sem);
> +
> +	return rc ? rc : count;
> +}
> +
> +static DEVICE_ATTR_WO(run_test);
> +
> +/*
> + * Reload the IFS image. When user wants to install new IFS image
> + */
> +static ssize_t reload_store(struct device *dev,
> +			    struct device_attribute *attr,
> +			    const char *buf, size_t count)
> +{
> +	struct ifs_data *ifsd = dev_get_drvdata(dev);
> +	int rc;
> +
> +	if (!sysfs_streq(buf, "1"))

kstrtobool()?

> +		return -EINVAL;
> +
> +	if (down_interruptible(&ifs_sem))
> +		return -EINTR;
> +
> +	rc = load_ifs_binary(dev);
> +
> +	ifsd->loaded = (rc == 0);
> +
> +	up(&ifs_sem);
> +
> +	return rc ? rc : count;
> +}
> +
> +static DEVICE_ATTR_WO(reload);
> +
> +/*
> + * Display currently loaded IFS image version.
> + */
> +static ssize_t image_version_show(struct device *dev,
> +				  struct device_attribute *attr, char *buf)
> +{
> +	struct ifs_data *ifsd = dev_get_drvdata(dev);
> +
> +	if (!ifsd->loaded)
> +		return sysfs_emit(buf, "%s\n", "none");
> +	else
> +		return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
> +}
> +
> +static DEVICE_ATTR_RO(image_version);
> +
> +/* global scan sysfs attributes */
> +static struct attribute *plat_ifs_attrs[] = {
> +	&dev_attr_details.attr,
> +	&dev_attr_status.attr,
> +	&dev_attr_run_test.attr,
> +	&dev_attr_reload.attr,
> +	&dev_attr_image_version.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group plat_ifs_attr_group = {
> +	.attrs = plat_ifs_attrs,
> +};
> +
> +const struct attribute_group *plat_ifs_groups[] = {
> +	&plat_ifs_attr_group,
> +	NULL
> +};

ATTRIBUTE_GROUPS()?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-19 17:20     ` Greg KH
@ 2022-04-19 17:35       ` Luck, Tony
  2022-04-19 17:58         ` Greg KH
  2022-04-19 18:24       ` Dan Williams
  1 sibling, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-19 17:35 UTC (permalink / raw)
  To: Greg KH
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 07:20:54PM +0200, Greg KH wrote:
> > +/*
> > + * Note there is no need for a ->remove() call back. There isn't an
> > + * "unload" operation to remove the scan binary from the BIOS reserved
> > + * area. Also ".dev_groups" removal order will guarantee that any in
> > + * flight tests have completed.
> > + */
> 
> So you are ok with the warning the kernel gives you when you unload the
> driver?  That feels wrong :(

What warning?

# dmesg | tail -5
[   38.084165] virbr0: port 1(virbr0-nic) entered listening state
[   38.149621] virbr0: port 1(virbr0-nic) entered disabled state
[   38.582054] broken atomic modeset userspace detected, disabling atomic
[   43.703321] igc 0000:01:00.0 enp1s0: NIC Link is Up 2500 Mbps Full Duplex, Flow Control: RX
[   43.703470] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready
# modprobe intel_ifs
# ls /sys/devices/platform/intel_ifs.0/
details  driver_override  modalias  reload    status     uevent
driver   image_version    power     run_test  subsystem
# rmmod intel_ifs
# dmesg | tail -5
[   38.084165] virbr0: port 1(virbr0-nic) entered listening state
[   38.149621] virbr0: port 1(virbr0-nic) entered disabled state
[   38.582054] broken atomic modeset userspace detected, disabling atomic
[   43.703321] igc 0000:01:00.0 enp1s0: NIC Link is Up 2500 Mbps Full Duplex, Flow Control: RX
[   43.703470] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready
#

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-19 17:35       ` Luck, Tony
@ 2022-04-19 17:58         ` Greg KH
  2022-04-19 18:15           ` Dan Williams
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-19 17:58 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 19, 2022 at 10:35:17AM -0700, Luck, Tony wrote:
> On Tue, Apr 19, 2022 at 07:20:54PM +0200, Greg KH wrote:
> > > +/*
> > > + * Note there is no need for a ->remove() call back. There isn't an
> > > + * "unload" operation to remove the scan binary from the BIOS reserved
> > > + * area. Also ".dev_groups" removal order will guarantee that any in
> > > + * flight tests have completed.
> > > + */
> > 
> > So you are ok with the warning the kernel gives you when you unload the
> > driver?  That feels wrong :(
> 
> What warning?
> 
> # dmesg | tail -5
> [   38.084165] virbr0: port 1(virbr0-nic) entered listening state
> [   38.149621] virbr0: port 1(virbr0-nic) entered disabled state
> [   38.582054] broken atomic modeset userspace detected, disabling atomic
> [   43.703321] igc 0000:01:00.0 enp1s0: NIC Link is Up 2500 Mbps Full Duplex, Flow Control: RX
> [   43.703470] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready
> # modprobe intel_ifs
> # ls /sys/devices/platform/intel_ifs.0/
> details  driver_override  modalias  reload    status     uevent
> driver   image_version    power     run_test  subsystem
> # rmmod intel_ifs
> # dmesg | tail -5
> [   38.084165] virbr0: port 1(virbr0-nic) entered listening state
> [   38.149621] virbr0: port 1(virbr0-nic) entered disabled state
> [   38.582054] broken atomic modeset userspace detected, disabling atomic
> [   43.703321] igc 0000:01:00.0 enp1s0: NIC Link is Up 2500 Mbps Full Duplex, Flow Control: RX
> [   43.703470] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready
> #

If there's no warning when the device goes away, why the crazy comment
trying to justify the lack of a remove callback?

confused,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-19 16:47     ` Greg KH
@ 2022-04-19 18:09       ` Dan Williams
  2022-04-19 22:28         ` Dan Williams
  2022-04-20  7:48         ` Greg KH
  0 siblings, 2 replies; 152+ messages in thread
From: Dan Williams @ 2022-04-19 18:09 UTC (permalink / raw)
  To: Greg KH
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 9:48 AM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Tue, Apr 19, 2022 at 09:38:51AM -0700, Tony Luck wrote:
> > The initial implementation of IFS is model specific. Enumeration is
> > via a combination of family-model-stepping and a check for a bit in the
> > CORE_CAPABILITIES MSR.
> >
> > Linux has handled this lack of enumeration before with a code stub to
> > create a device.  See arch/x86/kernel/pmem.c. Use the same approach
> > here.
>
> Ick, why?  Why not just create a simple virtual device and use that?  Do
> you really want to bind a driver to this?  Or do you already "know" the
> only driver that you have will bind to this?

With the realization that there may be multiple instances of an
IFS-like capability going forward, and that ideally those capabilities
would move away from a CPU capability bit to an ACPI description, then
it seemed to me that a simulated platform_device for this is a
reasonable fit. I.e. when / if an ACPI _HID is assigned for this
capability the same platform_driver can be reused for those instances.

> pmem.c should not be used as a good example of anything, sorry.

Yes, the arch/x86/kernel/pmem.c hack was supplanted by an ACPI device
description. There is no ACPI device description for the IFS
capability, yet.

So I saw these two cases as similar, that capabilities like this need
enumeration besides a CPU-id bit or an E820 table entry, and when they
move to an enumerable bus like ACPI a platform_driver is expected.

>
> greg k-h
>
>
> >
> > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> > Signed-off-by: Tony Luck <tony.luck@intel.com>
> > ---
> >  MAINTAINERS                                   |  7 +++
> >  drivers/platform/x86/intel/Kconfig            |  1 +
> >  drivers/platform/x86/intel/Makefile           |  1 +
> >  drivers/platform/x86/intel/ifs/Kconfig        |  2 +
> >  drivers/platform/x86/intel/ifs/Makefile       |  1 +
> >  .../platform/x86/intel/ifs/intel_ifs_device.c | 50 +++++++++++++++++++
> >  6 files changed, 62 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/intel_ifs_device.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 40fa1955ca3f..9e372a960fa5 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9861,6 +9861,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
> >
> > +INTEL IN FIELD SCAN (IFS) DRIVER
> > +M:   Jithu Joseph <jithu.joseph@intel.com>
> > +R:   Ashok Raj <ashok.raj@intel.com>
> > +R:   Tony Luck <tony.luck@intel.com>
> > +S:   Maintained
> > +F:   drivers/platform/x86/intel/ifs
> > +
> >  INTEL INTEGRATED SENSOR HUB DRIVER
> >  M:   Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> >  M:   Jiri Kosina <jikos@kernel.org>
> > diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
> > index 1f01a8a23c57..794968bda115 100644
> > --- a/drivers/platform/x86/intel/Kconfig
> > +++ b/drivers/platform/x86/intel/Kconfig
> > @@ -4,6 +4,7 @@
> >  #
> >
> >  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/int3472/Kconfig"
> >  source "drivers/platform/x86/intel/pmc/Kconfig"
> > diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
> > index c61bc3e97121..10285d0fd16a 100644
> > --- a/drivers/platform/x86/intel/Makefile
> > +++ b/drivers/platform/x86/intel/Makefile
> > @@ -5,6 +5,7 @@
> >  #
> >
> >  obj-$(CONFIG_INTEL_ATOMISP2_PDX86)   += atomisp2/
> > +obj-y                                        += ifs/
> >  obj-$(CONFIG_INTEL_SAR_INT1092)              += int1092/
> >  obj-$(CONFIG_INTEL_SKL_INT3472)              += int3472/
> >  obj-$(CONFIG_INTEL_PMC_CORE)         += pmc/
> > diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
> > new file mode 100644
> > index 000000000000..51325b699563
> > --- /dev/null
> > +++ b/drivers/platform/x86/intel/ifs/Kconfig
> > @@ -0,0 +1,2 @@
> > +config INTEL_IFS_DEVICE
> > +     bool
> > diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
> > new file mode 100644
> > index 000000000000..12c2f5ce9925
> > --- /dev/null
> > +++ b/drivers/platform/x86/intel/ifs/Makefile
> > @@ -0,0 +1 @@
> > +obj-$(CONFIG_INTEL_IFS_DEVICE)       += intel_ifs_device.o
> > diff --git a/drivers/platform/x86/intel/ifs/intel_ifs_device.c b/drivers/platform/x86/intel/ifs/intel_ifs_device.c
> > new file mode 100644
> > index 000000000000..64a143871d72
> > --- /dev/null
> > +++ b/drivers/platform/x86/intel/ifs/intel_ifs_device.c
> > @@ -0,0 +1,50 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright(c) 2022 Intel Corporation. */
> > +
> > +#include <linux/platform_device.h>
> > +#include <linux/init.h>
> > +#include <asm/cpu_device_id.h>
> > +
> > +#define MSR_IA32_CORE_CAPS_INTEGRITY_BIT     2
> > +#define MSR_IA32_CORE_CAPS_INTEGRITY         BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT)
> > +
> > +#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 = {
> > +     X86_MATCH(SAPPHIRERAPIDS_X),
> > +     {}
> > +};
> > +
> > +static __init int register_ifs_device(void)
> > +{
> > +     struct platform_device *pdev;
> > +     const struct x86_cpu_id *m;
> > +     u64 ia32_core_caps;
> > +
> > +     m = 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) {
> > +             pdev = platform_device_alloc("intel_ifs", 0);
> > +             if (pdev) {
> > +                     if (platform_device_add(pdev))
> > +                             platform_device_put(pdev);
> > +             }
> > +     }
> > +
> > +     /*
> > +      * Failure here will be visible by a missing device
> > +      * in sysfs. Returning an error code would not make
> > +      * that any easier to diagnose. Would also complicate
> > +      * future implementations that may support a subset of
> > +      * the types of tests.
> > +      */
> > +     return 0;
>
> So even if everything fails, you succeed?  But you are failing above for
> some cases, so why is creating the device somehow special here that you
> should succeed no matter what?

My bad, this failure is not fatal to init and test execution tooling
will notice the missing device, but yes this can just return the
initcall error to be logged.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-19 17:58         ` Greg KH
@ 2022-04-19 18:15           ` Dan Williams
  0 siblings, 0 replies; 152+ messages in thread
From: Dan Williams @ 2022-04-19 18:15 UTC (permalink / raw)
  To: Greg KH
  Cc: Luck, Tony, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 11:01 AM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Tue, Apr 19, 2022 at 10:35:17AM -0700, Luck, Tony wrote:
> > On Tue, Apr 19, 2022 at 07:20:54PM +0200, Greg KH wrote:
> > > > +/*
> > > > + * Note there is no need for a ->remove() call back. There isn't an
> > > > + * "unload" operation to remove the scan binary from the BIOS reserved
> > > > + * area. Also ".dev_groups" removal order will guarantee that any in
> > > > + * flight tests have completed.
> > > > + */
> > >
> > > So you are ok with the warning the kernel gives you when you unload the
> > > driver?  That feels wrong :(
> >
> > What warning?
> >
> > # dmesg | tail -5
> > [   38.084165] virbr0: port 1(virbr0-nic) entered listening state
> > [   38.149621] virbr0: port 1(virbr0-nic) entered disabled state
> > [   38.582054] broken atomic modeset userspace detected, disabling atomic
> > [   43.703321] igc 0000:01:00.0 enp1s0: NIC Link is Up 2500 Mbps Full Duplex, Flow Control: RX
> > [   43.703470] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready
> > # modprobe intel_ifs
> > # ls /sys/devices/platform/intel_ifs.0/
> > details  driver_override  modalias  reload    status     uevent
> > driver   image_version    power     run_test  subsystem
> > # rmmod intel_ifs
> > # dmesg | tail -5
> > [   38.084165] virbr0: port 1(virbr0-nic) entered listening state
> > [   38.149621] virbr0: port 1(virbr0-nic) entered disabled state
> > [   38.582054] broken atomic modeset userspace detected, disabling atomic
> > [   43.703321] igc 0000:01:00.0 enp1s0: NIC Link is Up 2500 Mbps Full Duplex, Flow Control: RX
> > [   43.703470] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready
> > #
>
> If there's no warning when the device goes away, why the crazy comment
> trying to justify the lack of a remove callback?

The comment clarifies the nuance that driver.dev_groups coordinates
flushing access sysfs ops users before ->remove() is called. It can
certainly be dropped.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-19 17:20     ` Greg KH
  2022-04-19 17:35       ` Luck, Tony
@ 2022-04-19 18:24       ` Dan Williams
  1 sibling, 0 replies; 152+ messages in thread
From: Dan Williams @ 2022-04-19 18:24 UTC (permalink / raw)
  To: Greg KH
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 10:21 AM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Tue, Apr 19, 2022 at 09:38:57AM -0700, Tony Luck wrote:
> > From: Jithu Joseph <jithu.joseph@intel.com>
> >
> > Implement sysfs interface to trigger ifs test for a specific cpu.
> > Additional interfaces related to checking the status of the
> > scan test and seeing the version of the loaded IFS binary
> > are also added.
> >
> > The basic usage is as below.
> >    - To start test, for example on cpu5:
> >        echo 5 > /sys/devices/platform/intel_ifs/run_test
> >    - To see the status of the last test
> >        cat /sys/devices/platform/intel_ifs/status
> >    - To see the version of the loaded scan binary
> >        cat /sys/devices/platform/intel_ifs/image_version
> >
> > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> > Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> > Co-developed-by: Tony Luck <tony.luck@intel.com>
> > Signed-off-by: Tony Luck <tony.luck@intel.com>
> > ---
> >  drivers/platform/x86/intel/ifs/Makefile  |   2 +-
> >  drivers/platform/x86/intel/ifs/core.c    |   9 ++
> >  drivers/platform/x86/intel/ifs/ifs.h     |   3 +
> >  drivers/platform/x86/intel/ifs/runtest.c |   7 ++
> >  drivers/platform/x86/intel/ifs/sysfs.c   | 151 +++++++++++++++++++++++
> >  5 files changed, 171 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 7de27361b479..dbbe0bf66987 100644
> > --- a/drivers/platform/x86/intel/ifs/Makefile
> > +++ b/drivers/platform/x86/intel/ifs/Makefile
> > @@ -2,4 +2,4 @@ obj-$(CONFIG_INTEL_IFS_DEVICE)        += intel_ifs_device.o
> >
> >  obj-$(CONFIG_INTEL_IFS)              += intel_ifs.o
> >
> > -intel_ifs-objs                       := core.o load.o runtest.o
> > +intel_ifs-objs                       := core.o load.o runtest.o sysfs.o
> > diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
> > index 0dc4cdda35ff..f56cde0cdfd6 100644
> > --- a/drivers/platform/x86/intel/ifs/core.c
> > +++ b/drivers/platform/x86/intel/ifs/core.c
> > @@ -3,6 +3,7 @@
> >
> >  #include <linux/module.h>
> >  #include <linux/platform_device.h>
> > +#include <linux/semaphore.h>
> >
> >  #include "ifs.h"
> >
> > @@ -26,10 +27,18 @@ static int ifs_probe(struct platform_device *pdev)
> >       return 0;
> >  }
> >
> > +/*
> > + * Note there is no need for a ->remove() call back. There isn't an
> > + * "unload" operation to remove the scan binary from the BIOS reserved
> > + * area. Also ".dev_groups" removal order will guarantee that any in
> > + * flight tests have completed.
> > + */
>
> So you are ok with the warning the kernel gives you when you unload the
> driver?  That feels wrong :(
>
> > +
> >  static struct platform_driver intel_ifs_driver = {
> >       .probe = ifs_probe,
> >       .driver = {
> >               .name = "intel_ifs",
> > +             .dev_groups = plat_ifs_groups,
> >       },
> >  };
> >
> > diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
> > index f5e3636d709f..4e6662f2d2f8 100644
> > --- a/drivers/platform/x86/intel/ifs/ifs.h
> > +++ b/drivers/platform/x86/intel/ifs/ifs.h
> > @@ -97,4 +97,7 @@ int ifs_setup_wq(void);
> >  void ifs_destroy_wq(void);
> >  int do_core_test(int cpu, struct device *dev);
> >
> > +extern const struct attribute_group *plat_ifs_groups[];
> > +extern struct semaphore ifs_sem;
> > +
> >  #endif
> > diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
> > index 7793a01f7b94..246eff250563 100644
> > --- a/drivers/platform/x86/intel/ifs/runtest.c
> > +++ b/drivers/platform/x86/intel/ifs/runtest.c
> > @@ -10,6 +10,13 @@
> >
> >  #include "ifs.h"
> >
> > +/*
> > + * Note all code and data in this file is protected by
> > + * ifs_sem. On HT systems all threads on a core will
> > + * execute together, but only the first thread on the
> > + * core will update results of the test and indicate
> > + * completion.
> > + */
> >  static struct workqueue_struct *ifs_wq;
> >  static struct completion test_thread_done;
> >  static atomic_t siblings_in;
> > diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
> > new file mode 100644
> > index 000000000000..41db2a12fbc8
> > --- /dev/null
> > +++ b/drivers/platform/x86/intel/ifs/sysfs.c
> > @@ -0,0 +1,151 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/* Copyright(c) 2022 Intel Corporation. */
> > +
> > +#include <linux/cpu.h>
> > +#include <linux/delay.h>
> > +#include <linux/fs.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/semaphore.h>
> > +#include <linux/slab.h>
> > +
> > +#include "ifs.h"
> > +
> > +/*
> > + * Protects against simultaneous tests on multiple cores, or
> > + * reloading can file while a test is in progress
> > + */
> > +DEFINE_SEMAPHORE(ifs_sem);
> > +
> > +/*
> > + * The sysfs interface to check additional details of last test
> > + * cat /sys/devices/system/platform/ifs/details
> > + */
> > +static ssize_t details_show(struct device *dev,
> > +                         struct device_attribute *attr,
> > +                         char *buf)
> > +{
> > +     struct ifs_data *ifsd = dev_get_drvdata(dev);
> > +
> > +     return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
> > +}
> > +
> > +static DEVICE_ATTR_RO(details);
> > +
> > +static const char * const status_msg[] = {
> > +     [SCAN_NOT_TESTED] = "untested",
> > +     [SCAN_TEST_PASS] = "pass",
> > +     [SCAN_TEST_FAIL] = "fail"
> > +};
> > +
> > +/*
> > + * The sysfs interface to check the test status:
> > + * To check the status of last test
> > + * cat /sys/devices/platform/ifs/status
> > + */
> > +static ssize_t status_show(struct device *dev,
> > +                        struct device_attribute *attr,
> > +                        char *buf)
> > +{
> > +     struct ifs_data *ifsd = dev_get_drvdata(dev);
> > +
> > +     return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
> > +}
> > +
> > +static DEVICE_ATTR_RO(status);
> > +
> > +/*
> > + * The sysfs interface for single core testing
> > + * To start test, for example, cpu5
> > + * echo 5 > /sys/devices/platform/ifs/run_test
> > + * To check the result:
> > + * cat /sys/devices/platform/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)
> > +{
> > +     struct ifs_data *ifsd = dev_get_drvdata(dev);
> > +     unsigned int cpu;
> > +     int rc;
> > +
> > +     rc = kstrtouint(buf, 0, &cpu);
> > +     if (rc < 0 || cpu >= nr_cpu_ids)
> > +             return -EINVAL;
> > +
> > +     if (down_interruptible(&ifs_sem))
> > +             return -EINTR;
> > +
> > +     if (!ifsd->loaded)
> > +             rc = -EPERM;
> > +     else
> > +             rc = do_core_test(cpu, dev);
> > +
> > +     up(&ifs_sem);
> > +
> > +     return rc ? rc : count;
> > +}
> > +
> > +static DEVICE_ATTR_WO(run_test);
> > +
> > +/*
> > + * Reload the IFS image. When user wants to install new IFS image
> > + */
> > +static ssize_t reload_store(struct device *dev,
> > +                         struct device_attribute *attr,
> > +                         const char *buf, size_t count)
> > +{
> > +     struct ifs_data *ifsd = dev_get_drvdata(dev);
> > +     int rc;
> > +
> > +     if (!sysfs_streq(buf, "1"))
>
> kstrtobool()?

I had asked them to drop kstrtobool() to save a line or 2, because
this is a write-only attribute where "1" is the only valid value.
Otherwise, no worries from me about supporting the other 'true'
values.

>
> > +             return -EINVAL;
> > +
> > +     if (down_interruptible(&ifs_sem))
> > +             return -EINTR;
> > +
> > +     rc = load_ifs_binary(dev);
> > +
> > +     ifsd->loaded = (rc == 0);
> > +
> > +     up(&ifs_sem);
> > +
> > +     return rc ? rc : count;
> > +}
> > +
> > +static DEVICE_ATTR_WO(reload);
> > +
> > +/*
> > + * Display currently loaded IFS image version.
> > + */
> > +static ssize_t image_version_show(struct device *dev,
> > +                               struct device_attribute *attr, char *buf)
> > +{
> > +     struct ifs_data *ifsd = dev_get_drvdata(dev);
> > +
> > +     if (!ifsd->loaded)
> > +             return sysfs_emit(buf, "%s\n", "none");
> > +     else
> > +             return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
> > +}
> > +
> > +static DEVICE_ATTR_RO(image_version);
> > +
> > +/* global scan sysfs attributes */
> > +static struct attribute *plat_ifs_attrs[] = {
> > +     &dev_attr_details.attr,
> > +     &dev_attr_status.attr,
> > +     &dev_attr_run_test.attr,
> > +     &dev_attr_reload.attr,
> > +     &dev_attr_image_version.attr,
> > +     NULL
> > +};
> > +
> > +static const struct attribute_group plat_ifs_attr_group = {
> > +     .attrs = plat_ifs_attrs,
> > +};
> > +
> > +const struct attribute_group *plat_ifs_groups[] = {
> > +     &plat_ifs_attr_group,
> > +     NULL
> > +};
>
> ATTRIBUTE_GROUPS()?

Yeah, I should have caught that.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 02/11] Documentation: In-Field Scan
  2022-04-19 16:48     ` Greg KH
@ 2022-04-19 19:45       ` Dan Williams
  2022-04-20  7:48         ` Greg KH
  0 siblings, 1 reply; 152+ messages in thread
From: Dan Williams @ 2022-04-19 19:45 UTC (permalink / raw)
  To: Greg KH
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 9:48 AM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Tue, Apr 19, 2022 at 09:38:50AM -0700, Tony Luck wrote:
> > 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.
> >
> > The full  github location for distributing the IFS images is
> > still being decided. So just a placeholder included for now
> > in the documentation.
> >
> > Future CPUs will support more than one type of test. Plan for
> > that now by using a ".0" suffix on the ABI directory names.
> > Additional test types will use ".1", etc.
> >
> > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> > Signed-off-by: Tony Luck <tony.luck@intel.com>
> > ---
> >  Documentation/x86/ifs.rst   | 101 ++++++++++++++++++++++++++++++++++++
> >  Documentation/x86/index.rst |   1 +
> >  2 files changed, 102 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..62f3c07d433a
> > --- /dev/null
> > +++ b/Documentation/x86/ifs.rst
> > @@ -0,0 +1,101 @@
> > +.. SPDX-License-Identifier: GPL-2.0
> > +
> > +=============
> > +In-Field Scan
> > +=============
> > +
> > +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.
> > +Future CPUs will support more than one type of test which will show up
> > +with a new platform-device instance-id, for now only .0 is exposed.
> > +
> > +
> > +IFS Image
> > +---------
> > +
> > +Intel provides a firmware file containing the scan tests via
> > +github [#f1]_.  Similar to microcode there is a separate file for each
> > +family-model-stepping.
> > +
> > +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 by writing to the driver reload file::
> > +
> > +  # echo 1 > /sys/bus/platform/drivers/intel_ifs.0/reload
> > +
> > +Similar to microcode, the current version of the scan tests is stored
> > +in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan
> > +
> > +Running tests
> > +-------------
> > +
> > +Tests are run by the driver 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. The driver makes the value of this MSR visible to applications
> > +via the "details" file (see below). Interrupted tests may be restarted.
> > +
> > +The IFS driver provides sysfs interfaces via /sys/devices/platform/intel_ifs.0/
> > +to control execution:
> > +
> > +Test a specific core::
> > +
> > +  # echo <cpu#> > /sys/devices/platform/intel_ifs.0/run_test
> > +
> > +when HT is enabled any of the sibling cpu# can be specified to test its
> > +corresponding physical core. Since the tests are per physical core, the
> > +result of testing any thread is same. It is only necessary to test one
> > +thread.
> > +
> > +For e.g. to test core corresponding to cpu5
> > +
> > +  # echo 5 > /sys/devices/platform/intel_ifs.0/run_test
> > +
> > +Results of the last test is provided in /sys::
> > +
> > +  $ cat /sys/devices/platform/intel_ifs.0/status
> > +  pass
>
> sysfs documentation belongs in Documentation/ABI/
>
> And why not just include this whole thing in the driver itself and suck
> the documentation out of that?  No need to have a separate file.

At a minimum a separate file is needed to house the
---
 .. kernel-doc:: $source_file
   :doc: $header
---
...statements, but ok, I'll recommend that going forward to
de-emphasize shipping content directly from Documentation/ when it can
be ingested from "DOC:" source. I had been assuming DOC: blocks in the
code were more for augmenting kernel-doc on driver internal ABIs and
not longer theory of operation documentation that is an awkward fit
for Documentation/ABI/.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-19 18:09       ` Dan Williams
@ 2022-04-19 22:28         ` Dan Williams
  2022-04-20  7:49           ` Greg KH
  2022-04-20  7:48         ` Greg KH
  1 sibling, 1 reply; 152+ messages in thread
From: Dan Williams @ 2022-04-19 22:28 UTC (permalink / raw)
  To: Greg KH
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 11:09 AM Dan Williams <dan.j.williams@intel.com> wrote:
>
> On Tue, Apr 19, 2022 at 9:48 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Tue, Apr 19, 2022 at 09:38:51AM -0700, Tony Luck wrote:
> > > The initial implementation of IFS is model specific. Enumeration is
> > > via a combination of family-model-stepping and a check for a bit in the
> > > CORE_CAPABILITIES MSR.
> > >
> > > Linux has handled this lack of enumeration before with a code stub to
> > > create a device.  See arch/x86/kernel/pmem.c. Use the same approach
> > > here.
> >
> > Ick, why?  Why not just create a simple virtual device and use that?  Do
> > you really want to bind a driver to this?  Or do you already "know" the
> > only driver that you have will bind to this?
>
> With the realization that there may be multiple instances of an
> IFS-like capability going forward, and that ideally those capabilities
> would move away from a CPU capability bit to an ACPI description, then
> it seemed to me that a simulated platform_device for this is a
> reasonable fit. I.e. when / if an ACPI _HID is assigned for this
> capability the same platform_driver can be reused for those instances.

Turns out the ACPI enumeration for this may not materialize, so this
can indeed move to a simple / driver-less device.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 02/11] Documentation: In-Field Scan
  2022-04-19 19:45       ` Dan Williams
@ 2022-04-20  7:48         ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-20  7:48 UTC (permalink / raw)
  To: Dan Williams
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 12:45:03PM -0700, Dan Williams wrote:
> On Tue, Apr 19, 2022 at 9:48 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Tue, Apr 19, 2022 at 09:38:50AM -0700, Tony Luck wrote:
> > > 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.
> > >
> > > The full  github location for distributing the IFS images is
> > > still being decided. So just a placeholder included for now
> > > in the documentation.
> > >
> > > Future CPUs will support more than one type of test. Plan for
> > > that now by using a ".0" suffix on the ABI directory names.
> > > Additional test types will use ".1", etc.
> > >
> > > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> > > Signed-off-by: Tony Luck <tony.luck@intel.com>
> > > ---
> > >  Documentation/x86/ifs.rst   | 101 ++++++++++++++++++++++++++++++++++++
> > >  Documentation/x86/index.rst |   1 +
> > >  2 files changed, 102 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..62f3c07d433a
> > > --- /dev/null
> > > +++ b/Documentation/x86/ifs.rst
> > > @@ -0,0 +1,101 @@
> > > +.. SPDX-License-Identifier: GPL-2.0
> > > +
> > > +=============
> > > +In-Field Scan
> > > +=============
> > > +
> > > +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.
> > > +Future CPUs will support more than one type of test which will show up
> > > +with a new platform-device instance-id, for now only .0 is exposed.
> > > +
> > > +
> > > +IFS Image
> > > +---------
> > > +
> > > +Intel provides a firmware file containing the scan tests via
> > > +github [#f1]_.  Similar to microcode there is a separate file for each
> > > +family-model-stepping.
> > > +
> > > +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 by writing to the driver reload file::
> > > +
> > > +  # echo 1 > /sys/bus/platform/drivers/intel_ifs.0/reload
> > > +
> > > +Similar to microcode, the current version of the scan tests is stored
> > > +in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan
> > > +
> > > +Running tests
> > > +-------------
> > > +
> > > +Tests are run by the driver 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. The driver makes the value of this MSR visible to applications
> > > +via the "details" file (see below). Interrupted tests may be restarted.
> > > +
> > > +The IFS driver provides sysfs interfaces via /sys/devices/platform/intel_ifs.0/
> > > +to control execution:
> > > +
> > > +Test a specific core::
> > > +
> > > +  # echo <cpu#> > /sys/devices/platform/intel_ifs.0/run_test
> > > +
> > > +when HT is enabled any of the sibling cpu# can be specified to test its
> > > +corresponding physical core. Since the tests are per physical core, the
> > > +result of testing any thread is same. It is only necessary to test one
> > > +thread.
> > > +
> > > +For e.g. to test core corresponding to cpu5
> > > +
> > > +  # echo 5 > /sys/devices/platform/intel_ifs.0/run_test
> > > +
> > > +Results of the last test is provided in /sys::
> > > +
> > > +  $ cat /sys/devices/platform/intel_ifs.0/status
> > > +  pass
> >
> > sysfs documentation belongs in Documentation/ABI/
> >
> > And why not just include this whole thing in the driver itself and suck
> > the documentation out of that?  No need to have a separate file.
> 
> At a minimum a separate file is needed to house the
> ---
>  .. kernel-doc:: $source_file
>    :doc: $header
> ---
> ...statements, but ok, I'll recommend that going forward to
> de-emphasize shipping content directly from Documentation/ when it can
> be ingested from "DOC:" source. I had been assuming DOC: blocks in the
> code were more for augmenting kernel-doc on driver internal ABIs and
> not longer theory of operation documentation that is an awkward fit
> for Documentation/ABI/.

I don't know which is better, it's just that creating a whole new
documentation file for a single tiny driver feels very odd as it will
get out of date and is totally removed from the driver itself.

I'd prefer that drivers be self-contained, including the documentation,
as it is much more obvious what is happening with that.  Spreading stuff
around the tree only causes stuff to get out of sync easier.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-19 18:09       ` Dan Williams
  2022-04-19 22:28         ` Dan Williams
@ 2022-04-20  7:48         ` Greg KH
  2022-04-20 15:27           ` Luck, Tony
  1 sibling, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-20  7:48 UTC (permalink / raw)
  To: Dan Williams
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 11:09:09AM -0700, Dan Williams wrote:
> On Tue, Apr 19, 2022 at 9:48 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Tue, Apr 19, 2022 at 09:38:51AM -0700, Tony Luck wrote:
> > > The initial implementation of IFS is model specific. Enumeration is
> > > via a combination of family-model-stepping and a check for a bit in the
> > > CORE_CAPABILITIES MSR.
> > >
> > > Linux has handled this lack of enumeration before with a code stub to
> > > create a device.  See arch/x86/kernel/pmem.c. Use the same approach
> > > here.
> >
> > Ick, why?  Why not just create a simple virtual device and use that?  Do
> > you really want to bind a driver to this?  Or do you already "know" the
> > only driver that you have will bind to this?
> 
> With the realization that there may be multiple instances of an
> IFS-like capability going forward, and that ideally those capabilities
> would move away from a CPU capability bit to an ACPI description, then
> it seemed to me that a simulated platform_device for this is a
> reasonable fit. I.e. when / if an ACPI _HID is assigned for this
> capability the same platform_driver can be reused for those instances.

Don't write code today for stuff you do not have right now, you all know
that.  We can always revisit it in the future.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-19 22:28         ` Dan Williams
@ 2022-04-20  7:49           ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-20  7:49 UTC (permalink / raw)
  To: Dan Williams
  Cc: Tony Luck, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Tue, Apr 19, 2022 at 03:28:26PM -0700, Dan Williams wrote:
> On Tue, Apr 19, 2022 at 11:09 AM Dan Williams <dan.j.williams@intel.com> wrote:
> >
> > On Tue, Apr 19, 2022 at 9:48 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> > >
> > > On Tue, Apr 19, 2022 at 09:38:51AM -0700, Tony Luck wrote:
> > > > The initial implementation of IFS is model specific. Enumeration is
> > > > via a combination of family-model-stepping and a check for a bit in the
> > > > CORE_CAPABILITIES MSR.
> > > >
> > > > Linux has handled this lack of enumeration before with a code stub to
> > > > create a device.  See arch/x86/kernel/pmem.c. Use the same approach
> > > > here.
> > >
> > > Ick, why?  Why not just create a simple virtual device and use that?  Do
> > > you really want to bind a driver to this?  Or do you already "know" the
> > > only driver that you have will bind to this?
> >
> > With the realization that there may be multiple instances of an
> > IFS-like capability going forward, and that ideally those capabilities
> > would move away from a CPU capability bit to an ACPI description, then
> > it seemed to me that a simulated platform_device for this is a
> > reasonable fit. I.e. when / if an ACPI _HID is assigned for this
> > capability the same platform_driver can be reused for those instances.
> 
> Turns out the ACPI enumeration for this may not materialize, so this
> can indeed move to a simple / driver-less device.

Hey, see, doing extra work now was not a good idea :)

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-20  7:48         ` Greg KH
@ 2022-04-20 15:27           ` Luck, Tony
  2022-04-20 17:46             ` Greg KH
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-20 15:27 UTC (permalink / raw)
  To: Greg KH
  Cc: Dan Williams, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Wed, Apr 20, 2022 at 09:48:58AM +0200, Greg KH wrote:
> Don't write code today for stuff you do not have right now, you all know
> that.  We can always revisit it in the future.

Direction check on the virtual device option. Is this what
you are asking for in "core.c"?

The second test type is happening internally right away ... so I
put in some example code of how it can be added. Upstream submission
will just have the one test that exists today.

Static definition of:

 static struct ifs_data ifs_data[IFS_NUMTESTS];

keeps the code simpler (no need to have code to
cleanup if dynamic allocation of this small structure
fails). But if you feel strongly that all static allocation
is bad, then I can kzallloc() per enumerated test type.

With this change it is no longer a platform driver. So maybe
doesn't belong in drivers/platform/x86/intel/ifs/*

Any thoughts on where I should move it to?

-Tony

---- core.c ---

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation. */

#include <linux/module.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/semaphore.h>

#include <asm/cpu_device_id.h>

#include "ifs.h"

enum test_types {
	IFS_SAF,
	IFS_ANOTHER,
	IFS_NUMTESTS
};

static struct class *ifs_class;
static struct ifs_data ifs_data[IFS_NUMTESTS];

#define MSR_IA32_CORE_CAPS_INTEGRITY_BIT	2
#define MSR_IA32_CORE_CAPS_INTEGRITY		BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT)

#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 = {
	X86_MATCH(SAPPHIRERAPIDS_X),
	{}
};
MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);

static int ifs_device_unregister(struct device *dev, void *data)
{
	device_unregister(dev);

	return 0;
}

static int __init ifs_init(void)
{
	const struct x86_cpu_id *m;
	u64 ia32_core_caps;
	struct device *dev;
	int ndevices = 0;
	int ret = 0;

	m = x86_match_cpu(ifs_cpu_ids);
	if (!m)
		return -ENODEV;

	if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &ia32_core_caps))
		return -ENODEV;

	ifs_class = class_create(THIS_MODULE, "intel_ifs");
	if (IS_ERR(ifs_class))
		return PTR_ERR(ifs_class);

	ret = ifs_setup_wq();
	if (ret)
		goto class_cleanup;

	if (ia32_core_caps & MSR_IA32_CORE_CAPS_INTEGRITY) {
		dev = device_create_with_groups(ifs_class, NULL, MKDEV(0, 0), &ifs_data[IFS_SAF],
					        plat_ifs_groups, "ifs%d", IFS_SAF);
		if (dev) {
			ndevices++;

			down(&ifs_sem);
			ifs_data[IFS_SAF].loaded = !ifs_load_firmware(dev);
			up(&ifs_sem);
		}
	}

	if (1) { // placeholder to test 2nd test
		dev = device_create_with_groups(ifs_class, NULL, MKDEV(0, 0), &ifs_data[IFS_ANOTHER],
					        plat_ifs_groups, "ifs%d", IFS_ANOTHER);
		if (dev)
			ndevices++;
	}

	if (ndevices)
		goto done;

	ret = -ENODEV;

	class_for_each_device(ifs_class, NULL, NULL, ifs_device_unregister);

class_cleanup:
	class_destroy(ifs_class);
done:
	return ret;
}

static void __exit ifs_exit(void)
{
	class_for_each_device(ifs_class, NULL, NULL, ifs_device_unregister);
	class_destroy(ifs_class);
	ifs_destroy_wq();
}

module_init(ifs_init);
module_exit(ifs_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Intel In Field Scan (IFS) driver");

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-20 15:27           ` Luck, Tony
@ 2022-04-20 17:46             ` Greg KH
  2022-04-20 17:57               ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-20 17:46 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Dan Williams, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches,
	Ravi V Shankar

On Wed, Apr 20, 2022 at 08:27:53AM -0700, Luck, Tony wrote:
> On Wed, Apr 20, 2022 at 09:48:58AM +0200, Greg KH wrote:
> > Don't write code today for stuff you do not have right now, you all know
> > that.  We can always revisit it in the future.
> 
> Direction check on the virtual device option. Is this what
> you are asking for in "core.c"?
> 
> The second test type is happening internally right away ... so I
> put in some example code of how it can be added. Upstream submission
> will just have the one test that exists today.
> 
> Static definition of:
> 
>  static struct ifs_data ifs_data[IFS_NUMTESTS];
> 
> keeps the code simpler (no need to have code to
> cleanup if dynamic allocation of this small structure
> fails). But if you feel strongly that all static allocation
> is bad, then I can kzallloc() per enumerated test type.
> 
> With this change it is no longer a platform driver. So maybe
> doesn't belong in drivers/platform/x86/intel/ifs/*
> 
> Any thoughts on where I should move it to?
> 
> -Tony
> 
> ---- core.c ---
> 
> // SPDX-License-Identifier: GPL-2.0-only
> /* Copyright(c) 2022 Intel Corporation. */
> 
> #include <linux/module.h>
> #include <linux/device.h>
> #include <linux/kdev_t.h>
> #include <linux/semaphore.h>
> 
> #include <asm/cpu_device_id.h>
> 
> #include "ifs.h"
> 
> enum test_types {
> 	IFS_SAF,
> 	IFS_ANOTHER,
> 	IFS_NUMTESTS
> };
> 
> static struct class *ifs_class;
> static struct ifs_data ifs_data[IFS_NUMTESTS];
> 
> #define MSR_IA32_CORE_CAPS_INTEGRITY_BIT	2
> #define MSR_IA32_CORE_CAPS_INTEGRITY		BIT(MSR_IA32_CORE_CAPS_INTEGRITY_BIT)
> 
> #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 = {
> 	X86_MATCH(SAPPHIRERAPIDS_X),
> 	{}
> };
> MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
> 
> static int ifs_device_unregister(struct device *dev, void *data)
> {
> 	device_unregister(dev);
> 
> 	return 0;
> }
> 
> static int __init ifs_init(void)
> {
> 	const struct x86_cpu_id *m;
> 	u64 ia32_core_caps;
> 	struct device *dev;
> 	int ndevices = 0;
> 	int ret = 0;
> 
> 	m = x86_match_cpu(ifs_cpu_ids);
> 	if (!m)
> 		return -ENODEV;
> 
> 	if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &ia32_core_caps))
> 		return -ENODEV;
> 
> 	ifs_class = class_create(THIS_MODULE, "intel_ifs");

Why do you need a class?  Why not just use a misc device?  Saves you
loads of boilerplate code that is sometimes tricky to get correct.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-20 17:46             ` Greg KH
@ 2022-04-20 17:57               ` Luck, Tony
  2022-04-20 18:04                 ` Greg KH
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-20 17:57 UTC (permalink / raw)
  To: Greg KH
  Cc: Williams, Dan J, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches, Shankar,
	Ravi V

>> 	ifs_class = class_create(THIS_MODULE, "intel_ifs");
>
> Why do you need a class?  Why not just use a misc device?  Saves you
> loads of boilerplate code that is sometimes tricky to get correct.

It didn't feel like a "ton" of boiler plate. Just class_create()/class_destroy()
for the class itself. And

	class_for_each_device(ifs_class, NULL, NULL, ifs_device_unregister);

to clean up devices on exit (or error cleanup in init()).


I thought I needed a class to make a directory for my per-test directories to live in:

$ ls -l /sys/devices/virtual/intel_ifs
total 0
drwxr-xr-x 3 root root 0 Apr 20 13:36 ifs0
drwxr-xr-x 3 root root 0 Apr 20 13:36 ifs1

Can I do that with a misc device?

Or is it ok for them all to sit at the top level of /sys/devices/virtual?

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-20 17:57               ` Luck, Tony
@ 2022-04-20 18:04                 ` Greg KH
  2022-04-20 18:08                   ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-20 18:04 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Williams, Dan J, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches, Shankar,
	Ravi V

On Wed, Apr 20, 2022 at 05:57:04PM +0000, Luck, Tony wrote:
> >> 	ifs_class = class_create(THIS_MODULE, "intel_ifs");
> >
> > Why do you need a class?  Why not just use a misc device?  Saves you
> > loads of boilerplate code that is sometimes tricky to get correct.
> 
> It didn't feel like a "ton" of boiler plate. Just class_create()/class_destroy()
> for the class itself. And
> 
> 	class_for_each_device(ifs_class, NULL, NULL, ifs_device_unregister);
> 
> to clean up devices on exit (or error cleanup in init()).
> 
> 
> I thought I needed a class to make a directory for my per-test directories to live in:
> 
> $ ls -l /sys/devices/virtual/intel_ifs
> total 0
> drwxr-xr-x 3 root root 0 Apr 20 13:36 ifs0
> drwxr-xr-x 3 root root 0 Apr 20 13:36 ifs1
> 
> Can I do that with a misc device?
> 
> Or is it ok for them all to sit at the top level of /sys/devices/virtual?

How many do you have?

And why is a directory needed for just one tiny driver type?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-20 18:04                 ` Greg KH
@ 2022-04-20 18:08                   ` Luck, Tony
  2022-04-20 19:04                     ` Greg KH
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-20 18:08 UTC (permalink / raw)
  To: Greg KH
  Cc: Williams, Dan J, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches, Shankar,
	Ravi V

>> Or is it ok for them all to sit at the top level of /sys/devices/virtual?
>
> How many do you have?
>
> And why is a directory needed for just one tiny driver type?

One today. Two tomorrow (internally ... next gen CPU).

Three eventually (That's how many are on the roadmap that I can see).

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan)
  2022-04-20 18:08                   ` Luck, Tony
@ 2022-04-20 19:04                     ` Greg KH
  0 siblings, 0 replies; 152+ messages in thread
From: Greg KH @ 2022-04-20 19:04 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Williams, Dan J, Hans de Goede, markgross, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML,
	H. Peter Anvin, Jonathan Corbet, Andy Shevchenko, Joseph, Jithu,
	Raj, Ashok, Steven Rostedt, Linux Kernel Mailing List,
	Linux Doc Mailing List, platform-driver-x86, patches, Shankar,
	Ravi V

On Wed, Apr 20, 2022 at 06:08:20PM +0000, Luck, Tony wrote:
> >> Or is it ok for them all to sit at the top level of /sys/devices/virtual?
> >
> > How many do you have?
> >
> > And why is a directory needed for just one tiny driver type?
> 
> One today. Two tomorrow (internally ... next gen CPU).
> 
> Three eventually (That's how many are on the roadmap that I can see).

Then just use a misc device, it's simple and saves you a ton of code.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-19 16:38   ` [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-04-20 23:38     ` Steven Rostedt
  2022-04-21  4:26       ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Steven Rostedt @ 2022-04-20 23:38 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, jithu.joseph, ashok.raj,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, 19 Apr 2022 09:38:58 -0700
Tony Luck <tony.luck@intel.com> wrote:

> +TRACE_EVENT(ifs_status,
> +
> +	TP_PROTO(union ifs_scan activate, union ifs_status status),

Really, you want to pass the structure in by value, so that we have two
copies? One to get to this function and then one to write to the ring
buffer?

-- Steve


> +
> +	TP_ARGS(activate, status),
> +
> +	TP_STRUCT__entry(
> +		__field(	u64,	status	)
> +		__field(	u8,	start	)
> +		__field(	u8,	stop	)
> +	),
> +
> +	TP_fast_assign(
> +		__entry->start	= activate.start;
> +		__entry->stop	= activate.stop;
> +		__entry->status	= status.data;
> +	),
> +
> +	TP_printk("start: %.2x, stop: %.2x, status: %llx",
> +		__entry->start,
> +		__entry->stop,
> +		__entry->status)
> +);
> +
> +#endif /* _TRACE_IFS_H */

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-20 23:38     ` Steven Rostedt
@ 2022-04-21  4:26       ` Luck, Tony
  2022-04-21 12:41         ` Steven Rostedt
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-21  4:26 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

>> +TRACE_EVENT(ifs_status,
>> +
>> +	TP_PROTO(union ifs_scan activate, union ifs_status status),
>
> Really, you want to pass the structure in by value, so that we have two
> copies? One to get to this function and then one to write to the ring
> buffer?

These "structures" are just bitfield helpers for a u64 that is passed into
WRMSR (in the case of activate) and received back from RDMSR in
the case of status.

So this is really just a pair of u64 arguments, with the compiler handling
the bit field extractions into the ring buffer.

Here are the definitions:

union ifs_scan {
        u64     data;
        struct {
                u32     start   :8;
                u32     stop    :8;
                u32     rsvd    :16;
                u32     delay   :31;
                u32     sigmce  :1;
        };
};

union ifs_status {
        u64     data;
        struct {
                u32     chunk_num               :8;
                u32     chunk_stop_index        :8;
                u32     rsvd1                   :16;
                u32     error_code              :8;
                u32     rsvd2                   :22;
                u32     control_error           :1;
                u32     signature_error         :1;
        };
};

Would it be better to do the bit extractions of the start/stop fields first?

-Tony



^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-21  4:26       ` Luck, Tony
@ 2022-04-21 12:41         ` Steven Rostedt
  0 siblings, 0 replies; 152+ messages in thread
From: Steven Rostedt @ 2022-04-21 12:41 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

On Thu, 21 Apr 2022 04:26:39 +0000
"Luck, Tony" <tony.luck@intel.com> wrote:

> >> +TRACE_EVENT(ifs_status,
> >> +
> >> +	TP_PROTO(union ifs_scan activate, union ifs_status status),  
> >
> > Really, you want to pass the structure in by value, so that we have two
> > copies? One to get to this function and then one to write to the ring
> > buffer?  
> 
> These "structures" are just bitfield helpers for a u64 that is passed into
> WRMSR (in the case of activate) and received back from RDMSR in
> the case of status.
> 
> So this is really just a pair of u64 arguments, with the compiler handling
> the bit field extractions into the ring buffer.

I was just wondering if passing by reference would be better, but as you
stated, they are just two u64 arguments.

> 
> Here are the definitions:
> 
> union ifs_scan {
>         u64     data;
>         struct {
>                 u32     start   :8;
>                 u32     stop    :8;
>                 u32     rsvd    :16;
>                 u32     delay   :31;
>                 u32     sigmce  :1;
>         };
> };
> 
> union ifs_status {
>         u64     data;
>         struct {
>                 u32     chunk_num               :8;
>                 u32     chunk_stop_index        :8;
>                 u32     rsvd1                   :16;
>                 u32     error_code              :8;
>                 u32     rsvd2                   :22;
>                 u32     control_error           :1;
>                 u32     signature_error         :1;
>         };
> };
> 
> Would it be better to do the bit extractions of the start/stop fields first?

No, I'm just paranoid about passing structures / unions in by value and not
reference. If you are fine with this, then I'm OK too.

-- Steve


^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS
  2022-04-08  8:34   ` Borislav Petkov
@ 2022-04-21 14:56     ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-04-21 14:56 UTC (permalink / raw)
  To: Borislav Petkov, Jithu Joseph
  Cc: hdegoede, markgross, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, Apr 08 2022 at 10:34, Borislav Petkov wrote:
> On Thu, Apr 07, 2022 at 12:13:38PM -0700, Jithu Joseph wrote:
>> +EXPORT_SYMBOL_GPL(cpu_signatures_match);
>> +
>> +int cpu_collect_info_early(struct ucode_cpu_info *uci)
>
> intel_collect_cpu_info_early()

That function name does not make sense in context of that driver...

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v4 00/10] Introduce In Field Scan driver
  2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
                     ` (10 preceding siblings ...)
  2022-04-19 16:38   ` [PATCH v3 11/11] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
@ 2022-04-22 20:02   ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
                       ` (10 more replies)
  11 siblings, 11 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

TL;DR this driver loads scan test files that can check whether silicon
in a CPU core is still running correctly. It is expected that these tests
would be run several times per day to catch problems as silicon ages.

Changes since v3:

Thomas Gleixner:
----------------
1) intel_collect_cpu_info_early() ... function name doesn't make sense
   in context of this driver

   True: Dropped the "_early" suffix from the name.

Greg Kroah-Hartman:
-------------------
1) "Ick, why?" and "pmem.c should not be used as a good example of anything"
   and "Why not just use a misc device?"

   Now using a misc device.

2) "So even if everything fails, you succeed?"

   This was w.r.t. the "pmem"-like driver, which is completely gone in
   v4. New driver succeeds if any of the test-types enumerate as present
   on the system. Fails with -ENODEV if no test types found.

3) "sysfs documentation belongs in Documentation/ABI/"

   See patch 10 of this series.

4) "And why not just include this whole thing in the driver itself and suck
   the documentation out of that?  No need to have a separate file."

   Dropped Documentation/x86/ifs.rst from v4. People should be able to
   figure out how to use it from the ABI docs for the sysfs files. If
   that turns out to be wrong, we can revisit.

5) "int load_ifs_binary(struct device *dev)
    Shouldn't all of your global symbols start with "ifs_"?  Your other ones
    seem to, what went wrong here?
    Also, how about "ifs_load_firmware()" makes more sense."

    Changed name to ifs_load_firmware()

6) "static bool ifs_image_sanity_check(struct device *dev, void *data)
    u8 *data?"  and
   "if (!ifs_image_sanity_check(dev, (void *)fw->data)) {
    It's not a void pointer, it's a pointer to u8.  Why cast it away?"

   Changed the top of that call stack to cast to "(struct microcode_header_intel *)
   which is what the lower level functions all want.

7) "if (!sysfs_streq(buf, "1"))
   kstrtobool()?

   Changed from sysfs_streq() to kstrtobool()

8) "ATTRIBUTE_GROUPS()?"

   Now using this macro.

Steven Rostedt:
---------------
1) "TP_PROTO(union ifs_scan activate, union ifs_status status),

   Really, you want to pass the structure in by value, so that we have two
   copies? One to get to this function and then one to write to the ring
   buffer?"

   Discussion on list resolved because these "pass by value" objects are
   just wrappers around a u64. Passing pointers wouldn't make any real
   difference. No code change.

Jithu Joseph (7):
  x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  platform/x86/intel/ifs: Read IFS firmware image
  platform/x86/intel/ifs: Check IFS Image sanity
  platform/x86/intel/ifs: Authenticate and copy to secured memory
  platform/x86/intel/ifs: Add scan test support
  platform/x86/intel/ifs: Add IFS sysfs interface
  platform/x86/intel/ifs: add ABI documentation for IFS

Tony Luck (3):
  x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  platform/x86/intel/ifs: Add stub driver for In-Field Scan
  trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
    operations

 .../ABI/testing/sysfs-platform-intel-ifs      |  39 ++
 MAINTAINERS                                   |   8 +
 arch/x86/include/asm/cpu.h                    |  18 +
 arch/x86/include/asm/msr-index.h              |   7 +
 arch/x86/kernel/cpu/intel.c                   |  32 ++
 arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
 drivers/platform/x86/intel/Kconfig            |   1 +
 drivers/platform/x86/intel/Makefile           |   1 +
 drivers/platform/x86/intel/ifs/Kconfig        |  13 +
 drivers/platform/x86/intel/ifs/Makefile       |   3 +
 drivers/platform/x86/intel/ifs/core.c         |  97 +++++
 drivers/platform/x86/intel/ifs/ifs.h          | 123 +++++++
 drivers/platform/x86/intel/ifs/load.c         | 262 ++++++++++++++
 drivers/platform/x86/intel/ifs/runtest.c      | 332 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/sysfs.c        | 147 ++++++++
 include/trace/events/intel_ifs.h              |  38 ++
 16 files changed, 1128 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
 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
 create mode 100644 drivers/platform/x86/intel/ifs/load.c
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
 create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
 create mode 100644 include/trace/events/intel_ifs.h


base-commit: b2d229d4ddb17db541098b83524d901257e93845
-- 
2.35.1


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v4 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs.

In support of an IFS driver to trigger loading, validation, and running
of these tests blobs, make the functionality of cpu_signatures_match()
and collect_cpu_info_early() available outside of the microcode driver.

Add an "intel_" prefix and drop the "_early" suffix from
collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
declaration to x86 <asm/cpu.h>

Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
and also give it an "intel_" prefix.

No functional change intended.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 arch/x86/include/asm/cpu.h            | 18 ++++++++
 arch/x86/kernel/cpu/intel.c           | 32 +++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c | 59 ++++-----------------------
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 86e5e4e26fcb..990167357c34 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -76,4 +76,22 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
 
 extern __noendbr void cet_disable(void);
 
+struct ucode_cpu_info;
+
+int intel_cpu_collect_info(struct ucode_cpu_info *uci);
+
+static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+					      unsigned int s2, unsigned int p2)
+{
+	if (s1 != s2)
+		return false;
+
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
+
+	/* ... or they intersect. */
+	return p1 & p2;
+}
+
 #endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f7a5370a9b3b..94779146275d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,6 +181,38 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 	return false;
 }
 
+int intel_cpu_collect_info(struct ucode_cpu_info *uci)
+{
+	unsigned int val[2];
+	unsigned int family, model;
+	struct cpu_signature csig = { 0 };
+	unsigned int eax, ebx, ecx, edx;
+
+	memset(uci, 0, sizeof(*uci));
+
+	eax = 0x00000001;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	csig.sig = eax;
+
+	family = x86_family(eax);
+	model  = x86_model(eax);
+
+	if (model >= 5 || family > 6) {
+		/* get processor flags from MSR 0x17 */
+		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		csig.pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	csig.rev = intel_get_microcode_revision();
+
+	uci->cpu_sig = csig;
+	uci->valid = 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index d28a9f8f3fec..025c8f0cd948 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */
@@ -69,7 +55,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	struct extended_signature *ext_sig;
 	int i;
 
-	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
 		return 1;
 
 	/* Look for ext. headers: */
@@ -80,7 +66,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
 
 	for (i = 0; i < ext_hdr->count; i++) {
-		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
 			return 1;
 		ext_sig++;
 	}
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 	return patch;
 }
 
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-	unsigned int val[2];
-	unsigned int family, model;
-	struct cpu_signature csig = { 0 };
-	unsigned int eax, ebx, ecx, edx;
-
-	memset(uci, 0, sizeof(*uci));
-
-	eax = 0x00000001;
-	ecx = 0;
-	native_cpuid(&eax, &ebx, &ecx, &edx);
-	csig.sig = eax;
-
-	family = x86_family(eax);
-	model  = x86_model(eax);
-
-	if ((model >= 5) || (family > 6)) {
-		/* get processor flags from MSR 0x17 */
-		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		csig.pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	csig.rev = intel_get_microcode_revision();
-
-	uci->cpu_sig = csig;
-	uci->valid = 1;
-
-	return 0;
-}
-
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
 		return;
 	}
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	sig	= uci.cpu_sig.sig;
 	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
 	struct ucode_cpu_info uci;
 
 	if (delay_ucode_info) {
-		collect_cpu_info_early(&uci);
+		intel_cpu_collect_info(&uci);
 		print_ucode_info(&uci, current_mc_date);
 		delay_ucode_info = 0;
 	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
 	if (!(cp.data && cp.size))
 		return 0;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	scan_microcode(cp.data, cp.size, &uci, true);
 
@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 	if (!(cp.data && cp.size))
 		return NULL;
 
-	collect_cpu_info_early(uci);
+	intel_cpu_collect_info(uci);
 
 	return scan_microcode(cp.data, cp.size, uci, false);
 }
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
 	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	p = find_patch(&uci);
 	if (!p)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
  2022-04-22 20:02     ` [PATCH v4 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

The INTEGRITY_CAPABILITIES MSR is enumerated by bit 2 of the
CORE_CAPABILITIES MSR.

Add defines for the CORE_CAPS enumeration as well as for the integrity
MSR.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 arch/x86/include/asm/msr-index.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index ee15311b6be1..c3dc7ae32f1f 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -76,6 +76,8 @@
 
 /* Abbreviated from Intel SDM name IA32_CORE_CAPABILITIES */
 #define MSR_IA32_CORE_CAPS			  0x000000cf
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT	  2
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS	  BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT)
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT  5
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT	  BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
 
@@ -154,6 +156,11 @@
 #define MSR_IA32_POWER_CTL		0x000001fc
 #define MSR_IA32_POWER_CTL_BIT_EE	19
 
+/* Abbreviated from Intel SDM name IA32_INTEGRITY_CAPABILITIES */
+#define MSR_INTEGRITY_CAPS			0x000002d9
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT	4
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST	BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
+
 #define MSR_LBR_NHM_FROM		0x00000680
 #define MSR_LBR_NHM_TO			0x000006c0
 #define MSR_LBR_CORE_FROM		0x00000040
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
  2022-04-22 20:02     ` [PATCH v4 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
  2022-04-22 20:02     ` [PATCH v4 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Cloud Service Providers that operate fleets of servers have reported
[1] occasions where they can detect that a CPU has gone bad due to
effects like electromigration, or isolated manufacturing defects.
However, that detection method is A/B testing seemingly random
application failures looking for a pattern. In-Field Scan (IFS) is
a driver for a platform capability to load a crafted 'scan image'
to run targeted low level diagnostics outside of the CPU's architectural
error detection capabilities.

Stub version of driver just does initial part of check for the IFS
feature. MSR_IA32_CORE_CAPS must enumerate the presence of the
MSR_INTEGRITY_CAPS MSR.

[1]: https://www.youtube.com/watch?v=QMF3rqhjYuM

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 MAINTAINERS                             |  7 ++++
 drivers/platform/x86/intel/Kconfig      |  1 +
 drivers/platform/x86/intel/Makefile     |  1 +
 drivers/platform/x86/intel/ifs/Kconfig  | 13 +++++++
 drivers/platform/x86/intel/ifs/Makefile |  3 ++
 drivers/platform/x86/intel/ifs/core.c   | 52 +++++++++++++++++++++++++
 6 files changed, 77 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

diff --git a/MAINTAINERS b/MAINTAINERS
index 40fa1955ca3f..d2ee63193ab3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9861,6 +9861,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
 
+INTEL IN FIELD SCAN (IFS) DEVICE
+M:	Jithu Joseph <jithu.joseph@intel.com>
+R:	Ashok Raj <ashok.raj@intel.com>
+R:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+F:	drivers/platform/x86/intel/ifs
+
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 1f01a8a23c57..794968bda115 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -4,6 +4,7 @@
 #
 
 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/int3472/Kconfig"
 source "drivers/platform/x86/intel/pmc/Kconfig"
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index c61bc3e97121..717933dd0cfd 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
+obj-$(CONFIG_INTEL_IFS)			+= ifs/
 obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
 obj-$(CONFIG_INTEL_SKL_INT3472)		+= int3472/
 obj-$(CONFIG_INTEL_PMC_CORE)		+= pmc/
diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
new file mode 100644
index 000000000000..d84491cfb0db
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Kconfig
@@ -0,0 +1,13 @@
+config INTEL_IFS
+	tristate "Intel In Field Scan"
+	depends on X86 && 64BIT && SMP
+	select INTEL_IFS_DEVICE
+	help
+	  Enable support for the In Field Scan capability in select
+	  CPUs. The capability allows for running low level tests via
+	  a scan image distributed by Intel via Github to validate CPU
+	  operation beyond baseline RAS capabilities. To compile this
+	  support 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..af904880e959
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
+
+intel_ifs-objs			:= core.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
new file mode 100644
index 000000000000..5713e6ee90f0
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+
+#include <asm/cpu_device_id.h>
+
+enum test_types {
+	IFS_SAF,
+};
+
+#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 = {
+	X86_MATCH(SAPPHIRERAPIDS_X),
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
+
+static int __init ifs_init(void)
+{
+	const struct x86_cpu_id *m;
+	u64 msrval;
+
+	m = x86_match_cpu(ifs_cpu_ids);
+	if (!m)
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &msrval))
+		return -ENODEV;
+
+	if (!(msrval & MSR_IA32_CORE_CAPS_INTEGRITY_CAPS))
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
+		return -ENODEV;
+
+	return 0;
+}
+
+static void __exit ifs_exit(void)
+{
+}
+
+module_init(ifs_init);
+module_exit(ifs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel In Field Scan (IFS) device");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (2 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-26 10:45       ` Greg KH
  2022-04-22 20:02     ` [PATCH v4 05/10] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
                       ` (6 subsequent siblings)
  10 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Driver probe routine allocates structure to communicate status
and parameters between functions in the driver. Also call
load_ifs_binary() to load the scan image file.

There is a separate scan image file for each processor family,
model, stepping combination. This is read from the static path:

  /lib/firmware/intel/ifs/{ff-mm-ss}.scan

Step 1 in loading is to generate the correct path and use
request_firmware_direct() to load into memory.

Subsequent patches will use the IFS MSR interfaces to copy
the image to BIOS reserved memory and validate the SHA256
checksums.

Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |  2 +-
 drivers/platform/x86/intel/ifs/core.c   | 36 ++++++++++++++++++++++++-
 drivers/platform/x86/intel/ifs/ifs.h    | 25 +++++++++++++++++
 drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++
 4 files changed, 89 insertions(+), 2 deletions(-)
 create mode 100644 drivers/platform/x86/intel/ifs/ifs.h
 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 af904880e959..98b6fde15689 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o
+intel_ifs-objs			:= core.o load.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 5713e6ee90f0..ed4ded6755b2 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -6,6 +6,8 @@
 
 #include <asm/cpu_device_id.h>
 
+#include "ifs.h"
+
 enum test_types {
 	IFS_SAF,
 };
@@ -20,10 +22,27 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
 };
 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 
+static struct ifs_device ifs_devices[] = {
+	[IFS_SAF] = {
+		.data = {
+			.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
+		},
+		.misc = {
+			.name = "intel_ifs_0",
+			.nodename = "intel_ifs/0",
+			.minor = MISC_DYNAMIC_MINOR,
+		},
+	},
+};
+
+#define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
+
 static int __init ifs_init(void)
 {
 	const struct x86_cpu_id *m;
+	int ndevices = 0;
 	u64 msrval;
+	int i;
 
 	m = x86_match_cpu(ifs_cpu_ids);
 	if (!m)
@@ -38,11 +57,26 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
-	return 0;
+	for (i = 0; i < IFS_NUMTESTS; i++) {
+		if (!(msrval & BIT(ifs_devices[i].data.integrity_cap_bit)))
+			continue;
+
+		if (!misc_register(&ifs_devices[i].misc)) {
+			ndevices++;
+			ifs_load_firmware(ifs_devices[i].misc.this_device);
+		}
+	}
+
+	return ndevices ? 0 : -ENODEV;
 }
 
 static void __exit ifs_exit(void)
 {
+	int i;
+
+	for (i = 0; i < IFS_NUMTESTS; i++)
+		if (ifs_devices[i].misc.this_device)
+			misc_deregister(&ifs_devices[i].misc);
 }
 
 module_init(ifs_init);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
new file mode 100644
index 000000000000..9a0f8e2077e2
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Intel Corporation. */
+
+#ifndef _IFS_H_
+#define _IFS_H_
+
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+
+/**
+ * struct ifs_data - attributes related to intel IFS driver
+ * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
+ */
+struct ifs_data {
+	int integrity_cap_bit;
+};
+
+struct ifs_device {
+	struct ifs_data data;
+	struct miscdevice misc;
+};
+
+void ifs_load_firmware(struct device *dev);
+
+#endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
new file mode 100644
index 000000000000..9fb71d38c819
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/firmware.h>
+
+#include "ifs.h"
+
+/*
+ * Load ifs image. Before loading ifs module, the ifs image must be located
+ * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
+ */
+void ifs_load_firmware(struct device *dev)
+{
+	const struct firmware *fw;
+	char scan_path[32];
+	int ret;
+
+	snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
+		 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
+
+	ret = request_firmware_direct(&fw, scan_path, dev);
+	if (ret) {
+		dev_err(dev, "ifs file %s load failed\n", scan_path);
+		return;
+	}
+
+	release_firmware(fw);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 05/10] platform/x86/intel/ifs: Check IFS Image sanity
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (3 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
                       ` (5 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/load.c | 68 +++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index 9fb71d38c819..aece78d1c757 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -2,9 +2,74 @@
 /* Copyright(c) 2022 Intel Corporation. */
 
 #include <linux/firmware.h>
+#include <asm/cpu.h>
+#include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+static int ifs_sanity_check(struct device *dev,
+			    const struct microcode_header_intel *mc_header)
+{
+	unsigned long total_size, data_size;
+	u32 sum, i;
+	u8 *mc;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+
+	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
+		dev_err(dev, "bad ifs data file size.\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		dev_err(dev, "invalid/unknown ifs update format.\n");
+		return -EINVAL;
+	}
+
+	mc = (u8 *)mc_header;
+	sum = 0;
+	i = total_size / sizeof(u32);
+	while (i--)
+		sum += ((u32 *)mc)[i];
+
+	if (sum) {
+		dev_err(dev, "bad ifs data checksum, aborting.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
+					const struct microcode_header_intel *shdr)
+{
+	unsigned int mc_size;
+
+	mc_size = get_totalsize(shdr);
+
+	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
+		dev_err(dev, "ifs sanity check failure\n");
+		return false;
+	}
+
+	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
+		dev_err(dev, "ifs signature, pf not matching\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
+{
+	struct ucode_cpu_info uci;
+
+	intel_cpu_collect_info(&uci);
+
+	return find_ifs_matching_signature(dev, &uci, data);
+}
+
 /*
  * Load ifs image. Before loading ifs module, the ifs image must be located
  * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
@@ -24,5 +89,8 @@ void ifs_load_firmware(struct device *dev)
 		return;
 	}
 
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+		dev_err(dev, "ifs header sanity check failed\n");
+
 	release_firmware(fw);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (4 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 05/10] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
                       ` (4 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/ifs.h  |  47 +++++++
 drivers/platform/x86/intel/ifs/load.c | 170 +++++++++++++++++++++++++-
 2 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 9a0f8e2077e2..a9e73346cd28 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -7,12 +7,51 @@
 #include <linux/device.h>
 #include <linux/miscdevice.h>
 
+#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 {
+		u32	chunk_size	:16;
+		u32	num_chunks	:8;
+		u32	rsvd1		:8;
+		u32	error_code	:8;
+		u32	rsvd2		:11;
+		u32	max_core_limit	:12;
+		u32	valid		:1;
+	};
+};
+
+/* MSR_CHUNKS_AUTH_STATUS bit fields */
+union ifs_chunks_auth_status {
+	u64	data;
+	struct {
+		u32	valid_chunks	:8;
+		u32	total_chunks	:8;
+		u32	rsvd1		:16;
+		u32	error_code	:8;
+		u32	rsvd2		:24;
+	};
+};
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
+ * @loaded_version: stores the currently loaded ifs image version.
+ * @loaded: If a valid test binary has been loaded into the memory
+ * @loading_error: Error occurred on another CPU while loading image
+ * @valid_chunks: number of chunks which could be validated.
  */
 struct ifs_data {
 	int integrity_cap_bit;
+	int loaded_version;
+	bool loaded;
+	bool loading_error;
+	int valid_chunks;
 };
 
 struct ifs_device {
@@ -20,6 +59,14 @@ struct ifs_device {
 	struct miscdevice misc;
 };
 
+static inline struct ifs_data *ifs_get_data(struct device *dev)
+{
+	struct miscdevice *m = dev_get_drvdata(dev);
+	struct ifs_device *d = container_of(m, struct ifs_device, misc);
+
+	return &d->data;
+}
+
 void ifs_load_firmware(struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index aece78d1c757..46a9b78aa195 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,10 +3,166 @@
 
 #include <linux/firmware.h>
 #include <asm/cpu.h>
+#include <linux/slab.h>
 #include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+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 header */
+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[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to copy scan hashes when copy already in progress",
+	[2] = "Secure Memory not set up correctly",
+	[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
+	[4] = "Reserved",
+	[5] = "Integrity check failed",
+	[6] = "Scan reload or test is in progress"
+};
+
+static const char * const scan_authentication_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to authenticate a chunk which is already marked as authentic",
+	[2] = "Chunk authentication error. The hash of chunk did not match expected value"
+};
+
+/*
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must 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_AUTHENTICATE_AND_COPY_CHUNK)
+ * for scan hash copy and test chunk authentication.
+ */
+static void 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;
+	struct device *dev = arg;
+	struct ifs_data *ifsd;
+	u64 linear_addr, base;
+	u32 err_code;
+
+	ifsd = ifs_get_data(dev);
+	/* 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 = hashes_status.num_chunks;
+	chunk_size = hashes_status.chunk_size * 1024;
+	err_code = hashes_status.error_code;
+
+	if (!hashes_status.valid) {
+		ifsd->loading_error = true;
+		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
+			dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
+			return;
+		}
+		dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
+		return;
+	}
+
+	/* base linear address to the scan data */
+	base = ifs_test_image_ptr;
+
+	/* scan data authentication and copy chunks to secured memory */
+	for (i = 0; i < num_chunks; i++) {
+		linear_addr = base + i * chunk_size;
+		linear_addr |= i;
+
+		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
+		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
+
+		ifsd->valid_chunks = chunk_status.valid_chunks;
+		err_code = chunk_status.error_code;
+
+		if (err_code) {
+			ifsd->loading_error = true;
+			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
+				dev_err(dev,
+					"invalid error code 0x%x for authentication\n", err_code);
+				return;
+			}
+			dev_err(dev, "Chunk authentication error %s\n",
+				scan_authentication_status[err_code]);
+			return;
+		}
+	}
+}
+
+/*
+ * IFS requires scan chunks authenticated per each socket in the platform.
+ * Once the test chunk is authenticated, it is automatically copied to secured memory
+ * and proceed the authentication for the next chunk.
+ */
+static int scan_chunks_sanity_check(struct device *dev)
+{
+	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	bool *package_authenticated;
+	char *test_ptr;
+
+	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
+	if (!package_authenticated)
+		return ret;
+
+	metadata_size = ifs_header_ptr->metadata_size;
+
+	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
+	if (metadata_size == 0)
+		metadata_size = 2000;
+
+	/* Scan chunk start must be 256 byte aligned */
+	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
+		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
+		return -EINVAL;
+	}
+
+	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
+	ifsd->loading_error = false;
+
+	ifs_test_image_ptr = (u64)test_ptr;
+	ifsd->loaded_version = ifs_header_ptr->blob_revision;
+
+	/* copy the scan hash and authenticate per package */
+	cpus_read_lock();
+	for_each_online_cpu(cpu) {
+		curr_pkg = topology_physical_package_id(cpu);
+		if (package_authenticated[curr_pkg])
+			continue;
+		package_authenticated[curr_pkg] = 1;
+		ret = smp_call_function_single(cpu, copy_hashes_authenticate_chunks,
+					       dev, 1);
+		if (ret || ifsd->loading_error) {
+			ret = ifsd->loading_error ? -ENOMEM : ret;
+			goto out;
+		}
+	}
+
+out:
+	cpus_read_unlock();
+	kfree(package_authenticated);
+
+	return ret;
+}
+
 static int ifs_sanity_check(struct device *dev,
 			    const struct microcode_header_intel *mc_header)
 {
@@ -76,6 +232,7 @@ static bool ifs_image_sanity_check(struct device *dev, const struct microcode_he
  */
 void ifs_load_firmware(struct device *dev)
 {
+	struct ifs_data *ifsd = ifs_get_data(dev);
 	const struct firmware *fw;
 	char scan_path[32];
 	int ret;
@@ -86,11 +243,20 @@ void ifs_load_firmware(struct device *dev)
 	ret = request_firmware_direct(&fw, scan_path, dev);
 	if (ret) {
 		dev_err(dev, "ifs file %s load failed\n", scan_path);
-		return;
+		goto done;
 	}
 
-	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
 		dev_err(dev, "ifs header sanity check failed\n");
+		goto release;
+	}
+
+	ifs_header_ptr = (struct ifs_header *)fw->data;
+	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
 
+	ret = scan_chunks_sanity_check(dev);
+release:
 	release_firmware(fw);
+done:
+	ifsd->loaded = (ret == 0);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 07/10] platform/x86/intel/ifs: Add scan test support
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (5 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

In a core, the scan engine is shared between sibling cpus.

When a Scan test (for a particular core) is triggered by the user,
worker threads for each sibling cpus(belonging to that core) are
queued to execute the scan test function in the Workqueue context.

All the siblings rendezvous before the test execution. 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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/core.c    |   7 +
 drivers/platform/x86/intel/ifs/ifs.h     |  48 ++++
 drivers/platform/x86/intel/ifs/runtest.c | 327 +++++++++++++++++++++++
 4 files changed, 383 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c

diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
index 98b6fde15689..cedcb103f860 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o
+intel_ifs-objs			:= core.o load.o runtest.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index ed4ded6755b2..fa4a6b13c1e2 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -57,6 +57,9 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
+	if (ifs_setup_wq())
+		return -ENOMEM;
+
 	for (i = 0; i < IFS_NUMTESTS; i++) {
 		if (!(msrval & BIT(ifs_devices[i].data.integrity_cap_bit)))
 			continue;
@@ -67,6 +70,9 @@ static int __init ifs_init(void)
 		}
 	}
 
+	if (!ndevices)
+		ifs_destroy_wq();
+
 	return ndevices ? 0 : -ENODEV;
 }
 
@@ -77,6 +83,7 @@ static void __exit ifs_exit(void)
 	for (i = 0; i < IFS_NUMTESTS; i++)
 		if (ifs_devices[i].misc.this_device)
 			misc_deregister(&ifs_devices[i].misc);
+	ifs_destroy_wq();
 }
 
 module_init(ifs_init);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index a9e73346cd28..1df796227ace 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -11,6 +11,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_NOT_TESTED				0
+#define SCAN_TEST_PASS				1
+#define SCAN_TEST_FAIL				2
+#define SPINUNIT				100
+#define THREAD_WAIT				5
 
 /* MSR_SCAN_HASHES_STATUS bit fields */
 union ifs_scan_hashes_status {
@@ -38,6 +45,40 @@ union ifs_chunks_auth_status {
 	};
 };
 
+/* MSR_ACTIVATE_SCAN bit fields */
+union ifs_scan {
+	u64	data;
+	struct {
+		u32	start	:8;
+		u32	stop	:8;
+		u32	rsvd	:16;
+		u32	delay	:31;
+		u32	sigmce	:1;
+	};
+};
+
+/* MSR_SCAN_STATUS bit fields */
+union ifs_status {
+	u64	data;
+	struct {
+		u32	chunk_num		:8;
+		u32	chunk_stop_index	:8;
+		u32	rsvd1			:16;
+		u32	error_code		:8;
+		u32	rsvd2			:22;
+		u32	control_error		:1;
+		u32	signature_error		:1;
+	};
+};
+
+/*
+ * Driver populated error-codes
+ * 0xFD: Test timed out before completing all the chunks.
+ * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
+ */
+#define IFS_SW_TIMEOUT				0xFD
+#define IFS_SW_PARTIAL_COMPLETION		0xFE
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
@@ -45,6 +86,8 @@ union ifs_chunks_auth_status {
  * @loaded: If a valid test binary has been loaded into the memory
  * @loading_error: Error occured on another CPU while loading image
  * @valid_chunks: number of chunks which could be validated.
+ * @status: it holds simple status pass/fail/untested
+ * @scan_details: opaque scan status code from h/w
  */
 struct ifs_data {
 	int integrity_cap_bit;
@@ -52,6 +95,8 @@ struct ifs_data {
 	bool loaded;
 	bool loading_error;
 	int valid_chunks;
+	int status;
+	u64 scan_details;
 };
 
 struct ifs_device {
@@ -68,5 +113,8 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
 }
 
 void ifs_load_firmware(struct device *dev);
+int ifs_setup_wq(void);
+void ifs_destroy_wq(void);
+int do_core_test(int cpu, struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
new file mode 100644
index 000000000000..c30cc9c95b4f
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/nmi.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Note all code and data in this file is protected by
+ * ifs_sem. On HT systems all threads on a core will
+ * execute together, but only the first thread on the
+ * core will update results of the test and indicate
+ * completion.
+ */
+static struct workqueue_struct *ifs_wq;
+static struct completion test_thread_done;
+static atomic_t siblings_in;
+static atomic_t siblings_out;
+static int cpu_sibl_ct;
+static bool scan_enabled = true;
+
+struct ifs_work {
+	struct work_struct w;
+	struct device *dev;
+};
+
+/* Max retries on the same chunk */
+#define MAX_IFS_RETRIES  5
+
+static unsigned long msec_to_tsc(unsigned long msec)
+{
+	return tsc_khz * 1000 * msec / MSEC_PER_SEC;
+}
+
+enum ifs_status_err_code {
+	IFS_NO_ERROR				= 0,
+	IFS_OTHER_THREAD_COULD_NOT_JOIN		= 1,
+	IFS_INTERRUPTED_BEFORE_RENDEZVOUS	= 2,
+	IFS_POWER_MGMT_INADEQUATE_FOR_SCAN	= 3,
+	IFS_INVALID_CHUNK_RANGE			= 4,
+	IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS	= 5,
+	IFS_CORE_NOT_CAPABLE_CURRENTLY		= 6,
+	IFS_UNASSIGNED_ERROR_CODE		= 7,
+	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT	= 8,
+	IFS_INTERRUPTED_DURING_EXECUTION	= 9,
+};
+
+static const char * const scan_test_status[] = {
+	[IFS_NO_ERROR] = "SCAN no error",
+	[IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.",
+	[IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.",
+	[IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] =
+	"Core Abort SCAN Response due to power management condition.",
+	[IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range",
+	[IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.",
+	[IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently",
+	[IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7",
+	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
+	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
+	[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start",
+};
+
+static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
+{
+	if (status.error_code < ARRAY_SIZE(scan_test_status))
+		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 scan_test_status[status.error_code]);
+	else if (status.error_code == IFS_SW_TIMEOUT)
+		dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	else if (status.error_code == IFS_SW_PARTIAL_COMPLETION)
+		dev_info(dev, "CPU(s) %*pbl: %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 "Not all scan chunks were executed. Maximum forward progress retries exceeded");
+	else
+		dev_info(dev, "CPU(s) %*pbl: SCAN unknown status %llx\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)), status.data);
+}
+
+static void message_fail(struct device *dev, int cpu, union ifs_status status)
+{
+	/*
+	 * control_error is set when the microcode runs into a problem
+	 * loading the image from the reserved BIOS memory, or it has
+	 * been corrupted. Reloading the image may fix this issue.
+	 */
+	if (status.control_error) {
+		dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+
+	/*
+	 * signature_error is set when the output from the scan chains does not
+	 * match the expected signature. This might be a transient problem (e.g.
+	 * due to a bit flip from an alpha particle or neutron). If the problem
+	 * repeats on a subsequent test, then it indicates an actual problem in
+	 * the core being tested.
+	 */
+	if (status.signature_error) {
+		dev_err(dev, "CPU(s) %*pbl: test signature incorrect.\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+}
+
+static bool can_restart(union ifs_status status)
+{
+	enum ifs_status_err_code err_code = status.error_code;
+
+	/* Signature for chunk is bad, or scan test failed */
+	if (status.signature_error || status.control_error)
+		return false;
+
+	switch (err_code) {
+	case IFS_NO_ERROR:
+	case IFS_OTHER_THREAD_COULD_NOT_JOIN:
+	case IFS_INTERRUPTED_BEFORE_RENDEZVOUS:
+	case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN:
+	case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT:
+	case IFS_INTERRUPTED_DURING_EXECUTION:
+		return true;
+	case IFS_INVALID_CHUNK_RANGE:
+	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
+	case IFS_CORE_NOT_CAPABLE_CURRENTLY:
+	case IFS_UNASSIGNED_ERROR_CODE:
+		break;
+	}
+	return false;
+}
+
+static bool wait_for_siblings(struct device *dev, struct ifs_data *ifsd, atomic_t *t, long long timeout)
+{
+	atomic_inc(t);
+	while (atomic_read(t) < cpu_sibl_ct) {
+		if (timeout < SPINUNIT) {
+			dev_err(dev,
+				"Timeout while waiting for CPUs rendezvous, remaining: %d\n",
+				cpu_sibl_ct - atomic_read(t));
+			return false;
+		}
+
+		ndelay(SPINUNIT);
+		timeout -= SPINUNIT;
+
+		touch_nmi_watchdog();
+	}
+
+	return true;
+}
+
+/*
+ * When a Scan test (for a particular core) is triggered by the user, worker threads
+ * for each sibling cpus(belonging to that core) are queued to execute this function in
+ * the Workqueue (ifs_wq) context.
+ * Wait for the sibling thread to join before the execution.
+ * Execute the scan test by running wrmsr(MSR_ACTIVATE_SCAN).
+ */
+static void ifs_work_func(struct work_struct *work)
+{
+	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
+	int cpu = smp_processor_id();
+	union ifs_scan activate;
+	union ifs_status status;
+	unsigned long timeout;
+	struct ifs_data *ifsd;
+	struct device *dev;
+	int retries;
+	u32 first;
+
+	dev = local_work->dev;
+	ifsd = ifs_get_data(dev);
+
+	activate.rsvd = 0;
+	activate.delay = msec_to_tsc(THREAD_WAIT);
+	activate.sigmce = 0;
+
+	/*
+	 * Need to get (and keep) the threads on this core executing close together
+	 * 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 = cpumask_first(topology_sibling_cpumask(cpu));
+	if (!wait_for_siblings(dev, ifsd, &siblings_in, NSEC_PER_SEC)) {
+		preempt_enable();
+		dev_err(dev, "cpu %d sibling did not join rendezvous\n", cpu);
+		goto out;
+	}
+
+	activate.start = 0;
+	activate.stop = ifsd->valid_chunks - 1;
+	timeout = jiffies + HZ / 2;
+	retries = MAX_IFS_RETRIES;
+
+	while (activate.start <= activate.stop) {
+		if (time_after(jiffies, timeout)) {
+			status.error_code = IFS_SW_TIMEOUT;
+			break;
+		}
+
+		local_irq_disable();
+		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
+		local_irq_enable();
+
+		/*
+		 * All logical CPUs on this core are now running IFS test. When it completes
+		 * execution or is interrupted, the following RDMSR gets the scan status.
+		 */
+
+		rdmsrl(MSR_SCAN_STATUS, status.data);
+
+		/* Some cases can be retried, give up for others */
+		if (!can_restart(status))
+			break;
+
+		if (status.chunk_num == activate.start) {
+			/* Check for forward progress */
+			if (retries-- == 0) {
+				if (status.error_code == IFS_NO_ERROR)
+					status.error_code = IFS_SW_PARTIAL_COMPLETION;
+				break;
+			}
+		} else {
+			retries = MAX_IFS_RETRIES;
+			activate.start = status.chunk_num;
+		}
+	}
+
+	preempt_enable();
+
+	if (cpu == first) {
+		/* Update status for this core */
+		ifsd->scan_details = status.data;
+
+		if (status.control_error || status.signature_error) {
+			ifsd->status = SCAN_TEST_FAIL;
+			message_fail(dev, cpu, status);
+		} else if (status.error_code) {
+			ifsd->status = SCAN_NOT_TESTED;
+			message_not_tested(dev, cpu, status);
+		} else {
+			ifsd->status = SCAN_TEST_PASS;
+		}
+	}
+
+	if (!wait_for_siblings(dev, ifsd, &siblings_out, NSEC_PER_SEC))
+		dev_err(dev, "cpu %d sibling did not exit rendezvous\n", cpu);
+
+out:
+	if (cpu == first)
+		complete(&test_thread_done);
+}
+
+/*
+ * Initiate per core test. It wakes up work queue threads on the target cpu and
+ * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
+ * wait for all sibling threads to finish the scan test.
+ */
+int do_core_test(int cpu, struct device *dev)
+{
+	struct ifs_work *local_work;
+	int sibling;
+	int ret = 0;
+	int i = 0;
+
+	if (!scan_enabled)
+		return -ENXIO;
+
+	cpu_hotplug_disable();
+	if (!cpu_online(cpu)) {
+		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	reinit_completion(&test_thread_done);
+	atomic_set(&siblings_in, 0);
+	atomic_set(&siblings_out, 0);
+
+	cpu_sibl_ct = cpumask_weight(topology_sibling_cpumask(cpu));
+	local_work = kcalloc(cpu_sibl_ct, sizeof(*local_work), GFP_NOWAIT);
+	if (!local_work) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for_each_cpu(sibling, topology_sibling_cpumask(cpu)) {
+		local_work[i].dev = dev;
+		INIT_WORK(&local_work[i].w, ifs_work_func);
+		queue_work_on(sibling, ifs_wq, &local_work[i].w);
+		i++;
+	}
+
+	if (wait_for_completion_timeout(&test_thread_done, HZ) == 0) {
+		dev_err(dev, "cpu %d Core locked up during IFS test? IFS disabled\n", cpu);
+		scan_enabled = false;
+	}
+
+	kfree(local_work);
+out:
+	cpu_hotplug_enable();
+	return ret;
+}
+
+int ifs_setup_wq(void)
+{
+	/* Flags are to keep all the sibling cpu worker threads (of a core) in close sync */
+	ifs_wq = alloc_workqueue("intel_ifs", (WQ_HIGHPRI | WQ_CPU_INTENSIVE), 1);
+	if (!ifs_wq)
+		return -ENOMEM;
+
+	init_completion(&test_thread_done);
+
+	return 0;
+}
+
+void ifs_destroy_wq(void)
+{
+	destroy_workqueue(ifs_wq);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 08/10] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (6 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-22 20:02     ` [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
                       ` (2 subsequent siblings)
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Implement sysfs interface to trigger ifs test for a specific cpu.
Additional interfaces related to checking the status of the
scan test and seeing the version of the loaded IFS binary
are also added.

The basic usage is as below.
   - To start test, for example on cpu5:
       echo 5 > /sys/devices/platform/intel_ifs/run_test
   - To see the status of the last test
       cat /sys/devices/platform/intel_ifs/status
   - To see the version of the loaded scan binary
       cat /sys/devices/platform/intel_ifs/image_version

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |   2 +-
 drivers/platform/x86/intel/ifs/core.c   |   4 +
 drivers/platform/x86/intel/ifs/ifs.h    |   3 +
 drivers/platform/x86/intel/ifs/sysfs.c  | 147 ++++++++++++++++++++++++
 4 files changed, 155 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 cedcb103f860..30f035ef5581 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o runtest.o
+intel_ifs-objs			:= core.o load.o runtest.o sysfs.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index fa4a6b13c1e2..317ed3225307 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -3,6 +3,7 @@
 
 #include <linux/module.h>
 #include <linux/kdev_t.h>
+#include <linux/semaphore.h>
 
 #include <asm/cpu_device_id.h>
 
@@ -64,9 +65,12 @@ static int __init ifs_init(void)
 		if (!(msrval & BIT(ifs_devices[i].data.integrity_cap_bit)))
 			continue;
 
+		ifs_devices[i].misc.groups = ifs_get_groups();
 		if (!misc_register(&ifs_devices[i].misc)) {
 			ndevices++;
+			down(&ifs_sem);
 			ifs_load_firmware(ifs_devices[i].misc.this_device);
+			up(&ifs_sem);
 		}
 	}
 
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 1df796227ace..2ba03b21e2f8 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -116,5 +116,8 @@ void ifs_load_firmware(struct device *dev);
 int ifs_setup_wq(void);
 void ifs_destroy_wq(void);
 int do_core_test(int cpu, struct device *dev);
+const struct attribute_group **ifs_get_groups(void);
+
+extern struct semaphore ifs_sem;
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
new file mode 100644
index 000000000000..8f3b0fb5a423
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Protects against simultaneous tests on multiple cores, or
+ * reloading can file while a test is in progress
+ */
+DEFINE_SEMAPHORE(ifs_sem);
+
+/*
+ * The sysfs interface to check additional details of last test
+ * cat /sys/devices/system/platform/ifs/details
+ */
+static ssize_t details_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
+}
+
+static DEVICE_ATTR_RO(details);
+
+static const char * const status_msg[] = {
+	[SCAN_NOT_TESTED] = "untested",
+	[SCAN_TEST_PASS] = "pass",
+	[SCAN_TEST_FAIL] = "fail"
+};
+
+/*
+ * The sysfs interface to check the test status:
+ * To check the status of last test
+ * cat /sys/devices/platform/ifs/status
+ */
+static ssize_t status_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
+}
+
+static DEVICE_ATTR_RO(status);
+
+/*
+ * The sysfs interface for single core testing
+ * To start test, for example, cpu5
+ * echo 5 > /sys/devices/platform/ifs/run_test
+ * To check the result:
+ * cat /sys/devices/platform/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)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	unsigned int cpu;
+	int rc;
+
+	rc = kstrtouint(buf, 0, &cpu);
+	if (rc < 0 || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	if (!ifsd->loaded)
+		rc = -EPERM;
+	else
+		rc = do_core_test(cpu, dev);
+
+	up(&ifs_sem);
+
+	return rc ? rc : count;
+}
+
+static DEVICE_ATTR_WO(run_test);
+
+/*
+ * Reload the IFS image. When user wants to install new IFS image
+ */
+static ssize_t reload_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	bool res;
+
+	if (kstrtobool(buf, &res))
+		return -EINVAL;
+	if (!res)
+		return count;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	ifs_load_firmware(dev);
+
+	up(&ifs_sem);
+
+	return count;
+}
+
+static DEVICE_ATTR_WO(reload);
+
+/*
+ * Display currently loaded IFS image version.
+ */
+static ssize_t image_version_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	if (!ifsd->loaded)
+		return sysfs_emit(buf, "%s\n", "none");
+	else
+		return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
+}
+
+static DEVICE_ATTR_RO(image_version);
+
+/* global scan sysfs attributes */
+static struct attribute *plat_ifs_attrs[] = {
+	&dev_attr_details.attr,
+	&dev_attr_status.attr,
+	&dev_attr_run_test.attr,
+	&dev_attr_reload.attr,
+	&dev_attr_image_version.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(plat_ifs);
+
+const struct attribute_group **ifs_get_groups(void)
+{
+	return plat_ifs_groups;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (7 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-25 14:52       ` Steven Rostedt
  2022-04-22 20:02     ` [PATCH v4 10/10] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
  10 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Add tracing support which may be useful for debugging systems that fail to complete
In Field Scan tests.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 MAINTAINERS                              |  1 +
 drivers/platform/x86/intel/ifs/runtest.c |  5 ++++
 include/trace/events/intel_ifs.h         | 38 ++++++++++++++++++++++++
 3 files changed, 44 insertions(+)
 create mode 100644 include/trace/events/intel_ifs.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d2ee63193ab3..abcf9b895ea8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9867,6 +9867,7 @@ R:	Ashok Raj <ashok.raj@intel.com>
 R:	Tony Luck <tony.luck@intel.com>
 S:	Maintained
 F:	drivers/platform/x86/intel/ifs
+F:	include/trace/events/intel_ifs.h
 
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index c30cc9c95b4f..d6cb5d9e44c2 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -23,6 +23,9 @@ static atomic_t siblings_out;
 static int cpu_sibl_ct;
 static bool scan_enabled = true;
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ifs.h>
+
 struct ifs_work {
 	struct work_struct w;
 	struct device *dev;
@@ -216,6 +219,8 @@ static void ifs_work_func(struct work_struct *work)
 
 		rdmsrl(MSR_SCAN_STATUS, status.data);
 
+		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/intel_ifs.h b/include/trace/events/intel_ifs.h
new file mode 100644
index 000000000000..0611f370cb37
--- /dev/null
+++ b/include/trace/events/intel_ifs.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ifs
+
+#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IFS_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ifs_status,
+
+	TP_PROTO(union ifs_scan activate, union ifs_status status),
+
+	TP_ARGS(activate, status),
+
+	TP_STRUCT__entry(
+		__field(	u64,	status	)
+		__field(	u8,	start	)
+		__field(	u8,	stop	)
+	),
+
+	TP_fast_assign(
+		__entry->start	= activate.start;
+		__entry->stop	= activate.stop;
+		__entry->status	= 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 <trace/define_trace.h>
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v4 10/10] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (8 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-04-22 20:02     ` Tony Luck
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
  10 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-22 20:02 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Add the sysfs attributes in ABI/testing for In-Field Scan.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 .../ABI/testing/sysfs-platform-intel-ifs      | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
new file mode 100644
index 000000000000..486d6d2ff8a0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -0,0 +1,39 @@
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/run_test
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write <cpu#> to trigger IFS test for one online core.
+		Note that the test is per core. The cpu# can be
+		for any thread on the core. Running on one thread
+		completes the test for the core containing that thread.
+		Example: to test the core containing cpu5: echo 5 >
+		/sys/devices/platform/intel_ifs.<N>/run_test
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/status
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	The status of the last test. It can be one of "pass", "fail"
+		or "untested".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/details
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Additional information regarding the last test. 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.
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/image_version
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Version (hexadecimal) of loaded IFS binary image. If no scan image
+		is loaded reports "none".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/reload
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write "1" (or "y" or "Y") to reload the IFS image from
+		/lib/firmware/intel/ifs/ff-mm-ss.scan.
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-22 20:02     ` [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-04-25 14:52       ` Steven Rostedt
  2022-04-25 16:49         ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Steven Rostedt @ 2022-04-25 14:52 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, jithu.joseph, ashok.raj,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, 22 Apr 2022 13:02:18 -0700
Tony Luck <tony.luck@intel.com> wrote:

> Add tracing support which may be useful for debugging systems that fail to complete
> In Field Scan tests.
> 
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  MAINTAINERS                              |  1 +
>  drivers/platform/x86/intel/ifs/runtest.c |  5 ++++
>  include/trace/events/intel_ifs.h         | 38 ++++++++++++++++++++++++

From the tracing POV:

Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>

-- Steve

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-25 14:52       ` Steven Rostedt
@ 2022-04-25 16:49         ` Luck, Tony
  2022-04-26  1:49           ` Steven Rostedt
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-25 16:49 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

> > Add tracing support which may be useful for debugging systems that fail to complete
> > In Field Scan tests.
> >
> > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> > Signed-off-by: Tony Luck <tony.luck@intel.com>
> > ---
> >  MAINTAINERS                              |  1 +
> >  drivers/platform/x86/intel/ifs/runtest.c |  5 ++++
> >  include/trace/events/intel_ifs.h         | 38 ++++++++++++++++++++++++
>
> From the tracing POV:
>
> Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>

Question for the future of this driver.  There are a couple more scan tools coming
in the future. The interface is similar:

	WRMSR to start a scan
	RDMSR to get the results

For this first one, I made the trace code do some user friendly decoding of the
WRMSR value to just show the two interesting fields (start & stop).

The future scan modes will have different fields.

I see two paths:

1) Create a new user friendly trace point for each new scan mode.
2) Just provide a generic one that dumps both the 64-bit WRMSR and RDMSR values.

Q: Are trace points "expensive" in some way ... so better to just have one than three?
     Or are the cheap enough that decoding for the user is an OK thing?

Thanks

-Tony



^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-25 16:49         ` Luck, Tony
@ 2022-04-26  1:49           ` Steven Rostedt
  2022-04-26 23:53             ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Steven Rostedt @ 2022-04-26  1:49 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

On Mon, 25 Apr 2022 16:49:35 +0000
"Luck, Tony" <tony.luck@intel.com> wrote:

> I see two paths:
> 
> 1) Create a new user friendly trace point for each new scan mode.
> 2) Just provide a generic one that dumps both the 64-bit WRMSR and RDMSR values.
> 
> Q: Are trace points "expensive" in some way ... so better to just have one than three?
>      Or are the cheap enough that decoding for the user is an OK thing?

Yes, they are expensive as each TRACE_EVENT() can add a few KB of text and
data. But you can add a DECLARE_EVENT_CLASS() and then add "printk"
differences that are less memory heavy.

See DEFINE_EVENT_PRINT().

-- Steve


^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-22 20:02     ` [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-04-26 10:45       ` Greg KH
  2022-04-26 16:12         ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-26 10:45 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, Apr 22, 2022 at 01:02:13PM -0700, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
> 
> Driver probe routine allocates structure to communicate status
> and parameters between functions in the driver. Also call
> load_ifs_binary() to load the scan image file.
> 
> There is a separate scan image file for each processor family,
> model, stepping combination. This is read from the static path:
> 
>   /lib/firmware/intel/ifs/{ff-mm-ss}.scan
> 
> Step 1 in loading is to generate the correct path and use
> request_firmware_direct() to load into memory.
> 
> Subsequent patches will use the IFS MSR interfaces to copy
> the image to BIOS reserved memory and validate the SHA256
> checksums.
> 
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  drivers/platform/x86/intel/ifs/Makefile |  2 +-
>  drivers/platform/x86/intel/ifs/core.c   | 36 ++++++++++++++++++++++++-
>  drivers/platform/x86/intel/ifs/ifs.h    | 25 +++++++++++++++++
>  drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++
>  4 files changed, 89 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/platform/x86/intel/ifs/ifs.h
>  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 af904880e959..98b6fde15689 100644
> --- a/drivers/platform/x86/intel/ifs/Makefile
> +++ b/drivers/platform/x86/intel/ifs/Makefile
> @@ -1,3 +1,3 @@
>  obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
>  
> -intel_ifs-objs			:= core.o
> +intel_ifs-objs			:= core.o load.o
> diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
> index 5713e6ee90f0..ed4ded6755b2 100644
> --- a/drivers/platform/x86/intel/ifs/core.c
> +++ b/drivers/platform/x86/intel/ifs/core.c
> @@ -6,6 +6,8 @@
>  
>  #include <asm/cpu_device_id.h>
>  
> +#include "ifs.h"
> +
>  enum test_types {
>  	IFS_SAF,
>  };
> @@ -20,10 +22,27 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
>  };
>  MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
>  
> +static struct ifs_device ifs_devices[] = {
> +	[IFS_SAF] = {
> +		.data = {
> +			.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
> +		},
> +		.misc = {
> +			.name = "intel_ifs_0",
> +			.nodename = "intel_ifs/0",
> +			.minor = MISC_DYNAMIC_MINOR,
> +		},
> +	},
> +};
> +
> +#define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)

Cute way to do this, but I don't see you ever have any more devices
added to this list in this series.  Did I miss them?

If not, why all the overhead and complexity involved here for just a
single misc device?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-26 10:45       ` Greg KH
@ 2022-04-26 16:12         ` Luck, Tony
  2022-04-26 16:36           ` Greg KH
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-26 16:12 UTC (permalink / raw)
  To: Greg KH
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 26, 2022 at 12:45:40PM +0200, Greg KH wrote:
> On Fri, Apr 22, 2022 at 01:02:13PM -0700, Tony Luck wrote:
> >  drivers/platform/x86/intel/ifs/Makefile |  2 +-
> >  drivers/platform/x86/intel/ifs/core.c   | 36 ++++++++++++++++++++++++-
> >  drivers/platform/x86/intel/ifs/ifs.h    | 25 +++++++++++++++++
> >  drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++

You haven't commented on the source tree location. With the change
to use misc_register() this isn't a "platform" device anymore.

Should I move to "drivers/misc/"? Or is there some better spot that
preseves the detail that this is an x86/intel driver in the path?

> > +static struct ifs_device ifs_devices[] = {
> > +	[IFS_SAF] = {
> > +		.data = {
> > +			.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
> > +		},
> > +		.misc = {
> > +			.name = "intel_ifs_0",
> > +			.nodename = "intel_ifs/0",
> > +			.minor = MISC_DYNAMIC_MINOR,
> > +		},
> > +	},
> > +};
> > +
> > +#define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
> 
> Cute way to do this, but I don't see you ever have any more devices
> added to this list in this series.  Did I miss them?

That's in part 11/10 ... I have hardware, so I'm pretty sure that this
is a real thing. Just not ready to post until Intel announces the
details of the new test type.

> If not, why all the overhead and complexity involved here for just a
> single misc device?

It didn't seem like a lot of complexity here. It makes the changes to
this file to add an extra test trivial (just a new name in the "enum"
and a new initializer in ifs_devices[]).

Obviously some more code in load.c and runtest.c to handle the new
test type.

If it really is too much now, I can rip it out from this submission
and add it back when the second test is ready for public view.

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-26 16:12         ` Luck, Tony
@ 2022-04-26 16:36           ` Greg KH
  2022-04-26 18:47             ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-26 16:36 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 26, 2022 at 09:12:37AM -0700, Luck, Tony wrote:
> On Tue, Apr 26, 2022 at 12:45:40PM +0200, Greg KH wrote:
> > On Fri, Apr 22, 2022 at 01:02:13PM -0700, Tony Luck wrote:
> > >  drivers/platform/x86/intel/ifs/Makefile |  2 +-
> > >  drivers/platform/x86/intel/ifs/core.c   | 36 ++++++++++++++++++++++++-
> > >  drivers/platform/x86/intel/ifs/ifs.h    | 25 +++++++++++++++++
> > >  drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++
> 
> You haven't commented on the source tree location. With the change
> to use misc_register() this isn't a "platform" device anymore.
> 
> Should I move to "drivers/misc/"? Or is there some better spot that
> preseves the detail that this is an x86/intel driver in the path?

There's misc_register() users all over the tree, no need for it to be in
drivers/misc/ at all, especially if this really is a platform device as
this one is.  It's fine here.

> > > +static struct ifs_device ifs_devices[] = {
> > > +	[IFS_SAF] = {
> > > +		.data = {
> > > +			.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
> > > +		},
> > > +		.misc = {
> > > +			.name = "intel_ifs_0",
> > > +			.nodename = "intel_ifs/0",
> > > +			.minor = MISC_DYNAMIC_MINOR,
> > > +		},
> > > +	},
> > > +};
> > > +
> > > +#define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
> > 
> > Cute way to do this, but I don't see you ever have any more devices
> > added to this list in this series.  Did I miss them?
> 
> That's in part 11/10 ... I have hardware, so I'm pretty sure that this
> is a real thing. Just not ready to post until Intel announces the
> details of the new test type.

Let's not over-engineer for anything we can not review today please.

> > If not, why all the overhead and complexity involved here for just a
> > single misc device?
> 
> It didn't seem like a lot of complexity here. It makes the changes to
> this file to add an extra test trivial (just a new name in the "enum"
> and a new initializer in ifs_devices[]).
> 
> Obviously some more code in load.c and runtest.c to handle the new
> test type.
> 
> If it really is too much now, I can rip it out from this submission
> and add it back when the second test is ready for public view.

Please do, thanks.

greg k-h

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-26 16:36           ` Greg KH
@ 2022-04-26 18:47             ` Luck, Tony
  0 siblings, 0 replies; 152+ messages in thread
From: Luck, Tony @ 2022-04-26 18:47 UTC (permalink / raw)
  To: Greg KH
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Tue, Apr 26, 2022 at 06:36:46PM +0200, Greg KH wrote:
> On Tue, Apr 26, 2022 at 09:12:37AM -0700, Luck, Tony wrote:
> > If it really is too much now, I can rip it out from this submission
> > and add it back when the second test is ready for public view.
> 
> Please do, thanks.

Hmmm ... maybe there were more bits than I thought.

 1 file changed, 19 insertions(+), 36 deletions(-)

core.c is now down to just 80 lines ... so that was a significant
fraction of the file.

Net change below (I'll thread it back into the patch series before reposting).

Any other comments on the series?

-Tony



diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index 317ed3225307..489b77645b5e 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -9,10 +9,6 @@
 
 #include "ifs.h"
 
-enum test_types {
-	IFS_SAF,
-};
-
 #define X86_MATCH(model)				\
 	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6,	\
 		INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL)
@@ -23,27 +19,21 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
 };
 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 
-static struct ifs_device ifs_devices[] = {
-	[IFS_SAF] = {
-		.data = {
-			.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
-		},
-		.misc = {
-			.name = "intel_ifs_0",
-			.nodename = "intel_ifs/0",
-			.minor = MISC_DYNAMIC_MINOR,
-		},
+static struct ifs_device ifs_device = {
+	.data = {
+		.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
+	},
+	.misc = {
+		.name = "intel_ifs_0",
+		.nodename = "intel_ifs/0",
+		.minor = MISC_DYNAMIC_MINOR,
 	},
 };
 
-#define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
-
 static int __init ifs_init(void)
 {
 	const struct x86_cpu_id *m;
-	int ndevices = 0;
 	u64 msrval;
-	int i;
 
 	m = x86_match_cpu(ifs_cpu_ids);
 	if (!m)
@@ -61,32 +51,25 @@ static int __init ifs_init(void)
 	if (ifs_setup_wq())
 		return -ENOMEM;
 
-	for (i = 0; i < IFS_NUMTESTS; i++) {
-		if (!(msrval & BIT(ifs_devices[i].data.integrity_cap_bit)))
-			continue;
-
-		ifs_devices[i].misc.groups = ifs_get_groups();
-		if (!misc_register(&ifs_devices[i].misc)) {
-			ndevices++;
-			down(&ifs_sem);
-			ifs_load_firmware(ifs_devices[i].misc.this_device);
-			up(&ifs_sem);
-		}
-	}
+	ifs_device.misc.groups = ifs_get_groups();
 
-	if (!ndevices)
+	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
+	    !misc_register(&ifs_device.misc)) {
+		down(&ifs_sem);
+		ifs_load_firmware(ifs_device.misc.this_device);
+		up(&ifs_sem);
+	} else {
 		ifs_destroy_wq();
+		return -ENODEV;
+	}
 
-	return ndevices ? 0 : -ENODEV;
+	return 0;
 }
 
 static void __exit ifs_exit(void)
 {
-	int i;
 
-	for (i = 0; i < IFS_NUMTESTS; i++)
-		if (ifs_devices[i].misc.this_device)
-			misc_deregister(&ifs_devices[i].misc);
+	misc_deregister(&ifs_device.misc);
 	ifs_destroy_wq();
 }
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-26  1:49           ` Steven Rostedt
@ 2022-04-26 23:53             ` Luck, Tony
  2022-04-27  2:42               ` Steven Rostedt
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-04-26 23:53 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

On Mon, Apr 25, 2022 at 09:49:28PM -0400, Steven Rostedt wrote:
> On Mon, 25 Apr 2022 16:49:35 +0000
> "Luck, Tony" <tony.luck@intel.com> wrote:
> 
> > I see two paths:
> > 
> > 1) Create a new user friendly trace point for each new scan mode.
> > 2) Just provide a generic one that dumps both the 64-bit WRMSR and RDMSR values.
> > 
> > Q: Are trace points "expensive" in some way ... so better to just have one than three?
> >      Or are the cheap enough that decoding for the user is an OK thing?
> 
> Yes, they are expensive as each TRACE_EVENT() can add a few KB of text and
> data. But you can add a DECLARE_EVENT_CLASS() and then add "printk"
> differences that are less memory heavy.
> 
> See DEFINE_EVENT_PRINT().

I looked at the examples in samples/trace_events/trace-events-sample.h
and tried to use this. But I'm doing something wrong because the
compiler barfs on something defined but not used.

Maybe my problem is the TP_printk() in the DECLARE_EVENT_CLASS() that
is over-ridden by DEFINE_EVENT_PRINT(). I wasn't at all sure what to
put here ... or how to use the base tracepoint that doesn't have the
printk() over-ridden.

I think I need my class to just save both the u64 values to the trace
buffer. Then the different trace points will extract the bits they want
and print in a user friendly way. While this increases space used in
the trace buffer, these events are not crazy high frequency. Usually 
one or two events per core with a gap 30 minutes or more between tests.

In my ".c" file the tracepoint looks like this using the name from
DEFINE_EVENT_PRINT(), and now passing the full u64 values:

	trace_ifs_status_saf(activate.data, status.data);

and my #include file looks like this:

----------------------------------------------
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM intel_ifs

#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_IFS_H

#include <linux/ktime.h>
#include <linux/tracepoint.h>

DECLARE_EVENT_CLASS(ifs_status,

	TP_PROTO(u64 activate, u64 status),

	TP_ARGS(activate, status),

	TP_STRUCT__entry(
		__field(	u64,	activate	)
		__field(	u64,	status		)
	),

	TP_fast_assign(
		__entry->activate = activate;
		__entry->status	= status;
	),

	TP_printk("activate: %llx status: %llx",
		__entry->activate,
		__entry->status)
);

DEFINE_EVENT_PRINT(ifs_status, ifs_status_saf,
	TP_PROTO(u64 activate, u64 status),
	TP_ARGS(activate, status),
	TP_printk("start: %.2x, stop: %.2x, status: %llx",
		((union ifs_scan *)&(__entry->activate))->start,
		((union ifs_scan *)&(__entry->activate))->stop,
		__entry->status)
);

#endif /* _TRACE_IFS_H */

/* This part must be outside protection */
#include <trace/define_trace.h>
-----------------------------------------------------

GCC messages:


  CC [M]  drivers/platform/x86/intel/ifs/runtest.o
In file included from /home/agluck/GIT/mywork/include/trace/define_trace.h:102,
                 from /home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:44,
                 from /home/agluck/GIT/mywork/drivers/platform/x86/intel/ifs/runtest.c:27:
/home/agluck/GIT/mywork/include/trace/trace_events.h:426:13: warning: ‘print_fmt_ifs_status’ defined but not used [-Wunused-variable]
  426 | static char print_fmt_##call[] = print;                                 \
      |             ^~~~~~~~~~
/home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:11:1: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
   11 | DECLARE_EVENT_CLASS(ifs_status,
      | ^~~~~~~~~~~~~~~~~~~
In file included from /home/agluck/GIT/mywork/include/trace/define_trace.h:102,
                 from /home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:44,
                 from /home/agluck/GIT/mywork/drivers/platform/x86/intel/ifs/runtest.c:27:
/home/agluck/GIT/mywork/include/trace/trace_events.h:207:37: warning: ‘trace_event_type_funcs_ifs_status’ defined but not used [-Wunused-variable]
  207 | static struct trace_event_functions trace_event_type_funcs_##call = {   \
      |                                     ^~~~~~~~~~~~~~~~~~~~~~~
/home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:11:1: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
   11 | DECLARE_EVENT_CLASS(ifs_status,
      | ^~~~~~~~~~~~~~~~~~~
make[1]: Leaving directory '/home/agluck/GIT/mywork/build/ifsv5-rc1'

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-26 23:53             ` Luck, Tony
@ 2022-04-27  2:42               ` Steven Rostedt
  0 siblings, 0 replies; 152+ messages in thread
From: Steven Rostedt @ 2022-04-27  2:42 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

On Tue, 26 Apr 2022 16:53:13 -0700
"Luck, Tony" <tony.luck@intel.com> wrote:
> 
> I looked at the examples in samples/trace_events/trace-events-sample.h
> and tried to use this. But I'm doing something wrong because the
> compiler barfs on something defined but not used.
> 
> Maybe my problem is the TP_printk() in the DECLARE_EVENT_CLASS() that
> is over-ridden by DEFINE_EVENT_PRINT(). I wasn't at all sure what to
> put here ... or how to use the base tracepoint that doesn't have the
> printk() over-ridden.

Yeah, that could be confusing.

Basically, TRACE_EVENT() is simply defined as:

DECLARE_EVENT_CLASS()
DEFINE_EVENT();

So technically you could create the class and event with the same name,
and then you could create a second event on top of that. But I usually
suggest people explicitly specify the DECLARE_EVENT_CLASS() and
DEFINE_EVENT().

I would not do this until you have more than one event. The what you
would do is create one event where the print matches the
DECLARE_EVENT_CLASS() TP_printk(), and have that event defined with
just DEFINE_EVENT(). Then create other events with the
DEFINE_EVENT_PRINT().

> 
> I think I need my class to just save both the u64 values to the trace
> buffer. Then the different trace points will extract the bits they want
> and print in a user friendly way. While this increases space used in
> the trace buffer, these events are not crazy high frequency. Usually 
> one or two events per core with a gap 30 minutes or more between tests.
> 
> In my ".c" file the tracepoint looks like this using the name from
> DEFINE_EVENT_PRINT(), and now passing the full u64 values:
> 
> 	trace_ifs_status_saf(activate.data, status.data);
> 
> and my #include file looks like this:
> 
> ----------------------------------------------
> /* SPDX-License-Identifier: GPL-2.0 */
> #undef TRACE_SYSTEM
> #define TRACE_SYSTEM intel_ifs
> 
> #if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
> #define _TRACE_IFS_H
> 
> #include <linux/ktime.h>
> #include <linux/tracepoint.h>
> 
> DECLARE_EVENT_CLASS(ifs_status,
> 
> 	TP_PROTO(u64 activate, u64 status),
> 
> 	TP_ARGS(activate, status),
> 
> 	TP_STRUCT__entry(
> 		__field(	u64,	activate	)
> 		__field(	u64,	status		)
> 	),
> 
> 	TP_fast_assign(
> 		__entry->activate = activate;
> 		__entry->status	= status;
> 	),
> 
> 	TP_printk("activate: %llx status: %llx",
> 		__entry->activate,
> 		__entry->status)
> );
> 
> DEFINE_EVENT_PRINT(ifs_status, ifs_status_saf,
> 	TP_PROTO(u64 activate, u64 status),
> 	TP_ARGS(activate, status),
> 	TP_printk("start: %.2x, stop: %.2x, status: %llx",
> 		((union ifs_scan *)&(__entry->activate))->start,
> 		((union ifs_scan *)&(__entry->activate))->stop,
> 		__entry->status)
> );
> 
> #endif /* _TRACE_IFS_H */
> 
> /* This part must be outside protection */
> #include <trace/define_trace.h>
> -----------------------------------------------------
> 
> GCC messages:
> 
> 
>   CC [M]  drivers/platform/x86/intel/ifs/runtest.o
> In file included from /home/agluck/GIT/mywork/include/trace/define_trace.h:102,
>                  from /home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:44,
>                  from /home/agluck/GIT/mywork/drivers/platform/x86/intel/ifs/runtest.c:27:
> /home/agluck/GIT/mywork/include/trace/trace_events.h:426:13: warning: ‘print_fmt_ifs_status’ defined but not used [-Wunused-variable]
>   426 | static char print_fmt_##call[] = print;                                 \
>       |             ^~~~~~~~~~
> /home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:11:1: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
>    11 | DECLARE_EVENT_CLASS(ifs_status,
>       | ^~~~~~~~~~~~~~~~~~~
> In file included from /home/agluck/GIT/mywork/include/trace/define_trace.h:102,
>                  from /home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:44,
>                  from /home/agluck/GIT/mywork/drivers/platform/x86/intel/ifs/runtest.c:27:
> /home/agluck/GIT/mywork/include/trace/trace_events.h:207:37: warning: ‘trace_event_type_funcs_ifs_status’ defined but not used [-Wunused-variable]
>   207 | static struct trace_event_functions trace_event_type_funcs_##call = {   \
>       |                                     ^~~~~~~~~~~~~~~~~~~~~~~
> /home/agluck/GIT/mywork/include/trace/events/intel_ifs.h:11:1: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
>    11 | DECLARE_EVENT_CLASS(ifs_status,
>       | ^~~~~~~~~~~~~~~~~~~
> make[1]: Leaving directory '/home/agluck/GIT/mywork/build/ifsv5-rc1'
> 

Yeah, because you don't have more than one event, so the
DEFINE_EVENT_PRINT() does not make sense.  You still need one
DEFINE_EVENT() otherwise, you will get that static function not used
warning.

-- Steve


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v5 00/10] Introduce In Field Scan driver
  2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
                       ` (9 preceding siblings ...)
  2022-04-22 20:02     ` [PATCH v4 10/10] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
@ 2022-04-28 15:38     ` Tony Luck
  2022-04-28 15:38       ` [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
                         ` (12 more replies)
  10 siblings, 13 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Hopefully this is close enough to done to begin discussion on which
maintainer tree will take this series.

Choices:
1) Hans/Mark take it into the platform-drivers tree
   Needs an Ack from x86 maintainers on parts 1 & 2
2) X86 maintainers take it into TIP
   Needs Ack from Hans/Mark on parts 2-10

TL;DR this driver loads scan test files that can check whether silicon
in a CPU core is still running correctly. It is expected that these tests
would be run several times per day to catch problems as silicon ages.

Changes since v4:

Greg Kroah-Hartman
------------------
 "Cute way to do this, but I don't see you ever have any more devices
 added to this list in this series."

 Removed the enum, arrays, loops, and count of test types discovered.
 Now just check for enumeration of the single test type that is being
 deployed on Sapphire Rapids.


Jithu Joseph (7):
  x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  platform/x86/intel/ifs: Read IFS firmware image
  platform/x86/intel/ifs: Check IFS Image sanity
  platform/x86/intel/ifs: Authenticate and copy to secured memory
  platform/x86/intel/ifs: Add scan test support
  platform/x86/intel/ifs: Add IFS sysfs interface
  platform/x86/intel/ifs: add ABI documentation for IFS

Tony Luck (3):
  x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  platform/x86/intel/ifs: Add stub driver for In-Field Scan
  trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
    operations

 .../ABI/testing/sysfs-platform-intel-ifs      |  39 ++
 MAINTAINERS                                   |   8 +
 arch/x86/include/asm/cpu.h                    |  18 +
 arch/x86/include/asm/msr-index.h              |   7 +
 arch/x86/kernel/cpu/intel.c                   |  32 ++
 arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
 drivers/platform/x86/intel/Kconfig            |   1 +
 drivers/platform/x86/intel/Makefile           |   1 +
 drivers/platform/x86/intel/ifs/Kconfig        |  13 +
 drivers/platform/x86/intel/ifs/Makefile       |   3 +
 drivers/platform/x86/intel/ifs/core.c         |  80 +++++
 drivers/platform/x86/intel/ifs/ifs.h          | 123 +++++++
 drivers/platform/x86/intel/ifs/load.c         | 262 ++++++++++++++
 drivers/platform/x86/intel/ifs/runtest.c      | 332 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/sysfs.c        | 147 ++++++++
 include/trace/events/intel_ifs.h              |  38 ++
 16 files changed, 1111 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
 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
 create mode 100644 drivers/platform/x86/intel/ifs/load.c
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
 create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
 create mode 100644 include/trace/events/intel_ifs.h


base-commit: af2d861d4cd2a4da5137f795ee3509e6f944a25b
-- 
2.35.1


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-05-03 15:29         ` Borislav Petkov
  2022-05-04 10:28         ` Thomas Gleixner
  2022-04-28 15:38       ` [PATCH v5 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
                         ` (11 subsequent siblings)
  12 siblings, 2 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs.

In support of an IFS driver to trigger loading, validation, and running
of these tests blobs, make the functionality of cpu_signatures_match()
and collect_cpu_info_early() available outside of the microcode driver.

Add an "intel_" prefix and drop the "_early" suffix from
collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
declaration to x86 <asm/cpu.h>

Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
and also give it an "intel_" prefix.

No functional change intended.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 arch/x86/include/asm/cpu.h            | 18 ++++++++
 arch/x86/kernel/cpu/intel.c           | 32 +++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c | 59 ++++-----------------------
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 86e5e4e26fcb..990167357c34 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -76,4 +76,22 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
 
 extern __noendbr void cet_disable(void);
 
+struct ucode_cpu_info;
+
+int intel_cpu_collect_info(struct ucode_cpu_info *uci);
+
+static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+					      unsigned int s2, unsigned int p2)
+{
+	if (s1 != s2)
+		return false;
+
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
+
+	/* ... or they intersect. */
+	return p1 & p2;
+}
+
 #endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f7a5370a9b3b..94779146275d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,6 +181,38 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 	return false;
 }
 
+int intel_cpu_collect_info(struct ucode_cpu_info *uci)
+{
+	unsigned int val[2];
+	unsigned int family, model;
+	struct cpu_signature csig = { 0 };
+	unsigned int eax, ebx, ecx, edx;
+
+	memset(uci, 0, sizeof(*uci));
+
+	eax = 0x00000001;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	csig.sig = eax;
+
+	family = x86_family(eax);
+	model  = x86_model(eax);
+
+	if (model >= 5 || family > 6) {
+		/* get processor flags from MSR 0x17 */
+		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		csig.pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	csig.rev = intel_get_microcode_revision();
+
+	uci->cpu_sig = csig;
+	uci->valid = 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index d28a9f8f3fec..025c8f0cd948 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */
@@ -69,7 +55,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	struct extended_signature *ext_sig;
 	int i;
 
-	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
 		return 1;
 
 	/* Look for ext. headers: */
@@ -80,7 +66,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
 
 	for (i = 0; i < ext_hdr->count; i++) {
-		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
 			return 1;
 		ext_sig++;
 	}
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 	return patch;
 }
 
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-	unsigned int val[2];
-	unsigned int family, model;
-	struct cpu_signature csig = { 0 };
-	unsigned int eax, ebx, ecx, edx;
-
-	memset(uci, 0, sizeof(*uci));
-
-	eax = 0x00000001;
-	ecx = 0;
-	native_cpuid(&eax, &ebx, &ecx, &edx);
-	csig.sig = eax;
-
-	family = x86_family(eax);
-	model  = x86_model(eax);
-
-	if ((model >= 5) || (family > 6)) {
-		/* get processor flags from MSR 0x17 */
-		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		csig.pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	csig.rev = intel_get_microcode_revision();
-
-	uci->cpu_sig = csig;
-	uci->valid = 1;
-
-	return 0;
-}
-
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
 		return;
 	}
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	sig	= uci.cpu_sig.sig;
 	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
 	struct ucode_cpu_info uci;
 
 	if (delay_ucode_info) {
-		collect_cpu_info_early(&uci);
+		intel_cpu_collect_info(&uci);
 		print_ucode_info(&uci, current_mc_date);
 		delay_ucode_info = 0;
 	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
 	if (!(cp.data && cp.size))
 		return 0;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	scan_microcode(cp.data, cp.size, &uci, true);
 
@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 	if (!(cp.data && cp.size))
 		return NULL;
 
-	collect_cpu_info_early(uci);
+	intel_cpu_collect_info(uci);
 
 	return scan_microcode(cp.data, cp.size, uci, false);
 }
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
 	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	p = find_patch(&uci);
 	if (!p)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
  2022-04-28 15:38       ` [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-04-28 15:38       ` [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
                         ` (10 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

The INTEGRITY_CAPABILITIES MSR is enumerated by bit 2 of the
CORE_CAPABILITIES MSR.

Add defines for the CORE_CAPS enumeration as well as for the integrity
MSR.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 arch/x86/include/asm/msr-index.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index ee15311b6be1..c3dc7ae32f1f 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -76,6 +76,8 @@
 
 /* Abbreviated from Intel SDM name IA32_CORE_CAPABILITIES */
 #define MSR_IA32_CORE_CAPS			  0x000000cf
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT	  2
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS	  BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT)
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT  5
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT	  BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
 
@@ -154,6 +156,11 @@
 #define MSR_IA32_POWER_CTL		0x000001fc
 #define MSR_IA32_POWER_CTL_BIT_EE	19
 
+/* Abbreviated from Intel SDM name IA32_INTEGRITY_CAPABILITIES */
+#define MSR_INTEGRITY_CAPS			0x000002d9
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT	4
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST	BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
+
 #define MSR_LBR_NHM_FROM		0x00000680
 #define MSR_LBR_NHM_TO			0x000006c0
 #define MSR_LBR_CORE_FROM		0x00000040
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
  2022-04-28 15:38       ` [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
  2022-04-28 15:38       ` [PATCH v5 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-05-04 10:35         ` Thomas Gleixner
  2022-04-28 15:38       ` [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
                         ` (9 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Cloud Service Providers that operate fleets of servers have reported
[1] occasions where they can detect that a CPU has gone bad due to
effects like electromigration, or isolated manufacturing defects.
However, that detection method is A/B testing seemingly random
application failures looking for a pattern. In-Field Scan (IFS) is
a driver for a platform capability to load a crafted 'scan image'
to run targeted low level diagnostics outside of the CPU's architectural
error detection capabilities.

Stub version of driver just does initial part of check for the IFS
feature. MSR_IA32_CORE_CAPS must enumerate the presence of the
MSR_INTEGRITY_CAPS MSR.

[1]: https://www.youtube.com/watch?v=QMF3rqhjYuM

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 MAINTAINERS                             |  7 ++++
 drivers/platform/x86/intel/Kconfig      |  1 +
 drivers/platform/x86/intel/Makefile     |  1 +
 drivers/platform/x86/intel/ifs/Kconfig  | 13 +++++++
 drivers/platform/x86/intel/ifs/Makefile |  3 ++
 drivers/platform/x86/intel/ifs/core.c   | 48 +++++++++++++++++++++++++
 6 files changed, 73 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

diff --git a/MAINTAINERS b/MAINTAINERS
index 5e8c2f611766..bc902d0c64d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9859,6 +9859,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
 
+INTEL IN FIELD SCAN (IFS) DEVICE
+M:	Jithu Joseph <jithu.joseph@intel.com>
+R:	Ashok Raj <ashok.raj@intel.com>
+R:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+F:	drivers/platform/x86/intel/ifs
+
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 1f01a8a23c57..794968bda115 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -4,6 +4,7 @@
 #
 
 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/int3472/Kconfig"
 source "drivers/platform/x86/intel/pmc/Kconfig"
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index c61bc3e97121..717933dd0cfd 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
+obj-$(CONFIG_INTEL_IFS)			+= ifs/
 obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
 obj-$(CONFIG_INTEL_SKL_INT3472)		+= int3472/
 obj-$(CONFIG_INTEL_PMC_CORE)		+= pmc/
diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
new file mode 100644
index 000000000000..d84491cfb0db
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Kconfig
@@ -0,0 +1,13 @@
+config INTEL_IFS
+	tristate "Intel In Field Scan"
+	depends on X86 && 64BIT && SMP
+	select INTEL_IFS_DEVICE
+	help
+	  Enable support for the In Field Scan capability in select
+	  CPUs. The capability allows for running low level tests via
+	  a scan image distributed by Intel via Github to validate CPU
+	  operation beyond baseline RAS capabilities. To compile this
+	  support 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..af904880e959
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
+
+intel_ifs-objs			:= core.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
new file mode 100644
index 000000000000..e3623ac691b5
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+
+#include <asm/cpu_device_id.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 = {
+	X86_MATCH(SAPPHIRERAPIDS_X),
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
+
+static int __init ifs_init(void)
+{
+	const struct x86_cpu_id *m;
+	u64 msrval;
+
+	m = x86_match_cpu(ifs_cpu_ids);
+	if (!m)
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &msrval))
+		return -ENODEV;
+
+	if (!(msrval & MSR_IA32_CORE_CAPS_INTEGRITY_CAPS))
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
+		return -ENODEV;
+
+	return 0;
+}
+
+static void __exit ifs_exit(void)
+{
+}
+
+module_init(ifs_init);
+module_exit(ifs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel In Field Scan (IFS) device");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (2 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-05-04 10:37         ` Thomas Gleixner
  2022-04-28 15:38       ` [PATCH v5 05/10] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
                         ` (8 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Driver probe routine allocates structure to communicate status
and parameters between functions in the driver. Also call
load_ifs_binary() to load the scan image file.

There is a separate scan image file for each processor family,
model, stepping combination. This is read from the static path:

  /lib/firmware/intel/ifs/{ff-mm-ss}.scan

Step 1 in loading is to generate the correct path and use
request_firmware_direct() to load into memory.

Subsequent patches will use the IFS MSR interfaces to copy
the image to BIOS reserved memory and validate the SHA256
checksums.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |  2 +-
 drivers/platform/x86/intel/ifs/core.c   | 21 +++++++++++++++++++
 drivers/platform/x86/intel/ifs/ifs.h    | 25 ++++++++++++++++++++++
 drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/ifs.h
 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 af904880e959..98b6fde15689 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o
+intel_ifs-objs			:= core.o load.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index e3623ac691b5..d4a54ff47447 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -6,6 +6,8 @@
 
 #include <asm/cpu_device_id.h>
 
+#include "ifs.h"
+
 #define X86_MATCH(model)				\
 	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6,	\
 		INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL)
@@ -16,6 +18,17 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
 };
 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 
+static struct ifs_device ifs_device = {
+	.data = {
+		.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
+	},
+	.misc = {
+		.name = "intel_ifs_0",
+		.nodename = "intel_ifs/0",
+		.minor = MISC_DYNAMIC_MINOR,
+	},
+};
+
 static int __init ifs_init(void)
 {
 	const struct x86_cpu_id *m;
@@ -34,11 +47,19 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
+	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
+	    !misc_register(&ifs_device.misc)) {
+		ifs_load_firmware(ifs_device.misc.this_device);
+	} else {
+		return -ENODEV;
+	}
+
 	return 0;
 }
 
 static void __exit ifs_exit(void)
 {
+	misc_deregister(&ifs_device.misc);
 }
 
 module_init(ifs_init);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
new file mode 100644
index 000000000000..9a0f8e2077e2
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Intel Corporation. */
+
+#ifndef _IFS_H_
+#define _IFS_H_
+
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+
+/**
+ * struct ifs_data - attributes related to intel IFS driver
+ * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
+ */
+struct ifs_data {
+	int integrity_cap_bit;
+};
+
+struct ifs_device {
+	struct ifs_data data;
+	struct miscdevice misc;
+};
+
+void ifs_load_firmware(struct device *dev);
+
+#endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
new file mode 100644
index 000000000000..9fb71d38c819
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/firmware.h>
+
+#include "ifs.h"
+
+/*
+ * Load ifs image. Before loading ifs module, the ifs image must be located
+ * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
+ */
+void ifs_load_firmware(struct device *dev)
+{
+	const struct firmware *fw;
+	char scan_path[32];
+	int ret;
+
+	snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
+		 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
+
+	ret = request_firmware_direct(&fw, scan_path, dev);
+	if (ret) {
+		dev_err(dev, "ifs file %s load failed\n", scan_path);
+		return;
+	}
+
+	release_firmware(fw);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 05/10] platform/x86/intel/ifs: Check IFS Image sanity
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (3 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-04-28 15:38       ` [PATCH v5 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
                         ` (7 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/load.c | 68 +++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index 9fb71d38c819..aece78d1c757 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -2,9 +2,74 @@
 /* Copyright(c) 2022 Intel Corporation. */
 
 #include <linux/firmware.h>
+#include <asm/cpu.h>
+#include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+static int ifs_sanity_check(struct device *dev,
+			    const struct microcode_header_intel *mc_header)
+{
+	unsigned long total_size, data_size;
+	u32 sum, i;
+	u8 *mc;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+
+	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
+		dev_err(dev, "bad ifs data file size.\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		dev_err(dev, "invalid/unknown ifs update format.\n");
+		return -EINVAL;
+	}
+
+	mc = (u8 *)mc_header;
+	sum = 0;
+	i = total_size / sizeof(u32);
+	while (i--)
+		sum += ((u32 *)mc)[i];
+
+	if (sum) {
+		dev_err(dev, "bad ifs data checksum, aborting.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
+					const struct microcode_header_intel *shdr)
+{
+	unsigned int mc_size;
+
+	mc_size = get_totalsize(shdr);
+
+	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
+		dev_err(dev, "ifs sanity check failure\n");
+		return false;
+	}
+
+	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
+		dev_err(dev, "ifs signature, pf not matching\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
+{
+	struct ucode_cpu_info uci;
+
+	intel_cpu_collect_info(&uci);
+
+	return find_ifs_matching_signature(dev, &uci, data);
+}
+
 /*
  * Load ifs image. Before loading ifs module, the ifs image must be located
  * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
@@ -24,5 +89,8 @@ void ifs_load_firmware(struct device *dev)
 		return;
 	}
 
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+		dev_err(dev, "ifs header sanity check failed\n");
+
 	release_firmware(fw);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (4 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 05/10] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-05-04 10:48         ` Thomas Gleixner
  2022-04-28 15:38       ` [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
                         ` (6 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/ifs.h  |  47 +++++++
 drivers/platform/x86/intel/ifs/load.c | 170 +++++++++++++++++++++++++-
 2 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 9a0f8e2077e2..d985b4a50f46 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -7,12 +7,51 @@
 #include <linux/device.h>
 #include <linux/miscdevice.h>
 
+#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 {
+		u32	chunk_size	:16;
+		u32	num_chunks	:8;
+		u32	rsvd1		:8;
+		u32	error_code	:8;
+		u32	rsvd2		:11;
+		u32	max_core_limit	:12;
+		u32	valid		:1;
+	};
+};
+
+/* MSR_CHUNKS_AUTH_STATUS bit fields */
+union ifs_chunks_auth_status {
+	u64	data;
+	struct {
+		u32	valid_chunks	:8;
+		u32	total_chunks	:8;
+		u32	rsvd1		:16;
+		u32	error_code	:8;
+		u32	rsvd2		:24;
+	};
+};
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
+ * @loaded_version: stores the currently loaded ifs image version.
+ * @loaded: If a valid test binary has been loaded into the memory
+ * @loading_error: Error occurred on another CPU while loading image
+ * @valid_chunks: number of chunks which could be validated.
  */
 struct ifs_data {
 	int integrity_cap_bit;
+	int loaded_version;
+	bool loaded;
+	bool loading_error;
+	int valid_chunks;
 };
 
 struct ifs_device {
@@ -20,6 +59,14 @@ struct ifs_device {
 	struct miscdevice misc;
 };
 
+static inline struct ifs_data *ifs_get_data(struct device *dev)
+{
+	struct miscdevice *m = dev_get_drvdata(dev);
+	struct ifs_device *d = container_of(m, struct ifs_device, misc);
+
+	return &d->data;
+}
+
 void ifs_load_firmware(struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index aece78d1c757..46a9b78aa195 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,10 +3,166 @@
 
 #include <linux/firmware.h>
 #include <asm/cpu.h>
+#include <linux/slab.h>
 #include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+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 header */
+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[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to copy scan hashes when copy already in progress",
+	[2] = "Secure Memory not set up correctly",
+	[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
+	[4] = "Reserved",
+	[5] = "Integrity check failed",
+	[6] = "Scan reload or test is in progress"
+};
+
+static const char * const scan_authentication_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to authenticate a chunk which is already marked as authentic",
+	[2] = "Chunk authentication error. The hash of chunk did not match expected value"
+};
+
+/*
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must 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_AUTHENTICATE_AND_COPY_CHUNK)
+ * for scan hash copy and test chunk authentication.
+ */
+static void 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;
+	struct device *dev = arg;
+	struct ifs_data *ifsd;
+	u64 linear_addr, base;
+	u32 err_code;
+
+	ifsd = ifs_get_data(dev);
+	/* 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 = hashes_status.num_chunks;
+	chunk_size = hashes_status.chunk_size * 1024;
+	err_code = hashes_status.error_code;
+
+	if (!hashes_status.valid) {
+		ifsd->loading_error = true;
+		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
+			dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
+			return;
+		}
+		dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
+		return;
+	}
+
+	/* base linear address to the scan data */
+	base = ifs_test_image_ptr;
+
+	/* scan data authentication and copy chunks to secured memory */
+	for (i = 0; i < num_chunks; i++) {
+		linear_addr = base + i * chunk_size;
+		linear_addr |= i;
+
+		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
+		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
+
+		ifsd->valid_chunks = chunk_status.valid_chunks;
+		err_code = chunk_status.error_code;
+
+		if (err_code) {
+			ifsd->loading_error = true;
+			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
+				dev_err(dev,
+					"invalid error code 0x%x for authentication\n", err_code);
+				return;
+			}
+			dev_err(dev, "Chunk authentication error %s\n",
+				scan_authentication_status[err_code]);
+			return;
+		}
+	}
+}
+
+/*
+ * IFS requires scan chunks authenticated per each socket in the platform.
+ * Once the test chunk is authenticated, it is automatically copied to secured memory
+ * and proceed the authentication for the next chunk.
+ */
+static int scan_chunks_sanity_check(struct device *dev)
+{
+	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	bool *package_authenticated;
+	char *test_ptr;
+
+	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
+	if (!package_authenticated)
+		return ret;
+
+	metadata_size = ifs_header_ptr->metadata_size;
+
+	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
+	if (metadata_size == 0)
+		metadata_size = 2000;
+
+	/* Scan chunk start must be 256 byte aligned */
+	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
+		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
+		return -EINVAL;
+	}
+
+	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
+	ifsd->loading_error = false;
+
+	ifs_test_image_ptr = (u64)test_ptr;
+	ifsd->loaded_version = ifs_header_ptr->blob_revision;
+
+	/* copy the scan hash and authenticate per package */
+	cpus_read_lock();
+	for_each_online_cpu(cpu) {
+		curr_pkg = topology_physical_package_id(cpu);
+		if (package_authenticated[curr_pkg])
+			continue;
+		package_authenticated[curr_pkg] = 1;
+		ret = smp_call_function_single(cpu, copy_hashes_authenticate_chunks,
+					       dev, 1);
+		if (ret || ifsd->loading_error) {
+			ret = ifsd->loading_error ? -ENOMEM : ret;
+			goto out;
+		}
+	}
+
+out:
+	cpus_read_unlock();
+	kfree(package_authenticated);
+
+	return ret;
+}
+
 static int ifs_sanity_check(struct device *dev,
 			    const struct microcode_header_intel *mc_header)
 {
@@ -76,6 +232,7 @@ static bool ifs_image_sanity_check(struct device *dev, const struct microcode_he
  */
 void ifs_load_firmware(struct device *dev)
 {
+	struct ifs_data *ifsd = ifs_get_data(dev);
 	const struct firmware *fw;
 	char scan_path[32];
 	int ret;
@@ -86,11 +243,20 @@ void ifs_load_firmware(struct device *dev)
 	ret = request_firmware_direct(&fw, scan_path, dev);
 	if (ret) {
 		dev_err(dev, "ifs file %s load failed\n", scan_path);
-		return;
+		goto done;
 	}
 
-	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
 		dev_err(dev, "ifs header sanity check failed\n");
+		goto release;
+	}
+
+	ifs_header_ptr = (struct ifs_header *)fw->data;
+	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
 
+	ret = scan_chunks_sanity_check(dev);
+release:
 	release_firmware(fw);
+done:
+	ifsd->loaded = (ret == 0);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (5 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-05-04 12:29         ` Thomas Gleixner
  2022-04-28 15:38       ` [PATCH v5 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
                         ` (5 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

In a core, the scan engine is shared between sibling cpus.

When a Scan test (for a particular core) is triggered by the user,
worker threads for each sibling cpus(belonging to that core) are
queued to execute the scan test function in the Workqueue context.

All the siblings rendezvous before the test execution. 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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/core.c    |   5 +
 drivers/platform/x86/intel/ifs/ifs.h     |  48 ++++
 drivers/platform/x86/intel/ifs/runtest.c | 327 +++++++++++++++++++++++
 4 files changed, 381 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c

diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
index 98b6fde15689..cedcb103f860 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o
+intel_ifs-objs			:= core.o load.o runtest.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index d4a54ff47447..d408290480c7 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -47,10 +47,14 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
+	if (ifs_setup_wq())
+		return -ENOMEM;
+
 	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
 	    !misc_register(&ifs_device.misc)) {
 		ifs_load_firmware(ifs_device.misc.this_device);
 	} else {
+		ifs_destroy_wq();
 		return -ENODEV;
 	}
 
@@ -60,6 +64,7 @@ static int __init ifs_init(void)
 static void __exit ifs_exit(void)
 {
 	misc_deregister(&ifs_device.misc);
+	ifs_destroy_wq();
 }
 
 module_init(ifs_init);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index d985b4a50f46..31e58a36ab75 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -11,6 +11,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_NOT_TESTED				0
+#define SCAN_TEST_PASS				1
+#define SCAN_TEST_FAIL				2
+#define SPINUNIT				100
+#define THREAD_WAIT				5
 
 /* MSR_SCAN_HASHES_STATUS bit fields */
 union ifs_scan_hashes_status {
@@ -38,6 +45,40 @@ union ifs_chunks_auth_status {
 	};
 };
 
+/* MSR_ACTIVATE_SCAN bit fields */
+union ifs_scan {
+	u64	data;
+	struct {
+		u32	start	:8;
+		u32	stop	:8;
+		u32	rsvd	:16;
+		u32	delay	:31;
+		u32	sigmce	:1;
+	};
+};
+
+/* MSR_SCAN_STATUS bit fields */
+union ifs_status {
+	u64	data;
+	struct {
+		u32	chunk_num		:8;
+		u32	chunk_stop_index	:8;
+		u32	rsvd1			:16;
+		u32	error_code		:8;
+		u32	rsvd2			:22;
+		u32	control_error		:1;
+		u32	signature_error		:1;
+	};
+};
+
+/*
+ * Driver populated error-codes
+ * 0xFD: Test timed out before completing all the chunks.
+ * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
+ */
+#define IFS_SW_TIMEOUT				0xFD
+#define IFS_SW_PARTIAL_COMPLETION		0xFE
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
@@ -45,6 +86,8 @@ union ifs_chunks_auth_status {
  * @loaded: If a valid test binary has been loaded into the memory
  * @loading_error: Error occurred on another CPU while loading image
  * @valid_chunks: number of chunks which could be validated.
+ * @status: it holds simple status pass/fail/untested
+ * @scan_details: opaque scan status code from h/w
  */
 struct ifs_data {
 	int integrity_cap_bit;
@@ -52,6 +95,8 @@ struct ifs_data {
 	bool loaded;
 	bool loading_error;
 	int valid_chunks;
+	int status;
+	u64 scan_details;
 };
 
 struct ifs_device {
@@ -68,5 +113,8 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
 }
 
 void ifs_load_firmware(struct device *dev);
+int ifs_setup_wq(void);
+void ifs_destroy_wq(void);
+int do_core_test(int cpu, struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
new file mode 100644
index 000000000000..c30cc9c95b4f
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/nmi.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Note all code and data in this file is protected by
+ * ifs_sem. On HT systems all threads on a core will
+ * execute together, but only the first thread on the
+ * core will update results of the test and indicate
+ * completion.
+ */
+static struct workqueue_struct *ifs_wq;
+static struct completion test_thread_done;
+static atomic_t siblings_in;
+static atomic_t siblings_out;
+static int cpu_sibl_ct;
+static bool scan_enabled = true;
+
+struct ifs_work {
+	struct work_struct w;
+	struct device *dev;
+};
+
+/* Max retries on the same chunk */
+#define MAX_IFS_RETRIES  5
+
+static unsigned long msec_to_tsc(unsigned long msec)
+{
+	return tsc_khz * 1000 * msec / MSEC_PER_SEC;
+}
+
+enum ifs_status_err_code {
+	IFS_NO_ERROR				= 0,
+	IFS_OTHER_THREAD_COULD_NOT_JOIN		= 1,
+	IFS_INTERRUPTED_BEFORE_RENDEZVOUS	= 2,
+	IFS_POWER_MGMT_INADEQUATE_FOR_SCAN	= 3,
+	IFS_INVALID_CHUNK_RANGE			= 4,
+	IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS	= 5,
+	IFS_CORE_NOT_CAPABLE_CURRENTLY		= 6,
+	IFS_UNASSIGNED_ERROR_CODE		= 7,
+	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT	= 8,
+	IFS_INTERRUPTED_DURING_EXECUTION	= 9,
+};
+
+static const char * const scan_test_status[] = {
+	[IFS_NO_ERROR] = "SCAN no error",
+	[IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.",
+	[IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.",
+	[IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] =
+	"Core Abort SCAN Response due to power management condition.",
+	[IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range",
+	[IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.",
+	[IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently",
+	[IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7",
+	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
+	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
+	[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start",
+};
+
+static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
+{
+	if (status.error_code < ARRAY_SIZE(scan_test_status))
+		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 scan_test_status[status.error_code]);
+	else if (status.error_code == IFS_SW_TIMEOUT)
+		dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	else if (status.error_code == IFS_SW_PARTIAL_COMPLETION)
+		dev_info(dev, "CPU(s) %*pbl: %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 "Not all scan chunks were executed. Maximum forward progress retries exceeded");
+	else
+		dev_info(dev, "CPU(s) %*pbl: SCAN unknown status %llx\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)), status.data);
+}
+
+static void message_fail(struct device *dev, int cpu, union ifs_status status)
+{
+	/*
+	 * control_error is set when the microcode runs into a problem
+	 * loading the image from the reserved BIOS memory, or it has
+	 * been corrupted. Reloading the image may fix this issue.
+	 */
+	if (status.control_error) {
+		dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+
+	/*
+	 * signature_error is set when the output from the scan chains does not
+	 * match the expected signature. This might be a transient problem (e.g.
+	 * due to a bit flip from an alpha particle or neutron). If the problem
+	 * repeats on a subsequent test, then it indicates an actual problem in
+	 * the core being tested.
+	 */
+	if (status.signature_error) {
+		dev_err(dev, "CPU(s) %*pbl: test signature incorrect.\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+}
+
+static bool can_restart(union ifs_status status)
+{
+	enum ifs_status_err_code err_code = status.error_code;
+
+	/* Signature for chunk is bad, or scan test failed */
+	if (status.signature_error || status.control_error)
+		return false;
+
+	switch (err_code) {
+	case IFS_NO_ERROR:
+	case IFS_OTHER_THREAD_COULD_NOT_JOIN:
+	case IFS_INTERRUPTED_BEFORE_RENDEZVOUS:
+	case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN:
+	case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT:
+	case IFS_INTERRUPTED_DURING_EXECUTION:
+		return true;
+	case IFS_INVALID_CHUNK_RANGE:
+	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
+	case IFS_CORE_NOT_CAPABLE_CURRENTLY:
+	case IFS_UNASSIGNED_ERROR_CODE:
+		break;
+	}
+	return false;
+}
+
+static bool wait_for_siblings(struct device *dev, struct ifs_data *ifsd, atomic_t *t, long long timeout)
+{
+	atomic_inc(t);
+	while (atomic_read(t) < cpu_sibl_ct) {
+		if (timeout < SPINUNIT) {
+			dev_err(dev,
+				"Timeout while waiting for CPUs rendezvous, remaining: %d\n",
+				cpu_sibl_ct - atomic_read(t));
+			return false;
+		}
+
+		ndelay(SPINUNIT);
+		timeout -= SPINUNIT;
+
+		touch_nmi_watchdog();
+	}
+
+	return true;
+}
+
+/*
+ * When a Scan test (for a particular core) is triggered by the user, worker threads
+ * for each sibling cpus(belonging to that core) are queued to execute this function in
+ * the Workqueue (ifs_wq) context.
+ * Wait for the sibling thread to join before the execution.
+ * Execute the scan test by running wrmsr(MSR_ACTIVATE_SCAN).
+ */
+static void ifs_work_func(struct work_struct *work)
+{
+	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
+	int cpu = smp_processor_id();
+	union ifs_scan activate;
+	union ifs_status status;
+	unsigned long timeout;
+	struct ifs_data *ifsd;
+	struct device *dev;
+	int retries;
+	u32 first;
+
+	dev = local_work->dev;
+	ifsd = ifs_get_data(dev);
+
+	activate.rsvd = 0;
+	activate.delay = msec_to_tsc(THREAD_WAIT);
+	activate.sigmce = 0;
+
+	/*
+	 * Need to get (and keep) the threads on this core executing close together
+	 * 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 = cpumask_first(topology_sibling_cpumask(cpu));
+	if (!wait_for_siblings(dev, ifsd, &siblings_in, NSEC_PER_SEC)) {
+		preempt_enable();
+		dev_err(dev, "cpu %d sibling did not join rendezvous\n", cpu);
+		goto out;
+	}
+
+	activate.start = 0;
+	activate.stop = ifsd->valid_chunks - 1;
+	timeout = jiffies + HZ / 2;
+	retries = MAX_IFS_RETRIES;
+
+	while (activate.start <= activate.stop) {
+		if (time_after(jiffies, timeout)) {
+			status.error_code = IFS_SW_TIMEOUT;
+			break;
+		}
+
+		local_irq_disable();
+		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
+		local_irq_enable();
+
+		/*
+		 * All logical CPUs on this core are now running IFS test. When it completes
+		 * execution or is interrupted, the following RDMSR gets the scan status.
+		 */
+
+		rdmsrl(MSR_SCAN_STATUS, status.data);
+
+		/* Some cases can be retried, give up for others */
+		if (!can_restart(status))
+			break;
+
+		if (status.chunk_num == activate.start) {
+			/* Check for forward progress */
+			if (retries-- == 0) {
+				if (status.error_code == IFS_NO_ERROR)
+					status.error_code = IFS_SW_PARTIAL_COMPLETION;
+				break;
+			}
+		} else {
+			retries = MAX_IFS_RETRIES;
+			activate.start = status.chunk_num;
+		}
+	}
+
+	preempt_enable();
+
+	if (cpu == first) {
+		/* Update status for this core */
+		ifsd->scan_details = status.data;
+
+		if (status.control_error || status.signature_error) {
+			ifsd->status = SCAN_TEST_FAIL;
+			message_fail(dev, cpu, status);
+		} else if (status.error_code) {
+			ifsd->status = SCAN_NOT_TESTED;
+			message_not_tested(dev, cpu, status);
+		} else {
+			ifsd->status = SCAN_TEST_PASS;
+		}
+	}
+
+	if (!wait_for_siblings(dev, ifsd, &siblings_out, NSEC_PER_SEC))
+		dev_err(dev, "cpu %d sibling did not exit rendezvous\n", cpu);
+
+out:
+	if (cpu == first)
+		complete(&test_thread_done);
+}
+
+/*
+ * Initiate per core test. It wakes up work queue threads on the target cpu and
+ * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
+ * wait for all sibling threads to finish the scan test.
+ */
+int do_core_test(int cpu, struct device *dev)
+{
+	struct ifs_work *local_work;
+	int sibling;
+	int ret = 0;
+	int i = 0;
+
+	if (!scan_enabled)
+		return -ENXIO;
+
+	cpu_hotplug_disable();
+	if (!cpu_online(cpu)) {
+		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	reinit_completion(&test_thread_done);
+	atomic_set(&siblings_in, 0);
+	atomic_set(&siblings_out, 0);
+
+	cpu_sibl_ct = cpumask_weight(topology_sibling_cpumask(cpu));
+	local_work = kcalloc(cpu_sibl_ct, sizeof(*local_work), GFP_NOWAIT);
+	if (!local_work) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for_each_cpu(sibling, topology_sibling_cpumask(cpu)) {
+		local_work[i].dev = dev;
+		INIT_WORK(&local_work[i].w, ifs_work_func);
+		queue_work_on(sibling, ifs_wq, &local_work[i].w);
+		i++;
+	}
+
+	if (wait_for_completion_timeout(&test_thread_done, HZ) == 0) {
+		dev_err(dev, "cpu %d Core locked up during IFS test? IFS disabled\n", cpu);
+		scan_enabled = false;
+	}
+
+	kfree(local_work);
+out:
+	cpu_hotplug_enable();
+	return ret;
+}
+
+int ifs_setup_wq(void)
+{
+	/* Flags are to keep all the sibling cpu worker threads (of a core) in close sync */
+	ifs_wq = alloc_workqueue("intel_ifs", (WQ_HIGHPRI | WQ_CPU_INTENSIVE), 1);
+	if (!ifs_wq)
+		return -ENOMEM;
+
+	init_completion(&test_thread_done);
+
+	return 0;
+}
+
+void ifs_destroy_wq(void)
+{
+	destroy_workqueue(ifs_wq);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 08/10] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (6 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-04-28 15:38       ` [PATCH v5 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
                         ` (4 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Implement sysfs interface to trigger ifs test for a specific cpu.
Additional interfaces related to checking the status of the
scan test and seeing the version of the loaded IFS binary
are also added.

The basic usage is as below.
   - To start test, for example on cpu5:
       echo 5 > /sys/devices/platform/intel_ifs/run_test
   - To see the status of the last test
       cat /sys/devices/platform/intel_ifs/status
   - To see the version of the loaded scan binary
       cat /sys/devices/platform/intel_ifs/image_version

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/platform/x86/intel/ifs/Makefile |   2 +-
 drivers/platform/x86/intel/ifs/core.c   |   6 +
 drivers/platform/x86/intel/ifs/ifs.h    |   3 +
 drivers/platform/x86/intel/ifs/sysfs.c  | 147 ++++++++++++++++++++++++
 4 files changed, 157 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 cedcb103f860..30f035ef5581 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o runtest.o
+intel_ifs-objs			:= core.o load.o runtest.o sysfs.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index d408290480c7..489b77645b5e 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -3,6 +3,7 @@
 
 #include <linux/module.h>
 #include <linux/kdev_t.h>
+#include <linux/semaphore.h>
 
 #include <asm/cpu_device_id.h>
 
@@ -50,9 +51,13 @@ static int __init ifs_init(void)
 	if (ifs_setup_wq())
 		return -ENOMEM;
 
+	ifs_device.misc.groups = ifs_get_groups();
+
 	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
 	    !misc_register(&ifs_device.misc)) {
+		down(&ifs_sem);
 		ifs_load_firmware(ifs_device.misc.this_device);
+		up(&ifs_sem);
 	} else {
 		ifs_destroy_wq();
 		return -ENODEV;
@@ -63,6 +68,7 @@ static int __init ifs_init(void)
 
 static void __exit ifs_exit(void)
 {
+
 	misc_deregister(&ifs_device.misc);
 	ifs_destroy_wq();
 }
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 31e58a36ab75..ddcdeda9016a 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -116,5 +116,8 @@ void ifs_load_firmware(struct device *dev);
 int ifs_setup_wq(void);
 void ifs_destroy_wq(void);
 int do_core_test(int cpu, struct device *dev);
+const struct attribute_group **ifs_get_groups(void);
+
+extern struct semaphore ifs_sem;
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
new file mode 100644
index 000000000000..8f3b0fb5a423
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Protects against simultaneous tests on multiple cores, or
+ * reloading can file while a test is in progress
+ */
+DEFINE_SEMAPHORE(ifs_sem);
+
+/*
+ * The sysfs interface to check additional details of last test
+ * cat /sys/devices/system/platform/ifs/details
+ */
+static ssize_t details_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
+}
+
+static DEVICE_ATTR_RO(details);
+
+static const char * const status_msg[] = {
+	[SCAN_NOT_TESTED] = "untested",
+	[SCAN_TEST_PASS] = "pass",
+	[SCAN_TEST_FAIL] = "fail"
+};
+
+/*
+ * The sysfs interface to check the test status:
+ * To check the status of last test
+ * cat /sys/devices/platform/ifs/status
+ */
+static ssize_t status_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
+}
+
+static DEVICE_ATTR_RO(status);
+
+/*
+ * The sysfs interface for single core testing
+ * To start test, for example, cpu5
+ * echo 5 > /sys/devices/platform/ifs/run_test
+ * To check the result:
+ * cat /sys/devices/platform/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)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	unsigned int cpu;
+	int rc;
+
+	rc = kstrtouint(buf, 0, &cpu);
+	if (rc < 0 || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	if (!ifsd->loaded)
+		rc = -EPERM;
+	else
+		rc = do_core_test(cpu, dev);
+
+	up(&ifs_sem);
+
+	return rc ? rc : count;
+}
+
+static DEVICE_ATTR_WO(run_test);
+
+/*
+ * Reload the IFS image. When user wants to install new IFS image
+ */
+static ssize_t reload_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	bool res;
+
+	if (kstrtobool(buf, &res))
+		return -EINVAL;
+	if (!res)
+		return count;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	ifs_load_firmware(dev);
+
+	up(&ifs_sem);
+
+	return count;
+}
+
+static DEVICE_ATTR_WO(reload);
+
+/*
+ * Display currently loaded IFS image version.
+ */
+static ssize_t image_version_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	if (!ifsd->loaded)
+		return sysfs_emit(buf, "%s\n", "none");
+	else
+		return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
+}
+
+static DEVICE_ATTR_RO(image_version);
+
+/* global scan sysfs attributes */
+static struct attribute *plat_ifs_attrs[] = {
+	&dev_attr_details.attr,
+	&dev_attr_status.attr,
+	&dev_attr_run_test.attr,
+	&dev_attr_reload.attr,
+	&dev_attr_image_version.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(plat_ifs);
+
+const struct attribute_group **ifs_get_groups(void)
+{
+	return plat_ifs_groups;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (7 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-04-28 15:38       ` [PATCH v5 10/10] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
                         ` (3 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Add tracing support which may be useful for debugging systems that fail to complete
In Field Scan tests.

Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 MAINTAINERS                              |  1 +
 drivers/platform/x86/intel/ifs/runtest.c |  5 ++++
 include/trace/events/intel_ifs.h         | 38 ++++++++++++++++++++++++
 3 files changed, 44 insertions(+)
 create mode 100644 include/trace/events/intel_ifs.h

diff --git a/MAINTAINERS b/MAINTAINERS
index bc902d0c64d2..f024b8bf1053 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9865,6 +9865,7 @@ R:	Ashok Raj <ashok.raj@intel.com>
 R:	Tony Luck <tony.luck@intel.com>
 S:	Maintained
 F:	drivers/platform/x86/intel/ifs
+F:	include/trace/events/intel_ifs.h
 
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index c30cc9c95b4f..d6cb5d9e44c2 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -23,6 +23,9 @@ static atomic_t siblings_out;
 static int cpu_sibl_ct;
 static bool scan_enabled = true;
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ifs.h>
+
 struct ifs_work {
 	struct work_struct w;
 	struct device *dev;
@@ -216,6 +219,8 @@ static void ifs_work_func(struct work_struct *work)
 
 		rdmsrl(MSR_SCAN_STATUS, status.data);
 
+		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/intel_ifs.h b/include/trace/events/intel_ifs.h
new file mode 100644
index 000000000000..0611f370cb37
--- /dev/null
+++ b/include/trace/events/intel_ifs.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ifs
+
+#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IFS_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ifs_status,
+
+	TP_PROTO(union ifs_scan activate, union ifs_status status),
+
+	TP_ARGS(activate, status),
+
+	TP_STRUCT__entry(
+		__field(	u64,	status	)
+		__field(	u8,	start	)
+		__field(	u8,	stop	)
+	),
+
+	TP_fast_assign(
+		__entry->start	= activate.start;
+		__entry->stop	= activate.stop;
+		__entry->status	= 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 <trace/define_trace.h>
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v5 10/10] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (8 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-04-28 15:38       ` Tony Luck
  2022-04-28 15:58       ` [PATCH v5 00/10] Introduce In Field Scan driver Greg KH
                         ` (2 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-04-28 15:38 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Add the sysfs attributes in ABI/testing for In-Field Scan.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 .../ABI/testing/sysfs-platform-intel-ifs      | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
new file mode 100644
index 000000000000..486d6d2ff8a0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -0,0 +1,39 @@
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/run_test
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write <cpu#> to trigger IFS test for one online core.
+		Note that the test is per core. The cpu# can be
+		for any thread on the core. Running on one thread
+		completes the test for the core containing that thread.
+		Example: to test the core containing cpu5: echo 5 >
+		/sys/devices/platform/intel_ifs.<N>/run_test
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/status
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	The status of the last test. It can be one of "pass", "fail"
+		or "untested".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/details
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Additional information regarding the last test. 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.
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/image_version
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Version (hexadecimal) of loaded IFS binary image. If no scan image
+		is loaded reports "none".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/reload
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write "1" (or "y" or "Y") to reload the IFS image from
+		/lib/firmware/intel/ifs/ff-mm-ss.scan.
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (9 preceding siblings ...)
  2022-04-28 15:38       ` [PATCH v5 10/10] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
@ 2022-04-28 15:58       ` Greg KH
  2022-04-28 16:07         ` Luck, Tony
  2022-05-02 15:15       ` Hans de Goede
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
  12 siblings, 1 reply; 152+ messages in thread
From: Greg KH @ 2022-04-28 15:58 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28, 2022 at 08:38:39AM -0700, Tony Luck wrote:
> Hopefully this is close enough to done to begin discussion on which
> maintainer tree will take this series.
> 
> Choices:
> 1) Hans/Mark take it into the platform-drivers tree
>    Needs an Ack from x86 maintainers on parts 1 & 2
> 2) X86 maintainers take it into TIP
>    Needs Ack from Hans/Mark on parts 2-10
> 
> TL;DR this driver loads scan test files that can check whether silicon
> in a CPU core is still running correctly. It is expected that these tests
> would be run several times per day to catch problems as silicon ages.

Much nicer and simpler as compared to the first version submitted,
thanks for sticking with it.  The diff seems about 1/3 smaller from the
first version sent out, peer-review works :)

Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>


^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-04-28 15:58       ` [PATCH v5 00/10] Introduce In Field Scan driver Greg KH
@ 2022-04-28 16:07         ` Luck, Tony
  0 siblings, 0 replies; 152+ messages in thread
From: Luck, Tony @ 2022-04-28 16:07 UTC (permalink / raw)
  To: Greg KH
  Cc: hdegoede, markgross, tglx, mingo, bp, dave.hansen, x86, hpa,
	corbet, andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

> Much nicer and simpler as compared to the first version submitted,
> thanks for sticking with it.  The diff seems about 1/3 smaller from the
> first version sent out, peer-review works :)
> 
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Thanks for your patience leading me to a much better driver.

-Tony


^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (10 preceding siblings ...)
  2022-04-28 15:58       ` [PATCH v5 00/10] Introduce In Field Scan driver Greg KH
@ 2022-05-02 15:15       ` Hans de Goede
  2022-05-02 17:23         ` Luck, Tony
  2022-05-03 15:32         ` Borislav Petkov
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
  12 siblings, 2 replies; 152+ messages in thread
From: Hans de Goede @ 2022-05-02 15:15 UTC (permalink / raw)
  To: Tony Luck, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Hi,

On 4/28/22 17:38, Tony Luck wrote:
> Hopefully this is close enough to done to begin discussion on which
> maintainer tree will take this series.
> 
> Choices:
> 1) Hans/Mark take it into the platform-drivers tree
>    Needs an Ack from x86 maintainers on parts 1 & 2
> 2) X86 maintainers take it into TIP
>    Needs Ack from Hans/Mark on parts 2-10

I've taken a quick look at the entire series and it looks good to me.

I'm fine with this entire series getting merged through the TIP
tree, here is my ack for merging the drivers/platform/x86 bits
through the TIP tree:

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans






> 
> TL;DR this driver loads scan test files that can check whether silicon
> in a CPU core is still running correctly. It is expected that these tests
> would be run several times per day to catch problems as silicon ages.
> 
> Changes since v4:
> 
> Greg Kroah-Hartman
> ------------------
>  "Cute way to do this, but I don't see you ever have any more devices
>  added to this list in this series."
> 
>  Removed the enum, arrays, loops, and count of test types discovered.
>  Now just check for enumeration of the single test type that is being
>  deployed on Sapphire Rapids.
> 
> 
> Jithu Joseph (7):
>   x86/microcode/intel: Expose collect_cpu_info_early() for IFS
>   platform/x86/intel/ifs: Read IFS firmware image
>   platform/x86/intel/ifs: Check IFS Image sanity
>   platform/x86/intel/ifs: Authenticate and copy to secured memory
>   platform/x86/intel/ifs: Add scan test support
>   platform/x86/intel/ifs: Add IFS sysfs interface
>   platform/x86/intel/ifs: add ABI documentation for IFS
> 
> Tony Luck (3):
>   x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
>   platform/x86/intel/ifs: Add stub driver for In-Field Scan
>   trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
>     operations
> 
>  .../ABI/testing/sysfs-platform-intel-ifs      |  39 ++
>  MAINTAINERS                                   |   8 +
>  arch/x86/include/asm/cpu.h                    |  18 +
>  arch/x86/include/asm/msr-index.h              |   7 +
>  arch/x86/kernel/cpu/intel.c                   |  32 ++
>  arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
>  drivers/platform/x86/intel/Kconfig            |   1 +
>  drivers/platform/x86/intel/Makefile           |   1 +
>  drivers/platform/x86/intel/ifs/Kconfig        |  13 +
>  drivers/platform/x86/intel/ifs/Makefile       |   3 +
>  drivers/platform/x86/intel/ifs/core.c         |  80 +++++
>  drivers/platform/x86/intel/ifs/ifs.h          | 123 +++++++
>  drivers/platform/x86/intel/ifs/load.c         | 262 ++++++++++++++
>  drivers/platform/x86/intel/ifs/runtest.c      | 332 ++++++++++++++++++
>  drivers/platform/x86/intel/ifs/sysfs.c        | 147 ++++++++
>  include/trace/events/intel_ifs.h              |  38 ++
>  16 files changed, 1111 insertions(+), 52 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
>  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
>  create mode 100644 drivers/platform/x86/intel/ifs/load.c
>  create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
>  create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
>  create mode 100644 include/trace/events/intel_ifs.h
> 
> 
> base-commit: af2d861d4cd2a4da5137f795ee3509e6f944a25b


^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-02 15:15       ` Hans de Goede
@ 2022-05-02 17:23         ` Luck, Tony
  2022-05-03 15:32         ` Borislav Petkov
  1 sibling, 0 replies; 152+ messages in thread
From: Luck, Tony @ 2022-05-02 17:23 UTC (permalink / raw)
  To: Hans de Goede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

> I've taken a quick look at the entire series and it looks good to me.
>
> I'm fine with this entire series getting merged through the TIP
> tree, here is my ack for merging the drivers/platform/x86 bits
> through the TIP tree:
>
> Acked-by: Hans de Goede <hdegoede@redhat.com>


Hans,

Thanks for looking, and double thanks for the "Ack".

-Tony


^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-04-28 15:38       ` [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
@ 2022-05-03 15:29         ` Borislav Petkov
  2022-05-04 10:28         ` Thomas Gleixner
  1 sibling, 0 replies; 152+ messages in thread
From: Borislav Petkov @ 2022-05-03 15:29 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28, 2022 at 08:38:40AM -0700, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
> 
> IFS is a CPU feature that allows a binary blob, similar to microcode,
> to be loaded and consumed to perform low level validation of CPU
> circuitry. In fact, it carries the same Processor Signature
> (family/model/stepping) details that are contained in Intel microcode
> blobs.
> 
> In support of an IFS driver to trigger loading, validation, and running
> of these tests blobs, make the functionality of cpu_signatures_match()
> and collect_cpu_info_early() available outside of the microcode driver.
> 
> Add an "intel_" prefix and drop the "_early" suffix from
> collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
> declaration to x86 <asm/cpu.h>
> 
> Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
> and also give it an "intel_" prefix.
> 
> No functional change intended.
> 
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  arch/x86/include/asm/cpu.h            | 18 ++++++++
>  arch/x86/kernel/cpu/intel.c           | 32 +++++++++++++++
>  arch/x86/kernel/cpu/microcode/intel.c | 59 ++++-----------------------
>  3 files changed, 57 insertions(+), 52 deletions(-)

Acked-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-02 15:15       ` Hans de Goede
  2022-05-02 17:23         ` Luck, Tony
@ 2022-05-03 15:32         ` Borislav Petkov
  2022-05-03 16:04           ` Luck, Tony
  2022-05-06 14:19           ` Hans de Goede
  1 sibling, 2 replies; 152+ messages in thread
From: Borislav Petkov @ 2022-05-03 15:32 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Tony Luck, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Mon, May 02, 2022 at 05:15:39PM +0200, Hans de Goede wrote:
> I'm fine with this entire series getting merged through the TIP
> tree,

Hmm, so looking at the diffstat - the majority of that is
drivers/platform/x86/ so I guess your tree would be better suited for
it...

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-03 15:32         ` Borislav Petkov
@ 2022-05-03 16:04           ` Luck, Tony
  2022-05-03 16:26             ` Luck, Tony
  2022-05-06 14:19           ` Hans de Goede
  1 sibling, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-03 16:04 UTC (permalink / raw)
  To: Borislav Petkov, Hans de Goede
  Cc: markgross, tglx, mingo, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

> Hmm, so looking at the diffstat - the majority of that is
> drivers/platform/x86/ so I guess your tree would be better suited for
> it...

Can you check that I fixed the issues in part 01/10 that you reported in v3 of this
series and give an Ack to Hans?

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-03 16:04           ` Luck, Tony
@ 2022-05-03 16:26             ` Luck, Tony
  0 siblings, 0 replies; 152+ messages in thread
From: Luck, Tony @ 2022-05-03 16:26 UTC (permalink / raw)
  To: Borislav Petkov, Hans de Goede
  Cc: markgross, tglx, mingo, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

> Can you check that I fixed the issues in part 01/10 that you reported in v3 of this
> series and give an Ack to Hans?

Oops ... reading e-mail out of order ... I see that you already gave the Ack.  Thanks!

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-04-28 15:38       ` [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
  2022-05-03 15:29         ` Borislav Petkov
@ 2022-05-04 10:28         ` Thomas Gleixner
  1 sibling, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-04 10:28 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
>
> IFS is a CPU feature that allows a binary blob, similar to microcode,
> to be loaded and consumed to perform low level validation of CPU
> circuitry. In fact, it carries the same Processor Signature
> (family/model/stepping) details that are contained in Intel microcode
> blobs.
>
> In support of an IFS driver to trigger loading, validation, and running
> of these tests blobs, make the functionality of cpu_signatures_match()
> and collect_cpu_info_early() available outside of the microcode driver.
>
> Add an "intel_" prefix and drop the "_early" suffix from
> collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
> declaration to x86 <asm/cpu.h>
>
> Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
> and also give it an "intel_" prefix.
>
> No functional change intended.
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-04-28 15:38       ` [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-05-04 10:35         ` Thomas Gleixner
  2022-05-04 16:24           ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-04 10:35 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
> +#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 = {
> +	X86_MATCH(SAPPHIRERAPIDS_X),

Why do we need a model match here? The core capabilities MSR is only
available when X86_FEATURE_CORE_CAPABILITIES is set:

    "If CPUID.(EAX=07H, ECX=0):EDX[30] = 1.
     This MSR provides an architectural enumeration
     function for model-specific behavior."

So checking for Intel Fam6 ANYMODEL and X86_FEATURE_CORE_CAPABILITIES is
sufficient, no?

We really don't need more match id tables with gazillions of CPU models.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-04-28 15:38       ` [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-05-04 10:37         ` Thomas Gleixner
  2022-05-04 16:49           ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-04 10:37 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
> +/*
> + * Load ifs image. Before loading ifs module, the ifs image must be located
> + * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
> + */
> +void ifs_load_firmware(struct device *dev)
> +{
> +	const struct firmware *fw;
> +	char scan_path[32];
> +	int ret;
> +
> +	snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
> +		 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
> +
> +	ret = request_firmware_direct(&fw, scan_path, dev);
> +	if (ret) {
> +		dev_err(dev, "ifs file %s load failed\n", scan_path);
> +		return;

Why is this not returning an error to the caller?

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-04-28 15:38       ` [PATCH v5 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-05-04 10:48         ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-04 10:48 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
> 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

s/also// ?

> +
> +/* MSR_CHUNKS_AUTH_STATUS bit fields */
> +union ifs_chunks_auth_status {
> +	u64	data;
> +	struct {
> +		u32	valid_chunks	:8;
> +		u32	total_chunks	:8;
> +		u32	rsvd1		:16;
> +		u32	error_code	:8;
> +		u32	rsvd2		:24;
> +	};
> +};
> +
>  /**
>   * struct ifs_data - attributes related to intel IFS driver
>   * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
> + * @loaded_version: stores the currently loaded ifs image version.
> + * @loaded: If a valid test binary has been loaded into the memory
> + * @loading_error: Error occurred on another CPU while loading image
> + * @valid_chunks: number of chunks which could be validated.
>   */
>  struct ifs_data {
>  	int integrity_cap_bit;
> +	int loaded_version;
> +	bool loaded;
> +	bool loading_error;
> +	int valid_chunks;

The above struct is nicely tabular. Can we have that here too please?

> +/*
> + * IFS requires scan chunks authenticated per each socket in the platform.
> + * Once the test chunk is authenticated, it is automatically copied to secured memory
> + * and proceed the authentication for the next chunk.
> + */
> +static int scan_chunks_sanity_check(struct device *dev)
> +{
> +	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
> +	struct ifs_data *ifsd = ifs_get_data(dev);
> +	bool *package_authenticated;
> +	char *test_ptr;
> +
> +	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
> +	if (!package_authenticated)
> +		return ret;
> +
> +	metadata_size = ifs_header_ptr->metadata_size;
> +
> +	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
> +	if (metadata_size == 0)
> +		metadata_size = 2000;
> +
> +	/* Scan chunk start must be 256 byte aligned */
> +	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
> +		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
> +		return -EINVAL;
> +	}
> +
> +	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
> +	ifsd->loading_error = false;
> +
> +	ifs_test_image_ptr = (u64)test_ptr;
> +	ifsd->loaded_version = ifs_header_ptr->blob_revision;
> +
> +	/* copy the scan hash and authenticate per package */
> +	cpus_read_lock();
> +	for_each_online_cpu(cpu) {
> +		curr_pkg = topology_physical_package_id(cpu);
> +		if (package_authenticated[curr_pkg])
> +			continue;
> +		package_authenticated[curr_pkg] = 1;

Setting the authenticated indicator _before_ actually doing the
authentication is just wrong. It does not matter in this case, but it's
still making my eyes bleed.

> +		ret = smp_call_function_single(cpu, copy_hashes_authenticate_chunks,
> +					       dev, 1);

Why has this to be a smp function call? Just because it's conveniant?
This is nothing urgent and no hotpath, so this really can use
queue_work_on().

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-04-28 15:38       ` [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-05-04 12:29         ` Thomas Gleixner
  2022-05-04 18:52           ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-04 12:29 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
> +static bool wait_for_siblings(struct device *dev, struct ifs_data *ifsd, atomic_t *t, long long timeout)
> +{
> +	atomic_inc(t);
> +	while (atomic_read(t) < cpu_sibl_ct) {
> +		if (timeout < SPINUNIT) {
> +			dev_err(dev,
> +				"Timeout while waiting for CPUs rendezvous, remaining: %d\n",
> +				cpu_sibl_ct - atomic_read(t));
> +			return false;
> +		}
> +
> +		ndelay(SPINUNIT);
> +		timeout -= SPINUNIT;
> +
> +		touch_nmi_watchdog();
> +	}
> +
> +	return true;
> +}
> +
> +/*
> + * When a Scan test (for a particular core) is triggered by the user, worker threads
> + * for each sibling cpus(belonging to that core) are queued to execute this function in
> + * the Workqueue (ifs_wq) context.
> + * Wait for the sibling thread to join before the execution.
> + * Execute the scan test by running wrmsr(MSR_ACTIVATE_SCAN).
> + */
> +static void ifs_work_func(struct work_struct *work)
> +{
> +	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
> +	int cpu = smp_processor_id();
> +	union ifs_scan activate;
> +	union ifs_status status;
> +	unsigned long timeout;
> +	struct ifs_data *ifsd;
> +	struct device *dev;
> +	int retries;
> +	u32 first;
> +
> +	dev = local_work->dev;
> +	ifsd = ifs_get_data(dev);
> +
> +	activate.rsvd = 0;
> +	activate.delay = msec_to_tsc(THREAD_WAIT);
> +	activate.sigmce = 0;
> +
> +	/*
> +	 * Need to get (and keep) the threads on this core executing close together
> +	 * 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 = cpumask_first(topology_sibling_cpumask(cpu));
> +	if (!wait_for_siblings(dev, ifsd, &siblings_in, NSEC_PER_SEC)) {

Waiting for a second with preemption disabled? Seriously?

> +		preempt_enable();
> +		dev_err(dev, "cpu %d sibling did not join rendezvous\n", cpu);
> +		goto out;
> +	}
> +
> +	activate.start = 0;
> +	activate.stop = ifsd->valid_chunks - 1;
> +	timeout = jiffies + HZ / 2;

Plus another half a second with preemption disabled. That's just insane.

> +	retries = MAX_IFS_RETRIES;
> +
> +	while (activate.start <= activate.stop) {
> +		if (time_after(jiffies, timeout)) {
> +			status.error_code = IFS_SW_TIMEOUT;
> +			break;
> +		}
> +
> +		local_irq_disable();
> +		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
> +		local_irq_enable();

That local_irq_disable() solves what?

> +		/*
> +		 * All logical CPUs on this core are now running IFS test. When it completes
> +		 * execution or is interrupted, the following RDMSR gets the scan status.
> +		 */
> +
> +		rdmsrl(MSR_SCAN_STATUS, status.data);

Wait. Is that rdmsrl() blocking execution until the scan completes?

If so, what's the stall time here? If not, how is the logic below
supposed to work?

> +		/* Some cases can be retried, give up for others */
> +		if (!can_restart(status))
> +			break;
> +
> +		if (status.chunk_num == activate.start) {
> +			/* Check for forward progress */
> +			if (retries-- == 0) {
> +				if (status.error_code == IFS_NO_ERROR)
> +					status.error_code = IFS_SW_PARTIAL_COMPLETION;
> +				break;
> +			}
> +		} else {
> +			retries = MAX_IFS_RETRIES;
> +			activate.start = status.chunk_num;
> +		}
> +	}
> +
> +	preempt_enable();
> +
> +	if (cpu == first) {
> +		/* Update status for this core */
> +		ifsd->scan_details = status.data;
> +
> +		if (status.control_error || status.signature_error) {
> +			ifsd->status = SCAN_TEST_FAIL;
> +			message_fail(dev, cpu, status);
> +		} else if (status.error_code) {
> +			ifsd->status = SCAN_NOT_TESTED;
> +			message_not_tested(dev, cpu, status);
> +		} else {
> +			ifsd->status = SCAN_TEST_PASS;
> +		}
> +	}
> +
> +	if (!wait_for_siblings(dev, ifsd, &siblings_out, NSEC_PER_SEC))
> +		dev_err(dev, "cpu %d sibling did not exit rendezvous\n", cpu);
> +
> +out:
> +	if (cpu == first)
> +		complete(&test_thread_done);
> +}
> +
> +/*
> + * Initiate per core test. It wakes up work queue threads on the target cpu and
> + * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
> + * wait for all sibling threads to finish the scan test.
> + */
> +int do_core_test(int cpu, struct device *dev)
> +{
> +	struct ifs_work *local_work;
> +	int sibling;
> +	int ret = 0;
> +	int i = 0;
> +
> +	if (!scan_enabled)
> +		return -ENXIO;
> +
> +	cpu_hotplug_disable();

Why cpu_hotplug_disable()? Why is cpus_read_lock() not sufficient here?

> +	if (!cpu_online(cpu)) {
> +		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	reinit_completion(&test_thread_done);
> +	atomic_set(&siblings_in, 0);
> +	atomic_set(&siblings_out, 0);
> +
> +	cpu_sibl_ct = cpumask_weight(topology_sibling_cpumask(cpu));
> +	local_work = kcalloc(cpu_sibl_ct, sizeof(*local_work), GFP_NOWAIT);

Why does this need GFP_NOWAIT?

> +int ifs_setup_wq(void)
> +{
> +	/* Flags are to keep all the sibling cpu worker threads (of a core) in close sync */

I put that into the wishful thinking realm.

Is there anywhere a proper specification of this mechanism? The public
available MSR list in the SDM is uselss.

Without proper documentation it's pretty much impossible to review this
code and to think about the approach.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-05-04 10:35         ` Thomas Gleixner
@ 2022-05-04 16:24           ` Luck, Tony
  2022-05-04 16:28             ` Borislav Petkov
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-04 16:24 UTC (permalink / raw)
  To: Thomas Gleixner, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

>> +static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
>> +	X86_MATCH(SAPPHIRERAPIDS_X),
>
> Why do we need a model match here? The core capabilities MSR is only
> available when X86_FEATURE_CORE_CAPABILITIES is set:
>
>    "If CPUID.(EAX=07H, ECX=0):EDX[30] = 1.
>     This MSR provides an architectural enumeration
>     function for model-specific behavior."
>
> So checking for Intel Fam6 ANYMODEL and X86_FEATURE_CORE_CAPABILITIES is
> sufficient, no?

IA32_CORE_CAPABILITES is a nightmare. Although it is an architectural
register, the bits inside it are model specific.

In particular bit 2 (which we check here for the existence of the INTEGRITY
MSR) has been assigned for other use on other models. See SDM volume 4
table 2-45 where bit 2 means FUSA supported on 06_8C and 06_8D (Tigerlake
mobile and desktop). Ditto in table 2-46 (Alderlake and Raptorlake).

> We really don't need more match id tables with gazillions of CPU models.

Sadly we do :-(

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-05-04 16:24           ` Luck, Tony
@ 2022-05-04 16:28             ` Borislav Petkov
  0 siblings, 0 replies; 152+ messages in thread
From: Borislav Petkov @ 2022-05-04 16:28 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Thomas Gleixner, hdegoede, markgross, mingo, dave.hansen, x86,
	hpa, corbet, gregkh, andriy.shevchenko, Joseph, Jithu, Raj,
	Ashok, rostedt, Williams, Dan J, linux-kernel, linux-doc,
	platform-driver-x86, patches, Shankar, Ravi V

On Wed, May 04, 2022 at 04:24:50PM +0000, Luck, Tony wrote:
> > We really don't need more match id tables with gazillions of CPU models.
> 
> Sadly we do :-(

So what was the reasoning about CPUID bits being so expensive so that we
need to match models? Ditto for the splitlock situation - that thing is
supported on a bunch of models but nope, not a CPUID bit in sight. What
was the convincing argument that made hw folks give a CPUID bit to the
PPIN thing? Perhaps we could use it there too. :)

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image
  2022-05-04 10:37         ` Thomas Gleixner
@ 2022-05-04 16:49           ` Luck, Tony
  0 siblings, 0 replies; 152+ messages in thread
From: Luck, Tony @ 2022-05-04 16:49 UTC (permalink / raw)
  To: Thomas Gleixner, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

>> +	ret = request_firmware_direct(&fw, scan_path, dev);
>> +	if (ret) {
>> +		dev_err(dev, "ifs file %s load failed\n", scan_path);
>> +		return;
>
> Why is this not returning an error to the caller?

There are three call sequences that lead here:

1) CONFIG_INTEL_IFS=y
    At boot this is pretty much guaranteed to fail (unless some crazy person includes the
   scan file in the initramfs). In this case there isn't a useful caller to return the code to.
   In this case the driver init routine must ignore any error to make sure the sysfs reload
   file is present to load the scan file once the file system is available.

2) CONFIG_INTEL_IFS=m module load time
    Same code path as built-in ... so must ignore a failed load here too (unless there is a
    way to distinguish the built-in vs. module execution environment).

3) echo 1 > reload
    Hmmm. Some older revision did return an error ... but I seem to have factored it out
   during cleanups. Limited to standard -E???? error codes. The reload_store() function
   can just check whether the load succeeded by looking at ifsd->loaded instead of a
   return value from ifs_load_firmware()

So, I will fix case 3. But probably by checking ifsd->loaded rather than by adding a return
code to this function.

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-05-04 12:29         ` Thomas Gleixner
@ 2022-05-04 18:52           ` Luck, Tony
  2022-05-04 23:15             ` Thomas Gleixner
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-04 18:52 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: hdegoede, markgross, mingo, bp, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Wed, May 04, 2022 at 02:29:33PM +0200, Thomas Gleixner wrote:
> On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
> > +
> > +	/* wait for the sibling threads to join */
> > +	first = cpumask_first(topology_sibling_cpumask(cpu));
> > +	if (!wait_for_siblings(dev, ifsd, &siblings_in, NSEC_PER_SEC)) {
> 
> Waiting for a second with preemption disabled? Seriously?

Probably won't ever wait for a second. Any suggestions for a reasonable
timeout for how long it might take before both threads on a core begin
executing the target code after a pair of:

	queue_work_on(sibling, ifs_wq, &local_work[i].w);

that the request to check this core fired off?

Possibly this could be dropped, and just built into the allowable delay
for the threads to execute the ACTIVATE_SCAN (31 bits of TSC cycles in
the value written to the MSR). But a future scan feature doesn't include
that user tuneable value.

> 
> > +		preempt_enable();
> > +		dev_err(dev, "cpu %d sibling did not join rendezvous\n", cpu);
> > +		goto out;
> > +	}
> > +
> > +	activate.start = 0;
> > +	activate.stop = ifsd->valid_chunks - 1;
> > +	timeout = jiffies + HZ / 2;
> 
> Plus another half a second with preemption disabled. That's just insane.

Another rounded up value. Experimentally we are seeing the core scan
test take aroun 50ms. The spec (I know, we haven't published the spec)
says "up to 200ms".

> 
> > +	retries = MAX_IFS_RETRIES;
> > +
> > +	while (activate.start <= activate.stop) {
> > +		if (time_after(jiffies, timeout)) {
> > +			status.error_code = IFS_SW_TIMEOUT;
> > +			break;
> > +		}
> > +
> > +		local_irq_disable();
> > +		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
> > +		local_irq_enable();
> 
> That local_irq_disable() solves what?

An interrupt will stop the currently running "chunk" of the scan.
It is a restartable case. But the concern is that with high rate of
interrupts the scan may not complete (or even make any forward
progress).

> 
> > +		/*
> > +		 * All logical CPUs on this core are now running IFS test. When it completes
> > +		 * execution or is interrupted, the following RDMSR gets the scan status.
> > +		 */
> > +
> > +		rdmsrl(MSR_SCAN_STATUS, status.data);
> 
> Wait. Is that rdmsrl() blocking execution until the scan completes?

The comment isn't quite accurate here (my fault). The WRMSR doesn't
retire until the scan stops (either because it completed, or because
some thing happend to stop before all chunks were processed).

So the two HT threads will continue after the WRMSR pretty much in
lockstep and do the RDMSR to get the status. Both will see the same
status in most cases.

> 
> If so, what's the stall time here? If not, how is the logic below
> supposed to work?

Exact time will depend how many chunks of the scan were completed, and
how long they took. I see 50 ms total on current test system.

> 
> > +		/* Some cases can be retried, give up for others */
> > +		if (!can_restart(status))
> > +			break;
> > +
> > +		if (status.chunk_num == activate.start) {
> > +			/* Check for forward progress */
> > +			if (retries-- == 0) {
> > +				if (status.error_code == IFS_NO_ERROR)
> > +					status.error_code = IFS_SW_PARTIAL_COMPLETION;
> > +				break;
> > +			}
> > +		} else {
> > +			retries = MAX_IFS_RETRIES;
> > +			activate.start = status.chunk_num;
> > +		}
> > +	}
> > +


> > +int do_core_test(int cpu, struct device *dev)
> > +{
> > +	struct ifs_work *local_work;
> > +	int sibling;
> > +	int ret = 0;
> > +	int i = 0;
> > +
> > +	if (!scan_enabled)
> > +		return -ENXIO;
> > +
> > +	cpu_hotplug_disable();
> 
> Why cpu_hotplug_disable()? Why is cpus_read_lock() not sufficient here?

May be left from earlier version. I'll check that cpus_read_lock() is
enough.

> 
> > +	if (!cpu_online(cpu)) {
> > +		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	reinit_completion(&test_thread_done);
> > +	atomic_set(&siblings_in, 0);
> > +	atomic_set(&siblings_out, 0);
> > +
> > +	cpu_sibl_ct = cpumask_weight(topology_sibling_cpumask(cpu));
> > +	local_work = kcalloc(cpu_sibl_ct, sizeof(*local_work), GFP_NOWAIT);
> 
> Why does this need GFP_NOWAIT?

It doesn't. Will fix.

> 
> > +int ifs_setup_wq(void)
> > +{
> > +	/* Flags are to keep all the sibling cpu worker threads (of a core) in close sync */
> 
> I put that into the wishful thinking realm.

Can change to "... to try to keep ..."
> 
> Is there anywhere a proper specification of this mechanism? The public
> available MSR list in the SDM is uselss.
> 
> Without proper documentation it's pretty much impossible to review this
> code and to think about the approach.

Step 1 (at boot or driver load) is loading the scan tests into BIOS
reserved memory. I will fix up the bits where you pointed out problems
there.

Step 2 is the run time test of each core. That requires the near
simultaneous execution of:

	wrmsrl(MSR_ACTIVATE_SCAN, activate.data);

on all HT threads on the core. Trivial on parts that do not support
HT, or where it is disabled in BIOS. The above code is trying to
achieve this "parallel" execution.
The follow-on :

	rdmsrl(MSR_SCAN_STATUS, status.data);

doesn't have to be synchronized ... but handy to do so for when not
all chunks were processed and need to loop back to run another
activate_scan to continue starting from the interrupted chunk. In
the lab, this seems common ... when scanning all cores many of them
complete all chunks in a single bite, but several take 2-3 times around
the loop before completing.

As noted above I'm seeing a core test take around 50ms (but spec says
up to 200ms). In some environments that doesn't require any special
application or system reconfiguration.  It's not much different from
time-slicing when you are running more processes (or guests) than you
have CPUs. So sysadmins in those environments can use this driver to
cylce through cores testing each in turn without any extra steps.

You've pointed out that the driver disables preemption for insanely
long amounts of time ... to use this driver to test cores on a system
running applications where that is an issue will require additonal steps
to migrate latency critical applications to a different core while the
test is in progess, also re-direct interrupts. That seems well beyond the
scope of what is possible in a driver without all the information about
what workloads are running to pick a new temporary home for processes
and interrupts while the core is being tested.

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-05-04 18:52           ` Luck, Tony
@ 2022-05-04 23:15             ` Thomas Gleixner
  2022-05-05  8:28               ` Peter Zijlstra
  0 siblings, 1 reply; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-04 23:15 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, mingo, bp, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar, Peter Zijlstra

On Wed, May 04 2022 at 11:52, Luck, Tony wrote:
> On Wed, May 04, 2022 at 02:29:33PM +0200, Thomas Gleixner wrote:
>> On Thu, Apr 28 2022 at 08:38, Tony Luck wrote:
>> > +
>> > +	/* wait for the sibling threads to join */
>> > +	first = cpumask_first(topology_sibling_cpumask(cpu));
>> > +	if (!wait_for_siblings(dev, ifsd, &siblings_in, NSEC_PER_SEC)) {
>> 
>> Waiting for a second with preemption disabled? Seriously?
>
> Probably won't ever wait for a second. Any suggestions for a reasonable
> timeout for how long it might take before both threads on a core begin
> executing the target code after a pair of:
>
> 	queue_work_on(sibling, ifs_wq, &local_work[i].w);
>
> that the request to check this core fired off?

The real question is why you try to rendevouz CPUs via work queues.

The kernel has a well established mechanism to do CPU rendevouz already:

    stomp_machine()

We all hate it with a passion, but it is already doing what you are
trying to achieve and as the stopper threads run with high priority they
are not subject to arbitrary scheduling delays which make one CPU wait
for a long time with preemption disabled.

>> Plus another half a second with preemption disabled. That's just insane.
>
> Another rounded up value. Experimentally we are seeing the core scan
> test take aroun 50ms. The spec (I know, we haven't published the spec)
> says "up to 200ms".

That's daft. Both the 200ms and the non-published spec, though the latter
is worse because it's wasting everyones time.

>> > +	retries = MAX_IFS_RETRIES;
>> > +
>> > +	while (activate.start <= activate.stop) {
>> > +		if (time_after(jiffies, timeout)) {
>> > +			status.error_code = IFS_SW_TIMEOUT;
>> > +			break;
>> > +		}
>> > +
>> > +		local_irq_disable();
>> > +		wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
>> > +		local_irq_enable();
>> 
>> That local_irq_disable() solves what?
>
> An interrupt will stop the currently running "chunk" of the scan.
> It is a restartable case. But the concern is that with high rate of
> interrupts the scan may not complete (or even make any forward
> progress).

What about NMI/MCE? What happens if the scan triggers an MCE?

If the scan is stopped, will it be stopped on both hyperthreads?

What happens in the case, when one of the CPUs is slightly behind the
other:

     CPU A                      CPU B
     local_irq_disable()
     wrmsrl(...);
                                <- Interrupt
                                   handle_irq();
                                local_irq_disable();
                                wrmsrl(...);

Will the interrupt which hit CPU B _after_ CPU A issued the MSR write
stop the operation on CPU A and make it return?

If not, then how long is CPU A waiting for CPU B to join the party?

>> > +		/*
>> > +		 * All logical CPUs on this core are now running IFS test. When it completes
>> > +		 * execution or is interrupted, the following RDMSR gets the scan status.
>> > +		 */
>> > +
>> > +		rdmsrl(MSR_SCAN_STATUS, status.data);
>> 
>> Wait. Is that rdmsrl() blocking execution until the scan completes?
>
> The comment isn't quite accurate here (my fault). The WRMSR doesn't
> retire until the scan stops (either because it completed, or because
> some thing happend to stop before all chunks were processed).

I suspected that due to the non-commented local_irq_disable() ...

>> If so, what's the stall time here? If not, how is the logic below
>> supposed to work?
>
> Exact time will depend how many chunks of the scan were completed, and
> how long they took. I see 50 ms total on current test system.

Per chunk or for all chunks? The interresting part is not the total
time, the interresting part is the time per chunk.

>> Is there anywhere a proper specification of this mechanism? The public
>> available MSR list in the SDM is uselss.
>> 
>> Without proper documentation it's pretty much impossible to review this
>> code and to think about the approach.

...

> Step 2 is the run time test of each core. That requires the near
> simultaneous execution of:
>
> 	wrmsrl(MSR_ACTIVATE_SCAN, activate.data);
>
> on all HT threads on the core. Trivial on parts that do not support
> HT, or where it is disabled in BIOS. The above code is trying to
> achieve this "parallel" execution.

How is that supposed to work on a system which has HT enabled in BIOS,
but disabled on the kernel command line or via /sys/..../smt/control or
when a HT sibling is offlined temporarily?

I assume it cannot work, but I can't see anything which handles those
cases.

> The follow-on :
>
> 	rdmsrl(MSR_SCAN_STATUS, status.data);
>
> doesn't have to be synchronized ... but handy to do so for when not
> all chunks were processed and need to loop back to run another
> activate_scan to continue starting from the interrupted chunk. In
> the lab, this seems common ... when scanning all cores many of them
> complete all chunks in a single bite, but several take 2-3 times around
> the loop before completing.

Is there a timeout for restarting an interrupted chunk?

> As noted above I'm seeing a core test take around 50ms (but spec says
> up to 200ms). In some environments that doesn't require any special
> application or system reconfiguration.  It's not much different from
> time-slicing when you are running more processes (or guests) than you
> have CPUs. So sysadmins in those environments can use this driver to
> cylce through cores testing each in turn without any extra steps.
>
> You've pointed out that the driver disables preemption for insanely
> long amounts of time ... to use this driver to test cores on a system
> running applications where that is an issue will require additonal steps
> to migrate latency critical applications to a different core while the
> test is in progess, also re-direct interrupts. That seems well beyond the
> scope of what is possible in a driver without all the information about
> what workloads are running to pick a new temporary home for processes
> and interrupts while the core is being tested.

I assume that's all described in Documentation/x86/intel-ifs.rst, which
was in patch 11/10 and unfortunately got lost in the intertubes.

Coming back to that rendevouz mechanism.

As far as I understand it, but of course my implementation of

   # pdforacle --remote=tony --condense sekrit-ifs-spec.pdf

might be suboptimal, the only hard requirement is to start the
scan for a particular chunk on all HT threads roughly at the same
time.

But there is no hard requirement that the individual chunks are started
right after each other or that a restart of an for whatever reason
interrupted chunk happens 'immediately'.

If that's the case and anything else would be an insanity, then you can
do something like this:

static DEFINE_PER_CPU(struct ifs_status, ifs_status);

int do_test(int cpu, struct device *dev)
{
        const struct cpumask *mask;
        struct ifsdata data;

        cpus_read_lock();
        mask = topology_sibling_cpumask(cpu);
        if (!sane(mask))
        	goto fail;

        for_each_cpu(sibling, mask)
        	init_ifs_status(sibling);

        init_data(data, dev);

        while (data.chunk < data.max_chunks) {
        	ret = stomp_cpumask(mask, doscan, data);

                if (!ret) {
                        data.chunk++;
                	continue;
                }

                // Analyze per CPU ifs_status to either
                // restart or abort with proper information
                // about the reason to abort
                .....
        }
        ....

We don't have stomp_cpumask() today, but that's trivial enough to
implement. Yes, we want to avoid expanding stomp_machine(), but trying
to resemble stomp_machine() with work queues is worse by several orders
of magnitude.

doscan() will boil down to:

    wrmsrl(RUN_SCAM, data->chunk);
    rdmsrl(STA_SCAM, status);
    this_cpu_write(ifs_status, status);
    return status ? -ECRAP : 0;

plus the required commentry which will be an order of magnitude more
lines than the actual code above.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-05-04 23:15             ` Thomas Gleixner
@ 2022-05-05  8:28               ` Peter Zijlstra
  2022-05-05  9:01                 ` Thomas Gleixner
  0 siblings, 1 reply; 152+ messages in thread
From: Peter Zijlstra @ 2022-05-05  8:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Luck, Tony, hdegoede, markgross, mingo, bp, dave.hansen, x86,
	hpa, corbet, gregkh, andriy.shevchenko, jithu.joseph, ashok.raj,
	rostedt, dan.j.williams, linux-kernel, linux-doc,
	platform-driver-x86, patches, ravi.v.shankar

On Thu, May 05, 2022 at 01:15:07AM +0200, Thomas Gleixner wrote:
> We don't have stomp_cpumask() today, but that's trivial enough to
> implement.

I don't think we want to gift people a random cpumask stop_machine(),
but here's one that stops a core. It runs the @fn on every cpu since I
thought to have understood that was the requirement for this muck.

*completely* untestededed.

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 6da7b91af353..2e7324e44e38 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -631,6 +631,34 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
 }
 EXPORT_SYMBOL_GPL(stop_machine);
 
+/*
+ * stop_core_cpuslocked - stop_machine a core
+ * @cpu: any cpu in the targeted core
+ * @fn: the function to run
+ * @data: the data ptr for @fn()
+ *
+ * RETURNS:
+ * 0 if all executions of @fn returned 0, any non zero return value if any
+ * returned non zero.
+ */
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data)
+{
+	const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+
+	struct multi_stop_data msdata = {
+		.fn = fn,
+		.data = data,
+		.num_threads = cpumask_weight(smt_mask);
+		.active_cpus = smt_mask,
+	};
+
+	lockdep_assert_cpus_held();
+
+	/* Set the initial state and stop all online cpus. */
+	set_state(&msdata, MULTI_STOP_PREPARE);
+	return stop_cpus(smt_mask, multi_cpu_stop, &msdata);
+}
+
 /**
  * stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
  * @fn: the function to run

^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-05-05  8:28               ` Peter Zijlstra
@ 2022-05-05  9:01                 ` Thomas Gleixner
  2022-05-05 18:32                   ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-05  9:01 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Luck, Tony, hdegoede, markgross, mingo, bp, dave.hansen, x86,
	hpa, corbet, gregkh, andriy.shevchenko, jithu.joseph, ashok.raj,
	rostedt, dan.j.williams, linux-kernel, linux-doc,
	platform-driver-x86, patches, ravi.v.shankar

On Thu, May 05 2022 at 10:28, Peter Zijlstra wrote:
> On Thu, May 05, 2022 at 01:15:07AM +0200, Thomas Gleixner wrote:
>> We don't have stomp_cpumask() today, but that's trivial enough to
>> implement.
>
> I don't think we want to gift people a random cpumask stop_machine(),

Fair enough.

> but here's one that stops a core. It runs the @fn on every cpu since I
> thought to have understood that was the requirement for this muck.

Yes.

> *completely* untestededed.

Looks about right neverthelessesseess.

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-05-05  9:01                 ` Thomas Gleixner
@ 2022-05-05 18:32                   ` Luck, Tony
  2022-05-05 20:21                     ` Peter Zijlstra
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-05 18:32 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Peter Zijlstra, hdegoede, markgross, mingo, bp, dave.hansen, x86,
	hpa, corbet, gregkh, andriy.shevchenko, jithu.joseph, ashok.raj,
	rostedt, dan.j.williams, linux-kernel, linux-doc,
	platform-driver-x86, patches, ravi.v.shankar

On Thu, May 05, 2022 at 11:01:27AM +0200, Thomas Gleixner wrote:
> On Thu, May 05 2022 at 10:28, Peter Zijlstra wrote:
> > On Thu, May 05, 2022 at 01:15:07AM +0200, Thomas Gleixner wrote:
> >> We don't have stomp_cpumask() today, but that's trivial enough to
> >> implement.
> >
> > I don't think we want to gift people a random cpumask stop_machine(),
> 
> Fair enough.
> 
> > but here's one that stops a core. It runs the @fn on every cpu since I
> > thought to have understood that was the requirement for this muck.
> 
> Yes.
> 
> > *completely* untestededed.
> 
> Looks about right neverthelessesseess.

Close enough. I made these changes:

1) Added EXPORT_SYMBOL_GPL()
2) Added protoype in <linux/stop_machine.h>
3) Moved the kerneldoc comment to the header (for some reason
   the other stop* functions document there).
4) Edited that kerneldoc a bit <<<< NEEDS REVIEW  >>>
5) Changed a ';' to a ',' to make it compile.

With that it works, and will do exactly what I need (with less code
in the IFS driver by the look of things).

A couple of thousand tests shows it works. The two threads
arrive within 20 TSC cycles of each other 60% of the time,
but I have some outliers up to 654 cycles ... which is plenty
close enough.

Patch now looks like this. Author credit to Peter ... are you willing
to add a Signed-off-by to stop checkpatch from whining at me?

There isn't a "Something-similar-suggested-by:" tag to credit Thomas
with this.  Perhaps "Inspired-by:"?

-Tony


From df5ca8024997d3d782978d154cfbff5147f451ad Mon Sep 17 00:00:00 2001
From: Peter Zijlstra <peterz@infradead.org>
Date: Thu, 5 May 2022 08:55:09 -0700
Subject: [PATCH] stop_machine: Add stop_core_cpuslocked() for per-core
 operations

Hardware core level testing features require near simultaneous execution
of WRMSR instructions on all threads of a core to initiate a test.

Provide a customized cut down version of stop_machine_cpuslocked() that
just operates on the threads of a single core.

Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 include/linux/stop_machine.h | 16 ++++++++++++++++
 kernel/stop_machine.c        | 19 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 46fb3ebdd16e..ea7a74ea7389 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -124,6 +124,22 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
  */
 int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
 
+/**
+ * stop_core_cpuslocked: - stop all threads on just one core
+ * @cpu: any cpu in the targeted core
+ * @fn: the function to run
+ * @data: the data ptr for @fn()
+ *
+ * Same as above, but instead of every CPU, only the logical CPUs of a
+ * single core are affected.
+ *
+ * Context: Must be called from within a cpus_read_lock() protected region.
+ *
+ * Return: 0 if all executions of @fn returned 0, any non zero return
+ * value if any returned non zero.
+ */
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data);
+
 int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
 				   const struct cpumask *cpus);
 #else	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index cbc30271ea4d..579761729836 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -633,6 +633,25 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
 }
 EXPORT_SYMBOL_GPL(stop_machine);
 
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data)
+{
+	const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+
+	struct multi_stop_data msdata = {
+		.fn = fn,
+		.data = data,
+		.num_threads = cpumask_weight(smt_mask),
+		.active_cpus = smt_mask,
+	};
+
+	lockdep_assert_cpus_held();
+
+	/* Set the initial state and stop all online cpus. */
+	set_state(&msdata, MULTI_STOP_PREPARE);
+	return stop_cpus(smt_mask, multi_cpu_stop, &msdata);
+}
+EXPORT_SYMBOL_GPL(stop_core_cpuslocked);
+
 /**
  * stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
  * @fn: the function to run
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support
  2022-05-05 18:32                   ` Luck, Tony
@ 2022-05-05 20:21                     ` Peter Zijlstra
  0 siblings, 0 replies; 152+ messages in thread
From: Peter Zijlstra @ 2022-05-05 20:21 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Thomas Gleixner, hdegoede, markgross, mingo, bp, dave.hansen,
	x86, hpa, corbet, gregkh, andriy.shevchenko, jithu.joseph,
	ashok.raj, rostedt, dan.j.williams, linux-kernel, linux-doc,
	platform-driver-x86, patches, ravi.v.shankar

On Thu, May 05, 2022 at 11:32:04AM -0700, Luck, Tony wrote:

> Patch now looks like this. Author credit to Peter ... are you willing
> to add a Signed-off-by to stop checkpatch from whining at me?

sure, see below.

> There isn't a "Something-similar-suggested-by:" tag to credit Thomas
> with this.  Perhaps "Inspired-by:"?

I'm all for creative one off tags, there's some marvelous ones in the
tree, but we always need more :-)

> -Tony
> 
> 
> From df5ca8024997d3d782978d154cfbff5147f451ad Mon Sep 17 00:00:00 2001
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Thu, 5 May 2022 08:55:09 -0700
> Subject: [PATCH] stop_machine: Add stop_core_cpuslocked() for per-core
>  operations
> 
> Hardware core level testing features require near simultaneous execution
> of WRMSR instructions on all threads of a core to initiate a test.
> 
> Provide a customized cut down version of stop_machine_cpuslocked() that
> just operates on the threads of a single core.
> 
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  include/linux/stop_machine.h | 16 ++++++++++++++++
>  kernel/stop_machine.c        | 19 +++++++++++++++++++
>  2 files changed, 35 insertions(+)
> 
> diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
> index 46fb3ebdd16e..ea7a74ea7389 100644
> --- a/include/linux/stop_machine.h
> +++ b/include/linux/stop_machine.h
> @@ -124,6 +124,22 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
>   */
>  int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
>  
> +/**
> + * stop_core_cpuslocked: - stop all threads on just one core
> + * @cpu: any cpu in the targeted core
> + * @fn: the function to run
> + * @data: the data ptr for @fn()
> + *
> + * Same as above, but instead of every CPU, only the logical CPUs of a
> + * single core are affected.
> + *
> + * Context: Must be called from within a cpus_read_lock() protected region.
> + *
> + * Return: 0 if all executions of @fn returned 0, any non zero return
> + * value if any returned non zero.
> + */
> +int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data);
> +
>  int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
>  				   const struct cpumask *cpus);
>  #else	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
> diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
> index cbc30271ea4d..579761729836 100644
> --- a/kernel/stop_machine.c
> +++ b/kernel/stop_machine.c
> @@ -633,6 +633,25 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
>  }
>  EXPORT_SYMBOL_GPL(stop_machine);
>  
> +int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data)
> +{
> +	const struct cpumask *smt_mask = cpu_smt_mask(cpu);
> +
> +	struct multi_stop_data msdata = {
> +		.fn = fn,
> +		.data = data,
> +		.num_threads = cpumask_weight(smt_mask),
> +		.active_cpus = smt_mask,
> +	};
> +
> +	lockdep_assert_cpus_held();
> +
> +	/* Set the initial state and stop all online cpus. */
> +	set_state(&msdata, MULTI_STOP_PREPARE);
> +	return stop_cpus(smt_mask, multi_cpu_stop, &msdata);
> +}
> +EXPORT_SYMBOL_GPL(stop_core_cpuslocked);
> +
>  /**
>   * stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
>   * @fn: the function to run
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v6 00/11] Introduce In Field Scan driver
  2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
                         ` (11 preceding siblings ...)
  2022-05-02 15:15       ` Hans de Goede
@ 2022-05-06  1:40       ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
                           ` (11 more replies)
  12 siblings, 12 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

TL;DR this driver loads scan test files that can check whether silicon
in a CPU core is still running correctly. It is expected that these tests
would be run several times per day to catch problems as silicon ages.

Changes since v5:

Added various Reviewed tags. If anyone wants to take one or more
back in the light of changes listed below, please speak up.

Thomas Gleixner
---------------
03 "So checking for Intel Fam6 ANYMODEL and X86_FEATURE_CORE_CAPABILITIES is
 sufficient, no?"

Longer explanation in earlier e-mail ... but the family/model/stepping
check is needed. No change.

04 "Why is ifs_load_firmware() not returning an error to the caller?"

In most cases the return isn't useful. But this did prompt a change
to make sure "echo 1 > reload" does give an error if the load fails.

05 "The above struct is nicely tabular. Can we have that here too please?"

Added <TAB>s to ifs_data structure to make it equally pretty.

06 "Setting the authenticated indicator _before_ actually doing the
authentication is just wrong. It does not matter in this case, but it's
still making my eyes bleed."

Moved indicator to after success has been checked.

06 "Why has this to be a smp function call? Just because it's conveniant?
This is nothing urgent and no hotpath, so this really can use
queue_work_on()."

Even simpler is schedule_work_on() [since other changes mean that
the driver no longer allocates a work queue.


07 "Waiting for a second with preemption disabled? Seriously?"
   "Plus another half a second with preemption disabled. That's just insane."
   "That local_irq_disable() solves what?"
   "Why cpu_hotplug_disable()? Why is cpus_read_lock() not sufficient here?"
   "Why does this need GFP_NOWAIT?"
   "I put that into the wishful thinking realm"
   "The real question is why you try to rendevouz CPUs via work queues."
   "pseudo-code to use stomp_machine()"

PeterZ contributed a neatly tailored for this usage "stop_core_cpuslocked()"
function that works beautifully. See part 0003 of this new series. That
meant all of the code that triggered the above comments has gone.

Tony Luck
---------
Noticed unnecessary casts from u8 to u32 in the checksum calculation
in load.c. Fixed.

Changed the tracepoint to include the CPU number of the core being
tested (the tracepoint otherwise just tells you which CPU is executing
the driver code and executing "stop_core_cpuslocked()" to do the actual
work on the target CPUs.

Dropped the msec_to_tsc() function that was used to initialize
activate.delay. Just use a #define of 100000 cycles (two orders
of magnitude bigger than I saw for the slew between the two threads
executing the "stop_core_cpuslocked()" target function ... but not
too insane so if the threads do not sync, we give up quickly).



Jithu Joseph (7):
  x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  platform/x86/intel/ifs: Read IFS firmware image
  platform/x86/intel/ifs: Check IFS Image sanity
  platform/x86/intel/ifs: Authenticate and copy to secured memory
  platform/x86/intel/ifs: Add scan test support
  platform/x86/intel/ifs: Add IFS sysfs interface
  platform/x86/intel/ifs: add ABI documentation for IFS

Peter Zijlstra (1):
  stop_machine: Add stop_core_cpuslocked() for per-core operations

Tony Luck (3):
  x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  platform/x86/intel/ifs: Add stub driver for In-Field Scan
  trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
    operations

 .../ABI/testing/sysfs-platform-intel-ifs      |  39 +++
 MAINTAINERS                                   |   8 +
 arch/x86/include/asm/cpu.h                    |  18 ++
 arch/x86/include/asm/msr-index.h              |   7 +
 arch/x86/kernel/cpu/intel.c                   |  32 +++
 arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
 drivers/platform/x86/intel/Kconfig            |   1 +
 drivers/platform/x86/intel/Makefile           |   1 +
 drivers/platform/x86/intel/ifs/Kconfig        |  13 +
 drivers/platform/x86/intel/ifs/Makefile       |   3 +
 drivers/platform/x86/intel/ifs/core.c         |  74 +++++
 drivers/platform/x86/intel/ifs/ifs.h          | 124 ++++++++
 drivers/platform/x86/intel/ifs/load.c         | 266 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/runtest.c      | 255 +++++++++++++++++
 drivers/platform/x86/intel/ifs/sysfs.c        | 149 ++++++++++
 include/linux/stop_machine.h                  |  16 ++
 include/trace/events/intel_ifs.h              |  41 +++
 kernel/stop_machine.c                         |  19 ++
 18 files changed, 1073 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
 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
 create mode 100644 drivers/platform/x86/intel/ifs/load.c
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
 create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
 create mode 100644 include/trace/events/intel_ifs.h


base-commit: 672c0c5173427e6b3e2a9bbb7be51ceeec78093a
-- 
2.35.1


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v6 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 02/11] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
                           ` (10 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar, Borislav Petkov

From: Jithu Joseph <jithu.joseph@intel.com>

IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs.

In support of an IFS driver to trigger loading, validation, and running
of these tests blobs, make the functionality of cpu_signatures_match()
and collect_cpu_info_early() available outside of the microcode driver.

Add an "intel_" prefix and drop the "_early" suffix from
collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
declaration to x86 <asm/cpu.h>

Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
and also give it an "intel_" prefix.

No functional change intended.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Borislav Petkov <bp@suse.de>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/x86/include/asm/cpu.h            | 18 ++++++++
 arch/x86/kernel/cpu/intel.c           | 32 +++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c | 59 ++++-----------------------
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 86e5e4e26fcb..990167357c34 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -76,4 +76,22 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
 
 extern __noendbr void cet_disable(void);
 
+struct ucode_cpu_info;
+
+int intel_cpu_collect_info(struct ucode_cpu_info *uci);
+
+static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+					      unsigned int s2, unsigned int p2)
+{
+	if (s1 != s2)
+		return false;
+
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
+
+	/* ... or they intersect. */
+	return p1 & p2;
+}
+
 #endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f7a5370a9b3b..94779146275d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,6 +181,38 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 	return false;
 }
 
+int intel_cpu_collect_info(struct ucode_cpu_info *uci)
+{
+	unsigned int val[2];
+	unsigned int family, model;
+	struct cpu_signature csig = { 0 };
+	unsigned int eax, ebx, ecx, edx;
+
+	memset(uci, 0, sizeof(*uci));
+
+	eax = 0x00000001;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	csig.sig = eax;
+
+	family = x86_family(eax);
+	model  = x86_model(eax);
+
+	if (model >= 5 || family > 6) {
+		/* get processor flags from MSR 0x17 */
+		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		csig.pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	csig.rev = intel_get_microcode_revision();
+
+	uci->cpu_sig = csig;
+	uci->valid = 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index d28a9f8f3fec..025c8f0cd948 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */
@@ -69,7 +55,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	struct extended_signature *ext_sig;
 	int i;
 
-	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
 		return 1;
 
 	/* Look for ext. headers: */
@@ -80,7 +66,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
 
 	for (i = 0; i < ext_hdr->count; i++) {
-		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
 			return 1;
 		ext_sig++;
 	}
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 	return patch;
 }
 
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-	unsigned int val[2];
-	unsigned int family, model;
-	struct cpu_signature csig = { 0 };
-	unsigned int eax, ebx, ecx, edx;
-
-	memset(uci, 0, sizeof(*uci));
-
-	eax = 0x00000001;
-	ecx = 0;
-	native_cpuid(&eax, &ebx, &ecx, &edx);
-	csig.sig = eax;
-
-	family = x86_family(eax);
-	model  = x86_model(eax);
-
-	if ((model >= 5) || (family > 6)) {
-		/* get processor flags from MSR 0x17 */
-		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		csig.pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	csig.rev = intel_get_microcode_revision();
-
-	uci->cpu_sig = csig;
-	uci->valid = 1;
-
-	return 0;
-}
-
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
 		return;
 	}
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	sig	= uci.cpu_sig.sig;
 	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
 	struct ucode_cpu_info uci;
 
 	if (delay_ucode_info) {
-		collect_cpu_info_early(&uci);
+		intel_cpu_collect_info(&uci);
 		print_ucode_info(&uci, current_mc_date);
 		delay_ucode_info = 0;
 	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
 	if (!(cp.data && cp.size))
 		return 0;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	scan_microcode(cp.data, cp.size, &uci, true);
 
@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 	if (!(cp.data && cp.size))
 		return NULL;
 
-	collect_cpu_info_early(uci);
+	intel_cpu_collect_info(uci);
 
 	return scan_microcode(cp.data, cp.size, uci, false);
 }
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
 	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	p = find_patch(&uci);
 	if (!p)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 02/11] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
  2022-05-06  1:40         ` [PATCH v6 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  8:19           ` Thomas Gleixner
  2022-05-06  1:40         ` [PATCH v6 03/11] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
                           ` (9 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

The INTEGRITY_CAPABILITIES MSR is enumerated by bit 2 of the
CORE_CAPABILITIES MSR.

Add defines for the CORE_CAPS enumeration as well as for the integrity
MSR.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/x86/include/asm/msr-index.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index ee15311b6be1..c3dc7ae32f1f 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -76,6 +76,8 @@
 
 /* Abbreviated from Intel SDM name IA32_CORE_CAPABILITIES */
 #define MSR_IA32_CORE_CAPS			  0x000000cf
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT	  2
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS	  BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT)
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT  5
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT	  BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
 
@@ -154,6 +156,11 @@
 #define MSR_IA32_POWER_CTL		0x000001fc
 #define MSR_IA32_POWER_CTL_BIT_EE	19
 
+/* Abbreviated from Intel SDM name IA32_INTEGRITY_CAPABILITIES */
+#define MSR_INTEGRITY_CAPS			0x000002d9
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT	4
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST	BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
+
 #define MSR_LBR_NHM_FROM		0x00000680
 #define MSR_LBR_NHM_TO			0x000006c0
 #define MSR_LBR_CORE_FROM		0x00000040
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 03/11] stop_machine: Add stop_core_cpuslocked() for per-core operations
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
  2022-05-06  1:40         ` [PATCH v6 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
  2022-05-06  1:40         ` [PATCH v6 02/11] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  8:20           ` Thomas Gleixner
  2022-05-06  1:40         ` [PATCH v6 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
                           ` (8 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar, Peter Zijlstra

From: Peter Zijlstra <peterz@infradead.org>

Hardware core level testing features require near simultaneous execution
of WRMSR instructions on all threads of a core to initiate a test.

Provide a customized cut down version of stop_machine_cpuslocked() that
just operates on the threads of a single core.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 include/linux/stop_machine.h | 16 ++++++++++++++++
 kernel/stop_machine.c        | 19 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 46fb3ebdd16e..ea7a74ea7389 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -124,6 +124,22 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
  */
 int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
 
+/**
+ * stop_core_cpuslocked: - stop all threads on just one core
+ * @cpu: any cpu in the targeted core
+ * @fn: the function to run
+ * @data: the data ptr for @fn()
+ *
+ * Same as above, but instead of every CPU, only the logical CPUs of a
+ * single core are affected.
+ *
+ * Context: Must be called from within a cpus_read_lock() protected region.
+ *
+ * Return: 0 if all executions of @fn returned 0, any non zero return
+ * value if any returned non zero.
+ */
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data);
+
 int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
 				   const struct cpumask *cpus);
 #else	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index cbc30271ea4d..579761729836 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -633,6 +633,25 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
 }
 EXPORT_SYMBOL_GPL(stop_machine);
 
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data)
+{
+	const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+
+	struct multi_stop_data msdata = {
+		.fn = fn,
+		.data = data,
+		.num_threads = cpumask_weight(smt_mask),
+		.active_cpus = smt_mask,
+	};
+
+	lockdep_assert_cpus_held();
+
+	/* Set the initial state and stop all online cpus. */
+	set_state(&msdata, MULTI_STOP_PREPARE);
+	return stop_cpus(smt_mask, multi_cpu_stop, &msdata);
+}
+EXPORT_SYMBOL_GPL(stop_core_cpuslocked);
+
 /**
  * stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
  * @fn: the function to run
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (2 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 03/11] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  8:23           ` Thomas Gleixner
  2022-05-06  1:40         ` [PATCH v6 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
                           ` (7 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Cloud Service Providers that operate fleets of servers have reported
[1] occasions where they can detect that a CPU has gone bad due to
effects like electromigration, or isolated manufacturing defects.
However, that detection method is A/B testing seemingly random
application failures looking for a pattern. In-Field Scan (IFS) is
a driver for a platform capability to load a crafted 'scan image'
to run targeted low level diagnostics outside of the CPU's architectural
error detection capabilities.

Stub version of driver just does initial part of check for the IFS
feature. MSR_IA32_CORE_CAPS must enumerate the presence of the
MSR_INTEGRITY_CAPS MSR.

[1]: https://www.youtube.com/watch?v=QMF3rqhjYuM

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 MAINTAINERS                             |  7 ++++
 drivers/platform/x86/intel/Kconfig      |  1 +
 drivers/platform/x86/intel/Makefile     |  1 +
 drivers/platform/x86/intel/ifs/Kconfig  | 13 +++++++
 drivers/platform/x86/intel/ifs/Makefile |  3 ++
 drivers/platform/x86/intel/ifs/core.c   | 48 +++++++++++++++++++++++++
 6 files changed, 73 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

diff --git a/MAINTAINERS b/MAINTAINERS
index edc96cdb85e8..bb0c4ff25942 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9862,6 +9862,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
 
+INTEL IN FIELD SCAN (IFS) DEVICE
+M:	Jithu Joseph <jithu.joseph@intel.com>
+R:	Ashok Raj <ashok.raj@intel.com>
+R:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+F:	drivers/platform/x86/intel/ifs
+
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 1f01a8a23c57..794968bda115 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -4,6 +4,7 @@
 #
 
 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/int3472/Kconfig"
 source "drivers/platform/x86/intel/pmc/Kconfig"
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index c61bc3e97121..717933dd0cfd 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
+obj-$(CONFIG_INTEL_IFS)			+= ifs/
 obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
 obj-$(CONFIG_INTEL_SKL_INT3472)		+= int3472/
 obj-$(CONFIG_INTEL_PMC_CORE)		+= pmc/
diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
new file mode 100644
index 000000000000..d84491cfb0db
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Kconfig
@@ -0,0 +1,13 @@
+config INTEL_IFS
+	tristate "Intel In Field Scan"
+	depends on X86 && 64BIT && SMP
+	select INTEL_IFS_DEVICE
+	help
+	  Enable support for the In Field Scan capability in select
+	  CPUs. The capability allows for running low level tests via
+	  a scan image distributed by Intel via Github to validate CPU
+	  operation beyond baseline RAS capabilities. To compile this
+	  support 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..af904880e959
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
+
+intel_ifs-objs			:= core.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
new file mode 100644
index 000000000000..e3623ac691b5
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+
+#include <asm/cpu_device_id.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 = {
+	X86_MATCH(SAPPHIRERAPIDS_X),
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
+
+static int __init ifs_init(void)
+{
+	const struct x86_cpu_id *m;
+	u64 msrval;
+
+	m = x86_match_cpu(ifs_cpu_ids);
+	if (!m)
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &msrval))
+		return -ENODEV;
+
+	if (!(msrval & MSR_IA32_CORE_CAPS_INTEGRITY_CAPS))
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
+		return -ENODEV;
+
+	return 0;
+}
+
+static void __exit ifs_exit(void)
+{
+}
+
+module_init(ifs_init);
+module_exit(ifs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel In Field Scan (IFS) device");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 05/11] platform/x86/intel/ifs: Read IFS firmware image
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (3 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
                           ` (6 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Driver probe routine allocates structure to communicate status
and parameters between functions in the driver. Also call
load_ifs_binary() to load the scan image file.

There is a separate scan image file for each processor family,
model, stepping combination. This is read from the static path:

  /lib/firmware/intel/ifs/{ff-mm-ss}.scan

Step 1 in loading is to generate the correct path and use
request_firmware_direct() to load into memory.

Subsequent patches will use the IFS MSR interfaces to copy
the image to BIOS reserved memory and validate the SHA256
checksums.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/Makefile |  2 +-
 drivers/platform/x86/intel/ifs/core.c   | 22 ++++++++++++++++++-
 drivers/platform/x86/intel/ifs/ifs.h    | 25 ++++++++++++++++++++++
 drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 drivers/platform/x86/intel/ifs/ifs.h
 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 af904880e959..98b6fde15689 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o
+intel_ifs-objs			:= core.o load.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index e3623ac691b5..f62578dae8e9 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -6,6 +6,8 @@
 
 #include <asm/cpu_device_id.h>
 
+#include "ifs.h"
+
 #define X86_MATCH(model)				\
 	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6,	\
 		INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL)
@@ -16,6 +18,17 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
 };
 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 
+static struct ifs_device ifs_device = {
+	.data = {
+		.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
+	},
+	.misc = {
+		.name = "intel_ifs_0",
+		.nodename = "intel_ifs/0",
+		.minor = MISC_DYNAMIC_MINOR,
+	},
+};
+
 static int __init ifs_init(void)
 {
 	const struct x86_cpu_id *m;
@@ -34,11 +47,18 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
-	return 0;
+	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
+	    !misc_register(&ifs_device.misc)) {
+		ifs_load_firmware(ifs_device.misc.this_device);
+		return 0;
+	}
+
+	return -ENODEV;
 }
 
 static void __exit ifs_exit(void)
 {
+	misc_deregister(&ifs_device.misc);
 }
 
 module_init(ifs_init);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
new file mode 100644
index 000000000000..47e5f8344fd8
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Intel Corporation. */
+
+#ifndef _IFS_H_
+#define _IFS_H_
+
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+
+/**
+ * struct ifs_data - attributes related to intel IFS driver
+ * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
+ */
+struct ifs_data {
+	int	integrity_cap_bit;
+};
+
+struct ifs_device {
+	struct ifs_data data;
+	struct miscdevice misc;
+};
+
+void ifs_load_firmware(struct device *dev);
+
+#endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
new file mode 100644
index 000000000000..9fb71d38c819
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/firmware.h>
+
+#include "ifs.h"
+
+/*
+ * Load ifs image. Before loading ifs module, the ifs image must be located
+ * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
+ */
+void ifs_load_firmware(struct device *dev)
+{
+	const struct firmware *fw;
+	char scan_path[32];
+	int ret;
+
+	snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
+		 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
+
+	ret = request_firmware_direct(&fw, scan_path, dev);
+	if (ret) {
+		dev_err(dev, "ifs file %s load failed\n", scan_path);
+		return;
+	}
+
+	release_firmware(fw);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 06/11] platform/x86/intel/ifs: Check IFS Image sanity
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (4 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
                           ` (5 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/load.c | 66 +++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index 9fb71d38c819..cfbf62494c89 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -2,9 +2,72 @@
 /* Copyright(c) 2022 Intel Corporation. */
 
 #include <linux/firmware.h>
+#include <asm/cpu.h>
+#include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+static int ifs_sanity_check(struct device *dev,
+			    const struct microcode_header_intel *mc_header)
+{
+	unsigned long total_size, data_size;
+	u32 sum, *mc;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+
+	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
+		dev_err(dev, "bad ifs data file size.\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		dev_err(dev, "invalid/unknown ifs update format.\n");
+		return -EINVAL;
+	}
+
+	mc = (u32 *)mc_header;
+	sum = 0;
+	for (int i = 0; i < total_size / sizeof(u32); i++)
+		sum += mc[i];
+
+	if (sum) {
+		dev_err(dev, "bad ifs data checksum, aborting.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
+					const struct microcode_header_intel *shdr)
+{
+	unsigned int mc_size;
+
+	mc_size = get_totalsize(shdr);
+
+	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
+		dev_err(dev, "ifs sanity check failure\n");
+		return false;
+	}
+
+	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
+		dev_err(dev, "ifs signature, pf not matching\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
+{
+	struct ucode_cpu_info uci;
+
+	intel_cpu_collect_info(&uci);
+
+	return find_ifs_matching_signature(dev, &uci, data);
+}
+
 /*
  * Load ifs image. Before loading ifs module, the ifs image must be located
  * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
@@ -24,5 +87,8 @@ void ifs_load_firmware(struct device *dev)
 		return;
 	}
 
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+		dev_err(dev, "ifs header sanity check failed\n");
+
 	release_firmware(fw);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (5 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
                           ` (4 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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
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.

Use schedule_work_on() to perform the hash copy and authentication. Note
this needs only be done on the first logical cpu of each socket.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/ifs.h  |  52 ++++++++
 drivers/platform/x86/intel/ifs/load.c | 176 +++++++++++++++++++++++++-
 2 files changed, 226 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 47e5f8344fd8..1a606c999b12 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -7,12 +7,56 @@
 #include <linux/device.h>
 #include <linux/miscdevice.h>
 
+#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 {
+		u32	chunk_size	:16;
+		u32	num_chunks	:8;
+		u32	rsvd1		:8;
+		u32	error_code	:8;
+		u32	rsvd2		:11;
+		u32	max_core_limit	:12;
+		u32	valid		:1;
+	};
+};
+
+/* MSR_CHUNKS_AUTH_STATUS bit fields */
+union ifs_chunks_auth_status {
+	u64	data;
+	struct {
+		u32	valid_chunks	:8;
+		u32	total_chunks	:8;
+		u32	rsvd1		:16;
+		u32	error_code	:8;
+		u32	rsvd2		:24;
+	};
+};
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
+ * @loaded_version: stores the currently loaded ifs image version.
+ * @loaded: If a valid test binary has been loaded into the memory
+ * @loading_error: Error occurred on another CPU while loading image
+ * @valid_chunks: number of chunks which could be validated.
  */
 struct ifs_data {
 	int	integrity_cap_bit;
+	int	loaded_version;
+	bool	loaded;
+	bool	loading_error;
+	int	valid_chunks;
+};
+
+struct ifs_work {
+	struct work_struct w;
+	struct device *dev;
 };
 
 struct ifs_device {
@@ -20,6 +64,14 @@ struct ifs_device {
 	struct miscdevice misc;
 };
 
+static inline struct ifs_data *ifs_get_data(struct device *dev)
+{
+	struct miscdevice *m = dev_get_drvdata(dev);
+	struct ifs_device *d = container_of(m, struct ifs_device, misc);
+
+	return &d->data;
+}
+
 void ifs_load_firmware(struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index cfbf62494c89..d056617ddc85 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,10 +3,172 @@
 
 #include <linux/firmware.h>
 #include <asm/cpu.h>
+#include <linux/slab.h>
 #include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+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 header */
+static u64 ifs_hash_ptr;			/* Address of ifs metadata (hash) */
+static u64 ifs_test_image_ptr;			/* 256B aligned address of test pattern */
+static DECLARE_COMPLETION(ifs_done);
+
+static const char * const scan_hash_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to copy scan hashes when copy already in progress",
+	[2] = "Secure Memory not set up correctly",
+	[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
+	[4] = "Reserved",
+	[5] = "Integrity check failed",
+	[6] = "Scan reload or test is in progress"
+};
+
+static const char * const scan_authentication_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to authenticate a chunk which is already marked as authentic",
+	[2] = "Chunk authentication error. The hash of chunk did not match expected value"
+};
+
+/*
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must 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_AUTHENTICATE_AND_COPY_CHUNK)
+ * for scan hash copy and test chunk authentication.
+ */
+static void copy_hashes_authenticate_chunks(struct work_struct *work)
+{
+	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
+	union ifs_scan_hashes_status hashes_status;
+	union ifs_chunks_auth_status chunk_status;
+	struct device *dev = local_work->dev;
+	int i, num_chunks, chunk_size;
+	struct ifs_data *ifsd;
+	u64 linear_addr, base;
+	u32 err_code;
+
+	ifsd = ifs_get_data(dev);
+	/* 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 = hashes_status.num_chunks;
+	chunk_size = hashes_status.chunk_size * 1024;
+	err_code = hashes_status.error_code;
+
+	if (!hashes_status.valid) {
+		ifsd->loading_error = true;
+		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
+			dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
+			goto done;
+		}
+		dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
+		goto done;
+	}
+
+	/* base linear address to the scan data */
+	base = ifs_test_image_ptr;
+
+	/* scan data authentication and copy chunks to secured memory */
+	for (i = 0; i < num_chunks; i++) {
+		linear_addr = base + i * chunk_size;
+		linear_addr |= i;
+
+		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
+		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
+
+		ifsd->valid_chunks = chunk_status.valid_chunks;
+		err_code = chunk_status.error_code;
+
+		if (err_code) {
+			ifsd->loading_error = true;
+			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
+				dev_err(dev,
+					"invalid error code 0x%x for authentication\n", err_code);
+				goto done;
+			}
+			dev_err(dev, "Chunk authentication error %s\n",
+				scan_authentication_status[err_code]);
+			goto done;
+		}
+	}
+done:
+	complete(&ifs_done);
+}
+
+/*
+ * IFS requires scan chunks authenticated per each socket in the platform.
+ * Once the test chunk is authenticated, it is automatically copied to secured memory
+ * and proceed the authentication for the next chunk.
+ */
+static int scan_chunks_sanity_check(struct device *dev)
+{
+	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	bool *package_authenticated;
+	struct ifs_work local_work;
+	char *test_ptr;
+
+	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
+	if (!package_authenticated)
+		return ret;
+
+	metadata_size = ifs_header_ptr->metadata_size;
+
+	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
+	if (metadata_size == 0)
+		metadata_size = 2000;
+
+	/* Scan chunk start must be 256 byte aligned */
+	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
+		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
+		return -EINVAL;
+	}
+
+	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
+	ifsd->loading_error = false;
+
+	ifs_test_image_ptr = (u64)test_ptr;
+	ifsd->loaded_version = ifs_header_ptr->blob_revision;
+
+	/* copy the scan hash and authenticate per package */
+	cpus_read_lock();
+	for_each_online_cpu(cpu) {
+		curr_pkg = topology_physical_package_id(cpu);
+		if (package_authenticated[curr_pkg])
+			continue;
+		reinit_completion(&ifs_done);
+		local_work.dev = dev;
+		INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
+		schedule_work_on(cpu, &local_work.w);
+		wait_for_completion(&ifs_done);
+		if (ifsd->loading_error)
+			goto out;
+		package_authenticated[curr_pkg] = 1;
+	}
+	ret = 0;
+out:
+	cpus_read_unlock();
+	kfree(package_authenticated);
+
+	return ret;
+}
+
 static int ifs_sanity_check(struct device *dev,
 			    const struct microcode_header_intel *mc_header)
 {
@@ -74,6 +236,7 @@ static bool ifs_image_sanity_check(struct device *dev, const struct microcode_he
  */
 void ifs_load_firmware(struct device *dev)
 {
+	struct ifs_data *ifsd = ifs_get_data(dev);
 	const struct firmware *fw;
 	char scan_path[32];
 	int ret;
@@ -84,11 +247,20 @@ void ifs_load_firmware(struct device *dev)
 	ret = request_firmware_direct(&fw, scan_path, dev);
 	if (ret) {
 		dev_err(dev, "ifs file %s load failed\n", scan_path);
-		return;
+		goto done;
 	}
 
-	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
 		dev_err(dev, "ifs header sanity check failed\n");
+		goto release;
+	}
+
+	ifs_header_ptr = (struct ifs_header *)fw->data;
+	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
 
+	ret = scan_chunks_sanity_check(dev);
+release:
 	release_firmware(fw);
+done:
+	ifsd->loaded = (ret == 0);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (6 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06 13:30           ` Thomas Gleixner
  2022-05-06  1:40         ` [PATCH v6 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
                           ` (3 subsequent siblings)
  11 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

In a core, the scan engine is shared between sibling cpus.

When a Scan test (for a particular core) is triggered by the user,
the scan chunks are executed on all the threads on the core using
stop_core_cpuslocked.

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/ifs.h     |  44 ++++
 drivers/platform/x86/intel/ifs/runtest.c | 250 +++++++++++++++++++++++
 3 files changed, 295 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c

diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
index 98b6fde15689..cedcb103f860 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o
+intel_ifs-objs			:= core.o load.o runtest.o
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 1a606c999b12..7435a5582df3 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -11,6 +11,11 @@
 #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_NOT_TESTED				0
+#define SCAN_TEST_PASS				1
+#define SCAN_TEST_FAIL				2
 
 /* MSR_SCAN_HASHES_STATUS bit fields */
 union ifs_scan_hashes_status {
@@ -38,6 +43,40 @@ union ifs_chunks_auth_status {
 	};
 };
 
+/* MSR_ACTIVATE_SCAN bit fields */
+union ifs_scan {
+	u64	data;
+	struct {
+		u32	start	:8;
+		u32	stop	:8;
+		u32	rsvd	:16;
+		u32	delay	:31;
+		u32	sigmce	:1;
+	};
+};
+
+/* MSR_SCAN_STATUS bit fields */
+union ifs_status {
+	u64	data;
+	struct {
+		u32	chunk_num		:8;
+		u32	chunk_stop_index	:8;
+		u32	rsvd1			:16;
+		u32	error_code		:8;
+		u32	rsvd2			:22;
+		u32	control_error		:1;
+		u32	signature_error		:1;
+	};
+};
+
+/*
+ * Driver populated error-codes
+ * 0xFD: Test timed out before completing all the chunks.
+ * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
+ */
+#define IFS_SW_TIMEOUT				0xFD
+#define IFS_SW_PARTIAL_COMPLETION		0xFE
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit - MSR_INTEGRITY_CAPS bit enumerating this test
@@ -45,6 +84,8 @@ union ifs_chunks_auth_status {
  * @loaded: If a valid test binary has been loaded into the memory
  * @loading_error: Error occurred on another CPU while loading image
  * @valid_chunks: number of chunks which could be validated.
+ * @status: it holds simple status pass/fail/untested
+ * @scan_details: opaque scan status code from h/w
  */
 struct ifs_data {
 	int	integrity_cap_bit;
@@ -52,6 +93,8 @@ struct ifs_data {
 	bool	loaded;
 	bool	loading_error;
 	int	valid_chunks;
+	int	status;
+	u64	scan_details;
 };
 
 struct ifs_work {
@@ -73,5 +116,6 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
 }
 
 void ifs_load_firmware(struct device *dev);
+int do_core_test(int cpu, struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
new file mode 100644
index 000000000000..fd3f5f3f31e5
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/nmi.h>
+#include <linux/slab.h>
+#include <linux/stop_machine.h>
+
+#include "ifs.h"
+
+/*
+ * Note all code and data in this file is protected by
+ * ifs_sem. On HT systems all threads on a core will
+ * execute together, but only the first thread on the
+ * core will update results of the test.
+ */
+struct workqueue_struct *ifs_wq;
+static bool scan_enabled = true;
+
+/* Max retries on the same chunk */
+#define MAX_IFS_RETRIES  5
+
+/*
+ * Number of TSC cycles that a logical CPU will wait for the other
+ * logical CPU on the core in the WRMSR(ACTIVATE_SCAN).
+ */
+#define IFS_THREAD_WAIT 100000
+
+enum ifs_status_err_code {
+	IFS_NO_ERROR				= 0,
+	IFS_OTHER_THREAD_COULD_NOT_JOIN		= 1,
+	IFS_INTERRUPTED_BEFORE_RENDEZVOUS	= 2,
+	IFS_POWER_MGMT_INADEQUATE_FOR_SCAN	= 3,
+	IFS_INVALID_CHUNK_RANGE			= 4,
+	IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS	= 5,
+	IFS_CORE_NOT_CAPABLE_CURRENTLY		= 6,
+	IFS_UNASSIGNED_ERROR_CODE		= 7,
+	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT	= 8,
+	IFS_INTERRUPTED_DURING_EXECUTION	= 9,
+};
+
+static const char * const scan_test_status[] = {
+	[IFS_NO_ERROR] = "SCAN no error",
+	[IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.",
+	[IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.",
+	[IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] =
+	"Core Abort SCAN Response due to power management condition.",
+	[IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range",
+	[IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.",
+	[IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently",
+	[IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7",
+	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
+	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
+	[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start",
+};
+
+static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
+{
+	if (status.error_code < ARRAY_SIZE(scan_test_status))
+		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 scan_test_status[status.error_code]);
+	else if (status.error_code == IFS_SW_TIMEOUT)
+		dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	else if (status.error_code == IFS_SW_PARTIAL_COMPLETION)
+		dev_info(dev, "CPU(s) %*pbl: %s\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
+			 "Not all scan chunks were executed. Maximum forward progress retries exceeded");
+	else
+		dev_info(dev, "CPU(s) %*pbl: SCAN unknown status %llx\n",
+			 cpumask_pr_args(topology_sibling_cpumask(cpu)), status.data);
+}
+
+static void message_fail(struct device *dev, int cpu, union ifs_status status)
+{
+	/*
+	 * control_error is set when the microcode runs into a problem
+	 * loading the image from the reserved BIOS memory, or it has
+	 * been corrupted. Reloading the image may fix this issue.
+	 */
+	if (status.control_error) {
+		dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+
+	/*
+	 * signature_error is set when the output from the scan chains does not
+	 * match the expected signature. This might be a transient problem (e.g.
+	 * due to a bit flip from an alpha particle or neutron). If the problem
+	 * repeats on a subsequent test, then it indicates an actual problem in
+	 * the core being tested.
+	 */
+	if (status.signature_error) {
+		dev_err(dev, "CPU(s) %*pbl: test signature incorrect.\n",
+			cpumask_pr_args(topology_sibling_cpumask(cpu)));
+	}
+}
+
+static bool can_restart(union ifs_status status)
+{
+	enum ifs_status_err_code err_code = status.error_code;
+
+	/* Signature for chunk is bad, or scan test failed */
+	if (status.signature_error || status.control_error)
+		return false;
+
+	switch (err_code) {
+	case IFS_NO_ERROR:
+	case IFS_OTHER_THREAD_COULD_NOT_JOIN:
+	case IFS_INTERRUPTED_BEFORE_RENDEZVOUS:
+	case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN:
+	case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT:
+	case IFS_INTERRUPTED_DURING_EXECUTION:
+		return true;
+	case IFS_INVALID_CHUNK_RANGE:
+	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
+	case IFS_CORE_NOT_CAPABLE_CURRENTLY:
+	case IFS_UNASSIGNED_ERROR_CODE:
+		break;
+	}
+	return false;
+}
+
+/*
+ * Execute the scan. Called "simultaneously" on all threads of a core
+ * at high priority using the stop_cpus mechanism.
+ */
+static int doscan(void *data)
+{
+	int cpu = smp_processor_id();
+	u64 *msrs = data;
+	int first;
+
+	/* Only the first logical CPU on a core reports result */
+	first = cpumask_first(topology_sibling_cpumask(cpu));
+
+	/*
+	 * This WRMSR will wait for other HT threads to also write
+	 * to this MSR (at most for activate.delay cycles). Then it
+	 * starts scan of each requested chunk. The core scan happens
+	 * during the "execution" of the WRMSR. This instruction can
+	 * take up to 200 milliseconds before it retires.
+	 */
+	wrmsrl(MSR_ACTIVATE_SCAN, msrs[0]);
+
+	if (cpu == first) {
+		/* Pass back the result of the scan */
+		rdmsrl(MSR_SCAN_STATUS, msrs[1]);
+	}
+
+	return 0;
+}
+
+/*
+ * Use stop_core_cpuslocked() to synchronize writing to MSR_ACTIVATE_SCAN
+ * on all threads of the core to be tested. Loop if necessary to complete
+ * run of all chunks. Include some defensive tests to make sure forward
+ * progress is made, and that the whole test completes in a reasonable time.
+ */
+static void ifs_test_core(int cpu, struct device *dev)
+{
+	union ifs_scan activate;
+	union ifs_status status;
+	unsigned long timeout;
+	struct ifs_data *ifsd;
+	u64 msrvals[2];
+	int retries;
+
+	ifsd = ifs_get_data(dev);
+
+	activate.rsvd = 0;
+	activate.delay = IFS_THREAD_WAIT;
+	activate.sigmce = 0;
+	activate.start = 0;
+	activate.stop = ifsd->valid_chunks - 1;
+
+	timeout = jiffies + HZ / 2;
+	retries = MAX_IFS_RETRIES;
+
+	while (activate.start <= activate.stop) {
+		if (time_after(jiffies, timeout)) {
+			status.error_code = IFS_SW_TIMEOUT;
+			break;
+		}
+
+		msrvals[0] = activate.data;
+		stop_core_cpuslocked(cpu, doscan, msrvals);
+
+		status.data = msrvals[1];
+
+		/* Some cases can be retried, give up for others */
+		if (!can_restart(status))
+			break;
+
+		if (status.chunk_num == activate.start) {
+			/* Check for forward progress */
+			if (retries-- == 0) {
+				if (status.error_code == IFS_NO_ERROR)
+					status.error_code = IFS_SW_PARTIAL_COMPLETION;
+				break;
+			}
+		} else {
+			retries = MAX_IFS_RETRIES;
+			activate.start = status.chunk_num;
+		}
+	}
+
+	/* Update status for this core */
+	ifsd->scan_details = status.data;
+
+	if (status.control_error || status.signature_error) {
+		ifsd->status = SCAN_TEST_FAIL;
+		message_fail(dev, cpu, status);
+	} else if (status.error_code) {
+		ifsd->status = SCAN_NOT_TESTED;
+		message_not_tested(dev, cpu, status);
+	} else {
+		ifsd->status = SCAN_TEST_PASS;
+	}
+}
+
+/*
+ * Initiate per core test. It wakes up work queue threads on the target cpu and
+ * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
+ * wait for all sibling threads to finish the scan test.
+ */
+int do_core_test(int cpu, struct device *dev)
+{
+	int ret = 0;
+
+	if (!scan_enabled)
+		return -ENXIO;
+
+	/* Prevent CPUs from being taken offline during the scan test */
+	cpus_read_lock();
+
+	if (!cpu_online(cpu)) {
+		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ifs_test_core(cpu, dev);
+out:
+	cpus_read_unlock();
+	return ret;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 09/11] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (7 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
                           ` (2 subsequent siblings)
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Implement sysfs interface to trigger ifs test for a specific cpu.
Additional interfaces related to checking the status of the
scan test and seeing the version of the loaded IFS binary
are also added.

The basic usage is as below.
   - To start test, for example on cpu5:
       echo 5 > /sys/devices/platform/intel_ifs/run_test
   - To see the status of the last test
       cat /sys/devices/platform/intel_ifs/status
   - To see the version of the loaded scan binary
       cat /sys/devices/platform/intel_ifs/image_version

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/Makefile |   2 +-
 drivers/platform/x86/intel/ifs/core.c   |   5 +
 drivers/platform/x86/intel/ifs/ifs.h    |   3 +
 drivers/platform/x86/intel/ifs/sysfs.c  | 149 ++++++++++++++++++++++++
 4 files changed, 158 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 cedcb103f860..30f035ef5581 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o runtest.o
+intel_ifs-objs			:= core.o load.o runtest.o sysfs.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index f62578dae8e9..27204e3d674d 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -3,6 +3,7 @@
 
 #include <linux/module.h>
 #include <linux/kdev_t.h>
+#include <linux/semaphore.h>
 
 #include <asm/cpu_device_id.h>
 
@@ -47,9 +48,13 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
+	ifs_device.misc.groups = ifs_get_groups();
+
 	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
 	    !misc_register(&ifs_device.misc)) {
+		down(&ifs_sem);
 		ifs_load_firmware(ifs_device.misc.this_device);
+		up(&ifs_sem);
 		return 0;
 	}
 
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 7435a5582df3..6606214773bc 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -117,5 +117,8 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
 
 void ifs_load_firmware(struct device *dev);
 int do_core_test(int cpu, struct device *dev);
+const struct attribute_group **ifs_get_groups(void);
+
+extern struct semaphore ifs_sem;
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
new file mode 100644
index 000000000000..37d8380d6fa8
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Protects against simultaneous tests on multiple cores, or
+ * reloading can file while a test is in progress
+ */
+DEFINE_SEMAPHORE(ifs_sem);
+
+/*
+ * The sysfs interface to check additional details of last test
+ * cat /sys/devices/system/platform/ifs/details
+ */
+static ssize_t details_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
+}
+
+static DEVICE_ATTR_RO(details);
+
+static const char * const status_msg[] = {
+	[SCAN_NOT_TESTED] = "untested",
+	[SCAN_TEST_PASS] = "pass",
+	[SCAN_TEST_FAIL] = "fail"
+};
+
+/*
+ * The sysfs interface to check the test status:
+ * To check the status of last test
+ * cat /sys/devices/platform/ifs/status
+ */
+static ssize_t status_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
+}
+
+static DEVICE_ATTR_RO(status);
+
+/*
+ * The sysfs interface for single core testing
+ * To start test, for example, cpu5
+ * echo 5 > /sys/devices/platform/ifs/run_test
+ * To check the result:
+ * cat /sys/devices/platform/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)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	unsigned int cpu;
+	int rc;
+
+	rc = kstrtouint(buf, 0, &cpu);
+	if (rc < 0 || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	if (!ifsd->loaded)
+		rc = -EPERM;
+	else
+		rc = do_core_test(cpu, dev);
+
+	up(&ifs_sem);
+
+	return rc ? rc : count;
+}
+
+static DEVICE_ATTR_WO(run_test);
+
+/*
+ * Reload the IFS image. When user wants to install new IFS image
+ */
+static ssize_t reload_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	bool res;
+
+
+	if (kstrtobool(buf, &res))
+		return -EINVAL;
+	if (!res)
+		return count;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	ifs_load_firmware(dev);
+
+	up(&ifs_sem);
+
+	return ifsd->loaded ? count : -ENODEV;
+}
+
+static DEVICE_ATTR_WO(reload);
+
+/*
+ * Display currently loaded IFS image version.
+ */
+static ssize_t image_version_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	if (!ifsd->loaded)
+		return sysfs_emit(buf, "%s\n", "none");
+	else
+		return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
+}
+
+static DEVICE_ATTR_RO(image_version);
+
+/* global scan sysfs attributes */
+static struct attribute *plat_ifs_attrs[] = {
+	&dev_attr_details.attr,
+	&dev_attr_status.attr,
+	&dev_attr_run_test.attr,
+	&dev_attr_reload.attr,
+	&dev_attr_image_version.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(plat_ifs);
+
+const struct attribute_group **ifs_get_groups(void)
+{
+	return plat_ifs_groups;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (8 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06  1:40         ` [PATCH v6 11/11] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Add tracing support which may be useful for debugging systems that fail to complete
In Field Scan tests.

Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 MAINTAINERS                              |  1 +
 drivers/platform/x86/intel/ifs/runtest.c |  5 +++
 include/trace/events/intel_ifs.h         | 41 ++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 include/trace/events/intel_ifs.h

diff --git a/MAINTAINERS b/MAINTAINERS
index bb0c4ff25942..6864fa039974 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9868,6 +9868,7 @@ R:	Ashok Raj <ashok.raj@intel.com>
 R:	Tony Luck <tony.luck@intel.com>
 S:	Maintained
 F:	drivers/platform/x86/intel/ifs
+F:	include/trace/events/intel_ifs.h
 
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index fd3f5f3f31e5..cd25817ceda0 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -19,6 +19,9 @@
 struct workqueue_struct *ifs_wq;
 static bool scan_enabled = true;
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ifs.h>
+
 /* Max retries on the same chunk */
 #define MAX_IFS_RETRIES  5
 
@@ -191,6 +194,8 @@ static void ifs_test_core(int cpu, struct device *dev)
 
 		status.data = msrvals[1];
 
+		trace_ifs_status(cpu, activate, status);
+
 		/* Some cases can be retried, give up for others */
 		if (!can_restart(status))
 			break;
diff --git a/include/trace/events/intel_ifs.h b/include/trace/events/intel_ifs.h
new file mode 100644
index 000000000000..d7353024016c
--- /dev/null
+++ b/include/trace/events/intel_ifs.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ifs
+
+#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IFS_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ifs_status,
+
+	TP_PROTO(int cpu, union ifs_scan activate, union ifs_status status),
+
+	TP_ARGS(cpu, activate, status),
+
+	TP_STRUCT__entry(
+		__field(	u64,	status	)
+		__field(	int,	cpu	)
+		__field(	u8,	start	)
+		__field(	u8,	stop	)
+	),
+
+	TP_fast_assign(
+		__entry->cpu	= cpu;
+		__entry->start	= activate.start;
+		__entry->stop	= activate.stop;
+		__entry->status	= status.data;
+	),
+
+	TP_printk("cpu: %d, start: %.2x, stop: %.2x, status: %llx",
+		__entry->cpu,
+		__entry->start,
+		__entry->stop,
+		__entry->status)
+);
+
+#endif /* _TRACE_IFS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v6 11/11] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (9 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-05-06  1:40         ` Tony Luck
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
  11 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06  1:40 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Add the sysfs attributes in ABI/testing for In-Field Scan.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 .../ABI/testing/sysfs-platform-intel-ifs      | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
new file mode 100644
index 000000000000..486d6d2ff8a0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -0,0 +1,39 @@
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/run_test
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write <cpu#> to trigger IFS test for one online core.
+		Note that the test is per core. The cpu# can be
+		for any thread on the core. Running on one thread
+		completes the test for the core containing that thread.
+		Example: to test the core containing cpu5: echo 5 >
+		/sys/devices/platform/intel_ifs.<N>/run_test
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/status
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	The status of the last test. It can be one of "pass", "fail"
+		or "untested".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/details
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Additional information regarding the last test. 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.
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/image_version
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Version (hexadecimal) of loaded IFS binary image. If no scan image
+		is loaded reports "none".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/reload
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write "1" (or "y" or "Y") to reload the IFS image from
+		/lib/firmware/intel/ifs/ff-mm-ss.scan.
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v6 02/11] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  2022-05-06  1:40         ` [PATCH v6 02/11] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
@ 2022-05-06  8:19           ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-06  8:19 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, May 05 2022 at 18:40, Tony Luck wrote:

> The INTEGRITY_CAPABILITIES MSR is enumerated by bit 2 of the
> CORE_CAPABILITIES MSR.
>
> Add defines for the CORE_CAPS enumeration as well as for the integrity
> MSR.
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v6 03/11] stop_machine: Add stop_core_cpuslocked() for per-core operations
  2022-05-06  1:40         ` [PATCH v6 03/11] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
@ 2022-05-06  8:20           ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-06  8:20 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar, Peter Zijlstra

On Thu, May 05 2022 at 18:40, Tony Luck wrote:
> From: Peter Zijlstra <peterz@infradead.org>
>
> Hardware core level testing features require near simultaneous execution
> of WRMSR instructions on all threads of a core to initiate a test.
>
> Provide a customized cut down version of stop_machine_cpuslocked() that
> just operates on the threads of a single core.
>
> Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Tony Luck <tony.luck@intel.com>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v6 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-05-06  1:40         ` [PATCH v6 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-05-06  8:23           ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-06  8:23 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, May 05 2022 at 18:40, Tony Luck wrote:
> +#include <asm/cpu_device_id.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 = {
> +	X86_MATCH(SAPPHIRERAPIDS_X),

I still hate this with a passion. Nevertheless:

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support
  2022-05-06  1:40         ` [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-05-06 13:30           ` Thomas Gleixner
  2022-05-06 18:49             ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-06 13:30 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Thu, May 05 2022 at 18:40, Tony Luck wrote:
> +/*
> + * Note all code and data in this file is protected by
> + * ifs_sem. On HT systems all threads on a core will
> + * execute together, but only the first thread on the
> + * core will update results of the test.
> + */
> +struct workqueue_struct *ifs_wq;

Seems to be unused.

> +static bool oscan_enabled = true;

What changes this?

> +static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
> +{
> +	if (status.error_code < ARRAY_SIZE(scan_test_status))

Please add curly brackets as these are not one-line statements.

> +		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
> +			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
> +			 scan_test_status[status.error_code]);
> +/*
> + * Execute the scan. Called "simultaneously" on all threads of a core
> + * at high priority using the stop_cpus mechanism.
> + */
> +static int doscan(void *data)
> +{
> +	int cpu = smp_processor_id();
> +	u64 *msrs = data;
> +	int first;
> +
> +	/* Only the first logical CPU on a core reports result */
> +	first = cpumask_first(topology_sibling_cpumask(cpu));

Shouldn't that be cpu_smt_mask()?

> +	/*
> +	 * This WRMSR will wait for other HT threads to also write
> +	 * to this MSR (at most for activate.delay cycles). Then it
> +	 * starts scan of each requested chunk. The core scan happens
> +	 * during the "execution" of the WRMSR. This instruction can
> +	 * take up to 200 milliseconds before it retires.

200ms per test chunk?

> +	 */
> +	wrmsrl(MSR_ACTIVATE_SCAN, msrs[0]);
> +

> +	while (activate.start <= activate.stop) {
> +		if (time_after(jiffies, timeout)) {
> +			status.error_code = IFS_SW_TIMEOUT;
> +			break;
> +		}
> +
> +		msrvals[0] = activate.data;
> +		stop_core_cpuslocked(cpu, doscan, msrvals);
> +
> +		status.data = msrvals[1];
> +
> +		/* Some cases can be retried, give up for others */
> +		if (!can_restart(status))
> +			break;
> +
> +		if (status.chunk_num == activate.start) {
> +			/* Check for forward progress */
> +			if (retries-- == 0) {
> +				if (status.error_code == IFS_NO_ERROR)
> +					status.error_code = IFS_SW_PARTIAL_COMPLETION;
> +				break;
> +			}
> +		} else {
> +			retries = MAX_IFS_RETRIES;
> +			activate.start = status.chunk_num;
> +		}
> +	}

Looks way better now.

> +}
> +/*
> + * Initiate per core test. It wakes up work queue threads on the target cpu and
> + * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
> + * wait for all sibling threads to finish the scan test.
> + */
> +int do_core_test(int cpu, struct device *dev)
> +{
> +	int ret = 0;
> +
> +	if (!scan_enabled)
> +		return -ENXIO;
> +
> +	/* Prevent CPUs from being taken offline during the scan test */
> +	cpus_read_lock();
> +
> +	if (!cpu_online(cpu)) {
> +		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
> +		ret = -EINVAL;
> +		goto out;
> +	}

Coming back to my points from the previous round:

1) How is that supposed to work on a system which has HT enabled in BIOS,
   but disabled on the kernel command line or via /sys/..../smt/control or
   when a HT sibling is offlined temporarily?

   I assume it cannot work, but I can't see anything which handles those
   cases.

2) That documentation for the admin/user got eaten by the gremlins in
   the intertubes again.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-03 15:32         ` Borislav Petkov
  2022-05-03 16:04           ` Luck, Tony
@ 2022-05-06 14:19           ` Hans de Goede
  2022-05-06 15:53             ` Luck, Tony
  1 sibling, 1 reply; 152+ messages in thread
From: Hans de Goede @ 2022-05-06 14:19 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Tony Luck, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Hi,

On 5/3/22 17:32, Borislav Petkov wrote:
> On Mon, May 02, 2022 at 05:15:39PM +0200, Hans de Goede wrote:
>> I'm fine with this entire series getting merged through the TIP
>> tree,
> 
> Hmm, so looking at the diffstat - the majority of that is
> drivers/platform/x86/ so I guess your tree would be better suited for
> it...

Ok, that also works for me and I see that the few arch/x86 already have
Ack-s / Reviewed-by-s from you / tglx .

I'll give it some more time for review for v6 and then pick up v6
(or v7 if review leads to more changes).

Regards,

Hans


^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-06 14:19           ` Hans de Goede
@ 2022-05-06 15:53             ` Luck, Tony
  2022-05-06 18:41               ` Hans de Goede
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-06 15:53 UTC (permalink / raw)
  To: Hans de Goede, Borislav Petkov
  Cc: markgross, tglx, mingo, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

> I'll give it some more time for review for v6 and then pick up v6
> (or v7 if review leads to more changes).

Hans,

Thomas has found one substantive problem, and a few minor things (so far ... he
still seems to be working through v6). 

So there will be a v7. Likely early next week. Is that OK? Do you still take patches after -rc6?

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-06 15:53             ` Luck, Tony
@ 2022-05-06 18:41               ` Hans de Goede
  2022-05-09 17:05                 ` Luck, Tony
  0 siblings, 1 reply; 152+ messages in thread
From: Hans de Goede @ 2022-05-06 18:41 UTC (permalink / raw)
  To: Luck, Tony, Borislav Petkov
  Cc: markgross, tglx, mingo, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

Hi,

On 5/6/22 17:53, Luck, Tony wrote:
>> I'll give it some more time for review for v6 and then pick up v6
>> (or v7 if review leads to more changes).
> 
> Hans,
> 
> Thomas has found one substantive problem, and a few minor things (so far ... he
> still seems to be working through v6). 

Ok.

> So there will be a v7. Likely early next week. Is that OK?

That is fine.

> Do you still take patches after -rc6?

If the patches are send soon (1-2 days) after rc6 I can still take them.

Regards,

Hans


^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support
  2022-05-06 13:30           ` Thomas Gleixner
@ 2022-05-06 18:49             ` Luck, Tony
  2022-05-06 19:06               ` Thomas Gleixner
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-06 18:49 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: hdegoede, markgross, mingo, bp, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06, 2022 at 03:30:30PM +0200, Thomas Gleixner wrote:
> On Thu, May 05 2022 at 18:40, Tony Luck wrote:
> > +/*
> > + * Note all code and data in this file is protected by
> > + * ifs_sem. On HT systems all threads on a core will
> > + * execute together, but only the first thread on the
> > + * core will update results of the test.
> > + */
> > +struct workqueue_struct *ifs_wq;
> 
> Seems to be unused.

Missed deleting the definition after dropping all the users.
Deleted now.

> > +static bool oscan_enabled = true;
> 
> What changes this?

Code that changed this has been deleted (was to deal with a "can't
happen" case where the kernel threads didn't set completion).

Variable (and the remaing place that checked it) now deleted.

> > +static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
> > +{
> > +	if (status.error_code < ARRAY_SIZE(scan_test_status))
> 
> Please add curly brackets as these are not one-line statements.

Done.

> > +		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
> > +			 cpumask_pr_args(topology_sibling_cpumask(cpu)),
> > +			 scan_test_status[status.error_code]);
> > +/*
> > + * Execute the scan. Called "simultaneously" on all threads of a core
> > + * at high priority using the stop_cpus mechanism.
> > + */
> > +static int doscan(void *data)
> > +{
> > +	int cpu = smp_processor_id();
> > +	u64 *msrs = data;
> > +	int first;
> > +
> > +	/* Only the first logical CPU on a core reports result */
> > +	first = cpumask_first(topology_sibling_cpumask(cpu));
> 
> Shouldn't that be cpu_smt_mask()?

I guess so. It seems part of a maze of CONFIG options and #defines.
The code worked because (except on power) cpu_smt_mask() is just
an inline funtion that calls topology_sibling_cpumask().

I've changed this (and the other places that use
topology_sibling_cpumask() to cpu_smt_mask(). Will probably save
me from a randconfig build error some time in the future.

> > +	/*
> > +	 * This WRMSR will wait for other HT threads to also write
> > +	 * to this MSR (at most for activate.delay cycles). Then it
> > +	 * starts scan of each requested chunk. The core scan happens
> > +	 * during the "execution" of the WRMSR. This instruction can
> > +	 * take up to 200 milliseconds before it retires.
> 
> 200ms per test chunk?

Updated comment to say that 200 ms is the time for all chunks.

Note that the loop that calls here tries to do all (remaining)
chunks on each iteration. Doing them 1 at a time would reduce
the time each spends in stomp_machine(), but not as much as you'd
like. Each WRMSR(ACTIVATE_SCAN)) has to save/restore the whole
state of the core (similar to a C6 entry+exit). 

> > +	 */
> > +	wrmsrl(MSR_ACTIVATE_SCAN, msrs[0]);
> > +
> 
> > +	while (activate.start <= activate.stop) {
> > +		if (time_after(jiffies, timeout)) {
> > +			status.error_code = IFS_SW_TIMEOUT;
> > +			break;
> > +		}
> > +
> > +		msrvals[0] = activate.data;
> > +		stop_core_cpuslocked(cpu, doscan, msrvals);
> > +
> > +		status.data = msrvals[1];
> > +
> > +		/* Some cases can be retried, give up for others */
> > +		if (!can_restart(status))
> > +			break;
> > +
> > +		if (status.chunk_num == activate.start) {
> > +			/* Check for forward progress */
> > +			if (retries-- == 0) {
> > +				if (status.error_code == IFS_NO_ERROR)
> > +					status.error_code = IFS_SW_PARTIAL_COMPLETION;
> > +				break;
> > +			}
> > +		} else {
> > +			retries = MAX_IFS_RETRIES;
> > +			activate.start = status.chunk_num;
> > +		}
> > +	}
> 
> Looks way better now.

Thanks to you!

> > +}
> > +/*
> > + * Initiate per core test. It wakes up work queue threads on the target cpu and
> > + * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
> > + * wait for all sibling threads to finish the scan test.
> > + */
> > +int do_core_test(int cpu, struct device *dev)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!scan_enabled)
> > +		return -ENXIO;
> > +
> > +	/* Prevent CPUs from being taken offline during the scan test */
> > +	cpus_read_lock();
> > +
> > +	if (!cpu_online(cpu)) {
> > +		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> 
> Coming back to my points from the previous round:
> 
> 1) How is that supposed to work on a system which has HT enabled in BIOS,
>    but disabled on the kernel command line or via /sys/..../smt/control or
>    when a HT sibling is offlined temporarily?
> 
>    I assume it cannot work, but I can't see anything which handles those
>    cases.

Correct. If HT is disabled in BIOS, then there is no other thread, so
core tests just use a single thread.

If a logical CPU is "offline" due to Linux actions, then core test will
fail. In an earlier version we did attempt to detect this before trying
to run the test. But we didn't find a simple way to determine that a
core has one thread online, and another offline. Rather than a bunch of
code to detect an operator error it seemed better to let it run & fail.

Here is what the user will see:

# echo 45 > run_test
# cat status
untested
# cat details
0x100008000

Console will see this message:
misc intel_ifs_0: CPU(s) 45: SCAN operation did not start. Other thread could not join.

If the user debugs using the trace point I included in the code they will see:

              sh-411499  [067] ..... 61260.698969: ifs_status: cpu: 45, start: 00, stop: 80, status: 100008000
              sh-411499  [067] ..... 61260.699968: ifs_status: cpu: 45, start: 00, stop: 80, status: 100008000
              sh-411499  [067] ..... 61260.700076: ifs_status: cpu: 45, start: 00, stop: 80, status: 100008000
              sh-411499  [067] ..... 61260.700187: ifs_status: cpu: 45, start: 00, stop: 80, status: 100008000
              sh-411499  [067] ..... 61260.700334: ifs_status: cpu: 45, start: 00, stop: 80, status: 100008000
              sh-411499  [067] ..... 61260.700437: ifs_status: cpu: 45, start: 00, stop: 80, status: 100008000

Hmmm ... looks like I have an off-by one error in the retry check.

/* Max retries on the same chunk */
#define MAX_IFS_RETRIES  5

But it tried SIX times before giving up.  Will fix.

> 2) That documentation for the admin/user got eaten by the gremlins in
>    the intertubes again.

GregKH wasn't a fan of this itty bitty driver cluttering up
Documentation/x86. He said:

   I don't know which is better, it's just that creating a whole new
   documentation file for a single tiny driver feels very odd as it will
   get out of date and is totally removed from the driver itself.

   I'd prefer that drivers be self-contained, including the documentation,
   as it is much more obvious what is happening with that.  Spreading stuff
   around the tree only causes stuff to get out of sync easier.

So the documentation patch was dropped after v3. Last version here:

https://lore.kernel.org/r/20220419163859.2228874-3-tony.luck@intel.com

That doc would need pathnames updated to match the move from a platform
device to a virtual misc device. But otherwise seems still accurate.

Does that cover what you want from documentation for this driver
(wherever it gets located in the tree)? Are you looking for more?

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support
  2022-05-06 18:49             ` Luck, Tony
@ 2022-05-06 19:06               ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-06 19:06 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, mingo, bp, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 11:49, Luck, Tony wrote:
> On Fri, May 06, 2022 at 03:30:30PM +0200, Thomas Gleixner wrote:
>> 1) How is that supposed to work on a system which has HT enabled in BIOS,
>>    but disabled on the kernel command line or via /sys/..../smt/control or
>>    when a HT sibling is offlined temporarily?
>> 
>>    I assume it cannot work, but I can't see anything which handles those
>>    cases.
>
> Correct. If HT is disabled in BIOS, then there is no other thread, so
> core tests just use a single thread.
>
> If a logical CPU is "offline" due to Linux actions, then core test will
> fail. In an earlier version we did attempt to detect this before trying
> to run the test. But we didn't find a simple way to determine that a
> core has one thread online, and another offline. Rather than a bunch of
> code to detect an operator error it seemed better to let it run &
> fail.

Fair enough.

> GregKH wasn't a fan of this itty bitty driver cluttering up
> Documentation/x86. He said:
>
>    I don't know which is better, it's just that creating a whole new
>    documentation file for a single tiny driver feels very odd as it will
>    get out of date and is totally removed from the driver itself.
>
>    I'd prefer that drivers be self-contained, including the documentation,
>    as it is much more obvious what is happening with that.  Spreading stuff
>    around the tree only causes stuff to get out of sync easier.

Well, I agree to some extent, but the documentation which I want to see
is documentation for admins. I'm not sure whether we want them to search
the code. Those are consumers of Documentation/ AFAICT.

> So the documentation patch was dropped after v3. Last version here:
>
> https://lore.kernel.org/r/20220419163859.2228874-3-tony.luck@intel.com
>
> That doc would need pathnames updated to match the move from a platform
> device to a virtual misc device. But otherwise seems still accurate.
>
> Does that cover what you want from documentation for this driver
> (wherever it gets located in the tree)? Are you looking for more?

It's pretty detailed on the inner workings, but lacks a big fat warning
for the admin vs. the impact, i.e. that it makes the core go out for
lunch for a while, which has consequences on workloads and interrupts
directed at that core. Plus some explanation vs. the HT (SMT=off, soft
offline) case above. Similar to what we have e.g. for buslocks.

Thanks,

        tglx


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v7 00/12] Introduce In Field Scan driver
  2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
                           ` (10 preceding siblings ...)
  2022-05-06  1:40         ` [PATCH v6 11/11] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
@ 2022-05-06 22:53         ` Tony Luck
  2022-05-06 22:53           ` [PATCH v7 01/12] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
                             ` (12 more replies)
  11 siblings, 13 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:53 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

TL;DR this driver loads scan test files that can check whether silicon
in a CPU core is still running correctly. It is expected that these tests
would be run several times per day to catch problems as silicon ages.

Changes since v6

Thomas Gleixner
---------------
"struct workqueue_struct *ifs_wq; Seems to be unused."

True. Deleted.

"static bool oscan_enabled = true; What changes this?"

Code that cleared it deleted. Drop this too.

"Please add curly brackets as these are not one-line statements"

Added

cpumask_first(topology_sibling_cpumask(cpu)); Shouldn't that be cpu_smt_mask()?"

Changed (and several other places)

"take up to 200 milliseconds before it retires.  200ms per test chunk?"

Updated comment to note that 200ms is for all chunks.

"Documentation lost in the intertubes"

Dredged up the version from v3 series and changed:
1) Fixed pathnames now this is a virtual misc device instead of platform
device
2) Put all the text into a "/** DOC:" comment section in ifs.h with just
a "kernel-doc:: drivers/platform/x86/intel/ifs/ifs.h" in the ifs.rst
file under Documentation/x86.
3) Added a "big fat warning" (in all CAPS) pointing out that a core test
can take up to 200 milliseconds. So admins must take extra steps if they
are running latency sensitive workloads.
4) Added note that all HT threads of a core must be online to run a
test.

Tony Luck
---------
Off-by-one on retries check (#define set to 5, but tried 6 times). Fixed
Fixed kerneldoc description of "integrity_cap_bit" (was missing a ":")

Jithu Joseph (7):
  x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  platform/x86/intel/ifs: Read IFS firmware image
  platform/x86/intel/ifs: Check IFS Image sanity
  platform/x86/intel/ifs: Authenticate and copy to secured memory
  platform/x86/intel/ifs: Add scan test support
  platform/x86/intel/ifs: Add IFS sysfs interface
  platform/x86/intel/ifs: add ABI documentation for IFS

Peter Zijlstra (1):
  stop_machine: Add stop_core_cpuslocked() for per-core operations

Tony Luck (4):
  x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  platform/x86/intel/ifs: Add stub driver for In-Field Scan
  trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
    operations
  Documentation: In-Field Scan

 .../ABI/testing/sysfs-platform-intel-ifs      |  39 +++
 Documentation/x86/ifs.rst                     |   2 +
 Documentation/x86/index.rst                   |   1 +
 MAINTAINERS                                   |   8 +
 arch/x86/include/asm/cpu.h                    |  18 ++
 arch/x86/include/asm/msr-index.h              |   7 +
 arch/x86/kernel/cpu/intel.c                   |  32 +++
 arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
 drivers/platform/x86/intel/Kconfig            |   1 +
 drivers/platform/x86/intel/Makefile           |   1 +
 drivers/platform/x86/intel/ifs/Kconfig        |  13 +
 drivers/platform/x86/intel/ifs/Makefile       |   3 +
 drivers/platform/x86/intel/ifs/core.c         |  73 +++++
 drivers/platform/x86/intel/ifs/ifs.h          | 234 +++++++++++++++
 drivers/platform/x86/intel/ifs/load.c         | 266 ++++++++++++++++++
 drivers/platform/x86/intel/ifs/runtest.c      | 252 +++++++++++++++++
 drivers/platform/x86/intel/ifs/sysfs.c        | 149 ++++++++++
 include/linux/stop_machine.h                  |  16 ++
 include/trace/events/intel_ifs.h              |  41 +++
 kernel/stop_machine.c                         |  19 ++
 20 files changed, 1182 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
 create mode 100644 Documentation/x86/ifs.rst
 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
 create mode 100644 drivers/platform/x86/intel/ifs/load.c
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
 create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
 create mode 100644 include/trace/events/intel_ifs.h


base-commit: 672c0c5173427e6b3e2a9bbb7be51ceeec78093a
-- 
2.35.1


^ permalink raw reply	[flat|nested] 152+ messages in thread

* [PATCH v7 01/12] x86/microcode/intel: Expose collect_cpu_info_early() for IFS
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
@ 2022-05-06 22:53           ` Tony Luck
  2022-05-06 22:54           ` [PATCH v7 02/12] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
                             ` (11 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:53 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar, Borislav Petkov

From: Jithu Joseph <jithu.joseph@intel.com>

IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs.

In support of an IFS driver to trigger loading, validation, and running
of these tests blobs, make the functionality of cpu_signatures_match()
and collect_cpu_info_early() available outside of the microcode driver.

Add an "intel_" prefix and drop the "_early" suffix from
collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
declaration to x86 <asm/cpu.h>

Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
and also give it an "intel_" prefix.

No functional change intended.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Borislav Petkov <bp@suse.de>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/x86/include/asm/cpu.h            | 18 ++++++++
 arch/x86/kernel/cpu/intel.c           | 32 +++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c | 59 ++++-----------------------
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 86e5e4e26fcb..990167357c34 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -76,4 +76,22 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
 
 extern __noendbr void cet_disable(void);
 
+struct ucode_cpu_info;
+
+int intel_cpu_collect_info(struct ucode_cpu_info *uci);
+
+static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+					      unsigned int s2, unsigned int p2)
+{
+	if (s1 != s2)
+		return false;
+
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
+
+	/* ... or they intersect. */
+	return p1 & p2;
+}
+
 #endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f7a5370a9b3b..94779146275d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,6 +181,38 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 	return false;
 }
 
+int intel_cpu_collect_info(struct ucode_cpu_info *uci)
+{
+	unsigned int val[2];
+	unsigned int family, model;
+	struct cpu_signature csig = { 0 };
+	unsigned int eax, ebx, ecx, edx;
+
+	memset(uci, 0, sizeof(*uci));
+
+	eax = 0x00000001;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	csig.sig = eax;
+
+	family = x86_family(eax);
+	model  = x86_model(eax);
+
+	if (model >= 5 || family > 6) {
+		/* get processor flags from MSR 0x17 */
+		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		csig.pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	csig.rev = intel_get_microcode_revision();
+
+	uci->cpu_sig = csig;
+	uci->valid = 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index d28a9f8f3fec..025c8f0cd948 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */
@@ -69,7 +55,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	struct extended_signature *ext_sig;
 	int i;
 
-	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
 		return 1;
 
 	/* Look for ext. headers: */
@@ -80,7 +66,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
 
 	for (i = 0; i < ext_hdr->count; i++) {
-		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
 			return 1;
 		ext_sig++;
 	}
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 	return patch;
 }
 
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-	unsigned int val[2];
-	unsigned int family, model;
-	struct cpu_signature csig = { 0 };
-	unsigned int eax, ebx, ecx, edx;
-
-	memset(uci, 0, sizeof(*uci));
-
-	eax = 0x00000001;
-	ecx = 0;
-	native_cpuid(&eax, &ebx, &ecx, &edx);
-	csig.sig = eax;
-
-	family = x86_family(eax);
-	model  = x86_model(eax);
-
-	if ((model >= 5) || (family > 6)) {
-		/* get processor flags from MSR 0x17 */
-		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		csig.pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	csig.rev = intel_get_microcode_revision();
-
-	uci->cpu_sig = csig;
-	uci->valid = 1;
-
-	return 0;
-}
-
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
 		return;
 	}
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	sig	= uci.cpu_sig.sig;
 	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
 	struct ucode_cpu_info uci;
 
 	if (delay_ucode_info) {
-		collect_cpu_info_early(&uci);
+		intel_cpu_collect_info(&uci);
 		print_ucode_info(&uci, current_mc_date);
 		delay_ucode_info = 0;
 	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
 	if (!(cp.data && cp.size))
 		return 0;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	scan_microcode(cp.data, cp.size, &uci, true);
 
@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 	if (!(cp.data && cp.size))
 		return NULL;
 
-	collect_cpu_info_early(uci);
+	intel_cpu_collect_info(uci);
 
 	return scan_microcode(cp.data, cp.size, uci, false);
 }
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
 	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
 
-	collect_cpu_info_early(&uci);
+	intel_cpu_collect_info(&uci);
 
 	p = find_patch(&uci);
 	if (!p)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 02/12] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
  2022-05-06 22:53           ` [PATCH v7 01/12] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-06 22:54           ` [PATCH v7 03/12] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
                             ` (10 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

The INTEGRITY_CAPABILITIES MSR is enumerated by bit 2 of the
CORE_CAPABILITIES MSR.

Add defines for the CORE_CAPS enumeration as well as for the integrity
MSR.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/msr-index.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index ee15311b6be1..c3dc7ae32f1f 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -76,6 +76,8 @@
 
 /* Abbreviated from Intel SDM name IA32_CORE_CAPABILITIES */
 #define MSR_IA32_CORE_CAPS			  0x000000cf
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT	  2
+#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS	  BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT)
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT  5
 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT	  BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
 
@@ -154,6 +156,11 @@
 #define MSR_IA32_POWER_CTL		0x000001fc
 #define MSR_IA32_POWER_CTL_BIT_EE	19
 
+/* Abbreviated from Intel SDM name IA32_INTEGRITY_CAPABILITIES */
+#define MSR_INTEGRITY_CAPS			0x000002d9
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT	4
+#define MSR_INTEGRITY_CAPS_PERIODIC_BIST	BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
+
 #define MSR_LBR_NHM_FROM		0x00000680
 #define MSR_LBR_NHM_TO			0x000006c0
 #define MSR_LBR_CORE_FROM		0x00000040
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 03/12] stop_machine: Add stop_core_cpuslocked() for per-core operations
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
  2022-05-06 22:53           ` [PATCH v7 01/12] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
  2022-05-06 22:54           ` [PATCH v7 02/12] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-06 22:54           ` [PATCH v7 04/12] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
                             ` (9 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar, Peter Zijlstra

From: Peter Zijlstra <peterz@infradead.org>

Hardware core level testing features require near simultaneous execution
of WRMSR instructions on all threads of a core to initiate a test.

Provide a customized cut down version of stop_machine_cpuslocked() that
just operates on the threads of a single core.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/stop_machine.h | 16 ++++++++++++++++
 kernel/stop_machine.c        | 19 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 46fb3ebdd16e..ea7a74ea7389 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -124,6 +124,22 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
  */
 int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
 
+/**
+ * stop_core_cpuslocked: - stop all threads on just one core
+ * @cpu: any cpu in the targeted core
+ * @fn: the function to run
+ * @data: the data ptr for @fn()
+ *
+ * Same as above, but instead of every CPU, only the logical CPUs of a
+ * single core are affected.
+ *
+ * Context: Must be called from within a cpus_read_lock() protected region.
+ *
+ * Return: 0 if all executions of @fn returned 0, any non zero return
+ * value if any returned non zero.
+ */
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data);
+
 int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
 				   const struct cpumask *cpus);
 #else	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index cbc30271ea4d..579761729836 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -633,6 +633,25 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
 }
 EXPORT_SYMBOL_GPL(stop_machine);
 
+int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data)
+{
+	const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+
+	struct multi_stop_data msdata = {
+		.fn = fn,
+		.data = data,
+		.num_threads = cpumask_weight(smt_mask),
+		.active_cpus = smt_mask,
+	};
+
+	lockdep_assert_cpus_held();
+
+	/* Set the initial state and stop all online cpus. */
+	set_state(&msdata, MULTI_STOP_PREPARE);
+	return stop_cpus(smt_mask, multi_cpu_stop, &msdata);
+}
+EXPORT_SYMBOL_GPL(stop_core_cpuslocked);
+
 /**
  * stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
  * @fn: the function to run
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 04/12] platform/x86/intel/ifs: Add stub driver for In-Field Scan
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (2 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 03/12] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-06 22:54           ` [PATCH v7 05/12] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
                             ` (8 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Cloud Service Providers that operate fleets of servers have reported
[1] occasions where they can detect that a CPU has gone bad due to
effects like electromigration, or isolated manufacturing defects.
However, that detection method is A/B testing seemingly random
application failures looking for a pattern. In-Field Scan (IFS) is
a driver for a platform capability to load a crafted 'scan image'
to run targeted low level diagnostics outside of the CPU's architectural
error detection capabilities.

Stub version of driver just does initial part of check for the IFS
feature. MSR_IA32_CORE_CAPS must enumerate the presence of the
MSR_INTEGRITY_CAPS MSR.

[1]: https://www.youtube.com/watch?v=QMF3rqhjYuM

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
---
 MAINTAINERS                             |  7 ++++
 drivers/platform/x86/intel/Kconfig      |  1 +
 drivers/platform/x86/intel/Makefile     |  1 +
 drivers/platform/x86/intel/ifs/Kconfig  | 13 +++++++
 drivers/platform/x86/intel/ifs/Makefile |  3 ++
 drivers/platform/x86/intel/ifs/core.c   | 48 +++++++++++++++++++++++++
 6 files changed, 73 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

diff --git a/MAINTAINERS b/MAINTAINERS
index edc96cdb85e8..bb0c4ff25942 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9862,6 +9862,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
 
+INTEL IN FIELD SCAN (IFS) DEVICE
+M:	Jithu Joseph <jithu.joseph@intel.com>
+R:	Ashok Raj <ashok.raj@intel.com>
+R:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+F:	drivers/platform/x86/intel/ifs
+
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 1f01a8a23c57..794968bda115 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -4,6 +4,7 @@
 #
 
 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/int3472/Kconfig"
 source "drivers/platform/x86/intel/pmc/Kconfig"
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index c61bc3e97121..717933dd0cfd 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_INTEL_ATOMISP2_PDX86)	+= atomisp2/
+obj-$(CONFIG_INTEL_IFS)			+= ifs/
 obj-$(CONFIG_INTEL_SAR_INT1092)		+= int1092/
 obj-$(CONFIG_INTEL_SKL_INT3472)		+= int3472/
 obj-$(CONFIG_INTEL_PMC_CORE)		+= pmc/
diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig
new file mode 100644
index 000000000000..d84491cfb0db
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Kconfig
@@ -0,0 +1,13 @@
+config INTEL_IFS
+	tristate "Intel In Field Scan"
+	depends on X86 && 64BIT && SMP
+	select INTEL_IFS_DEVICE
+	help
+	  Enable support for the In Field Scan capability in select
+	  CPUs. The capability allows for running low level tests via
+	  a scan image distributed by Intel via Github to validate CPU
+	  operation beyond baseline RAS capabilities. To compile this
+	  support 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..af904880e959
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
+
+intel_ifs-objs			:= core.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
new file mode 100644
index 000000000000..e3623ac691b5
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+
+#include <asm/cpu_device_id.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 = {
+	X86_MATCH(SAPPHIRERAPIDS_X),
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
+
+static int __init ifs_init(void)
+{
+	const struct x86_cpu_id *m;
+	u64 msrval;
+
+	m = x86_match_cpu(ifs_cpu_ids);
+	if (!m)
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &msrval))
+		return -ENODEV;
+
+	if (!(msrval & MSR_IA32_CORE_CAPS_INTEGRITY_CAPS))
+		return -ENODEV;
+
+	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
+		return -ENODEV;
+
+	return 0;
+}
+
+static void __exit ifs_exit(void)
+{
+}
+
+module_init(ifs_init);
+module_exit(ifs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel In Field Scan (IFS) device");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 05/12] platform/x86/intel/ifs: Read IFS firmware image
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (3 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 04/12] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-09 12:11             ` Thomas Gleixner
  2022-05-06 22:54           ` [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
                             ` (7 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Driver probe routine allocates structure to communicate status
and parameters between functions in the driver. Also call
load_ifs_binary() to load the scan image file.

There is a separate scan image file for each processor family,
model, stepping combination. This is read from the static path:

  /lib/firmware/intel/ifs/{ff-mm-ss}.scan

Step 1 in loading is to generate the correct path and use
request_firmware_direct() to load into memory.

Subsequent patches will use the IFS MSR interfaces to copy
the image to BIOS reserved memory and validate the SHA256
checksums.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/Makefile |  2 +-
 drivers/platform/x86/intel/ifs/core.c   | 22 ++++++++++++++++++-
 drivers/platform/x86/intel/ifs/ifs.h    | 25 ++++++++++++++++++++++
 drivers/platform/x86/intel/ifs/load.c   | 28 +++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 drivers/platform/x86/intel/ifs/ifs.h
 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 af904880e959..98b6fde15689 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o
+intel_ifs-objs			:= core.o load.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index e3623ac691b5..f62578dae8e9 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -6,6 +6,8 @@
 
 #include <asm/cpu_device_id.h>
 
+#include "ifs.h"
+
 #define X86_MATCH(model)				\
 	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6,	\
 		INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL)
@@ -16,6 +18,17 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
 };
 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 
+static struct ifs_device ifs_device = {
+	.data = {
+		.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
+	},
+	.misc = {
+		.name = "intel_ifs_0",
+		.nodename = "intel_ifs/0",
+		.minor = MISC_DYNAMIC_MINOR,
+	},
+};
+
 static int __init ifs_init(void)
 {
 	const struct x86_cpu_id *m;
@@ -34,11 +47,18 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
-	return 0;
+	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
+	    !misc_register(&ifs_device.misc)) {
+		ifs_load_firmware(ifs_device.misc.this_device);
+		return 0;
+	}
+
+	return -ENODEV;
 }
 
 static void __exit ifs_exit(void)
 {
+	misc_deregister(&ifs_device.misc);
 }
 
 module_init(ifs_init);
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
new file mode 100644
index 000000000000..9d151324ae83
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Intel Corporation. */
+
+#ifndef _IFS_H_
+#define _IFS_H_
+
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+
+/**
+ * struct ifs_data - attributes related to intel IFS driver
+ * @integrity_cap_bit: MSR_INTEGRITY_CAPS bit enumerating this test
+ */
+struct ifs_data {
+	int	integrity_cap_bit;
+};
+
+struct ifs_device {
+	struct ifs_data data;
+	struct miscdevice misc;
+};
+
+void ifs_load_firmware(struct device *dev);
+
+#endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
new file mode 100644
index 000000000000..9fb71d38c819
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/firmware.h>
+
+#include "ifs.h"
+
+/*
+ * Load ifs image. Before loading ifs module, the ifs image must be located
+ * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
+ */
+void ifs_load_firmware(struct device *dev)
+{
+	const struct firmware *fw;
+	char scan_path[32];
+	int ret;
+
+	snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
+		 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
+
+	ret = request_firmware_direct(&fw, scan_path, dev);
+	if (ret) {
+		dev_err(dev, "ifs file %s load failed\n", scan_path);
+		return;
+	}
+
+	release_firmware(fw);
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (4 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 05/12] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-09 12:11             ` Thomas Gleixner
  2022-05-09 16:31             ` Borislav Petkov
  2022-05-06 22:54           ` [PATCH v7 07/12] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
                             ` (6 subsequent siblings)
  12 siblings, 2 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/load.c | 66 +++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index 9fb71d38c819..cfbf62494c89 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -2,9 +2,72 @@
 /* Copyright(c) 2022 Intel Corporation. */
 
 #include <linux/firmware.h>
+#include <asm/cpu.h>
+#include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+static int ifs_sanity_check(struct device *dev,
+			    const struct microcode_header_intel *mc_header)
+{
+	unsigned long total_size, data_size;
+	u32 sum, *mc;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+
+	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
+		dev_err(dev, "bad ifs data file size.\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		dev_err(dev, "invalid/unknown ifs update format.\n");
+		return -EINVAL;
+	}
+
+	mc = (u32 *)mc_header;
+	sum = 0;
+	for (int i = 0; i < total_size / sizeof(u32); i++)
+		sum += mc[i];
+
+	if (sum) {
+		dev_err(dev, "bad ifs data checksum, aborting.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
+					const struct microcode_header_intel *shdr)
+{
+	unsigned int mc_size;
+
+	mc_size = get_totalsize(shdr);
+
+	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
+		dev_err(dev, "ifs sanity check failure\n");
+		return false;
+	}
+
+	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
+		dev_err(dev, "ifs signature, pf not matching\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
+{
+	struct ucode_cpu_info uci;
+
+	intel_cpu_collect_info(&uci);
+
+	return find_ifs_matching_signature(dev, &uci, data);
+}
+
 /*
  * Load ifs image. Before loading ifs module, the ifs image must be located
  * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
@@ -24,5 +87,8 @@ void ifs_load_firmware(struct device *dev)
 		return;
 	}
 
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+		dev_err(dev, "ifs header sanity check failed\n");
+
 	release_firmware(fw);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 07/12] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (5 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-09 12:11             ` Thomas Gleixner
  2022-05-06 22:54           ` [PATCH v7 08/12] platform/x86/intel/ifs: Add scan test support Tony Luck
                             ` (5 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

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
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.

Use schedule_work_on() to perform the hash copy and authentication. Note
this needs only be done on the first logical cpu of each socket.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/ifs.h  |  52 ++++++++
 drivers/platform/x86/intel/ifs/load.c | 176 +++++++++++++++++++++++++-
 2 files changed, 226 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 9d151324ae83..bed70dc1e5b7 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -7,12 +7,56 @@
 #include <linux/device.h>
 #include <linux/miscdevice.h>
 
+#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 {
+		u32	chunk_size	:16;
+		u32	num_chunks	:8;
+		u32	rsvd1		:8;
+		u32	error_code	:8;
+		u32	rsvd2		:11;
+		u32	max_core_limit	:12;
+		u32	valid		:1;
+	};
+};
+
+/* MSR_CHUNKS_AUTH_STATUS bit fields */
+union ifs_chunks_auth_status {
+	u64	data;
+	struct {
+		u32	valid_chunks	:8;
+		u32	total_chunks	:8;
+		u32	rsvd1		:16;
+		u32	error_code	:8;
+		u32	rsvd2		:24;
+	};
+};
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit: MSR_INTEGRITY_CAPS bit enumerating this test
+ * @loaded_version: stores the currently loaded ifs image version.
+ * @loaded: If a valid test binary has been loaded into the memory
+ * @loading_error: Error occurred on another CPU while loading image
+ * @valid_chunks: number of chunks which could be validated.
  */
 struct ifs_data {
 	int	integrity_cap_bit;
+	int	loaded_version;
+	bool	loaded;
+	bool	loading_error;
+	int	valid_chunks;
+};
+
+struct ifs_work {
+	struct work_struct w;
+	struct device *dev;
 };
 
 struct ifs_device {
@@ -20,6 +64,14 @@ struct ifs_device {
 	struct miscdevice misc;
 };
 
+static inline struct ifs_data *ifs_get_data(struct device *dev)
+{
+	struct miscdevice *m = dev_get_drvdata(dev);
+	struct ifs_device *d = container_of(m, struct ifs_device, misc);
+
+	return &d->data;
+}
+
 void ifs_load_firmware(struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
index cfbf62494c89..d056617ddc85 100644
--- a/drivers/platform/x86/intel/ifs/load.c
+++ b/drivers/platform/x86/intel/ifs/load.c
@@ -3,10 +3,172 @@
 
 #include <linux/firmware.h>
 #include <asm/cpu.h>
+#include <linux/slab.h>
 #include <asm/microcode_intel.h>
 
 #include "ifs.h"
 
+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 header */
+static u64 ifs_hash_ptr;			/* Address of ifs metadata (hash) */
+static u64 ifs_test_image_ptr;			/* 256B aligned address of test pattern */
+static DECLARE_COMPLETION(ifs_done);
+
+static const char * const scan_hash_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to copy scan hashes when copy already in progress",
+	[2] = "Secure Memory not set up correctly",
+	[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
+	[4] = "Reserved",
+	[5] = "Integrity check failed",
+	[6] = "Scan reload or test is in progress"
+};
+
+static const char * const scan_authentication_status[] = {
+	[0] = "No error reported",
+	[1] = "Attempt to authenticate a chunk which is already marked as authentic",
+	[2] = "Chunk authentication error. The hash of chunk did not match expected value"
+};
+
+/*
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must 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_AUTHENTICATE_AND_COPY_CHUNK)
+ * for scan hash copy and test chunk authentication.
+ */
+static void copy_hashes_authenticate_chunks(struct work_struct *work)
+{
+	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
+	union ifs_scan_hashes_status hashes_status;
+	union ifs_chunks_auth_status chunk_status;
+	struct device *dev = local_work->dev;
+	int i, num_chunks, chunk_size;
+	struct ifs_data *ifsd;
+	u64 linear_addr, base;
+	u32 err_code;
+
+	ifsd = ifs_get_data(dev);
+	/* 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 = hashes_status.num_chunks;
+	chunk_size = hashes_status.chunk_size * 1024;
+	err_code = hashes_status.error_code;
+
+	if (!hashes_status.valid) {
+		ifsd->loading_error = true;
+		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
+			dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
+			goto done;
+		}
+		dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
+		goto done;
+	}
+
+	/* base linear address to the scan data */
+	base = ifs_test_image_ptr;
+
+	/* scan data authentication and copy chunks to secured memory */
+	for (i = 0; i < num_chunks; i++) {
+		linear_addr = base + i * chunk_size;
+		linear_addr |= i;
+
+		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
+		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
+
+		ifsd->valid_chunks = chunk_status.valid_chunks;
+		err_code = chunk_status.error_code;
+
+		if (err_code) {
+			ifsd->loading_error = true;
+			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
+				dev_err(dev,
+					"invalid error code 0x%x for authentication\n", err_code);
+				goto done;
+			}
+			dev_err(dev, "Chunk authentication error %s\n",
+				scan_authentication_status[err_code]);
+			goto done;
+		}
+	}
+done:
+	complete(&ifs_done);
+}
+
+/*
+ * IFS requires scan chunks authenticated per each socket in the platform.
+ * Once the test chunk is authenticated, it is automatically copied to secured memory
+ * and proceed the authentication for the next chunk.
+ */
+static int scan_chunks_sanity_check(struct device *dev)
+{
+	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	bool *package_authenticated;
+	struct ifs_work local_work;
+	char *test_ptr;
+
+	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
+	if (!package_authenticated)
+		return ret;
+
+	metadata_size = ifs_header_ptr->metadata_size;
+
+	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
+	if (metadata_size == 0)
+		metadata_size = 2000;
+
+	/* Scan chunk start must be 256 byte aligned */
+	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
+		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
+		return -EINVAL;
+	}
+
+	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
+	ifsd->loading_error = false;
+
+	ifs_test_image_ptr = (u64)test_ptr;
+	ifsd->loaded_version = ifs_header_ptr->blob_revision;
+
+	/* copy the scan hash and authenticate per package */
+	cpus_read_lock();
+	for_each_online_cpu(cpu) {
+		curr_pkg = topology_physical_package_id(cpu);
+		if (package_authenticated[curr_pkg])
+			continue;
+		reinit_completion(&ifs_done);
+		local_work.dev = dev;
+		INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
+		schedule_work_on(cpu, &local_work.w);
+		wait_for_completion(&ifs_done);
+		if (ifsd->loading_error)
+			goto out;
+		package_authenticated[curr_pkg] = 1;
+	}
+	ret = 0;
+out:
+	cpus_read_unlock();
+	kfree(package_authenticated);
+
+	return ret;
+}
+
 static int ifs_sanity_check(struct device *dev,
 			    const struct microcode_header_intel *mc_header)
 {
@@ -74,6 +236,7 @@ static bool ifs_image_sanity_check(struct device *dev, const struct microcode_he
  */
 void ifs_load_firmware(struct device *dev)
 {
+	struct ifs_data *ifsd = ifs_get_data(dev);
 	const struct firmware *fw;
 	char scan_path[32];
 	int ret;
@@ -84,11 +247,20 @@ void ifs_load_firmware(struct device *dev)
 	ret = request_firmware_direct(&fw, scan_path, dev);
 	if (ret) {
 		dev_err(dev, "ifs file %s load failed\n", scan_path);
-		return;
+		goto done;
 	}
 
-	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data))
+	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
 		dev_err(dev, "ifs header sanity check failed\n");
+		goto release;
+	}
+
+	ifs_header_ptr = (struct ifs_header *)fw->data;
+	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
 
+	ret = scan_chunks_sanity_check(dev);
+release:
 	release_firmware(fw);
+done:
+	ifsd->loaded = (ret == 0);
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 08/12] platform/x86/intel/ifs: Add scan test support
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (6 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 07/12] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-09 12:11             ` Thomas Gleixner
  2022-05-06 22:54           ` [PATCH v7 09/12] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
                             ` (4 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

In a core, the scan engine is shared between sibling cpus.

When a Scan test (for a particular core) is triggered by the user,
the scan chunks are executed on all the threads on the core using
stop_core_cpuslocked.

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.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/Makefile  |   2 +-
 drivers/platform/x86/intel/ifs/ifs.h     |  44 ++++
 drivers/platform/x86/intel/ifs/runtest.c | 247 +++++++++++++++++++++++
 3 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel/ifs/runtest.c

diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile
index 98b6fde15689..cedcb103f860 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o
+intel_ifs-objs			:= core.o load.o runtest.o
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index bed70dc1e5b7..b648cccda3ec 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -11,6 +11,11 @@
 #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_NOT_TESTED				0
+#define SCAN_TEST_PASS				1
+#define SCAN_TEST_FAIL				2
 
 /* MSR_SCAN_HASHES_STATUS bit fields */
 union ifs_scan_hashes_status {
@@ -38,6 +43,40 @@ union ifs_chunks_auth_status {
 	};
 };
 
+/* MSR_ACTIVATE_SCAN bit fields */
+union ifs_scan {
+	u64	data;
+	struct {
+		u32	start	:8;
+		u32	stop	:8;
+		u32	rsvd	:16;
+		u32	delay	:31;
+		u32	sigmce	:1;
+	};
+};
+
+/* MSR_SCAN_STATUS bit fields */
+union ifs_status {
+	u64	data;
+	struct {
+		u32	chunk_num		:8;
+		u32	chunk_stop_index	:8;
+		u32	rsvd1			:16;
+		u32	error_code		:8;
+		u32	rsvd2			:22;
+		u32	control_error		:1;
+		u32	signature_error		:1;
+	};
+};
+
+/*
+ * Driver populated error-codes
+ * 0xFD: Test timed out before completing all the chunks.
+ * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
+ */
+#define IFS_SW_TIMEOUT				0xFD
+#define IFS_SW_PARTIAL_COMPLETION		0xFE
+
 /**
  * struct ifs_data - attributes related to intel IFS driver
  * @integrity_cap_bit: MSR_INTEGRITY_CAPS bit enumerating this test
@@ -45,6 +84,8 @@ union ifs_chunks_auth_status {
  * @loaded: If a valid test binary has been loaded into the memory
  * @loading_error: Error occurred on another CPU while loading image
  * @valid_chunks: number of chunks which could be validated.
+ * @status: it holds simple status pass/fail/untested
+ * @scan_details: opaque scan status code from h/w
  */
 struct ifs_data {
 	int	integrity_cap_bit;
@@ -52,6 +93,8 @@ struct ifs_data {
 	bool	loaded;
 	bool	loading_error;
 	int	valid_chunks;
+	int	status;
+	u64	scan_details;
 };
 
 struct ifs_work {
@@ -73,5 +116,6 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
 }
 
 void ifs_load_firmware(struct device *dev);
+int do_core_test(int cpu, struct device *dev);
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
new file mode 100644
index 000000000000..7efcce35e0e9
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/nmi.h>
+#include <linux/slab.h>
+#include <linux/stop_machine.h>
+
+#include "ifs.h"
+
+/*
+ * Note all code and data in this file is protected by
+ * ifs_sem. On HT systems all threads on a core will
+ * execute together, but only the first thread on the
+ * core will update results of the test.
+ */
+
+/* Max retries on the same chunk */
+#define MAX_IFS_RETRIES  5
+
+/*
+ * Number of TSC cycles that a logical CPU will wait for the other
+ * logical CPU on the core in the WRMSR(ACTIVATE_SCAN).
+ */
+#define IFS_THREAD_WAIT 100000
+
+enum ifs_status_err_code {
+	IFS_NO_ERROR				= 0,
+	IFS_OTHER_THREAD_COULD_NOT_JOIN		= 1,
+	IFS_INTERRUPTED_BEFORE_RENDEZVOUS	= 2,
+	IFS_POWER_MGMT_INADEQUATE_FOR_SCAN	= 3,
+	IFS_INVALID_CHUNK_RANGE			= 4,
+	IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS	= 5,
+	IFS_CORE_NOT_CAPABLE_CURRENTLY		= 6,
+	IFS_UNASSIGNED_ERROR_CODE		= 7,
+	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT	= 8,
+	IFS_INTERRUPTED_DURING_EXECUTION	= 9,
+};
+
+static const char * const scan_test_status[] = {
+	[IFS_NO_ERROR] = "SCAN no error",
+	[IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.",
+	[IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.",
+	[IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] =
+	"Core Abort SCAN Response due to power management condition.",
+	[IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range",
+	[IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.",
+	[IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently",
+	[IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7",
+	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
+	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
+	[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start",
+};
+
+static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
+{
+	if (status.error_code < ARRAY_SIZE(scan_test_status)) {
+		dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n",
+			 cpumask_pr_args(cpu_smt_mask(cpu)),
+			 scan_test_status[status.error_code]);
+	} else if (status.error_code == IFS_SW_TIMEOUT) {
+		dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n",
+			 cpumask_pr_args(cpu_smt_mask(cpu)));
+	} else if (status.error_code == IFS_SW_PARTIAL_COMPLETION) {
+		dev_info(dev, "CPU(s) %*pbl: %s\n",
+			 cpumask_pr_args(cpu_smt_mask(cpu)),
+			 "Not all scan chunks were executed. Maximum forward progress retries exceeded");
+	} else {
+		dev_info(dev, "CPU(s) %*pbl: SCAN unknown status %llx\n",
+			 cpumask_pr_args(cpu_smt_mask(cpu)), status.data);
+	}
+}
+
+static void message_fail(struct device *dev, int cpu, union ifs_status status)
+{
+	/*
+	 * control_error is set when the microcode runs into a problem
+	 * loading the image from the reserved BIOS memory, or it has
+	 * been corrupted. Reloading the image may fix this issue.
+	 */
+	if (status.control_error) {
+		dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image\n",
+			cpumask_pr_args(cpu_smt_mask(cpu)));
+	}
+
+	/*
+	 * signature_error is set when the output from the scan chains does not
+	 * match the expected signature. This might be a transient problem (e.g.
+	 * due to a bit flip from an alpha particle or neutron). If the problem
+	 * repeats on a subsequent test, then it indicates an actual problem in
+	 * the core being tested.
+	 */
+	if (status.signature_error) {
+		dev_err(dev, "CPU(s) %*pbl: test signature incorrect.\n",
+			cpumask_pr_args(cpu_smt_mask(cpu)));
+	}
+}
+
+static bool can_restart(union ifs_status status)
+{
+	enum ifs_status_err_code err_code = status.error_code;
+
+	/* Signature for chunk is bad, or scan test failed */
+	if (status.signature_error || status.control_error)
+		return false;
+
+	switch (err_code) {
+	case IFS_NO_ERROR:
+	case IFS_OTHER_THREAD_COULD_NOT_JOIN:
+	case IFS_INTERRUPTED_BEFORE_RENDEZVOUS:
+	case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN:
+	case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT:
+	case IFS_INTERRUPTED_DURING_EXECUTION:
+		return true;
+	case IFS_INVALID_CHUNK_RANGE:
+	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
+	case IFS_CORE_NOT_CAPABLE_CURRENTLY:
+	case IFS_UNASSIGNED_ERROR_CODE:
+		break;
+	}
+	return false;
+}
+
+/*
+ * Execute the scan. Called "simultaneously" on all threads of a core
+ * at high priority using the stop_cpus mechanism.
+ */
+static int doscan(void *data)
+{
+	int cpu = smp_processor_id();
+	u64 *msrs = data;
+	int first;
+
+	/* Only the first logical CPU on a core reports result */
+	first = cpumask_first(cpu_smt_mask(cpu));
+
+	/*
+	 * This WRMSR will wait for other HT threads to also write
+	 * to this MSR (at most for activate.delay cycles). Then it
+	 * starts scan of each requested chunk. The core scan happens
+	 * during the "execution" of the WRMSR. This instruction can
+	 * take up to 200 milliseconds (in the case where all chunks
+	 * are processed in a single pass) before it retires.
+	 */
+	wrmsrl(MSR_ACTIVATE_SCAN, msrs[0]);
+
+	if (cpu == first) {
+		/* Pass back the result of the scan */
+		rdmsrl(MSR_SCAN_STATUS, msrs[1]);
+	}
+
+	return 0;
+}
+
+/*
+ * Use stop_core_cpuslocked() to synchronize writing to MSR_ACTIVATE_SCAN
+ * on all threads of the core to be tested. Loop if necessary to complete
+ * run of all chunks. Include some defensive tests to make sure forward
+ * progress is made, and that the whole test completes in a reasonable time.
+ */
+static void ifs_test_core(int cpu, struct device *dev)
+{
+	union ifs_scan activate;
+	union ifs_status status;
+	unsigned long timeout;
+	struct ifs_data *ifsd;
+	u64 msrvals[2];
+	int retries;
+
+	ifsd = ifs_get_data(dev);
+
+	activate.rsvd = 0;
+	activate.delay = IFS_THREAD_WAIT;
+	activate.sigmce = 0;
+	activate.start = 0;
+	activate.stop = ifsd->valid_chunks - 1;
+
+	timeout = jiffies + HZ / 2;
+	retries = MAX_IFS_RETRIES;
+
+	while (activate.start <= activate.stop) {
+		if (time_after(jiffies, timeout)) {
+			status.error_code = IFS_SW_TIMEOUT;
+			break;
+		}
+
+		msrvals[0] = activate.data;
+		stop_core_cpuslocked(cpu, doscan, msrvals);
+
+		status.data = msrvals[1];
+
+		/* Some cases can be retried, give up for others */
+		if (!can_restart(status))
+			break;
+
+		if (status.chunk_num == activate.start) {
+			/* Check for forward progress */
+			if (--retries == 0) {
+				if (status.error_code == IFS_NO_ERROR)
+					status.error_code = IFS_SW_PARTIAL_COMPLETION;
+				break;
+			}
+		} else {
+			retries = MAX_IFS_RETRIES;
+			activate.start = status.chunk_num;
+		}
+	}
+
+	/* Update status for this core */
+	ifsd->scan_details = status.data;
+
+	if (status.control_error || status.signature_error) {
+		ifsd->status = SCAN_TEST_FAIL;
+		message_fail(dev, cpu, status);
+	} else if (status.error_code) {
+		ifsd->status = SCAN_NOT_TESTED;
+		message_not_tested(dev, cpu, status);
+	} else {
+		ifsd->status = SCAN_TEST_PASS;
+	}
+}
+
+/*
+ * Initiate per core test. It wakes up work queue threads on the target cpu and
+ * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
+ * wait for all sibling threads to finish the scan test.
+ */
+int do_core_test(int cpu, struct device *dev)
+{
+	int ret = 0;
+
+	/* Prevent CPUs from being taken offline during the scan test */
+	cpus_read_lock();
+
+	if (!cpu_online(cpu)) {
+		dev_info(dev, "cannot test on the offline cpu %d\n", cpu);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ifs_test_core(cpu, dev);
+out:
+	cpus_read_unlock();
+	return ret;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 09/12] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (7 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 08/12] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-09 12:12             ` Thomas Gleixner
  2022-05-06 22:54           ` [PATCH v7 10/12] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
                             ` (3 subsequent siblings)
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Implement sysfs interface to trigger ifs test for a specific cpu.
Additional interfaces related to checking the status of the
scan test and seeing the version of the loaded IFS binary
are also added.

The basic usage is as below.
   - To start test, for example on cpu5:
       echo 5 > /sys/devices/platform/intel_ifs/run_test
   - To see the status of the last test
       cat /sys/devices/platform/intel_ifs/status
   - To see the version of the loaded scan binary
       cat /sys/devices/platform/intel_ifs/image_version

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/platform/x86/intel/ifs/Makefile |   2 +-
 drivers/platform/x86/intel/ifs/core.c   |   5 +
 drivers/platform/x86/intel/ifs/ifs.h    |   3 +
 drivers/platform/x86/intel/ifs/sysfs.c  | 149 ++++++++++++++++++++++++
 4 files changed, 158 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 cedcb103f860..30f035ef5581 100644
--- a/drivers/platform/x86/intel/ifs/Makefile
+++ b/drivers/platform/x86/intel/ifs/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INTEL_IFS)		+= intel_ifs.o
 
-intel_ifs-objs			:= core.o load.o runtest.o
+intel_ifs-objs			:= core.o load.o runtest.o sysfs.o
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index f62578dae8e9..27204e3d674d 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -3,6 +3,7 @@
 
 #include <linux/module.h>
 #include <linux/kdev_t.h>
+#include <linux/semaphore.h>
 
 #include <asm/cpu_device_id.h>
 
@@ -47,9 +48,13 @@ static int __init ifs_init(void)
 	if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval))
 		return -ENODEV;
 
+	ifs_device.misc.groups = ifs_get_groups();
+
 	if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) &&
 	    !misc_register(&ifs_device.misc)) {
+		down(&ifs_sem);
 		ifs_load_firmware(ifs_device.misc.this_device);
+		up(&ifs_sem);
 		return 0;
 	}
 
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index b648cccda3ec..720bd18a5e91 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -117,5 +117,8 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
 
 void ifs_load_firmware(struct device *dev);
 int do_core_test(int cpu, struct device *dev);
+const struct attribute_group **ifs_get_groups(void);
+
+extern struct semaphore ifs_sem;
 
 #endif
diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c
new file mode 100644
index 000000000000..37d8380d6fa8
--- /dev/null
+++ b/drivers/platform/x86/intel/ifs/sysfs.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "ifs.h"
+
+/*
+ * Protects against simultaneous tests on multiple cores, or
+ * reloading can file while a test is in progress
+ */
+DEFINE_SEMAPHORE(ifs_sem);
+
+/*
+ * The sysfs interface to check additional details of last test
+ * cat /sys/devices/system/platform/ifs/details
+ */
+static ssize_t details_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%#llx\n", ifsd->scan_details);
+}
+
+static DEVICE_ATTR_RO(details);
+
+static const char * const status_msg[] = {
+	[SCAN_NOT_TESTED] = "untested",
+	[SCAN_TEST_PASS] = "pass",
+	[SCAN_TEST_FAIL] = "fail"
+};
+
+/*
+ * The sysfs interface to check the test status:
+ * To check the status of last test
+ * cat /sys/devices/platform/ifs/status
+ */
+static ssize_t status_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	return sysfs_emit(buf, "%s\n", status_msg[ifsd->status]);
+}
+
+static DEVICE_ATTR_RO(status);
+
+/*
+ * The sysfs interface for single core testing
+ * To start test, for example, cpu5
+ * echo 5 > /sys/devices/platform/ifs/run_test
+ * To check the result:
+ * cat /sys/devices/platform/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)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	unsigned int cpu;
+	int rc;
+
+	rc = kstrtouint(buf, 0, &cpu);
+	if (rc < 0 || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	if (!ifsd->loaded)
+		rc = -EPERM;
+	else
+		rc = do_core_test(cpu, dev);
+
+	up(&ifs_sem);
+
+	return rc ? rc : count;
+}
+
+static DEVICE_ATTR_WO(run_test);
+
+/*
+ * Reload the IFS image. When user wants to install new IFS image
+ */
+static ssize_t reload_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+	bool res;
+
+
+	if (kstrtobool(buf, &res))
+		return -EINVAL;
+	if (!res)
+		return count;
+
+	if (down_interruptible(&ifs_sem))
+		return -EINTR;
+
+	ifs_load_firmware(dev);
+
+	up(&ifs_sem);
+
+	return ifsd->loaded ? count : -ENODEV;
+}
+
+static DEVICE_ATTR_WO(reload);
+
+/*
+ * Display currently loaded IFS image version.
+ */
+static ssize_t image_version_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct ifs_data *ifsd = ifs_get_data(dev);
+
+	if (!ifsd->loaded)
+		return sysfs_emit(buf, "%s\n", "none");
+	else
+		return sysfs_emit(buf, "%#x\n", ifsd->loaded_version);
+}
+
+static DEVICE_ATTR_RO(image_version);
+
+/* global scan sysfs attributes */
+static struct attribute *plat_ifs_attrs[] = {
+	&dev_attr_details.attr,
+	&dev_attr_status.attr,
+	&dev_attr_run_test.attr,
+	&dev_attr_reload.attr,
+	&dev_attr_image_version.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(plat_ifs);
+
+const struct attribute_group **ifs_get_groups(void)
+{
+	return plat_ifs_groups;
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 10/12] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (8 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 09/12] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-06 22:54           ` [PATCH v7 11/12] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
                             ` (2 subsequent siblings)
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Add tracing support which may be useful for debugging systems that fail to complete
In Field Scan tests.

Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 MAINTAINERS                              |  1 +
 drivers/platform/x86/intel/ifs/runtest.c |  5 +++
 include/trace/events/intel_ifs.h         | 41 ++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 include/trace/events/intel_ifs.h

diff --git a/MAINTAINERS b/MAINTAINERS
index bb0c4ff25942..6864fa039974 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9868,6 +9868,7 @@ R:	Ashok Raj <ashok.raj@intel.com>
 R:	Tony Luck <tony.luck@intel.com>
 S:	Maintained
 F:	drivers/platform/x86/intel/ifs
+F:	include/trace/events/intel_ifs.h
 
 INTEL INTEGRATED SENSOR HUB DRIVER
 M:	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
index 7efcce35e0e9..b2ca2bb4501f 100644
--- a/drivers/platform/x86/intel/ifs/runtest.c
+++ b/drivers/platform/x86/intel/ifs/runtest.c
@@ -17,6 +17,9 @@
  * core will update results of the test.
  */
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ifs.h>
+
 /* Max retries on the same chunk */
 #define MAX_IFS_RETRIES  5
 
@@ -191,6 +194,8 @@ static void ifs_test_core(int cpu, struct device *dev)
 
 		status.data = msrvals[1];
 
+		trace_ifs_status(cpu, activate, status);
+
 		/* Some cases can be retried, give up for others */
 		if (!can_restart(status))
 			break;
diff --git a/include/trace/events/intel_ifs.h b/include/trace/events/intel_ifs.h
new file mode 100644
index 000000000000..d7353024016c
--- /dev/null
+++ b/include/trace/events/intel_ifs.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ifs
+
+#if !defined(_TRACE_IFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IFS_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ifs_status,
+
+	TP_PROTO(int cpu, union ifs_scan activate, union ifs_status status),
+
+	TP_ARGS(cpu, activate, status),
+
+	TP_STRUCT__entry(
+		__field(	u64,	status	)
+		__field(	int,	cpu	)
+		__field(	u8,	start	)
+		__field(	u8,	stop	)
+	),
+
+	TP_fast_assign(
+		__entry->cpu	= cpu;
+		__entry->start	= activate.start;
+		__entry->stop	= activate.stop;
+		__entry->status	= status.data;
+	),
+
+	TP_printk("cpu: %d, start: %.2x, stop: %.2x, status: %llx",
+		__entry->cpu,
+		__entry->start,
+		__entry->stop,
+		__entry->status)
+);
+
+#endif /* _TRACE_IFS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 11/12] platform/x86/intel/ifs: add ABI documentation for IFS
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (9 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 10/12] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-06 22:54           ` [PATCH v7 12/12] Documentation: In-Field Scan Tony Luck
  2022-05-11 15:51           ` [PATCH v7 00/12] Introduce In Field Scan driver Hans de Goede
  12 siblings, 0 replies; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

From: Jithu Joseph <jithu.joseph@intel.com>

Add the sysfs attributes in ABI/testing for In-Field Scan.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 .../ABI/testing/sysfs-platform-intel-ifs      | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
new file mode 100644
index 000000000000..486d6d2ff8a0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -0,0 +1,39 @@
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/run_test
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write <cpu#> to trigger IFS test for one online core.
+		Note that the test is per core. The cpu# can be
+		for any thread on the core. Running on one thread
+		completes the test for the core containing that thread.
+		Example: to test the core containing cpu5: echo 5 >
+		/sys/devices/platform/intel_ifs.<N>/run_test
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/status
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	The status of the last test. It can be one of "pass", "fail"
+		or "untested".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/details
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Additional information regarding the last test. 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.
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/image_version
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Version (hexadecimal) of loaded IFS binary image. If no scan image
+		is loaded reports "none".
+
+What:		/sys/devices/virtual/misc/intel_ifs_<N>/reload
+Date:		April 21 2022
+KernelVersion:	5.19
+Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
+Description:	Write "1" (or "y" or "Y") to reload the IFS image from
+		/lib/firmware/intel/ifs/ff-mm-ss.scan.
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* [PATCH v7 12/12] Documentation: In-Field Scan
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (10 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 11/12] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
@ 2022-05-06 22:54           ` Tony Luck
  2022-05-09 12:16             ` Thomas Gleixner
  2022-05-11 15:51           ` [PATCH v7 00/12] Introduce In Field Scan driver Hans de Goede
  12 siblings, 1 reply; 152+ messages in thread
From: Tony Luck @ 2022-05-06 22:54 UTC (permalink / raw)
  To: hdegoede, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

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.

The CORE_CAPABILITIES MSR enumerates whether IFS is supported.

The full  github location for distributing the IFS images is
still being decided. So just a placeholder included for now
in the documentation.

Future CPUs will support more than one type of test. Plan for
that now by using a "_0" suffix on the ABI directory names.
Additional test types will use "_1", etc.

Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 Documentation/x86/ifs.rst            |   2 +
 Documentation/x86/index.rst          |   1 +
 drivers/platform/x86/intel/ifs/ifs.h | 110 +++++++++++++++++++++++++++
 3 files changed, 113 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..97abb696a680
--- /dev/null
+++ b/Documentation/x86/ifs.rst
@@ -0,0 +1,2 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. kernel-doc:: drivers/platform/x86/intel/ifs/ifs.h
diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst
index 91b2fa456618..9d8e8a73d57b 100644
--- a/Documentation/x86/index.rst
+++ b/Documentation/x86/index.rst
@@ -35,6 +35,7 @@ x86-specific Documentation
    usb-legacy-support
    i386/index
    x86_64/index
+   ifs
    sva
    sgx
    features
diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h
index 720bd18a5e91..73c8e91cf144 100644
--- a/drivers/platform/x86/intel/ifs/ifs.h
+++ b/drivers/platform/x86/intel/ifs/ifs.h
@@ -4,6 +4,116 @@
 #ifndef _IFS_H_
 #define _IFS_H_
 
+/**
+ * DOC: In-Field Scan
+ *
+ * =============
+ * In-Field Scan
+ * =============
+ *
+ * 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.
+ * Future CPUs will support more than one type of test which will show up
+ * with a new platform-device instance-id, for now only .0 is exposed.
+ *
+ *
+ * IFS Image
+ * ---------
+ *
+ * Intel provides a firmware file containing the scan tests via
+ * github [#f1]_.  Similar to microcode there is a separate file for each
+ * family-model-stepping.
+ *
+ * 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 by writing to the driver reload file::
+ *
+ *   # echo 1 > /sys/devices/virtual/misc/intel_ifs_0/reload
+ *
+ * Similar to microcode, the current version of the scan tests is stored
+ * in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan
+ *
+ * Running tests
+ * -------------
+ *
+ * Tests are run by the driver 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.
+ *
+ * Note that ALL THREADS ON THE CORE ARE EFFECTIVELY OFFLINE FOR THE
+ * DURATION OF THE TEST. This can be up to 200 milliseconds. If the system
+ * is running latency sensitive applications that cannot tolerate an
+ * interruption of this magnitude, the system administrator must arrange
+ * to migrate those applications to other cores before running a core test.
+ * It may also be necessary to redirect interrupts to other CPUs.
+ *
+ * In all cases reading the SCAN_STATUS MSR provides details on what
+ * happened. The driver makes the value of this MSR visible to applications
+ * via the "details" file (see below). Interrupted tests may be restarted.
+ *
+ * The IFS driver provides sysfs interfaces via /sys/devices/virtual/misc/intel_ifs_0/
+ * to control execution:
+ *
+ * Test a specific core::
+ *
+ *   # echo <cpu#> > /sys/devices/virtual/misc/intel_ifs_0/run_test
+ *
+ * when HT is enabled any of the sibling cpu# can be specified to test
+ * its corresponding physical core. Since the tests are per physical core,
+ * the result of testing any thread is same. All siblings must be online
+ * to run a core test. It is only necessary to test one thread.
+ *
+ * For e.g. to test core corresponding to cpu5
+ *
+ *   # echo 5 > /sys/devices/virtual/misc/intel_ifs_0/run_test
+ *
+ * Results of the last test is provided in /sys::
+ *
+ *   $ cat /sys/devices/virtual/misc/intel_ifs_0/status
+ *   pass
+ *
+ * Status can be one of pass, fail, untested
+ *
+ * Additional details of the last test is provided by the details file::
+ *
+ *   $ cat /sys/devices/virtual/misc/intel_ifs_0/details
+ *   0x8081
+ *
+ * The details file reports the hex value of the SCAN_STATUS MSR.
+ * Hardware defined error codes are documented in volume 4 of the Intel
+ * Software Developer's Manual but the error_code field may contain one of
+ * the following driver defined software codes:
+ *
+ * +------+--------------------+
+ * | 0xFD | Software timeout   |
+ * +------+--------------------+
+ * | 0xFE | Partial completion |
+ * +------+--------------------+
+ *
+ * Driver design choices
+ * ---------------------
+ *
+ * 1) The ACTIVATE_SCAN MSR allows for running any consecutive subrange of
+ * 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.
+ *
+ * .. [#f1] https://github.com/intel/TBD
+ */
 #include <linux/device.h>
 #include <linux/miscdevice.h>
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 05/12] platform/x86/intel/ifs: Read IFS firmware image
  2022-05-06 22:54           ` [PATCH v7 05/12] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
@ 2022-05-09 12:11             ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-09 12:11 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 15:54, Tony Luck wrote:
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Acked-by: Hans de Goede <hdegoede@redhat.com>
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity
  2022-05-06 22:54           ` [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
@ 2022-05-09 12:11             ` Thomas Gleixner
  2022-05-09 16:31             ` Borislav Petkov
  1 sibling, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-09 12:11 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 15:54, Tony Luck wrote:
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Acked-by: Hans de Goede <hdegoede@redhat.com>
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 07/12] platform/x86/intel/ifs: Authenticate and copy to secured memory
  2022-05-06 22:54           ` [PATCH v7 07/12] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
@ 2022-05-09 12:11             ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-09 12:11 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 15:54, Tony Luck wrote:
> Use schedule_work_on() to perform the hash copy and authentication. Note
> this needs only be done on the first logical cpu of each socket.
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Acked-by: Hans de Goede <hdegoede@redhat.com>
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 08/12] platform/x86/intel/ifs: Add scan test support
  2022-05-06 22:54           ` [PATCH v7 08/12] platform/x86/intel/ifs: Add scan test support Tony Luck
@ 2022-05-09 12:11             ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-09 12:11 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 15:54, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
>
> In a core, the scan engine is shared between sibling cpus.
>
> When a Scan test (for a particular core) is triggered by the user,
> the scan chunks are executed on all the threads on the core using
> stop_core_cpuslocked.
>
> 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.
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Acked-by: Hans de Goede <hdegoede@redhat.com>
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 09/12] platform/x86/intel/ifs: Add IFS sysfs interface
  2022-05-06 22:54           ` [PATCH v7 09/12] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
@ 2022-05-09 12:12             ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-09 12:12 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 15:54, Tony Luck wrote:
> Implement sysfs interface to trigger ifs test for a specific cpu.
> Additional interfaces related to checking the status of the
> scan test and seeing the version of the loaded IFS binary
> are also added.
>
> The basic usage is as below.
>    - To start test, for example on cpu5:
>        echo 5 > /sys/devices/platform/intel_ifs/run_test
>    - To see the status of the last test
>        cat /sys/devices/platform/intel_ifs/status
>    - To see the version of the loaded scan binary
>        cat /sys/devices/platform/intel_ifs/image_version
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
> Co-developed-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Acked-by: Hans de Goede <hdegoede@redhat.com>
> Reviewed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 12/12] Documentation: In-Field Scan
  2022-05-06 22:54           ` [PATCH v7 12/12] Documentation: In-Field Scan Tony Luck
@ 2022-05-09 12:16             ` Thomas Gleixner
  0 siblings, 0 replies; 152+ messages in thread
From: Thomas Gleixner @ 2022-05-09 12:16 UTC (permalink / raw)
  To: Tony Luck, hdegoede, markgross
  Cc: mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, tony.luck, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06 2022 at 15:54, Tony Luck wrote:
> 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.
>
> The CORE_CAPABILITIES MSR enumerates whether IFS is supported.
>
> The full  github location for distributing the IFS images is
> still being decided. So just a placeholder included for now
> in the documentation.
>
> Future CPUs will support more than one type of test. Plan for
> that now by using a "_0" suffix on the ABI directory names.
> Additional test types will use "_1", etc.
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity
  2022-05-06 22:54           ` [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
  2022-05-09 12:11             ` Thomas Gleixner
@ 2022-05-09 16:31             ` Borislav Petkov
  2022-05-09 16:51               ` Luck, Tony
  1 sibling, 1 reply; 152+ messages in thread
From: Borislav Petkov @ 2022-05-09 16:31 UTC (permalink / raw)
  To: Tony Luck
  Cc: hdegoede, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

On Fri, May 06, 2022 at 03:54:04PM -0700, Tony Luck wrote:
> From: Jithu Joseph <jithu.joseph@intel.com>
> 
> 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.

Is the checksum the only protection against people loading arbitrary IFS
images or are those things signed or encrypted, just like the microcode?

I'd hope they pass the same checks as microcode, when they get loaded,
considering the similarity of how they're handled...

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity
  2022-05-09 16:31             ` Borislav Petkov
@ 2022-05-09 16:51               ` Luck, Tony
  2022-05-09 16:56                 ` Borislav Petkov
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-09 16:51 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: hdegoede, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

> Is the checksum the only protection against people loading arbitrary IFS
> images or are those things signed or encrypted, just like the microcode?
>
> I'd hope they pass the same checks as microcode, when they get loaded,
> considering the similarity of how they're handled...

The checksum is just a "did this file get corrupted check". The file contains
SHA256 checksums for each of the chunks. These checksums are digitally
signed. Checking of these is done by microcode when the file is loaded into
BIOS reserved memory (where it is inaccessible to OS and I/O).

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity
  2022-05-09 16:51               ` Luck, Tony
@ 2022-05-09 16:56                 ` Borislav Petkov
  0 siblings, 0 replies; 152+ messages in thread
From: Borislav Petkov @ 2022-05-09 16:56 UTC (permalink / raw)
  To: Luck, Tony
  Cc: hdegoede, markgross, tglx, mingo, dave.hansen, x86, hpa, corbet,
	gregkh, andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt,
	Williams, Dan J, linux-kernel, linux-doc, platform-driver-x86,
	patches, Shankar, Ravi V

On Mon, May 09, 2022 at 04:51:56PM +0000, Luck, Tony wrote:
> The checksum is just a "did this file get corrupted check". The file contains
> SHA256 checksums for each of the chunks. These checksums are digitally
> signed. Checking of these is done by microcode when the file is loaded into
> BIOS reserved memory (where it is inaccessible to OS and I/O).

That sounds like something I was hoping to hear, good. :-)

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 152+ messages in thread

* RE: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-06 18:41               ` Hans de Goede
@ 2022-05-09 17:05                 ` Luck, Tony
  2022-05-09 18:12                   ` Hans de Goede
  0 siblings, 1 reply; 152+ messages in thread
From: Luck, Tony @ 2022-05-09 17:05 UTC (permalink / raw)
  To: Hans de Goede, Borislav Petkov
  Cc: markgross, tglx, mingo, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

>> Do you still take patches after -rc6?
>
> If the patches are send soon (1-2 days) after rc6 I can still take them.

Hans,

V7 was posted Friday. It survived my weekend testing, and another round of tglx scrutiny (ending with
his "Reviewed-by" on the latter parts of the series.

Let me know if there is anything else you need to get them applied.

Thanks

-Tony

^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v5 00/10] Introduce In Field Scan driver
  2022-05-09 17:05                 ` Luck, Tony
@ 2022-05-09 18:12                   ` Hans de Goede
  0 siblings, 0 replies; 152+ messages in thread
From: Hans de Goede @ 2022-05-09 18:12 UTC (permalink / raw)
  To: Luck, Tony, Borislav Petkov
  Cc: markgross, tglx, mingo, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, Joseph, Jithu, Raj, Ashok, rostedt, Williams,
	Dan J, linux-kernel, linux-doc, platform-driver-x86, patches,
	Shankar, Ravi V

Hi,

On 5/9/22 19:05, Luck, Tony wrote:
>>> Do you still take patches after -rc6?
>>
>> If the patches are send soon (1-2 days) after rc6 I can still take them.
> 
> Hans,
> 
> V7 was posted Friday. It survived my weekend testing, and another round of tglx scrutiny (ending with
> his "Reviewed-by" on the latter parts of the series.
> 
> Let me know if there is anything else you need to get them applied.

From my side everything looks good. I plan to merge this
into my review-hans (*) branch coming Wednesday.

Regards,

Hans



*) And then from there move it to for-next once the build bots
have had a chance to play with it



^ permalink raw reply	[flat|nested] 152+ messages in thread

* Re: [PATCH v7 00/12] Introduce In Field Scan driver
  2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
                             ` (11 preceding siblings ...)
  2022-05-06 22:54           ` [PATCH v7 12/12] Documentation: In-Field Scan Tony Luck
@ 2022-05-11 15:51           ` Hans de Goede
  12 siblings, 0 replies; 152+ messages in thread
From: Hans de Goede @ 2022-05-11 15:51 UTC (permalink / raw)
  To: Tony Luck, markgross
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, corbet, gregkh,
	andriy.shevchenko, jithu.joseph, ashok.raj, rostedt,
	dan.j.williams, linux-kernel, linux-doc, platform-driver-x86,
	patches, ravi.v.shankar

Hi,

On 5/7/22 00:53, Tony Luck wrote:
> TL;DR this driver loads scan test files that can check whether silicon
> in a CPU core is still running correctly. It is expected that these tests
> would be run several times per day to catch problems as silicon ages.

Thank you for your patch-series, I've applied the series to my
review-hans branch:
https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans

Note it will show up in my review-hans branch once I've pushed my
local branch there, which might take a while.

Once I've run some tests on this branch the patches there will be
added to the platform-drivers-x86/for-next branch and eventually
will be included in the pdx86 pull-request to Linus for the next
merge-window.

Regards,

Hans




> 
> Changes since v6
> 
> Thomas Gleixner
> ---------------
> "struct workqueue_struct *ifs_wq; Seems to be unused."
> 
> True. Deleted.
> 
> "static bool oscan_enabled = true; What changes this?"
> 
> Code that cleared it deleted. Drop this too.
> 
> "Please add curly brackets as these are not one-line statements"
> 
> Added
> 
> cpumask_first(topology_sibling_cpumask(cpu)); Shouldn't that be cpu_smt_mask()?"
> 
> Changed (and several other places)
> 
> "take up to 200 milliseconds before it retires.  200ms per test chunk?"
> 
> Updated comment to note that 200ms is for all chunks.
> 
> "Documentation lost in the intertubes"
> 
> Dredged up the version from v3 series and changed:
> 1) Fixed pathnames now this is a virtual misc device instead of platform
> device
> 2) Put all the text into a "/** DOC:" comment section in ifs.h with just
> a "kernel-doc:: drivers/platform/x86/intel/ifs/ifs.h" in the ifs.rst
> file under Documentation/x86.
> 3) Added a "big fat warning" (in all CAPS) pointing out that a core test
> can take up to 200 milliseconds. So admins must take extra steps if they
> are running latency sensitive workloads.
> 4) Added note that all HT threads of a core must be online to run a
> test.
> 
> Tony Luck
> ---------
> Off-by-one on retries check (#define set to 5, but tried 6 times). Fixed
> Fixed kerneldoc description of "integrity_cap_bit" (was missing a ":")
> 
> Jithu Joseph (7):
>   x86/microcode/intel: Expose collect_cpu_info_early() for IFS
>   platform/x86/intel/ifs: Read IFS firmware image
>   platform/x86/intel/ifs: Check IFS Image sanity
>   platform/x86/intel/ifs: Authenticate and copy to secured memory
>   platform/x86/intel/ifs: Add scan test support
>   platform/x86/intel/ifs: Add IFS sysfs interface
>   platform/x86/intel/ifs: add ABI documentation for IFS
> 
> Peter Zijlstra (1):
>   stop_machine: Add stop_core_cpuslocked() for per-core operations
> 
> Tony Luck (4):
>   x86/msr-index: Define INTEGRITY_CAPABILITIES MSR
>   platform/x86/intel/ifs: Add stub driver for In-Field Scan
>   trace: platform/x86/intel/ifs: Add trace point to track Intel IFS
>     operations
>   Documentation: In-Field Scan
> 
>  .../ABI/testing/sysfs-platform-intel-ifs      |  39 +++
>  Documentation/x86/ifs.rst                     |   2 +
>  Documentation/x86/index.rst                   |   1 +
>  MAINTAINERS                                   |   8 +
>  arch/x86/include/asm/cpu.h                    |  18 ++
>  arch/x86/include/asm/msr-index.h              |   7 +
>  arch/x86/kernel/cpu/intel.c                   |  32 +++
>  arch/x86/kernel/cpu/microcode/intel.c         |  59 +---
>  drivers/platform/x86/intel/Kconfig            |   1 +
>  drivers/platform/x86/intel/Makefile           |   1 +
>  drivers/platform/x86/intel/ifs/Kconfig        |  13 +
>  drivers/platform/x86/intel/ifs/Makefile       |   3 +
>  drivers/platform/x86/intel/ifs/core.c         |  73 +++++
>  drivers/platform/x86/intel/ifs/ifs.h          | 234 +++++++++++++++
>  drivers/platform/x86/intel/ifs/load.c         | 266 ++++++++++++++++++
>  drivers/platform/x86/intel/ifs/runtest.c      | 252 +++++++++++++++++
>  drivers/platform/x86/intel/ifs/sysfs.c        | 149 ++++++++++
>  include/linux/stop_machine.h                  |  16 ++
>  include/trace/events/intel_ifs.h              |  41 +++
>  kernel/stop_machine.c                         |  19 ++
>  20 files changed, 1182 insertions(+), 52 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-ifs
>  create mode 100644 Documentation/x86/ifs.rst
>  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
>  create mode 100644 drivers/platform/x86/intel/ifs/load.c
>  create mode 100644 drivers/platform/x86/intel/ifs/runtest.c
>  create mode 100644 drivers/platform/x86/intel/ifs/sysfs.c
>  create mode 100644 include/trace/events/intel_ifs.h
> 
> 
> base-commit: 672c0c5173427e6b3e2a9bbb7be51ceeec78093a


^ permalink raw reply	[flat|nested] 152+ messages in thread

end of thread, other threads:[~2022-05-11 15:52 UTC | newest]

Thread overview: 152+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-07 19:13 [PATCH v2 00/10] Introduce In Field Scan driver Jithu Joseph
2022-04-07 19:13 ` [PATCH v2 01/10] x86/microcode/intel: expose collect_cpu_info_early() for IFS Jithu Joseph
2022-04-08  8:34   ` Borislav Petkov
2022-04-21 14:56     ` Thomas Gleixner
2022-04-07 19:13 ` [PATCH v2 02/10] Documentation: In-Field Scan Jithu Joseph
2022-04-07 19:13 ` [PATCH v2 03/10] platform/x86/intel/ifs: Add driver for " Jithu Joseph
2022-04-07 19:13 ` [PATCH v2 04/10] platform/x86/intel/ifs: Load IFS Image Jithu Joseph
2022-04-08  5:02   ` Greg KH
2022-04-08  5:04   ` Greg KH
2022-04-07 19:13 ` [PATCH v2 05/10] platform/x86/intel/ifs: Check IFS Image sanity Jithu Joseph
2022-04-07 19:13 ` [PATCH v2 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Jithu Joseph
2022-04-07 19:13 ` [PATCH v2 07/10] platform/x86/intel/ifs: Add scan test support Jithu Joseph
2022-04-07 19:13 ` [PATCH v2 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Jithu Joseph
2022-04-08  4:59   ` Greg KH
2022-04-07 19:13 ` [PATCH v2 09/10] platform/x86/intel/ifs: add ABI documentation for IFS Jithu Joseph
2022-04-08  5:02   ` Greg KH
2022-04-07 19:13 ` [PATCH v2 10/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Jithu Joseph
2022-04-19 16:38 ` [PATCH v3 00/11] Introduce In Field Scan driver Tony Luck
2022-04-19 16:38   ` [PATCH v3 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
2022-04-19 16:38   ` [PATCH v3 02/11] Documentation: In-Field Scan Tony Luck
2022-04-19 16:48     ` Greg KH
2022-04-19 19:45       ` Dan Williams
2022-04-20  7:48         ` Greg KH
2022-04-19 16:38   ` [PATCH v3 03/11] platform/x86/intel/ifs: Create device for Intel IFS (In Field Scan) Tony Luck
2022-04-19 16:47     ` Greg KH
2022-04-19 18:09       ` Dan Williams
2022-04-19 22:28         ` Dan Williams
2022-04-20  7:49           ` Greg KH
2022-04-20  7:48         ` Greg KH
2022-04-20 15:27           ` Luck, Tony
2022-04-20 17:46             ` Greg KH
2022-04-20 17:57               ` Luck, Tony
2022-04-20 18:04                 ` Greg KH
2022-04-20 18:08                   ` Luck, Tony
2022-04-20 19:04                     ` Greg KH
2022-04-19 16:38   ` [PATCH v3 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
2022-04-19 16:38   ` [PATCH v3 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
2022-04-19 17:14     ` Greg KH
2022-04-19 16:38   ` [PATCH v3 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
2022-04-19 17:16     ` Greg KH
2022-04-19 16:38   ` [PATCH v3 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
2022-04-19 16:38   ` [PATCH v3 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
2022-04-19 16:38   ` [PATCH v3 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
2022-04-19 17:20     ` Greg KH
2022-04-19 17:35       ` Luck, Tony
2022-04-19 17:58         ` Greg KH
2022-04-19 18:15           ` Dan Williams
2022-04-19 18:24       ` Dan Williams
2022-04-19 16:38   ` [PATCH v3 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
2022-04-20 23:38     ` Steven Rostedt
2022-04-21  4:26       ` Luck, Tony
2022-04-21 12:41         ` Steven Rostedt
2022-04-19 16:38   ` [PATCH v3 11/11] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
2022-04-22 20:02   ` [PATCH v4 00/10] Introduce In Field Scan driver Tony Luck
2022-04-22 20:02     ` [PATCH v4 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
2022-04-22 20:02     ` [PATCH v4 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
2022-04-22 20:02     ` [PATCH v4 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
2022-04-22 20:02     ` [PATCH v4 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
2022-04-26 10:45       ` Greg KH
2022-04-26 16:12         ` Luck, Tony
2022-04-26 16:36           ` Greg KH
2022-04-26 18:47             ` Luck, Tony
2022-04-22 20:02     ` [PATCH v4 05/10] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
2022-04-22 20:02     ` [PATCH v4 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
2022-04-22 20:02     ` [PATCH v4 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
2022-04-22 20:02     ` [PATCH v4 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
2022-04-22 20:02     ` [PATCH v4 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
2022-04-25 14:52       ` Steven Rostedt
2022-04-25 16:49         ` Luck, Tony
2022-04-26  1:49           ` Steven Rostedt
2022-04-26 23:53             ` Luck, Tony
2022-04-27  2:42               ` Steven Rostedt
2022-04-22 20:02     ` [PATCH v4 10/10] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
2022-04-28 15:38     ` [PATCH v5 00/10] Introduce In Field Scan driver Tony Luck
2022-04-28 15:38       ` [PATCH v5 01/10] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
2022-05-03 15:29         ` Borislav Petkov
2022-05-04 10:28         ` Thomas Gleixner
2022-04-28 15:38       ` [PATCH v5 02/10] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
2022-04-28 15:38       ` [PATCH v5 03/10] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
2022-05-04 10:35         ` Thomas Gleixner
2022-05-04 16:24           ` Luck, Tony
2022-05-04 16:28             ` Borislav Petkov
2022-04-28 15:38       ` [PATCH v5 04/10] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
2022-05-04 10:37         ` Thomas Gleixner
2022-05-04 16:49           ` Luck, Tony
2022-04-28 15:38       ` [PATCH v5 05/10] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
2022-04-28 15:38       ` [PATCH v5 06/10] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
2022-05-04 10:48         ` Thomas Gleixner
2022-04-28 15:38       ` [PATCH v5 07/10] platform/x86/intel/ifs: Add scan test support Tony Luck
2022-05-04 12:29         ` Thomas Gleixner
2022-05-04 18:52           ` Luck, Tony
2022-05-04 23:15             ` Thomas Gleixner
2022-05-05  8:28               ` Peter Zijlstra
2022-05-05  9:01                 ` Thomas Gleixner
2022-05-05 18:32                   ` Luck, Tony
2022-05-05 20:21                     ` Peter Zijlstra
2022-04-28 15:38       ` [PATCH v5 08/10] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
2022-04-28 15:38       ` [PATCH v5 09/10] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
2022-04-28 15:38       ` [PATCH v5 10/10] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
2022-04-28 15:58       ` [PATCH v5 00/10] Introduce In Field Scan driver Greg KH
2022-04-28 16:07         ` Luck, Tony
2022-05-02 15:15       ` Hans de Goede
2022-05-02 17:23         ` Luck, Tony
2022-05-03 15:32         ` Borislav Petkov
2022-05-03 16:04           ` Luck, Tony
2022-05-03 16:26             ` Luck, Tony
2022-05-06 14:19           ` Hans de Goede
2022-05-06 15:53             ` Luck, Tony
2022-05-06 18:41               ` Hans de Goede
2022-05-09 17:05                 ` Luck, Tony
2022-05-09 18:12                   ` Hans de Goede
2022-05-06  1:40       ` [PATCH v6 00/11] " Tony Luck
2022-05-06  1:40         ` [PATCH v6 01/11] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
2022-05-06  1:40         ` [PATCH v6 02/11] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
2022-05-06  8:19           ` Thomas Gleixner
2022-05-06  1:40         ` [PATCH v6 03/11] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
2022-05-06  8:20           ` Thomas Gleixner
2022-05-06  1:40         ` [PATCH v6 04/11] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
2022-05-06  8:23           ` Thomas Gleixner
2022-05-06  1:40         ` [PATCH v6 05/11] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
2022-05-06  1:40         ` [PATCH v6 06/11] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
2022-05-06  1:40         ` [PATCH v6 07/11] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
2022-05-06  1:40         ` [PATCH v6 08/11] platform/x86/intel/ifs: Add scan test support Tony Luck
2022-05-06 13:30           ` Thomas Gleixner
2022-05-06 18:49             ` Luck, Tony
2022-05-06 19:06               ` Thomas Gleixner
2022-05-06  1:40         ` [PATCH v6 09/11] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
2022-05-06  1:40         ` [PATCH v6 10/11] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
2022-05-06  1:40         ` [PATCH v6 11/11] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
2022-05-06 22:53         ` [PATCH v7 00/12] Introduce In Field Scan driver Tony Luck
2022-05-06 22:53           ` [PATCH v7 01/12] x86/microcode/intel: Expose collect_cpu_info_early() for IFS Tony Luck
2022-05-06 22:54           ` [PATCH v7 02/12] x86/msr-index: Define INTEGRITY_CAPABILITIES MSR Tony Luck
2022-05-06 22:54           ` [PATCH v7 03/12] stop_machine: Add stop_core_cpuslocked() for per-core operations Tony Luck
2022-05-06 22:54           ` [PATCH v7 04/12] platform/x86/intel/ifs: Add stub driver for In-Field Scan Tony Luck
2022-05-06 22:54           ` [PATCH v7 05/12] platform/x86/intel/ifs: Read IFS firmware image Tony Luck
2022-05-09 12:11             ` Thomas Gleixner
2022-05-06 22:54           ` [PATCH v7 06/12] platform/x86/intel/ifs: Check IFS Image sanity Tony Luck
2022-05-09 12:11             ` Thomas Gleixner
2022-05-09 16:31             ` Borislav Petkov
2022-05-09 16:51               ` Luck, Tony
2022-05-09 16:56                 ` Borislav Petkov
2022-05-06 22:54           ` [PATCH v7 07/12] platform/x86/intel/ifs: Authenticate and copy to secured memory Tony Luck
2022-05-09 12:11             ` Thomas Gleixner
2022-05-06 22:54           ` [PATCH v7 08/12] platform/x86/intel/ifs: Add scan test support Tony Luck
2022-05-09 12:11             ` Thomas Gleixner
2022-05-06 22:54           ` [PATCH v7 09/12] platform/x86/intel/ifs: Add IFS sysfs interface Tony Luck
2022-05-09 12:12             ` Thomas Gleixner
2022-05-06 22:54           ` [PATCH v7 10/12] trace: platform/x86/intel/ifs: Add trace point to track Intel IFS operations Tony Luck
2022-05-06 22:54           ` [PATCH v7 11/12] platform/x86/intel/ifs: add ABI documentation for IFS Tony Luck
2022-05-06 22:54           ` [PATCH v7 12/12] Documentation: In-Field Scan Tony Luck
2022-05-09 12:16             ` Thomas Gleixner
2022-05-11 15:51           ` [PATCH v7 00/12] Introduce In Field Scan driver Hans de Goede

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.