Skip to content

Commit 6912ec9

Browse files
nicolincwilldeacon
authored andcommitted
iommu/arm-smmu-v3: Support IOMMU_GET_HW_INFO via struct arm_smmu_hw_info
For virtualization cases the IDR/IIDR/AIDR values of the actual SMMU instance need to be available to the VMM so it can construct an appropriate vSMMUv3 that reflects the correct HW capabilities. For userspace page tables these values are required to constrain the valid values within the CD table and the IOPTEs. The kernel does not sanitize these values. If building a VMM then userspace is required to only forward bits into a VM that it knows it can implement. Some bits will also require a VMM to detect if appropriate kernel support is available such as for ATS and BTM. Start a new file and kconfig for the advanced iommufd support. This lets it be compiled out for kernels that are not intended to support virtualization, and allows distros to leave it disabled until they are shipping a matching qemu too. Tested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Reviewed-by: Donald Dutile <ddutile@redhat.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/5-v4-9e99b76f3518+3a8-smmuv3_nesting_jgg@nvidia.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent e89573c commit 6912ec9

File tree

6 files changed

+86
-0
lines changed

6 files changed

+86
-0
lines changed

drivers/iommu/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,15 @@ config ARM_SMMU_V3_SVA
415415
Say Y here if your system supports SVA extensions such as PCIe PASID
416416
and PRI.
417417

418+
config ARM_SMMU_V3_IOMMUFD
419+
bool "Enable IOMMUFD features for ARM SMMUv3 (EXPERIMENTAL)"
420+
depends on IOMMUFD
421+
help
422+
Support for IOMMUFD features intended to support virtual machines
423+
with accelerated virtual IOMMUs.
424+
425+
Say Y here if you are doing development and testing on this feature.
426+
418427
config ARM_SMMU_V3_KUNIT_TEST
419428
tristate "KUnit tests for arm-smmu-v3 driver" if !KUNIT_ALL_TESTS
420429
depends on KUNIT

drivers/iommu/arm/arm-smmu-v3/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o
33
arm_smmu_v3-y := arm-smmu-v3.o
4+
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_IOMMUFD) += arm-smmu-v3-iommufd.o
45
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
56
arm_smmu_v3-$(CONFIG_TEGRA241_CMDQV) += tegra241-cmdqv.o
67

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
4+
*/
5+
6+
#include <uapi/linux/iommufd.h>
7+
8+
#include "arm-smmu-v3.h"
9+
10+
void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type)
11+
{
12+
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
13+
struct iommu_hw_info_arm_smmuv3 *info;
14+
u32 __iomem *base_idr;
15+
unsigned int i;
16+
17+
info = kzalloc(sizeof(*info), GFP_KERNEL);
18+
if (!info)
19+
return ERR_PTR(-ENOMEM);
20+
21+
base_idr = master->smmu->base + ARM_SMMU_IDR0;
22+
for (i = 0; i <= 5; i++)
23+
info->idr[i] = readl_relaxed(base_idr + i);
24+
info->iidr = readl_relaxed(master->smmu->base + ARM_SMMU_IIDR);
25+
info->aidr = readl_relaxed(master->smmu->base + ARM_SMMU_AIDR);
26+
27+
*length = sizeof(*info);
28+
*type = IOMMU_HW_INFO_TYPE_ARM_SMMUV3;
29+
30+
return info;
31+
}

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3506,6 +3506,7 @@ static struct iommu_ops arm_smmu_ops = {
35063506
.identity_domain = &arm_smmu_identity_domain,
35073507
.blocked_domain = &arm_smmu_blocked_domain,
35083508
.capable = arm_smmu_capable,
3509+
.hw_info = arm_smmu_hw_info,
35093510
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
35103511
.domain_alloc_sva = arm_smmu_sva_domain_alloc,
35113512
.domain_alloc_user = arm_smmu_domain_alloc_user,

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ struct arm_smmu_device;
8181
#define IIDR_REVISION GENMASK(15, 12)
8282
#define IIDR_IMPLEMENTER GENMASK(11, 0)
8383

84+
#define ARM_SMMU_AIDR 0x1C
85+
8486
#define ARM_SMMU_CR0 0x20
8587
#define CR0_ATSCHK (1 << 4)
8688
#define CR0_CMDQEN (1 << 3)
@@ -956,4 +958,11 @@ tegra241_cmdqv_probe(struct arm_smmu_device *smmu)
956958
return ERR_PTR(-ENODEV);
957959
}
958960
#endif /* CONFIG_TEGRA241_CMDQV */
961+
962+
#if IS_ENABLED(CONFIG_ARM_SMMU_V3_IOMMUFD)
963+
void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type);
964+
#else
965+
#define arm_smmu_hw_info NULL
966+
#endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */
967+
959968
#endif /* _ARM_SMMU_V3_H */

include/uapi/linux/iommufd.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,15 +484,50 @@ struct iommu_hw_info_vtd {
484484
__aligned_u64 ecap_reg;
485485
};
486486

487+
/**
488+
* struct iommu_hw_info_arm_smmuv3 - ARM SMMUv3 hardware information
489+
* (IOMMU_HW_INFO_TYPE_ARM_SMMUV3)
490+
*
491+
* @flags: Must be set to 0
492+
* @__reserved: Must be 0
493+
* @idr: Implemented features for ARM SMMU Non-secure programming interface
494+
* @iidr: Information about the implementation and implementer of ARM SMMU,
495+
* and architecture version supported
496+
* @aidr: ARM SMMU architecture version
497+
*
498+
* For the details of @idr, @iidr and @aidr, please refer to the chapters
499+
* from 6.3.1 to 6.3.6 in the SMMUv3 Spec.
500+
*
501+
* User space should read the underlying ARM SMMUv3 hardware information for
502+
* the list of supported features.
503+
*
504+
* Note that these values reflect the raw HW capability, without any insight if
505+
* any required kernel driver support is present. Bits may be set indicating the
506+
* HW has functionality that is lacking kernel software support, such as BTM. If
507+
* a VMM is using this information to construct emulated copies of these
508+
* registers it should only forward bits that it knows it can support.
509+
*
510+
* In future, presence of required kernel support will be indicated in flags.
511+
*/
512+
struct iommu_hw_info_arm_smmuv3 {
513+
__u32 flags;
514+
__u32 __reserved;
515+
__u32 idr[6];
516+
__u32 iidr;
517+
__u32 aidr;
518+
};
519+
487520
/**
488521
* enum iommu_hw_info_type - IOMMU Hardware Info Types
489522
* @IOMMU_HW_INFO_TYPE_NONE: Used by the drivers that do not report hardware
490523
* info
491524
* @IOMMU_HW_INFO_TYPE_INTEL_VTD: Intel VT-d iommu info type
525+
* @IOMMU_HW_INFO_TYPE_ARM_SMMUV3: ARM SMMUv3 iommu info type
492526
*/
493527
enum iommu_hw_info_type {
494528
IOMMU_HW_INFO_TYPE_NONE = 0,
495529
IOMMU_HW_INFO_TYPE_INTEL_VTD = 1,
530+
IOMMU_HW_INFO_TYPE_ARM_SMMUV3 = 2,
496531
};
497532

498533
/**

0 commit comments

Comments
 (0)