xref: /linux/drivers/virt/coco/tsm-core.c (revision 3225f52cde56f46789a4972d3c54df8a4d75f022)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */
3 
4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5 
6 #include <linux/tsm.h>
7 #include <linux/rwsem.h>
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/cleanup.h>
11 #include <linux/pci-tsm.h>
12 
13 static struct class *tsm_class;
14 static DECLARE_RWSEM(tsm_rwsem);
15 static DEFINE_IDA(tsm_ida);
16 
17 static int match_id(struct device *dev, const void *data)
18 {
19 	struct tsm_dev *tsm_dev = container_of(dev, struct tsm_dev, dev);
20 	int id = *(const int *)data;
21 
22 	return tsm_dev->id == id;
23 }
24 
25 struct tsm_dev *find_tsm_dev(int id)
26 {
27 	struct device *dev = class_find_device(tsm_class, NULL, &id, match_id);
28 
29 	if (!dev)
30 		return NULL;
31 	return container_of(dev, struct tsm_dev, dev);
32 }
33 
34 static struct tsm_dev *alloc_tsm_dev(struct device *parent)
35 {
36 	struct device *dev;
37 	int id;
38 
39 	struct tsm_dev *tsm_dev __free(kfree) =
40 		kzalloc(sizeof(*tsm_dev), GFP_KERNEL);
41 	if (!tsm_dev)
42 		return ERR_PTR(-ENOMEM);
43 
44 	id = ida_alloc(&tsm_ida, GFP_KERNEL);
45 	if (id < 0)
46 		return ERR_PTR(id);
47 
48 	tsm_dev->id = id;
49 	dev = &tsm_dev->dev;
50 	dev->parent = parent;
51 	dev->class = tsm_class;
52 	device_initialize(dev);
53 
54 	return no_free_ptr(tsm_dev);
55 }
56 
57 static struct tsm_dev *tsm_register_pci_or_reset(struct tsm_dev *tsm_dev,
58 						 struct pci_tsm_ops *pci_ops)
59 {
60 	int rc;
61 
62 	if (!pci_ops)
63 		return tsm_dev;
64 
65 	tsm_dev->pci_ops = pci_ops;
66 	rc = pci_tsm_register(tsm_dev);
67 	if (rc) {
68 		dev_err(tsm_dev->dev.parent,
69 			"PCI/TSM registration failure: %d\n", rc);
70 		device_unregister(&tsm_dev->dev);
71 		return ERR_PTR(rc);
72 	}
73 
74 	/* Notify TSM userspace that PCI/TSM operations are now possible */
75 	kobject_uevent(&tsm_dev->dev.kobj, KOBJ_CHANGE);
76 	return tsm_dev;
77 }
78 
79 struct tsm_dev *tsm_register(struct device *parent, struct pci_tsm_ops *pci_ops)
80 {
81 	struct tsm_dev *tsm_dev __free(put_tsm_dev) = alloc_tsm_dev(parent);
82 	struct device *dev;
83 	int rc;
84 
85 	if (IS_ERR(tsm_dev))
86 		return tsm_dev;
87 
88 	dev = &tsm_dev->dev;
89 	rc = dev_set_name(dev, "tsm%d", tsm_dev->id);
90 	if (rc)
91 		return ERR_PTR(rc);
92 
93 	rc = device_add(dev);
94 	if (rc)
95 		return ERR_PTR(rc);
96 
97 	return tsm_register_pci_or_reset(no_free_ptr(tsm_dev), pci_ops);
98 }
99 EXPORT_SYMBOL_GPL(tsm_register);
100 
101 void tsm_unregister(struct tsm_dev *tsm_dev)
102 {
103 	if (tsm_dev->pci_ops)
104 		pci_tsm_unregister(tsm_dev);
105 	device_unregister(&tsm_dev->dev);
106 }
107 EXPORT_SYMBOL_GPL(tsm_unregister);
108 
109 static void tsm_release(struct device *dev)
110 {
111 	struct tsm_dev *tsm_dev = container_of(dev, typeof(*tsm_dev), dev);
112 
113 	ida_free(&tsm_ida, tsm_dev->id);
114 	kfree(tsm_dev);
115 }
116 
117 static int __init tsm_init(void)
118 {
119 	tsm_class = class_create("tsm");
120 	if (IS_ERR(tsm_class))
121 		return PTR_ERR(tsm_class);
122 
123 	tsm_class->dev_release = tsm_release;
124 	return 0;
125 }
126 module_init(tsm_init)
127 
128 static void __exit tsm_exit(void)
129 {
130 	class_destroy(tsm_class);
131 }
132 module_exit(tsm_exit)
133 
134 MODULE_LICENSE("GPL");
135 MODULE_DESCRIPTION("TEE Security Manager Class Device");
136