Commit 0a3e4e94 authored by Jithu Joseph's avatar Jithu Joseph Committed by Hans de Goede

platform/x86/intel/ifs: Add SBAF test image loading support

Structural Based Functional Test at Field (SBAF) is a new type of
testing that provides comprehensive core test coverage complementing
existing IFS tests like Scan at Field (SAF) or ArrayBist.

SBAF device will appear as a new device instance (intel_ifs_2) under
/sys/devices/virtual/misc. The user interaction necessary to load the
test image and test a particular core is the same as the existing scan
test (intel_ifs_0).

During the loading stage, the driver will look for a file named
ff-mm-ss-<batch02x>.sbft in the /lib/firmware/intel/ifs_2 directory.
The hardware interaction needed for loading the image is similar to
SAF, with the only difference being the MSR addresses used. Reuse the
SAF image loading code, passing the SBAF-specific MSR addresses via
struct ifs_test_msrs in the driver device data.

Unlike SAF, the SBAF test image chunks are further divided into smaller
logical entities called bundles. Since the SBAF test is initiated per
bundle, cache the maximum number of bundles in the current image, which
is used for iterating through bundles during SBAF test execution.
Reviewed-by: default avatarAshok Raj <ashok.raj@intel.com>
Reviewed-by: default avatarTony Luck <tony.luck@intel.com>
Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarJithu Joseph <jithu.joseph@intel.com>
Co-developed-by: default avatarKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: default avatarKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.comSigned-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 7e597d49
...@@ -247,6 +247,8 @@ ...@@ -247,6 +247,8 @@
#define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT) #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 4
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) #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_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9)
#define MSR_LBR_NHM_FROM 0x00000680 #define MSR_LBR_NHM_FROM 0x00000680
......
...@@ -32,6 +32,7 @@ bool *ifs_pkg_auth; ...@@ -32,6 +32,7 @@ bool *ifs_pkg_auth;
static const struct ifs_test_caps scan_test = { static const struct ifs_test_caps scan_test = {
.integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT, .integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT,
.test_num = IFS_TYPE_SAF, .test_num = IFS_TYPE_SAF,
.image_suffix = "scan",
}; };
static const struct ifs_test_caps array_test = { static const struct ifs_test_caps array_test = {
...@@ -47,6 +48,20 @@ static const struct ifs_test_msrs scan_msrs = { ...@@ -47,6 +48,20 @@ static const struct ifs_test_msrs scan_msrs = {
.test_ctrl = MSR_SAF_CTRL, .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[] = { static struct ifs_device ifs_devices[] = {
[IFS_TYPE_SAF] = { [IFS_TYPE_SAF] = {
.test_caps = &scan_test, .test_caps = &scan_test,
...@@ -65,6 +80,15 @@ static struct ifs_device ifs_devices[] = { ...@@ -65,6 +80,15 @@ static struct ifs_device ifs_devices[] = {
.groups = plat_ifs_array_groups, .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) #define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
......
...@@ -126,11 +126,38 @@ ...@@ -126,11 +126,38 @@
* The driver does not make use of this, it only tests one core at a time. * The driver does not make use of this, it only tests one core at a time.
* *
* .. [#f1] https://github.com/intel/TBD * .. [#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/device.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#define MSR_ARRAY_BIST 0x00000105 #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_COPY_SCAN_HASHES 0x000002c2
#define MSR_SCAN_HASHES_STATUS 0x000002c3 #define MSR_SCAN_HASHES_STATUS 0x000002c3
#define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4 #define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4
...@@ -140,6 +167,7 @@ ...@@ -140,6 +167,7 @@
#define MSR_ARRAY_TRIGGER 0x000002d6 #define MSR_ARRAY_TRIGGER 0x000002d6
#define MSR_ARRAY_STATUS 0x000002d7 #define MSR_ARRAY_STATUS 0x000002d7
#define MSR_SAF_CTRL 0x000004f0 #define MSR_SAF_CTRL 0x000004f0
#define MSR_SBAF_CTRL 0x000004f8
#define SCAN_NOT_TESTED 0 #define SCAN_NOT_TESTED 0
#define SCAN_TEST_PASS 1 #define SCAN_TEST_PASS 1
...@@ -147,6 +175,7 @@ ...@@ -147,6 +175,7 @@
#define IFS_TYPE_SAF 0 #define IFS_TYPE_SAF 0
#define IFS_TYPE_ARRAY_BIST 1 #define IFS_TYPE_ARRAY_BIST 1
#define IFS_TYPE_SBAF 2
#define ARRAY_GEN0 0 #define ARRAY_GEN0 0
#define ARRAY_GEN1 1 #define ARRAY_GEN1 1
...@@ -196,7 +225,8 @@ union ifs_chunks_auth_status_gen2 { ...@@ -196,7 +225,8 @@ union ifs_chunks_auth_status_gen2 {
u16 valid_chunks; u16 valid_chunks;
u16 total_chunks; u16 total_chunks;
u32 error_code :8; u32 error_code :8;
u32 rsvd2 :24; u32 rsvd2 :8;
u32 max_bundle :16;
}; };
}; };
...@@ -261,9 +291,12 @@ union ifs_array { ...@@ -261,9 +291,12 @@ union ifs_array {
#define IFS_SW_TIMEOUT 0xFD #define IFS_SW_TIMEOUT 0xFD
#define IFS_SW_PARTIAL_COMPLETION 0xFE #define IFS_SW_PARTIAL_COMPLETION 0xFE
#define IFS_SUFFIX_SZ 5
struct ifs_test_caps { struct ifs_test_caps {
int integrity_cap_bit; int integrity_cap_bit;
int test_num; int test_num;
char image_suffix[IFS_SUFFIX_SZ];
}; };
/** /**
...@@ -294,6 +327,7 @@ struct ifs_test_msrs { ...@@ -294,6 +327,7 @@ struct ifs_test_msrs {
* @generation: IFS test generation enumerated by hardware * @generation: IFS test generation enumerated by hardware
* @chunk_size: size of a test chunk * @chunk_size: size of a test chunk
* @array_gen: test generation of array test * @array_gen: test generation of array test
* @max_bundle: maximum bundle index
*/ */
struct ifs_data { struct ifs_data {
int loaded_version; int loaded_version;
...@@ -306,6 +340,7 @@ struct ifs_data { ...@@ -306,6 +340,7 @@ struct ifs_data {
u32 generation; u32 generation;
u32 chunk_size; u32 chunk_size;
u32 array_gen; u32 array_gen;
u32 max_bundle;
}; };
struct ifs_work { struct ifs_work {
......
...@@ -261,20 +261,22 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev) ...@@ -261,20 +261,22 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
return -EIO; return -EIO;
} }
ifsd->valid_chunks = valid_chunks; ifsd->valid_chunks = valid_chunks;
ifsd->max_bundle = chunk_status.max_bundle;
return 0; return 0;
} }
static int validate_ifs_metadata(struct device *dev) 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); struct ifs_data *ifsd = ifs_get_data(dev);
union meta_data *ifs_meta; union meta_data *ifs_meta;
char test_file[64]; char test_file[64];
int ret = -EINVAL; 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, 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); ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS);
if (!ifs_meta) { if (!ifs_meta) {
...@@ -304,6 +306,12 @@ static int validate_ifs_metadata(struct device *dev) ...@@ -304,6 +306,12 @@ static int validate_ifs_metadata(struct device *dev)
return ret; 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 ret;
}
return 0; return 0;
} }
...@@ -391,9 +399,9 @@ int ifs_load_firmware(struct device *dev) ...@@ -391,9 +399,9 @@ int ifs_load_firmware(struct device *dev)
char scan_path[64]; char scan_path[64];
int ret; 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, 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); ret = request_firmware_direct(&fw, scan_path, dev);
if (ret) { if (ret) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment