|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +/* |
| 3 | + * nested.c - nested mode translation support |
| 4 | + * |
| 5 | + * Copyright (C) 2023 Intel Corporation |
| 6 | + * |
| 7 | + * Author: Lu Baolu <baolu.lu@linux.intel.com> |
| 8 | + * Jacob Pan <jacob.jun.pan@linux.intel.com> |
| 9 | + * Yi Liu <yi.l.liu@intel.com> |
| 10 | + */ |
| 11 | + |
| 12 | +#define pr_fmt(fmt) "DMAR: " fmt |
| 13 | + |
| 14 | +#include <linux/iommu.h> |
| 15 | + |
| 16 | +#include "iommu.h" |
| 17 | + |
| 18 | +static void intel_nested_domain_free(struct iommu_domain *domain) |
| 19 | +{ |
| 20 | + kfree(to_dmar_domain(domain)); |
| 21 | +} |
| 22 | + |
| 23 | +static const struct iommu_domain_ops intel_nested_domain_ops = { |
| 24 | + .free = intel_nested_domain_free, |
| 25 | +}; |
| 26 | + |
| 27 | +struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent, |
| 28 | + const struct iommu_user_data *user_data) |
| 29 | +{ |
| 30 | + struct dmar_domain *s2_domain = to_dmar_domain(parent); |
| 31 | + struct iommu_hwpt_vtd_s1 vtd; |
| 32 | + struct dmar_domain *domain; |
| 33 | + int ret; |
| 34 | + |
| 35 | + /* Must be nested domain */ |
| 36 | + if (user_data->type != IOMMU_HWPT_DATA_VTD_S1) |
| 37 | + return ERR_PTR(-EOPNOTSUPP); |
| 38 | + if (parent->ops != intel_iommu_ops.default_domain_ops) |
| 39 | + return ERR_PTR(-EINVAL); |
| 40 | + |
| 41 | + ret = iommu_copy_struct_from_user(&vtd, user_data, |
| 42 | + IOMMU_HWPT_DATA_VTD_S1, __reserved); |
| 43 | + if (ret) |
| 44 | + return ERR_PTR(ret); |
| 45 | + |
| 46 | + domain = kzalloc(sizeof(*domain), GFP_KERNEL_ACCOUNT); |
| 47 | + if (!domain) |
| 48 | + return ERR_PTR(-ENOMEM); |
| 49 | + |
| 50 | + domain->use_first_level = true; |
| 51 | + domain->s2_domain = s2_domain; |
| 52 | + domain->s1_pgtbl = vtd.pgtbl_addr; |
| 53 | + domain->s1_cfg = vtd; |
| 54 | + domain->domain.ops = &intel_nested_domain_ops; |
| 55 | + domain->domain.type = IOMMU_DOMAIN_NESTED; |
| 56 | + INIT_LIST_HEAD(&domain->devices); |
| 57 | + INIT_LIST_HEAD(&domain->dev_pasids); |
| 58 | + spin_lock_init(&domain->lock); |
| 59 | + xa_init(&domain->iommu_array); |
| 60 | + |
| 61 | + return &domain->domain; |
| 62 | +} |
0 commit comments