]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
platform/x86/intel/ifs: Add current_batch sysfs entry
authorJithu Joseph <jithu.joseph@intel.com>
Thu, 17 Nov 2022 03:59:33 +0000 (19:59 -0800)
committerBorislav Petkov <bp@suse.de>
Sat, 19 Nov 2022 10:29:00 +0000 (11:29 +0100)
Initial implementation assumed a single IFS test image file with a
fixed name ff-mm-ss.scan. (where ff, mm, ss refers to family, model and
stepping of the core).

Subsequently, it became evident that supporting more than one test
image file is needed to provide more comprehensive test coverage. (Test
coverage in this scenario refers to testing more transistors in the core
to identify faults).

The other alternative of increasing the size of a single scan test image
file would not work as the  upper bound is limited by the size of memory
area reserved by BIOS for loading IFS test image.

Introduce "current_batch" file which accepts a number. Writing a
number to the current_batch file would load the test image file by
name ff-mm-ss-<xy>.scan, where <xy> is the number written to the
"current_batch" file in hex. Range check of the input is done to verify
it not greater than 0xff.

For e.g if the scan test image comprises of 6 files, they would be named:

  06-8f-06-01.scan
  06-8f-06-02.scan
  06-8f-06-03.scan
  06-8f-06-04.scan
  06-8f-06-05.scan
  06-8f-06-06.scan

And writing 3 to current_batch would result in loading 06-8f-06-03.scan
above. The file can also be read to know the currently loaded file.

And testing a system looks like:

  for each scan file
  do
   load the IFS test image file (write to the batch file)
   for each core
   do
   test the core with this set of tests
   done
  done

Qualify few error messages with the test image file suffix to provide
better context.

  [ bp: Massage commit message. Add link to the discussion. ]

Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20221107225323.2733518-13-jithu.joseph@intel.com
drivers/platform/x86/intel/ifs/core.c
drivers/platform/x86/intel/ifs/ifs.h
drivers/platform/x86/intel/ifs/load.c
drivers/platform/x86/intel/ifs/runtest.c
drivers/platform/x86/intel/ifs/sysfs.c

