Skip to content

Commit 07f47c0

Browse files
jithu83ij-intel
authored andcommitted
platform/x86/intel/ifs: Gen2 scan image loading
Scan image loading flow for newer IFS generations are slightly different from that of current generation. In newer schemes, loading need not be done once for each socket as was done in gen0. Also the width of NUM_CHUNKS bitfield in SCAN_HASHES_STATUS MSR has increased from 8 -> 16 bits. Similarly there are width differences for CHUNK_AUTHENTICATION_STATUS too. Further the parameter to AUTHENTICATE_AND_COPY_CHUNK is passed differently in newer generations. Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Tested-by: Pengfei Xu <pengfei.xu@intel.com> Link: https://lore.kernel.org/r/20231005195137.3117166-4-jithu.joseph@intel.com Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
1 parent a138ac2 commit 07f47c0

2 files changed

Lines changed: 137 additions & 2 deletions

File tree

drivers/platform/x86/intel/ifs/ifs.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@
137137
#define MSR_CHUNKS_AUTHENTICATION_STATUS 0x000002c5
138138
#define MSR_ACTIVATE_SCAN 0x000002c6
139139
#define MSR_SCAN_STATUS 0x000002c7
140+
#define MSR_SAF_CTRL 0x000004f0
141+
140142
#define SCAN_NOT_TESTED 0
141143
#define SCAN_TEST_PASS 1
142144
#define SCAN_TEST_FAIL 2
@@ -158,6 +160,19 @@ union ifs_scan_hashes_status {
158160
};
159161
};
160162

163+
union ifs_scan_hashes_status_gen2 {
164+
u64 data;
165+
struct {
166+
u16 chunk_size;
167+
u16 num_chunks;
168+
u32 error_code :8;
169+
u32 chunks_in_stride :9;
170+
u32 rsvd :2;
171+
u32 max_core_limit :12;
172+
u32 valid :1;
173+
};
174+
};
175+
161176
/* MSR_CHUNKS_AUTH_STATUS bit fields */
162177
union ifs_chunks_auth_status {
163178
u64 data;
@@ -170,6 +185,16 @@ union ifs_chunks_auth_status {
170185
};
171186
};
172187

