mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
iommu/vt-d: Refine intel_iommu_domain_alloc_user()
The domain_alloc_user ops should always allocate a guest-compatible page table unless specific allocation flags are specified. Currently, IOMMU_HWPT_ALLOC_NEST_PARENT and IOMMU_HWPT_ALLOC_DIRTY_TRACKING require special handling, as both require hardware support for scalable mode and second-stage translation. In such cases, the driver should select a second-stage page table for the paging domain. Suggested-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/20241021085125.192333-8-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
ed56de8a9e
commit
621838c718
1 changed files with 15 additions and 2 deletions
|
@ -3297,6 +3297,7 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
|
|||
struct intel_iommu *iommu = info->iommu;
|
||||
struct dmar_domain *dmar_domain;
|
||||
struct iommu_domain *domain;
|
||||
bool first_stage;
|
||||
|
||||
/* Must be NESTING domain */
|
||||
if (parent) {
|
||||
|
@ -3313,8 +3314,20 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
|
|||
if (user_data || (dirty_tracking && !ssads_supported(iommu)))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
/* Do not use first stage for user domain translation. */
|
||||
dmar_domain = paging_domain_alloc(dev, false);
|
||||
/*
|
||||
* Always allocate the guest compatible page table unless
|
||||
* IOMMU_HWPT_ALLOC_NEST_PARENT or IOMMU_HWPT_ALLOC_DIRTY_TRACKING
|
||||
* is specified.
|
||||
*/
|
||||
if (nested_parent || dirty_tracking) {
|
||||
if (!sm_supported(iommu) || !ecap_slts(iommu->ecap))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
first_stage = false;
|
||||
} else {
|
||||
first_stage = first_level_by_default(iommu);
|
||||
}
|
||||
|
||||
dmar_domain = paging_domain_alloc(dev, first_stage);
|
||||
if (IS_ERR(dmar_domain))
|
||||
return ERR_CAST(dmar_domain);
|
||||
domain = &dmar_domain->domain;
|
||||
|
|
Loading…
Add table
Reference in a new issue