Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -10601,6 +10601,7 @@ R: Tony Luck <tony.luck@intel.com>
S: Maintained
F: drivers/platform/x86/intel/ifs
F: include/trace/events/intel_ifs.h
F: tools/testing/selftests/drivers/platform/x86/intel/ifs/

INTEL INTEGRATED SENSOR HUB DRIVER
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/msr-index.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,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
Expand Down
33 changes: 33 additions & 0 deletions drivers/platform/x86/intel/ifs/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,40 @@ 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 = {
.integrity_cap_bit = MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT,
.test_num = IFS_TYPE_ARRAY_BIST,
};

static const struct ifs_test_msrs scan_msrs = {
.copy_hashes = MSR_COPY_SCAN_HASHES,
.copy_hashes_status = MSR_SCAN_HASHES_STATUS,
.copy_chunks = MSR_AUTHENTICATE_AND_COPY_CHUNK,
.copy_chunks_status = MSR_CHUNKS_AUTHENTICATION_STATUS,
.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,
.test_msrs = &scan_msrs,
.misc = {
.name = "intel_ifs_0",
.minor = MISC_DYNAMIC_MINOR,
Expand All @@ -57,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)
Expand Down
92 changes: 91 additions & 1 deletion drivers/platform/x86/intel/ifs/ifs.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,40 @@
* 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_ACTIVATE_SBAF 0x000002bc
#define MSR_SBAF_STATUS 0x000002bd

#define MSR_COPY_SCAN_HASHES 0x000002c2
#define MSR_SCAN_HASHES_STATUS 0x000002c3
#define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4
Expand All @@ -140,13 +169,15 @@
#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
#define SCAN_TEST_FAIL 2

#define IFS_TYPE_SAF 0
#define IFS_TYPE_ARRAY_BIST 1
#define IFS_TYPE_SBAF 2

#define ARRAY_GEN0 0
#define ARRAY_GEN1 1
Expand Down Expand Up @@ -196,7 +227,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;
};
};

Expand Down Expand Up @@ -253,6 +285,34 @@ union ifs_array {
};
};

/* MSR_ACTIVATE_SBAF bit fields */
union ifs_sbaf {
u64 data;
struct {
u32 bundle_idx :9;
u32 rsvd1 :5;
u32 pgm_idx :2;
u32 rsvd2 :16;
u32 delay :31;
u32 sigmce :1;
};
};

/* MSR_SBAF_STATUS bit fields */
union ifs_sbaf_status {
u64 data;
struct {
u32 bundle_idx :9;
u32 rsvd1 :5;
u32 pgm_idx :2;
u32 rsvd2 :16;
u32 error_code :8;
u32 rsvd3 :21;
u32 test_fail :1;
u32 sbaf_status :2;
};
};

/*
* Driver populated error-codes
* 0xFD: Test timed out before completing all the chunks.
Expand All @@ -261,9 +321,28 @@ 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];
};

/**
* struct ifs_test_msrs - MSRs used in IFS tests
* @copy_hashes: Copy test hash data
* @copy_hashes_status: Status of copied test hash data
* @copy_chunks: Copy chunks of the test data
* @copy_chunks_status: Status of the copied test data chunks
* @test_ctrl: Control the test attributes
*/
struct ifs_test_msrs {
u32 copy_hashes;
u32 copy_hashes_status;
u32 copy_chunks;
u32 copy_chunks_status;
u32 test_ctrl;
};