index 943eb2a17c6403004c6ec81340b9e0381902d475..206a617c2e02c1daebe32b3058193f4bdd2f07f8 100644 (file)
@@ -23,6 +23,7 @@ MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
 static struct ifs_device ifs_device = {
        .data = {
                .integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
+               .test_num = 0,
        },
        .misc = {
                .name = "intel_ifs_0",
index 74c051c544f4dd1919d02957a5516d804da8645f..da1474e1d8eb3178f2942c0d69dd9c5a90f8a933 100644 (file)
  * 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::
+ * feedback on the success/failure of these steps.
  *
- *   # echo 1 > /sys/devices/virtual/misc/intel_ifs_0/reload
+ * The test files are kept in a fixed location: /lib/firmware/intel/ifs_0/
+ * For e.g if there are 3 test files, they would be named in the following
+ * fashion:
+ * ff-mm-ss-01.scan
+ * ff-mm-ss-02.scan
+ * ff-mm-ss-03.scan
+ * (where ff refers to family, mm indicates model and ss indicates stepping)
  *
- * 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
+ * A different test file can be loaded by writing the numerical portion
+ * (e.g 1, 2 or 3 in the above scenario) into the curent_batch file.
+ * To load ff-mm-ss-02.scan, the following command can be used::
+ *
+ *   # echo 2 > /sys/devices/virtual/misc/intel_ifs_0/current_batch
+ *
+ * The above file can also be read to know the currently loaded image.
  *
  * Running tests
  * -------------
@@ -209,6 +219,7 @@ struct ifs_data {
        int     status;
        u64     scan_details;
        u32     cur_batch;
+       int     test_num;
 };
 
 struct ifs_work {
@@ -229,7 +240,7 @@ static inline struct ifs_data *ifs_get_data(struct device *dev)
        return &d->data;
 }
 
-void ifs_load_firmware(struct device *dev);
+int ifs_load_firmware(struct device *dev);
 int do_core_test(int cpu, struct device *dev);
 const struct attribute_group **ifs_get_groups(void);
 
index edc7baa976bf88cbed7e8ef8351fb7d6bc694485..c5c24e6fdc436e580db4d4cb75132405d2c7dd45 100644 (file)
@@ -253,17 +253,18 @@ static int image_sanity_check(struct device *dev, const struct microcode_header_
 
 /*
  * 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}.
+ * in /lib/firmware/intel/ifs_x/ and named as family-model-stepping-02x.{testname}.
  */
-void ifs_load_firmware(struct device *dev)
+int ifs_load_firmware(struct device *dev)
 {
        struct ifs_data *ifsd = ifs_get_data(dev);
        const struct firmware *fw;
-       char scan_path[32];
-       int ret;
+       char scan_path[64];
+       int ret = -EINVAL;
 
-       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);
+       snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.scan",
+                ifsd->test_num, boot_cpu_data.x86, boot_cpu_data.x86_model,
+                boot_cpu_data.x86_stepping, ifsd->cur_batch);
 
        ret = request_firmware_direct(&fw, scan_path, dev);
        if (ret) {
@@ -279,8 +280,13 @@ void ifs_load_firmware(struct device *dev)
        ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
 
        ret = scan_chunks_sanity_check(dev);
+       if (ret)
+               dev_err(dev, "Load failure for batch: %02x\n", ifsd->cur_batch);
+
 release:
        release_firmware(fw);
 done:
        ifsd->loaded = (ret == 0);
+
+       return ret;
 }
index b2ca2bb4501f6e7e7cdbc9343f2b695da212580e..0bfd8fcdd7e804150124c77830b8935496195a5c 100644 (file)
@@ -78,14 +78,16 @@ static void message_not_tested(struct device *dev, int cpu, union ifs_status sta
 
 static void message_fail(struct device *dev, int cpu, union ifs_status status)
 {
+       struct ifs_data *ifsd = ifs_get_data(dev);
+
        /*
         * 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)));
+               dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image. Batch: %02x version: 0x%x\n",
+                       cpumask_pr_args(cpu_smt_mask(cpu)), ifsd->cur_batch, ifsd->loaded_version);
        }
 
        /*
@@ -96,8 +98,8 @@ static void message_fail(struct device *dev, int cpu, union ifs_status status)
         * 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)));
+               dev_err(dev, "CPU(s) %*pbl: test signature incorrect. Batch: %02x version: 0x%x\n",
+                       cpumask_pr_args(cpu_smt_mask(cpu)), ifsd->cur_batch, ifsd->loaded_version);
        }
 }
 
index e077910c5d28071d63f962d8a84bb1473a22d4da..ee636a76b083ab26d3afa956307a9d3c38f3babb 100644 (file)
@@ -87,6 +87,43 @@ static ssize_t run_test_store(struct device *dev,
 
 static DEVICE_ATTR_WO(run_test);
 
+static ssize_t current_batch_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       struct ifs_data *ifsd = ifs_get_data(dev);
+       unsigned int cur_batch;
+       int rc;
+
+       rc = kstrtouint(buf, 0, &cur_batch);
+       if (rc < 0 || cur_batch > 0xff)
+               return -EINVAL;
+
+       if (down_interruptible(&ifs_sem))
+               return -EINTR;
+
+       ifsd->cur_batch = cur_batch;
+
+       rc = ifs_load_firmware(dev);
+
+       up(&ifs_sem);
+
+       return (rc == 0) ? count : rc;
+}
+
+static ssize_t current_batch_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, "none\n");
+       else
+               return sysfs_emit(buf, "0x%02x\n", ifsd->cur_batch);
+}
+
+static DEVICE_ATTR_RW(current_batch);
+
 /*
  * Display currently loaded IFS image version.
  */
@@ -108,6 +145,7 @@ static struct attribute *plat_ifs_attrs[] = {
        &dev_attr_details.attr,
        &dev_attr_status.attr,
        &dev_attr_run_test.attr,
+       &dev_attr_current_batch.attr,
        &dev_attr_image_version.attr,
        NULL
 };