xref: /linux/drivers/iommu/amd/iommufd.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2025 Advanced Micro Devices, Inc.
4  */
5 
6 #include <linux/iommu.h>
7 
8 #include "iommufd.h"
9 #include "amd_iommu.h"
10 #include "amd_iommu_types.h"
11 
12 static const struct iommufd_viommu_ops amd_viommu_ops;
13 
14 void *amd_iommufd_hw_info(struct device *dev, u32 *length, enum iommu_hw_info_type *type)
15 {
16 	struct iommu_hw_info_amd *hwinfo;
17 
18 	if (*type != IOMMU_HW_INFO_TYPE_DEFAULT &&
19 	    *type != IOMMU_HW_INFO_TYPE_AMD)
20 		return ERR_PTR(-EOPNOTSUPP);
21 
22 	hwinfo = kzalloc_obj(*hwinfo);
23 	if (!hwinfo)
24 		return ERR_PTR(-ENOMEM);
25 
26 	*length = sizeof(*hwinfo);
27 	*type = IOMMU_HW_INFO_TYPE_AMD;
28 
29 	hwinfo->efr = amd_iommu_efr;
30 	hwinfo->efr2 = amd_iommu_efr2;
31 
32 	return hwinfo;
33 }
34 
35 size_t amd_iommufd_get_viommu_size(struct device *dev, enum iommu_viommu_type viommu_type)
36 {
37 	return VIOMMU_STRUCT_SIZE(struct amd_iommu_viommu, core);
38 }
39 
40 int amd_iommufd_viommu_init(struct iommufd_viommu *viommu, struct iommu_domain *parent,
41 			    const struct iommu_user_data *user_data)
42 {
43 	unsigned long flags;
44 	struct protection_domain *pdom = to_pdomain(parent);
45 	struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core);
46 
47 	xa_init_flags(&aviommu->gdomid_array, XA_FLAGS_ALLOC1);
48 	aviommu->parent = pdom;
49 
50 	viommu->ops = &amd_viommu_ops;
51 
52 	spin_lock_irqsave(&pdom->lock, flags);
53 	list_add(&aviommu->pdom_list, &pdom->viommu_list);
54 	spin_unlock_irqrestore(&pdom->lock, flags);
55 
56 	return 0;
57 }
58 
59 static void amd_iommufd_viommu_destroy(struct iommufd_viommu *viommu)
60 {
61 	unsigned long flags;
62 	struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core);
63 	struct protection_domain *pdom = aviommu->parent;
64 
65 	spin_lock_irqsave(&pdom->lock, flags);
66 	list_del(&aviommu->pdom_list);
67 	spin_unlock_irqrestore(&pdom->lock, flags);
68 	xa_destroy(&aviommu->gdomid_array);
69 }
70 
71 /*
72  * See include/linux/iommufd.h
73  * struct iommufd_viommu_ops - vIOMMU specific operations
74  */
75 static const struct iommufd_viommu_ops amd_viommu_ops = {
76 	.destroy = amd_iommufd_viommu_destroy,
77 };
78