File Index
Files and directories
Sign in
FILE

tsm-core.c

File preview with syntax highlighting.

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