Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

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