1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2022 Intel Corporation. */
4 #include <linux/bitfield.h>
5 #include <linux/module.h>
6 #include <linux/kdev_t.h>
7 #include <linux/semaphore.h>
8 #include <linux/slab.h>
10 #include <asm/cpu_device_id.h>
14 #define X86_MATCH(vfm, array_gen) \
15 X86_MATCH_VFM_FEATURE(vfm, X86_FEATURE_CORE_CAPABILITIES, array_gen)
17 static const struct x86_cpu_id ifs_cpu_ids
[] __initconst
= {
18 X86_MATCH(INTEL_SAPPHIRERAPIDS_X
, ARRAY_GEN0
),
19 X86_MATCH(INTEL_EMERALDRAPIDS_X
, ARRAY_GEN0
),
20 X86_MATCH(INTEL_GRANITERAPIDS_X
, ARRAY_GEN0
),
21 X86_MATCH(INTEL_GRANITERAPIDS_D
, ARRAY_GEN0
),
22 X86_MATCH(INTEL_ATOM_CRESTMONT_X
, ARRAY_GEN1
),
25 MODULE_DEVICE_TABLE(x86cpu
, ifs_cpu_ids
);
27 ATTRIBUTE_GROUPS(plat_ifs
);
28 ATTRIBUTE_GROUPS(plat_ifs_array
);
32 static const struct ifs_test_caps scan_test
= {
33 .integrity_cap_bit
= MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT
,
34 .test_num
= IFS_TYPE_SAF
,
35 .image_suffix
= "scan",
38 static const struct ifs_test_caps array_test
= {
39 .integrity_cap_bit
= MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT
,
40 .test_num
= IFS_TYPE_ARRAY_BIST
,
43 static const struct ifs_test_msrs scan_msrs
= {
44 .copy_hashes
= MSR_COPY_SCAN_HASHES
,
45 .copy_hashes_status
= MSR_SCAN_HASHES_STATUS
,
46 .copy_chunks
= MSR_AUTHENTICATE_AND_COPY_CHUNK
,
47 .copy_chunks_status
= MSR_CHUNKS_AUTHENTICATION_STATUS
,
48 .test_ctrl
= MSR_SAF_CTRL
,
51 static const struct ifs_test_msrs sbaf_msrs
= {
52 .copy_hashes
= MSR_COPY_SBAF_HASHES
,
53 .copy_hashes_status
= MSR_SBAF_HASHES_STATUS
,
54 .copy_chunks
= MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK
,
55 .copy_chunks_status
= MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS
,
56 .test_ctrl
= MSR_SBAF_CTRL
,
59 static const struct ifs_test_caps sbaf_test
= {
60 .integrity_cap_bit
= MSR_INTEGRITY_CAPS_SBAF_BIT
,
61 .test_num
= IFS_TYPE_SBAF
,
62 .image_suffix
= "sbft",
65 static struct ifs_device ifs_devices
[] = {
67 .test_caps
= &scan_test
,
68 .test_msrs
= &scan_msrs
,
70 .name
= "intel_ifs_0",
71 .minor
= MISC_DYNAMIC_MINOR
,
72 .groups
= plat_ifs_groups
,
75 [IFS_TYPE_ARRAY_BIST
] = {
76 .test_caps
= &array_test
,
78 .name
= "intel_ifs_1",
79 .minor
= MISC_DYNAMIC_MINOR
,
80 .groups
= plat_ifs_array_groups
,
84 .test_caps
= &sbaf_test
,
85 .test_msrs
= &sbaf_msrs
,
87 .name
= "intel_ifs_2",
88 .minor
= MISC_DYNAMIC_MINOR
,
89 .groups
= plat_ifs_groups
,
94 #define IFS_NUMTESTS ARRAY_SIZE(ifs_devices)
96 static void ifs_cleanup(void)
100 for (i
= 0; i
< IFS_NUMTESTS
; i
++) {
101 if (ifs_devices
[i
].misc
.this_device
)
102 misc_deregister(&ifs_devices
[i
].misc
);
107 static int __init
ifs_init(void)
109 const struct x86_cpu_id
*m
;
113 m
= x86_match_cpu(ifs_cpu_ids
);
117 if (rdmsrl_safe(MSR_IA32_CORE_CAPS
, &msrval
))
120 if (!(msrval
& MSR_IA32_CORE_CAPS_INTEGRITY_CAPS
))
123 if (rdmsrl_safe(MSR_INTEGRITY_CAPS
, &msrval
))
126 ifs_pkg_auth
= kmalloc_array(topology_max_packages(), sizeof(bool), GFP_KERNEL
);
130 for (i
= 0; i
< IFS_NUMTESTS
; i
++) {
131 if (!(msrval
& BIT(ifs_devices
[i
].test_caps
->integrity_cap_bit
)))
133 ifs_devices
[i
].rw_data
.generation
= FIELD_GET(MSR_INTEGRITY_CAPS_SAF_GEN_MASK
,
135 ifs_devices
[i
].rw_data
.array_gen
= (u32
)m
->driver_data
;
136 ret
= misc_register(&ifs_devices
[i
].misc
);
147 static void __exit
ifs_exit(void)
152 module_init(ifs_init
);
153 module_exit(ifs_exit
);
155 MODULE_LICENSE("GPL");
156 MODULE_DESCRIPTION("Intel In Field Scan (IFS) device");