188+
union ifs_chunks_auth_status_gen2 {
189+
u64 data;
190+
struct {
191+
u16 valid_chunks;
192+
u16 total_chunks;
193+
u32 error_code :8;
194+
u32 rsvd2 :24;
195+
};
196+
};
197+
173198
/* MSR_ACTIVATE_SCAN bit fields */
174199
union ifs_scan {
175200
u64 data;
@@ -230,6 +255,7 @@ struct ifs_test_caps {
230255
* @scan_details: opaque scan status code from h/w
231256
* @cur_batch: number indicating the currently loaded test file
232257
* @generation: IFS test generation enumerated by hardware
258+
* @chunk_size: size of a test chunk
233259
*/
234260
struct ifs_data {
235261
int loaded_version;
@@ -240,6 +266,7 @@ struct ifs_data {
240266
u64 scan_details;
241267
u32 cur_batch;
242268
u32 generation;
269+
u32 chunk_size;
243270
};
244271

245272
struct ifs_work {

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

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Copyright(c) 2022 Intel Corporation. */
33

44
#include <linux/firmware.h>
5+
#include <linux/sizes.h>
56
#include <asm/cpu.h>
67
#include <asm/microcode.h>
78

@@ -26,6 +27,11 @@ union meta_data {
2627

2728
#define IFS_HEADER_SIZE (sizeof(struct microcode_header_intel))
2829
#define META_TYPE_IFS 1
30+
#define INVALIDATE_STRIDE 0x1UL
31+
#define IFS_GEN_STRIDE_AWARE 2
32+
#define AUTH_INTERRUPTED_ERROR 5
33+
#define IFS_AUTH_RETRY_CT 10
34+
2935
static struct microcode_header_intel *ifs_header_ptr; /* pointer to the ifs image header */
3036
static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */
3137
static u64 ifs_test_image_ptr; /* 256B aligned address of test pattern */
@@ -44,7 +50,10 @@ static const char * const scan_hash_status[] = {
4450
static const char * const scan_authentication_status[] = {
4551
[0] = "No error reported",
4652
[1] = "Attempt to authenticate a chunk which is already marked as authentic",
47-
[2] = "Chunk authentication error. The hash of chunk did not match expected value"
53+
[2] = "Chunk authentication error. The hash of chunk did not match expected value",
54+
[3] = "Reserved",
55+
[4] = "Chunk outside the current stride",
56+
[5] = "Authentication flow interrupted",
4857
};
4958

5059
#define MC_HEADER_META_TYPE_END (0)
@@ -154,6 +163,102 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work)
154163
complete(&ifs_done);
155164
}
156165

166+
static int get_num_chunks(int gen, union ifs_scan_hashes_status_gen2 status)
167+
{
168+
return gen >= IFS_GEN_STRIDE_AWARE ? status.chunks_in_stride : status.num_chunks;
169+
}
170+
171+
static bool need_copy_scan_hashes(struct ifs_data *ifsd)
172+
{
173+
return !ifsd->loaded ||
174+
ifsd->generation < IFS_GEN_STRIDE_AWARE ||
175+
ifsd->loaded_version != ifs_header_ptr->rev;
176+
}
177+
178+
static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
179+
{
180+
union ifs_scan_hashes_status_gen2 hashes_status;
181+
union ifs_chunks_auth_status_gen2 chunk_status;
182+
u32 err_code, valid_chunks, total_chunks;
183+
int i, num_chunks, chunk_size;
184+
union meta_data *ifs_meta;
185+
int starting_chunk_nr;
186+
struct ifs_data *ifsd;
187+
u64 linear_addr, base;
188+
u64 chunk_table[2];
189+
int retry_count;
190+
191+
ifsd = ifs_get_data(dev);
192+
193+
if (need_copy_scan_hashes(ifsd)) {
194+
wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
195+
rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);
196+
197+
/* enumerate the scan image information */
198+
chunk_size = hashes_status.chunk_size * SZ_1K;
199+
err_code = hashes_status.error_code;
200+
201+
num_chunks = get_num_chunks(ifsd->generation, hashes_status);
202+
203+
if (!hashes_status.valid) {
204+
hashcopy_err_message(dev, err_code);
205+
return -EIO;
206+
}
207+
ifsd->loaded_version = ifs_header_ptr->rev;
208+
ifsd->chunk_size = chunk_size;
209+
} else {
210+
num_chunks = ifsd->valid_chunks;
211+
chunk_size = ifsd->chunk_size;
212+
}
213+
214+
if (ifsd->generation >= IFS_GEN_STRIDE_AWARE) {
215+
wrmsrl(MSR_SAF_CTRL, INVALIDATE_STRIDE);
216+
rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
217+
if (chunk_status.valid_chunks != 0) {
218+
dev_err(dev, "Couldn't invalidate installed stride - %d\n",
219+
chunk_status.valid_chunks);
220+
return -EIO;
221+
}
222+
}
223+
224+
base = ifs_test_image_ptr;
225+
ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS);
226+
starting_chunk_nr = ifs_meta->starting_chunk;
227+
228+
/* scan data authentication and copy chunks to secured memory */
229+
for (i = 0; i < num_chunks; i++) {
230+
retry_count = IFS_AUTH_RETRY_CT;
231+
linear_addr = base + i * chunk_size;
232+
233+
chunk_table[0] = starting_chunk_nr + i;
234+
chunk_table[1] = linear_addr;
235+
do {
236+
wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, (u64)chunk_table);
237+
rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
238+
err_code = chunk_status.error_code;
239+
} while (err_code == AUTH_INTERRUPTED_ERROR && --retry_count);
240+
241+
if (err_code) {
242+
ifsd->loading_error = true;
243+
auth_err_message(dev, err_code);
244+
return -EIO;
245+
}
246+
}
247+
248+
valid_chunks = chunk_status.valid_chunks;
249+
total_chunks = chunk_status.total_chunks;
250+
251+
if (valid_chunks != total_chunks) {
252+
ifsd->loading_error = true;
253+
dev_err(dev, "Couldn't authenticate all the chunks. Authenticated %d total %d.\n",
254+
valid_chunks, total_chunks);
255+
return -EIO;
256+
}
257+
ifsd->valid_chunks = valid_chunks;
258+
259+
return 0;
260+
}
261+
157262
static int validate_ifs_metadata(struct device *dev)
158263
{
159264
struct ifs_data *ifsd = ifs_get_data(dev);
@@ -206,7 +311,9 @@ static int scan_chunks_sanity_check(struct device *dev)
206311
return ret;
207312

208313
ifsd->loading_error = false;
209-
ifsd->loaded_version = ifs_header_ptr->rev;
314+
315+
if (ifsd->generation > 0)
316+
return copy_hashes_authenticate_chunks_gen2(dev);
210317

211318
/* copy the scan hash and authenticate per package */
212319
cpus_read_lock();
@@ -226,6 +333,7 @@ static int scan_chunks_sanity_check(struct device *dev)
226333
ifs_pkg_auth[curr_pkg] = 1;
227334
}
228335
ret = 0;
336+
ifsd->loaded_version = ifs_header_ptr->rev;
229337
out:
230338
cpus_read_unlock();
231339

0 commit comments

Comments
 (0)