@@ -247,6 +247,8 @@
#define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT)
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
+#define MSR_INTEGRITY_CAPS_SBAF_BIT 8
+#define MSR_INTEGRITY_CAPS_SBAF BIT(MSR_INTEGRITY_CAPS_SBAF_BIT)
#define MSR_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9)
#define MSR_LBR_NHM_FROM 0x00000680
@@ -126,11 +126,38 @@
* The driver does not make use of this, it only tests one core at a time.
*
* .. [#f1] https://github.com/intel/TBD
+ *
+ *
+ * Structural Based Functional Test at Field (SBAF):
+ * ------------------------------------------------
+ *
+ * SBAF is a new type of testing that provides comprehensive core test
+ * coverage complementing Scan at Field (SAF) testing. SBAF mimics the
+ * manufacturing screening environment and leverages the same test suite.
+ * It makes use of Design For Test (DFT) observation sites and features
+ * to maximize coverage in minimum time.
+ *
+ * Similar to the SAF test, SBAF isolates the core under test from the
+ * rest of the system during execution. Upon completion, the core
+ * seamlessly resets to its pre-test state and resumes normal operation.
+ * Any machine checks or hangs encountered during the test are confined to
+ * the isolated core, preventing disruption to the overall system.
+ *
+ * Like the SAF test, the SBAF test is also divided into multiple batches,
+ * and each batch test can take hundreds of milliseconds (100-200 ms) to
+ * complete. If such a lengthy interruption is undesirable, it is
+ * recommended to relocate the time-sensitive applications to other cores.
*/
#include <linux/device.h>
#include <linux/miscdevice.h>
#define MSR_ARRAY_BIST 0x00000105
+
+#define MSR_COPY_SBAF_HASHES 0x000002b8
+#define MSR_SBAF_HASHES_STATUS 0x000002b9
+#define MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK 0x000002ba
+#define MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS 0x000002bb
+
#define MSR_COPY_SCAN_HASHES 0x000002c2
#define MSR_SCAN_HASHES_STATUS 0x000002c3
#define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4
@@ -140,6 +167,7 @@
#define MSR_ARRAY_TRIGGER 0x000002d6
#define MSR_ARRAY_STATUS 0x000002d7
#define MSR_SAF_CTRL 0x000004f0
+#define MSR_SBAF_CTRL 0x000004f8
#define SCAN_NOT_TESTED 0
#define SCAN_TEST_PASS 1
@@ -147,6 +175,7 @@
#define IFS_TYPE_SAF 0
#define IFS_TYPE_ARRAY_BIST 1
+#define IFS_TYPE_SBAF 2
#define ARRAY_GEN0 0
#define ARRAY_GEN1 1
@@ -196,7 +225,8 @@ union ifs_chunks_auth_status_gen2 {
u16 valid_chunks;
u16 total_chunks;
u32 error_code :8;
- u32 rsvd2 :24;
+ u32 rsvd2 :8;
+ u32 max_bundle :16;
};
};
@@ -261,9 +291,12 @@ union ifs_array {
#define IFS_SW_TIMEOUT 0xFD
#define IFS_SW_PARTIAL_COMPLETION 0xFE
+#define IFS_SUFFIX_SZ 5
+
struct ifs_test_caps {
int integrity_cap_bit;
int test_num;
+ char image_suffix[IFS_SUFFIX_SZ];
};
/**
@@ -294,6 +327,7 @@ struct ifs_test_msrs {
* @generation: IFS test generation enumerated by hardware
* @chunk_size: size of a test chunk
* @array_gen: test generation of array test
+ * @max_bundle: maximum bundle index
*/
struct ifs_data {
int loaded_version;
@@ -306,6 +340,7 @@ struct ifs_data {
u32 generation;
u32 chunk_size;
u32 array_gen;
+ u32 max_bundle;
};
struct ifs_work {
@@ -33,6 +33,7 @@ bool *ifs_pkg_auth;
static const struct ifs_test_caps scan_test = {
.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
.test_num = IFS_TYPE_SAF,
+ .image_suffix = "scan",
};
static const struct ifs_test_caps array_test = {
@@ -48,6 +49,20 @@ static const struct ifs_test_msrs scan_msrs = {
.test_ctrl = MSR_SAF_CTRL,
};
+static const struct ifs_test_msrs sbaf_msrs = {
+ .copy_hashes = MSR_COPY_SBAF_HASHES,
+ .copy_hashes_status = MSR_SBAF_HASHES_STATUS,
+ .copy_chunks = MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK,
+ .copy_chunks_status = MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS,
+ .test_ctrl = MSR_SBAF_CTRL,
+};
+
+static const struct ifs_test_caps sbaf_test = {
+ .integrity_cap_bit = MSR_INTEGRITY_CAPS_SBAF_BIT,
+ .test_num = IFS_TYPE_SBAF,
+ .image_suffix = "sbft",
+};
+
static struct ifs_device ifs_devices[] = {
[IFS_TYPE_SAF] = {
.test_caps = &scan_test,
@@ -66,6 +81,15 @@ static struct ifs_device ifs_devices[] = {
.groups = plat_ifs_array_groups,
},
},
+ [IFS_TYPE_SBAF] = {
+ .test_caps = &sbaf_test,
+ .test_msrs = &sbaf_msrs,
+ .misc = {
+ .name = "intel_ifs_2",
+ .minor = MISC_DYNAMIC_MINOR,
+ .groups = plat_ifs_groups,
+ },
+ },
};
#define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
@@ -261,20 +261,22 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
return -EIO;
}
ifsd->valid_chunks = valid_chunks;
+ ifsd->max_bundle = chunk_status.max_bundle;
return 0;
}
static int validate_ifs_metadata(struct device *dev)
{
+ const struct ifs_test_caps *test = ifs_get_test_caps(dev);
struct ifs_data *ifsd = ifs_get_data(dev);
union meta_data *ifs_meta;
char test_file[64];
int ret = -EINVAL;
- snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.scan",
+ snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.%s",
boot_cpu_data.x86, boot_cpu_data.x86_model,
- boot_cpu_data.x86_stepping, ifsd->cur_batch);
+ boot_cpu_data.x86_stepping, ifsd->cur_batch, test->image_suffix);
ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS);
if (!ifs_meta) {
@@ -304,6 +306,11 @@ static int validate_ifs_metadata(struct device *dev)
return ret;
}
+ if (ifs_meta->test_type != test->test_num) {
+ dev_warn(dev, "Metadata test_type %d mismatches with device type\n",
+ ifs_meta->test_type);
+ }
+
return 0;
}
@@ -391,9 +398,9 @@ int ifs_load_firmware(struct device *dev)
char scan_path[64];
int ret;
- snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.scan",
+ snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.%s",
test->test_num, boot_cpu_data.x86, boot_cpu_data.x86_model,
- boot_cpu_data.x86_stepping, ifsd->cur_batch);
+ boot_cpu_data.x86_stepping, ifsd->cur_batch, test->image_suffix);
ret = request_firmware_direct(&fw, scan_path, dev);
if (ret) {