linux/drivers/platform/x86/intel/ifs/load.c

439 lines
12 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation. */
#include <linux/firmware.h>
#include <linux/sizes.h>
#include <asm/cpu.h>
#include <asm/microcode.h>
#include <asm/msr.h>
#include "ifs.h"
#define IFS_CHUNK_ALIGNMENT 256
union meta_data {
struct {
u32 meta_type; // metadata type
u32 meta_size; // size of this entire struct including hdrs.
u32 test_type; // IFS test type
u32 fusa_info; // Fusa info
u32 total_images; // Total number of images
u32 current_image; // Current Image #
u32 total_chunks; // Total number of chunks in this image
u32 starting_chunk; // Starting chunk number in this image
u32 size_per_chunk; // size of each chunk
u32 chunks_per_stride; // number of chunks in a stride
};
u8 padding[IFS_CHUNK_ALIGNMENT];
};
#define IFS_HEADER_SIZE (sizeof(struct microcode_header_intel))
#define META_TYPE_IFS 1
#define INVALIDATE_STRIDE 0x1UL
#define IFS_GEN_STRIDE_AWARE 2
#define AUTH_INTERRUPTED_ERROR 5
#define IFS_AUTH_RETRY_CT 10
static struct microcode_header_intel *ifs_header_ptr; /* pointer to the ifs image header */
static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */
static u64 ifs_test_image_ptr; /* 256B aligned address of test pattern */
static DECLARE_COMPLETION(ifs_done);
static const char * const scan_hash_status[] = {
[0] = "No error reported",
[1] = "Attempt to copy scan hashes when copy already in progress",
[2] = "Secure Memory not set up correctly",
[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
[4] = "Reserved",
[5] = "Integrity check failed",
[6] = "Scan reload or test is in progress"
};
static const char * const scan_authentication_status[] = {
[0] = "No error reported",
[1] = "Attempt to authenticate a chunk which is already marked as authentic",
[2] = "Chunk authentication error. The hash of chunk did not match expected value",
[3] = "Reserved",
[4] = "Chunk outside the current stride",
[5] = "Authentication flow interrupted",
};
platform/x86/intel/ifs: Add metadata support One of the existing reserved fields in the microcode header has been allocated to indicate the size of metadata structures. The location of metadata section within microcode header is as shown below: Microcode Blob Format +----------------------+ Base |Header Version | +----------------------+ |Update revision | +----------------------+ |Date DDMMYYYY | +----------------------+ |Sig | +----------------------+ |Checksum | +----------------------+ |Loader Version | +----------------------+ |Processor Flags | +----------------------+ |Data Size | +----------------------+ |Total Size | +----------------------+ |Meta Size | +----------------------+ |Reserved | +----------------------+ |Reserved | +----------------------+ Base+48 | | | Microcode | | Data | | | +----------------------+ Base+48+data_size- | | meta_size | Meta Data | | structure(s) | | | +----------------------+ Base+48+data_size | | | Extended Signature | | Table | | | +----------------------+ Base+total_size Add an accessor function which will return a pointer to the start of a specific meta_type being queried. [ bp: Massage commit message. ] Signed-off-by: Ashok Raj <ashok.raj@intel.com> 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/20221117035935.4136738-11-jithu.joseph@intel.com
2022-11-16 19:59:29 -08:00
#define MC_HEADER_META_TYPE_END (0)
struct metadata_header {
unsigned int type;
unsigned int blk_size;
};
static struct metadata_header *find_meta_data(void *ucode, unsigned int meta_type)
{
struct microcode_header_intel *hdr = &((struct microcode_intel *)ucode)->hdr;
platform/x86/intel/ifs: Add metadata support One of the existing reserved fields in the microcode header has been allocated to indicate the size of metadata structures. The location of metadata section within microcode header is as shown below: Microcode Blob Format +----------------------+ Base |Header Version | +----------------------+ |Update revision | +----------------------+ |Date DDMMYYYY | +----------------------+ |Sig | +----------------------+ |Checksum | +----------------------+ |Loader Version | +----------------------+ |Processor Flags | +----------------------+ |Data Size | +----------------------+ |Total Size | +----------------------+ |Meta Size | +----------------------+ |Reserved | +----------------------+ |Reserved | +----------------------+ Base+48 | | | Microcode | | Data | | | +----------------------+ Base+48+data_size- | | meta_size | Meta Data | | structure(s) | | | +----------------------+ Base+48+data_size | | | Extended Signature | | Table | | | +----------------------+ Base+total_size Add an accessor function which will return a pointer to the start of a specific meta_type being queried. [ bp: Massage commit message. ] Signed-off-by: Ashok Raj <ashok.raj@intel.com> 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/20221117035935.4136738-11-jithu.joseph@intel.com
2022-11-16 19:59:29 -08:00
struct metadata_header *meta_header;
unsigned long data_size, total_meta;
unsigned long meta_size = 0;
data_size = intel_microcode_get_datasize(hdr);
total_meta = hdr->metasize;
platform/x86/intel/ifs: Add metadata support One of the existing reserved fields in the microcode header has been allocated to indicate the size of metadata structures. The location of metadata section within microcode header is as shown below: Microcode Blob Format +----------------------+ Base |Header Version | +----------------------+ |Update revision | +----------------------+ |Date DDMMYYYY | +----------------------+ |Sig | +----------------------+ |Checksum | +----------------------+ |Loader Version | +----------------------+ |Processor Flags | +----------------------+ |Data Size | +----------------------+ |Total Size | +----------------------+ |Meta Size | +----------------------+ |Reserved | +----------------------+ |Reserved | +----------------------+ Base+48 | | | Microcode | | Data | | | +----------------------+ Base+48+data_size- | | meta_size | Meta Data | | structure(s) | | | +----------------------+ Base+48+data_size | | | Extended Signature | | Table | | | +----------------------+ Base+total_size Add an accessor function which will return a pointer to the start of a specific meta_type being queried. [ bp: Massage commit message. ] Signed-off-by: Ashok Raj <ashok.raj@intel.com> 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/20221117035935.4136738-11-jithu.joseph@intel.com
2022-11-16 19:59:29 -08:00
if (!total_meta)
return NULL;
meta_header = (ucode + MC_HEADER_SIZE + data_size) - total_meta;
while (meta_header->type != MC_HEADER_META_TYPE_END &&
meta_header->blk_size &&
meta_size < total_meta) {
meta_size += meta_header->blk_size;
if (meta_header->type == meta_type)
return meta_header;
meta_header = (void *)meta_header + meta_header->blk_size;
}
return NULL;
}
static void hashcopy_err_message(struct device *dev, u32 err_code)
{
if (err_code >= ARRAY_SIZE(scan_hash_status))
dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
else
dev_err(dev, "Hash copy error : %s\n", scan_hash_status[err_code]);
}
static void auth_err_message(struct device *dev, u32 err_code)
{
if (err_code >= ARRAY_SIZE(scan_authentication_status))
dev_err(dev, "invalid error code 0x%x for authentication\n", err_code);
else
dev_err(dev, "Chunk authentication error : %s\n",
scan_authentication_status[err_code]);
}
/*
* To copy scan hashes and authenticate test chunks, the initiating cpu must point
* to the EDX:EAX to the test image in linear address.
* Run wrmsr(MSR_COPY_SCAN_HASHES) for scan hash copy and run wrmsr(MSR_AUTHENTICATE_AND_COPY_CHUNK)
* for scan hash copy and test chunk authentication.
*/
static void copy_hashes_authenticate_chunks(struct work_struct *work)
{
struct ifs_work *local_work = container_of(work, struct ifs_work, w);
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 */
wrmsrq(msrs->copy_hashes, ifs_hash_ptr);
rdmsrq(msrs->copy_hashes_status, hashes_status.data);
/* enumerate the scan image information */
num_chunks = hashes_status.num_chunks;
chunk_size = hashes_status.chunk_size * 1024;
err_code = hashes_status.error_code;
if (!hashes_status.valid) {
ifsd->loading_error = true;
hashcopy_err_message(dev, err_code);
goto done;
}
/* base linear address to the scan data */
base = ifs_test_image_ptr;
/* scan data authentication and copy chunks to secured memory */
for (i = 0; i < num_chunks; i++) {
linear_addr = base + i * chunk_size;
linear_addr |= i;
wrmsrq(msrs->copy_chunks, linear_addr);
rdmsrq(msrs->copy_chunks_status, chunk_status.data);
ifsd->valid_chunks = chunk_status.valid_chunks;
err_code = chunk_status.error_code;
if (err_code) {
ifsd->loading_error = true;
auth_err_message(dev, err_code);
goto done;
}
}
done:
complete(&ifs_done);
}
static int get_num_chunks(int gen, union ifs_scan_hashes_status_gen2 status)
{
return gen >= IFS_GEN_STRIDE_AWARE ? status.chunks_in_stride : status.num_chunks;
}
static bool need_copy_scan_hashes(struct ifs_data *ifsd)
{
return !ifsd->loaded ||
ifsd->generation < IFS_GEN_STRIDE_AWARE ||
ifsd->loaded_version != ifs_header_ptr->rev;
}
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;
struct ifs_data *ifsd;
u64 linear_addr, base;
u64 chunk_table[2];
int retry_count;
ifsd = ifs_get_data(dev);
msrs = ifs_get_test_msrs(dev);
if (need_copy_scan_hashes(ifsd)) {
wrmsrq(msrs->copy_hashes, ifs_hash_ptr);
rdmsrq(msrs->copy_hashes_status, hashes_status.data);
/* enumerate the scan image information */
chunk_size = hashes_status.chunk_size * SZ_1K;
err_code = hashes_status.error_code;
num_chunks = get_num_chunks(ifsd->generation, hashes_status);
if (!hashes_status.valid) {
hashcopy_err_message(dev, err_code);
return -EIO;
}
ifsd->loaded_version = ifs_header_ptr->rev;
ifsd->chunk_size = chunk_size;
} else {
num_chunks = ifsd->valid_chunks;
chunk_size = ifsd->chunk_size;
}
if (ifsd->generation >= IFS_GEN_STRIDE_AWARE) {
wrmsrq(msrs->test_ctrl, INVALIDATE_STRIDE);
rdmsrq(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);
return -EIO;
}
}
base = ifs_test_image_ptr;
ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS);
starting_chunk_nr = ifs_meta->starting_chunk;
/* scan data authentication and copy chunks to secured memory */
for (i = 0; i < num_chunks; i++) {
retry_count = IFS_AUTH_RETRY_CT;
linear_addr = base + i * chunk_size;
chunk_table[0] = starting_chunk_nr + i;
chunk_table[1] = linear_addr;
do {
local_irq_disable();
wrmsrq(msrs->copy_chunks, (u64)chunk_table);
local_irq_enable();
rdmsrq(msrs->copy_chunks_status, chunk_status.data);
err_code = chunk_status.error_code;
} while (err_code == AUTH_INTERRUPTED_ERROR && --retry_count);
if (err_code) {
ifsd->loading_error = true;
auth_err_message(dev, err_code);
return -EIO;
}
}
valid_chunks = chunk_status.valid_chunks;
total_chunks = chunk_status.total_chunks;
if (valid_chunks != total_chunks) {
ifsd->loading_error = true;
dev_err(dev, "Couldn't authenticate all the chunks. Authenticated %d total %d.\n",
valid_chunks, total_chunks);
return -EIO;
}
ifsd->valid_chunks = valid_chunks;
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
ifsd->max_bundle = chunk_status.max_bundle;
return 0;
}
static int validate_ifs_metadata(struct device *dev)
{
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
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;
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.%s",
boot_cpu_data.x86, boot_cpu_data.x86_model,
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
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) {
dev_err(dev, "IFS Metadata missing in file %s\n", test_file);
return ret;
}
ifs_test_image_ptr = (u64)ifs_meta + sizeof(union meta_data);
/* Scan chunk start must be 256 byte aligned */
if (!IS_ALIGNED(ifs_test_image_ptr, IFS_CHUNK_ALIGNMENT)) {
dev_err(dev, "Scan pattern is not aligned on %d bytes aligned in %s\n",
IFS_CHUNK_ALIGNMENT, test_file);
return ret;
}
if (ifs_meta->current_image != ifsd->cur_batch) {
dev_warn(dev, "Mismatch between filename %s and batch metadata 0x%02x\n",
test_file, ifs_meta->current_image);
return ret;
}
if (ifs_meta->chunks_per_stride &&
(ifs_meta->starting_chunk % ifs_meta->chunks_per_stride != 0)) {
dev_warn(dev, "Starting chunk num %u not a multiple of chunks_per_stride %u\n",
ifs_meta->starting_chunk, ifs_meta->chunks_per_stride);
return ret;
}
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
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;
}
/*
* IFS requires scan chunks authenticated per each socket in the platform.
* Once the test chunk is authenticated, it is automatically copied to secured memory
* and proceed the authentication for the next chunk.
*/
static int scan_chunks_sanity_check(struct device *dev)
{
struct ifs_data *ifsd = ifs_get_data(dev);
struct ifs_work local_work;
int curr_pkg, cpu, ret;
memset(ifs_pkg_auth, 0, (topology_max_packages() * sizeof(bool)));
ret = validate_ifs_metadata(dev);
if (ret)
return ret;
ifsd->loading_error = false;
if (ifsd->generation > 0)
return copy_hashes_authenticate_chunks_gen2(dev);
/* copy the scan hash and authenticate per package */
cpus_read_lock();
for_each_online_cpu(cpu) {
curr_pkg = topology_physical_package_id(cpu);
if (ifs_pkg_auth[curr_pkg])
continue;
reinit_completion(&ifs_done);
local_work.dev = dev;
platform/x86/intel/ifs: Annotate work queue on stack so object debug does not complain Object Debug results in the following warning while attempting to load ifs firmware: [ 220.007422] ODEBUG: object 000000003bf952db is on stack 00000000e843994b, but NOT annotated. [ 220.007459] ------------[ cut here ]------------ [ 220.007461] WARNING: CPU: 0 PID: 11774 at lib/debugobjects.c:548 __debug_object_init.cold+0x22e/0x2d5 [ 220.137476] RIP: 0010:__debug_object_init.cold+0x22e/0x2d5 [ 220.254774] Call Trace: [ 220.257641] <TASK> [ 220.265606] scan_chunks_sanity_check+0x368/0x5f0 [intel_ifs] [ 220.288292] ifs_load_firmware+0x2a3/0x400 [intel_ifs] [ 220.332793] current_batch_store+0xea/0x160 [intel_ifs] [ 220.357947] kernfs_fop_write_iter+0x355/0x530 [ 220.363048] new_sync_write+0x28e/0x4a0 [ 220.381226] vfs_write+0x62a/0x920 [ 220.385160] ksys_write+0xf9/0x1d0 [ 220.399421] do_syscall_64+0x59/0x90 [ 220.440635] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 220.566845] ---[ end trace 3a01b299db142b41 ]--- Correct this by calling INIT_WORK_ONSTACK instead of INIT_WORK. Fixes: 684ec215706d ("platform/x86/intel/ifs: Authenticate and copy to secured memory") Signed-off-by: David Arcari <darcari@redhat.com> Cc: Jithu Joseph <jithu.joseph@intel.com> Cc: Ashok Raj <ashok.raj@intel.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Hans de Goede <hdegoede@redhat.com> Cc: Mark Gross <markgross@kernel.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Dan Williams <dan.j.williams@intel.com> Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230523105400.674152-1-darcari@redhat.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2023-05-23 06:54:00 -04:00
INIT_WORK_ONSTACK(&local_work.w, copy_hashes_authenticate_chunks);
schedule_work_on(cpu, &local_work.w);
wait_for_completion(&ifs_done);
if (ifsd->loading_error) {
ret = -EIO;
goto out;
}
ifs_pkg_auth[curr_pkg] = 1;
}
ret = 0;
ifsd->loaded_version = ifs_header_ptr->rev;
out:
cpus_read_unlock();
return ret;
}
static int image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
{
struct cpu_signature sig;
/* Provide a specific error message when loading an older/unsupported image */
if (data->hdrver != MC_HEADER_TYPE_IFS) {
dev_err(dev, "Header version %d not supported\n", data->hdrver);
return -EINVAL;
}
if (intel_microcode_sanity_check((void *)data, true, MC_HEADER_TYPE_IFS)) {
dev_err(dev, "sanity check failed\n");
return -EINVAL;
}
intel_collect_cpu_info(&sig);
if (!intel_find_matching_signature((void *)data, &sig)) {
dev_err(dev, "cpu signature, processor flags not matching\n");
return -EINVAL;
}
return 0;
}
/*
* Load ifs image. Before loading ifs module, the ifs image must be located
platform/x86/intel/ifs: Add current_batch sysfs entry 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
2022-11-16 19:59:33 -08:00
* in /lib/firmware/intel/ifs_x/ and named as family-model-stepping-02x.{testname}.
*/
platform/x86/intel/ifs: Add current_batch sysfs entry 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
2022-11-16 19:59:33 -08:00
int ifs_load_firmware(struct device *dev)
{
const struct ifs_test_caps *test = ifs_get_test_caps(dev);
struct ifs_data *ifsd = ifs_get_data(dev);
unsigned int expected_size;
const struct firmware *fw;
platform/x86/intel/ifs: Add current_batch sysfs entry 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
2022-11-16 19:59:33 -08:00
char scan_path[64];
int ret;
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
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,
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: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://lore.kernel.org/r/20240801051814.1935149-3-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-01 05:18:12 +00:00
boot_cpu_data.x86_stepping, ifsd->cur_batch, test->image_suffix);
ret = request_firmware_direct(&fw, scan_path, dev);
if (ret) {
dev_err(dev, "ifs file %s load failed\n", scan_path);
goto done;
}
expected_size = ((struct microcode_header_intel *)fw->data)->totalsize;
if (fw->size != expected_size) {
dev_err(dev, "File size mismatch (expected %u, actual %zu). Corrupted IFS image.\n",
expected_size, fw->size);
ret = -EINVAL;
goto release;
}
ret = image_sanity_check(dev, (struct microcode_header_intel *)fw->data);
if (ret)
goto release;
ifs_header_ptr = (struct microcode_header_intel *)fw->data;
ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
ret = scan_chunks_sanity_check(dev);
platform/x86/intel/ifs: Add current_batch sysfs entry 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
2022-11-16 19:59:33 -08:00
if (ret)
dev_err(dev, "Load failure for batch: %02x\n", ifsd->cur_batch);
release:
release_firmware(fw);
done:
ifsd->loaded = (ret == 0);
platform/x86/intel/ifs: Add current_batch sysfs entry 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
2022-11-16 19:59:33 -08:00
return ret;
}