Hi Nicolin,
On 26-04-2025 11:28, Nicolin Chen wrote:
The CMDQV HW supports a user-space use for virtualization cases. It allows the VM to issue guest-level TLBI or ATC_INV commands directly to the queue and executes them without a VMEXIT, as HW will replace the VMID field in a TLBI command and the SID field in an ATC_INV command with the preset VMID and SID.
[clip]
+/**
- struct iommu_viommu_tegra241_cmdqv - NVIDIA Tegra241 CMDQV Virtual Interface
(IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV)
- @out_vintf_page0_pgoff: Offset of the VINTF page0 for mmap syscall
- @out_vintf_page0_pgsz: Size of the VINTF page0 for mmap syscall
- Both @out_vintf_page0_pgoff and @out_vintf_page0_pgsz are given by the kernel
- for user space to mmap the VINTF page0 from the host physical address space
- to the guest physical address space so that a guest kernel can directly R/W
- access to the VINTF page0 in order to control its virtual comamnd queues.
typo comamnd
- */
+struct iommu_viommu_tegra241_cmdqv {
- __aligned_u64 out_vintf_page0_pgoff;
- __aligned_u64 out_vintf_page0_pgsz; };
/** @@ -1152,9 +1183,23 @@ struct iommu_veventq_alloc { /**
- enum iommu_vcmdq_type - Virtual Command Queue Type
- @IOMMU_VCMDQ_TYPE_DEFAULT: Reserved for future use
*/ enum iommu_vcmdq_type { IOMMU_VCMDQ_TYPE_DEFAULT = 0,
- @IOMMU_VCMDQ_TYPE_TEGRA241_CMDQV: NVIDIA Tegra241 CMDQV Extension for SMMUv3
- /*
* TEGRA241_CMDQV requirements (otherwise it will fail)
* - alloc starts from the lowest @index=0 in ascending order
* - destroy starts from the last allocated @index in descending order
* - @addr must be aligned to @length in bytes and be mmapped in IOAS
* - @length must be a power of 2, with a minimum 32 bytes and a maximum
* 1 ^ idr[1].CMDQS x 16 bytes (do GET_HW_INFO call to read idr[1] in
This line is ambiguous to me intended to express a power of 2. 1 ^ idr[1].CMDQS x 16 bytes -> (2 ^ idr[1].CMDQS) x 16 bytes ?
You could consider like this (2 ^ idr[1].CMDQS) * 16 bytes (use GET_HW_INFO call to read idr[1] from struct iommu_hw_info_arm_smmuv3) or more clear (2 to the power of idr[1].CMDQS)
* struct iommu_hw_info_arm_smmuv3)
* - suggest to back the queue memory with contiguous physical pages or
* a single huge page with alignment of the queue size, limit vSMMU's
* IDR1.CMDQS to the huge page size divided by 16 bytes
*/
- IOMMU_VCMDQ_TYPE_TEGRA241_CMDQV = 1, };
/**
[clip]
struct arm_smmu_device *smmu = vsmmu->smmu; diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c index 869c90b660c1..88e2b6506b3a 100644 --- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c @@ -8,7 +8,9 @@ #include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/iommu.h> +#include <linux/iommufd.h> #include <linux/iopoll.h> +#include <uapi/linux/iommufd.h> #include <acpi/acpixf.h>
[clip]
+/**
- struct tegra241_vintf_sid - Virtual Interface Stream ID Replacement
- @core: Embedded iommufd_vdevice structure, holding virtual Stream ID
- @vintf: Parent VINTF pointer
- @sid: Physical Stream ID
- @id: Slot index in the VINTF
@idx
- */
+struct tegra241_vintf_sid {
- struct iommufd_vdevice core;
- struct tegra241_vintf *vintf;
- u32 sid;
- u8 idx; };
[clip]
- /*
* HW requires to map LVCMDQs in ascending order, so reject if the
* previous lvcmdqs is not allocated yet.
*/
- if (index) {
prev = vintf->lvcmdqs[index - 1];
if (!prev)
return ERR_PTR(-EIO);
- }
- /*
* @length must be a power of 2, in range of
* [ 32, 1 ^ (idr[1].CMDQS + CMDQ_ENT_SZ_SHIFT) ]
2 ^ (idr[1].CMDQS + CMDQ_ENT_SZ_SHIFT) or 1 << idr[1].CMDQS
*/
- max_n_shift = FIELD_GET(IDR1_CMDQS,
readl_relaxed(smmu->base + ARM_SMMU_IDR1));
LGTM, aside from a minor cosmetic thing.
Thanks, Alok