/**
Expand All @@ -278,6 +357,7 @@ struct ifs_test_caps {
* @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;
Expand All @@ -290,6 +370,7 @@ struct ifs_data {
u32 generation;
u32 chunk_size;
u32 array_gen;
u32 max_bundle;
};

struct ifs_work {
Expand All @@ -299,6 +380,7 @@ struct ifs_work {

struct ifs_device {
const struct ifs_test_caps *test_caps;
const struct ifs_test_msrs *test_msrs;
struct ifs_data rw_data;
struct miscdevice misc;
};
Expand All @@ -319,6 +401,14 @@ static inline const struct ifs_test_caps *ifs_get_test_caps(struct device *dev)
return d->test_caps;
}

static inline const struct ifs_test_msrs *ifs_get_test_msrs(struct device *dev)
{
struct miscdevice *m = dev_get_drvdata(dev);
struct ifs_device *d = container_of(m, struct ifs_device, misc);

return d->test_msrs;
}

extern bool *ifs_pkg_auth;
int ifs_load_firmware(struct device *dev);
int do_core_test(int cpu, struct device *dev);
Expand Down
44 changes: 29 additions & 15 deletions drivers/platform/x86/intel/ifs/load.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,17 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work)
union ifs_scan_hashes_status hashes_status;
union ifs_chunks_auth_status chunk_status;
struct device *dev = local_work->dev;
const struct ifs_test_msrs *msrs;
int i, num_chunks, chunk_size;
struct ifs_data *ifsd;
u64 linear_addr, base;
u32 err_code;

ifsd = ifs_get_data(dev);
msrs = ifs_get_test_msrs(dev);
/* run scan hash copy */
wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);
wrmsrl(msrs->copy_hashes, ifs_hash_ptr);
rdmsrl(msrs->copy_hashes_status, hashes_status.data);

/* enumerate the scan image information */
num_chunks = hashes_status.num_chunks;
Expand All @@ -147,8 +149,8 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work)
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);
wrmsrl(msrs->copy_chunks, linear_addr);
rdmsrl(msrs->copy_chunks_status, chunk_status.data);

ifsd->valid_chunks = chunk_status.valid_chunks;
err_code = chunk_status.error_code;
Expand Down Expand Up @@ -180,6 +182,7 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
union ifs_scan_hashes_status_gen2 hashes_status;
union ifs_chunks_auth_status_gen2 chunk_status;
u32 err_code, valid_chunks, total_chunks;
const struct ifs_test_msrs *msrs;
int i, num_chunks, chunk_size;
union meta_data *ifs_meta;
int starting_chunk_nr;
Expand All @@ -189,10 +192,11 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
int retry_count;

ifsd = ifs_get_data(dev);
msrs = ifs_get_test_msrs(dev);

if (need_copy_scan_hashes(ifsd)) {
wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);
wrmsrl(msrs->copy_hashes, ifs_hash_ptr);
rdmsrl(msrs->copy_hashes_status, hashes_status.data);

/* enumerate the scan image information */
chunk_size = hashes_status.chunk_size * SZ_1K;
Expand All @@ -212,8 +216,8 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
}

if (ifsd->generation >= IFS_GEN_STRIDE_AWARE) {
wrmsrl(MSR_SAF_CTRL, INVALIDATE_STRIDE);
rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
wrmsrl(msrs->test_ctrl, INVALIDATE_STRIDE);
rdmsrl(msrs->copy_chunks_status, chunk_status.data);
if (chunk_status.valid_chunks != 0) {
dev_err(dev, "Couldn't invalidate installed stride - %d\n",
chunk_status.valid_chunks);
Expand All @@ -233,8 +237,10 @@ static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
chunk_table[0] = starting_chunk_nr + i;
chunk_table[1] = linear_addr;
do {
wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, (u64)chunk_table);
rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
local_irq_disable();
wrmsrl(msrs->copy_chunks, (u64)chunk_table);
local_irq_enable();
rdmsrl(msrs->copy_chunks_status, chunk_status.data);
err_code = chunk_status.error_code;
} while (err_code == AUTH_INTERRUPTED_ERROR && --retry_count);

Expand All @@ -255,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) {
Expand Down Expand Up @@ -298,6 +306,12 @@ 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 ret;
}

return 0;
}

Expand Down Expand Up @@ -383,11 +397,11 @@ int ifs_load_firmware(struct device *dev)
unsigned int expected_size;
const struct firmware *fw;
char scan_path[64];
int ret = -EINVAL;
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) {
Expand Down
Loading