1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2022 Intel Corporation. */ 3 4 #include <linux/module.h> 5 #include <linux/kdev_t.h> 6 #include <linux/semaphore.h> 7 #include <linux/slab.h> 8 9 #include <asm/cpu_device_id.h> 10 11 #include "ifs.h" 12 13 #define X86_MATCH(model) \ 14 X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, \ 15 INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL) 16 17 static const struct x86_cpu_id ifs_cpu_ids[] __initconst = { 18 X86_MATCH(SAPPHIRERAPIDS_X), 19 X86_MATCH(EMERALDRAPIDS_X), 20 {} 21 }; 22 MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids); 23 24 ATTRIBUTE_GROUPS(plat_ifs); 25 ATTRIBUTE_GROUPS(plat_ifs_array); 26 27 bool *ifs_pkg_auth; 28 29 static const struct ifs_test_caps scan_test = { 30 .integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT, 31 .test_num = IFS_TYPE_SAF, 32 }; 33 34 static const struct ifs_test_caps array_test = { 35 .integrity_cap_bit = MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT, 36 .test_num = IFS_TYPE_ARRAY_BIST, 37 }; 38 39 static struct ifs_device ifs_devices[] = { 40 [IFS_TYPE_SAF] = { 41 .test_caps = &scan_test, 42 .misc = { 43 .name = "intel_ifs_0", 44 .minor = MISC_DYNAMIC_MINOR, 45 .groups = plat_ifs_groups, 46 }, 47 }, 48 [IFS_TYPE_ARRAY_BIST] = { 49 .test_caps = &array_test, 50 .misc = { 51 .name = "intel_ifs_1", 52 .minor = MISC_DYNAMIC_MINOR, 53 .groups = plat_ifs_array_groups, 54 }, 55 }, 56 }; 57 58 #define IFS_NUMTESTS ARRAY_SIZE(ifs_devices) 59 60 static void ifs_cleanup(void) 61 { 62 int i; 63 64 for (i = 0; i < IFS_NUMTESTS; i++) { 65 if (ifs_devices[i].misc.this_device) 66 misc_deregister(&ifs_devices[i].misc); 67 } 68 kfree(ifs_pkg_auth); 69 } 70 71 static int __init ifs_init(void) 72 { 73 const struct x86_cpu_id *m; 74 u64 msrval; 75 int i, ret; 76 77 m = x86_match_cpu(ifs_cpu_ids); 78 if (!m) 79 return -ENODEV; 80 81 if (rdmsrl_safe(MSR_IA32_CORE_CAPS, &msrval)) 82 return -ENODEV; 83 84 if (!(msrval & MSR_IA32_CORE_CAPS_INTEGRITY_CAPS)) 85 return -ENODEV; 86 87 if (rdmsrl_safe(MSR_INTEGRITY_CAPS, &msrval)) 88 return -ENODEV; 89 90 ifs_pkg_auth = kmalloc_array(topology_max_packages(), sizeof(bool), GFP_KERNEL); 91 if (!ifs_pkg_auth) 92 return -ENOMEM; 93 94 for (i = 0; i < IFS_NUMTESTS; i++) { 95 if (!(msrval & BIT(ifs_devices[i].test_caps->integrity_cap_bit))) 96 continue; 97 ret = misc_register(&ifs_devices[i].misc); 98 if (ret) 99 goto err_exit; 100 } 101 return 0; 102 103 err_exit: 104 ifs_cleanup(); 105 return ret; 106 } 107 108 static void __exit ifs_exit(void) 109 { 110 ifs_cleanup(); 111 } 112 113 module_init(ifs_init); 114 module_exit(ifs_exit); 115 116 MODULE_LICENSE("GPL"); 117 MODULE_DESCRIPTION("Intel In Field Scan (IFS) device"); 118