// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2025 Advanced Micro Devices, Inc. */ #include #include "iommufd.h" #include "amd_iommu.h" #include "amd_iommu_types.h" static const struct iommufd_viommu_ops amd_viommu_ops; void *amd_iommufd_hw_info(struct device *dev, u32 *length, enum iommu_hw_info_type *type) { struct iommu_hw_info_amd *hwinfo; if (*type != IOMMU_HW_INFO_TYPE_DEFAULT && *type != IOMMU_HW_INFO_TYPE_AMD) return ERR_PTR(-EOPNOTSUPP); hwinfo = kzalloc_obj(*hwinfo); if (!hwinfo) return ERR_PTR(-ENOMEM); *length = sizeof(*hwinfo); *type = IOMMU_HW_INFO_TYPE_AMD; hwinfo->efr = amd_iommu_efr; hwinfo->efr2 = amd_iommu_efr2; return hwinfo; } size_t amd_iommufd_get_viommu_size(struct device *dev, enum iommu_viommu_type viommu_type) { return VIOMMU_STRUCT_SIZE(struct amd_iommu_viommu, core); } int amd_iommufd_viommu_init(struct iommufd_viommu *viommu, struct iommu_domain *parent, const struct iommu_user_data *user_data) { unsigned long flags; struct protection_domain *pdom = to_pdomain(parent); struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core); xa_init_flags(&aviommu->gdomid_array, XA_FLAGS_ALLOC1); aviommu->parent = pdom; viommu->ops = &amd_viommu_ops; spin_lock_irqsave(&pdom->lock, flags); list_add(&aviommu->pdom_list, &pdom->viommu_list); spin_unlock_irqrestore(&pdom->lock, flags); return 0; } static void amd_iommufd_viommu_destroy(struct iommufd_viommu *viommu) { unsigned long flags; struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core); struct protection_domain *pdom = aviommu->parent; spin_lock_irqsave(&pdom->lock, flags); list_del(&aviommu->pdom_list); spin_unlock_irqrestore(&pdom->lock, flags); xa_destroy(&aviommu->gdomid_array); } /* * See include/linux/iommufd.h * struct iommufd_viommu_ops - vIOMMU specific operations */ static const struct iommufd_viommu_ops amd_viommu_ops = { .destroy = amd_iommufd_viommu_destroy, };