Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /* Copyright(c) 2022 Intel Corporation. */
0003 
0004 #ifndef _IFS_H_
0005 #define _IFS_H_
0006 
0007 /**
0008  * DOC: In-Field Scan
0009  *
0010  * =============
0011  * In-Field Scan
0012  * =============
0013  *
0014  * Introduction
0015  * ------------
0016  *
0017  * In Field Scan (IFS) is a hardware feature to run circuit level tests on
0018  * a CPU core to detect problems that are not caught by parity or ECC checks.
0019  * Future CPUs will support more than one type of test which will show up
0020  * with a new platform-device instance-id, for now only .0 is exposed.
0021  *
0022  *
0023  * IFS Image
0024  * ---------
0025  *
0026  * Intel provides a firmware file containing the scan tests via
0027  * github [#f1]_.  Similar to microcode there is a separate file for each
0028  * family-model-stepping.
0029  *
0030  * IFS Image Loading
0031  * -----------------
0032  *
0033  * The driver loads the tests into memory reserved BIOS local to each CPU
0034  * socket in a two step process using writes to MSRs to first load the
0035  * SHA hashes for the test. Then the tests themselves. Status MSRs provide
0036  * feedback on the success/failure of these steps. When a new test file
0037  * is installed it can be loaded by writing to the driver reload file::
0038  *
0039  *   # echo 1 > /sys/devices/virtual/misc/intel_ifs_0/reload
0040  *
0041  * Similar to microcode, the current version of the scan tests is stored
0042  * in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan
0043  *
0044  * Running tests
0045  * -------------
0046  *
0047  * Tests are run by the driver synchronizing execution of all threads on a
0048  * core and then writing to the ACTIVATE_SCAN MSR on all threads. Instruction
0049  * execution continues when:
0050  *
0051  * 1) All tests have completed.
0052  * 2) Execution was interrupted.
0053  * 3) A test detected a problem.
0054  *
0055  * Note that ALL THREADS ON THE CORE ARE EFFECTIVELY OFFLINE FOR THE
0056  * DURATION OF THE TEST. This can be up to 200 milliseconds. If the system
0057  * is running latency sensitive applications that cannot tolerate an
0058  * interruption of this magnitude, the system administrator must arrange
0059  * to migrate those applications to other cores before running a core test.
0060  * It may also be necessary to redirect interrupts to other CPUs.
0061  *
0062  * In all cases reading the SCAN_STATUS MSR provides details on what
0063  * happened. The driver makes the value of this MSR visible to applications
0064  * via the "details" file (see below). Interrupted tests may be restarted.
0065  *
0066  * The IFS driver provides sysfs interfaces via /sys/devices/virtual/misc/intel_ifs_0/
0067  * to control execution:
0068  *
0069  * Test a specific core::
0070  *
0071  *   # echo <cpu#> > /sys/devices/virtual/misc/intel_ifs_0/run_test
0072  *
0073  * when HT is enabled any of the sibling cpu# can be specified to test
0074  * its corresponding physical core. Since the tests are per physical core,
0075  * the result of testing any thread is same. All siblings must be online
0076  * to run a core test. It is only necessary to test one thread.
0077  *
0078  * For e.g. to test core corresponding to cpu5
0079  *
0080  *   # echo 5 > /sys/devices/virtual/misc/intel_ifs_0/run_test
0081  *
0082  * Results of the last test is provided in /sys::
0083  *
0084  *   $ cat /sys/devices/virtual/misc/intel_ifs_0/status
0085  *   pass
0086  *
0087  * Status can be one of pass, fail, untested
0088  *
0089  * Additional details of the last test is provided by the details file::
0090  *
0091  *   $ cat /sys/devices/virtual/misc/intel_ifs_0/details
0092  *   0x8081
0093  *
0094  * The details file reports the hex value of the SCAN_STATUS MSR.
0095  * Hardware defined error codes are documented in volume 4 of the Intel
0096  * Software Developer's Manual but the error_code field may contain one of
0097  * the following driver defined software codes:
0098  *
0099  * +------+--------------------+
0100  * | 0xFD | Software timeout   |
0101  * +------+--------------------+
0102  * | 0xFE | Partial completion |
0103  * +------+--------------------+
0104  *
0105  * Driver design choices
0106  * ---------------------
0107  *
0108  * 1) The ACTIVATE_SCAN MSR allows for running any consecutive subrange of
0109  * available tests. But the driver always tries to run all tests and only
0110  * uses the subrange feature to restart an interrupted test.
0111  *
0112  * 2) Hardware allows for some number of cores to be tested in parallel.
0113  * The driver does not make use of this, it only tests one core at a time.
0114  *
0115  * .. [#f1] https://github.com/intel/TBD
0116  */
0117 #include <linux/device.h>
0118 #include <linux/miscdevice.h>
0119 
0120 #define MSR_COPY_SCAN_HASHES            0x000002c2
0121 #define MSR_SCAN_HASHES_STATUS          0x000002c3
0122 #define MSR_AUTHENTICATE_AND_COPY_CHUNK     0x000002c4
0123 #define MSR_CHUNKS_AUTHENTICATION_STATUS    0x000002c5
0124 #define MSR_ACTIVATE_SCAN           0x000002c6
0125 #define MSR_SCAN_STATUS             0x000002c7
0126 #define SCAN_NOT_TESTED             0
0127 #define SCAN_TEST_PASS              1
0128 #define SCAN_TEST_FAIL              2
0129 
0130 /* MSR_SCAN_HASHES_STATUS bit fields */
0131 union ifs_scan_hashes_status {
0132     u64 data;
0133     struct {
0134         u32 chunk_size  :16;
0135         u32 num_chunks  :8;
0136         u32 rsvd1       :8;
0137         u32 error_code  :8;
0138         u32 rsvd2       :11;
0139         u32 max_core_limit  :12;
0140         u32 valid       :1;
0141     };
0142 };
0143 
0144 /* MSR_CHUNKS_AUTH_STATUS bit fields */
0145 union ifs_chunks_auth_status {
0146     u64 data;
0147     struct {
0148         u32 valid_chunks    :8;
0149         u32 total_chunks    :8;
0150         u32 rsvd1       :16;
0151         u32 error_code  :8;
0152         u32 rsvd2       :24;
0153     };
0154 };
0155 
0156 /* MSR_ACTIVATE_SCAN bit fields */
0157 union ifs_scan {
0158     u64 data;
0159     struct {
0160         u32 start   :8;
0161         u32 stop    :8;
0162         u32 rsvd    :16;
0163         u32 delay   :31;
0164         u32 sigmce  :1;
0165     };
0166 };
0167 
0168 /* MSR_SCAN_STATUS bit fields */
0169 union ifs_status {
0170     u64 data;
0171     struct {
0172         u32 chunk_num       :8;
0173         u32 chunk_stop_index    :8;
0174         u32 rsvd1           :16;
0175         u32 error_code      :8;
0176         u32 rsvd2           :22;
0177         u32 control_error       :1;
0178         u32 signature_error     :1;
0179     };
0180 };
0181 
0182 /*
0183  * Driver populated error-codes
0184  * 0xFD: Test timed out before completing all the chunks.
0185  * 0xFE: not all scan chunks were executed. Maximum forward progress retries exceeded.
0186  */
0187 #define IFS_SW_TIMEOUT              0xFD
0188 #define IFS_SW_PARTIAL_COMPLETION       0xFE
0189 
0190 /**
0191  * struct ifs_data - attributes related to intel IFS driver
0192  * @integrity_cap_bit: MSR_INTEGRITY_CAPS bit enumerating this test
0193  * @loaded_version: stores the currently loaded ifs image version.
0194  * @loaded: If a valid test binary has been loaded into the memory
0195  * @loading_error: Error occurred on another CPU while loading image
0196  * @valid_chunks: number of chunks which could be validated.
0197  * @status: it holds simple status pass/fail/untested
0198  * @scan_details: opaque scan status code from h/w
0199  */
0200 struct ifs_data {
0201     int integrity_cap_bit;
0202     int loaded_version;
0203     bool    loaded;
0204     bool    loading_error;
0205     int valid_chunks;
0206     int status;
0207     u64 scan_details;
0208 };
0209 
0210 struct ifs_work {
0211     struct work_struct w;
0212     struct device *dev;
0213 };
0214 
0215 struct ifs_device {
0216     struct ifs_data data;
0217     struct miscdevice misc;
0218 };
0219 
0220 static inline struct ifs_data *ifs_get_data(struct device *dev)
0221 {
0222     struct miscdevice *m = dev_get_drvdata(dev);
0223     struct ifs_device *d = container_of(m, struct ifs_device, misc);
0224 
0225     return &d->data;
0226 }
0227 
0228 void ifs_load_firmware(struct device *dev);
0229 int do_core_test(int cpu, struct device *dev);
0230 const struct attribute_group **ifs_get_groups(void);
0231 
0232 extern struct semaphore ifs_sem;
0233 
0234 #endif