From nobody Mon May 25 01:15:57 2026 Received: from canpmsgout07.his.huawei.com (canpmsgout07.his.huawei.com [113.46.200.222]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 279B633B6D0 for ; Wed, 20 May 2026 06:37:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.222 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259050; cv=none; b=s5liXKNjQeNK2J9lbViSxjNdgXtA8NTvJl8L5WUMykOnv3Ts4QZfA5xiJPW/vbr6Aop2S3pxDeOjuQHEpAA+m1N/r4Y5TzdmZaG/fme++p3mwJoRlyEFdGq7MXpJPmHwNBwKIKWcmPiMcXL3LgB74ceoNNijj6eUl/PPFQ8q0lE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259050; c=relaxed/simple; bh=2ftl18dR7HOEi8sG+gLqp4JAKOMYbTvgLeQIMATXcIg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XInFILARD6n+d8W+fuiFO/FFDGUajjfERw3BdbT5fmT3vTFmf0CIKKkWg1p2NZcI523WW3XwwMfzQDtX0x3vlMfmLsME4eAy3PqlZl0duhA4MArvLBv8tnBrH1KWaYpHsFQdoW9GZBVbXas0IdjfEe90GeQsGnqFHAmqmi582wA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=nC8RY6CR; arc=none smtp.client-ip=113.46.200.222 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="nC8RY6CR" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=ZprKFw1Gp7/I6QbK1zEmmCPK6+j7d5nsxaS0M84UAs0=; b=nC8RY6CRmXzV3YtBXxwR944ibgKcGXKOJELOmWxPMbPN0yzMZrZ8yxhLfkPFFchJJyrA2yc+/ KFy1E4Zhf3ogJporZGWE0fgYno7dDgLjBbeEfOo4oHhsXS0ycP4Q+zJoblGgVU3xhqeCKH/xFJ1 tYpVjbxn41x3JF79nuRaM2o= Received: from mail.maildlp.com (unknown [172.19.162.92]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4gL1q35P84zLm45; Wed, 20 May 2026 14:29:35 +0800 (CST) Received: from kwepemj200003.china.huawei.com (unknown [7.202.194.15]) by mail.maildlp.com (Postfix) with ESMTPS id A38C740562; Wed, 20 May 2026 14:37:16 +0800 (CST) Received: from localhost.huawei.com (10.90.31.46) by kwepemj200003.china.huawei.com (7.202.194.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 20 May 2026 14:37:15 +0800 From: Qinxin Xia To: , , , CC: , , , , , , , , , Subject: [PATCH 1/5] iommu/arm-smmu-v3: Add basic debugfs framework Date: Wed, 20 May 2026 14:37:07 +0800 Message-ID: <20260520063714.2440584-1-xiaqinxin@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com> References: <20260328101706.3448655-1-xiaqinxin@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To kwepemj200003.china.huawei.com (7.202.194.15) Add basic debugfs framework for ARM SMMUv3 driver. This creates the root directory structure and provides capability display functionality. The debugfs hierarchy is organized as: /sys/kernel/debug/iommu/arm_smmu_v3/ =E2=94=94=E2=94=80=E2=94=80 smmu/ =E2=94=94=E2=94=80=E2=94=80 capabilities Signed-off-by: Qinxin Xia --- drivers/iommu/Kconfig | 11 ++ drivers/iommu/arm/arm-smmu-v3/Makefile | 1 + .../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 172 ++++++++++++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 16 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 13 ++ 5 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index f86262b11416..f28f09adba03 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -93,6 +93,17 @@ config IOMMU_DEBUGFS debug/iommu directory, and then populate a subdirectory with entries as required. =20 +config ARM_SMMU_V3_DEBUGFS + bool "ARM SMMUv3 DebugFS support" + depends on ARM_SMMU_V3 && IOMMU_DEBUGFS + help + Expose ARM SMMUv3 internal state via debugfs for debugging and + diagnostics. This creates /sys/kernel/debug/iommu/arm_smmu_v3/ + with detailed information about SMMU configuration, stream tables, + and context descriptors. + + Say N unless you are debugging SMMU issues. + choice prompt "IOMMU default domain type" depends on IOMMU_API diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile b/drivers/iommu/arm/arm= -smmu-v3/Makefile index 493a659cc66b..787538fb7054 100644 --- a/drivers/iommu/arm/arm-smmu-v3/Makefile +++ b/drivers/iommu/arm/arm-smmu-v3/Makefile @@ -4,5 +4,6 @@ arm_smmu_v3-y :=3D arm-smmu-v3.o arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_IOMMUFD) +=3D arm-smmu-v3-iommufd.o arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) +=3D arm-smmu-v3-sva.o arm_smmu_v3-$(CONFIG_TEGRA241_CMDQV) +=3D tegra241-cmdqv.o +arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_DEBUGFS) +=3D arm-smmu-v3-debugfs.o =20 obj-$(CONFIG_ARM_SMMU_V3_KUNIT_TEST) +=3D arm-smmu-v3-test.o diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/= iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c new file mode 100644 index 000000000000..1fc2cd1651b4 --- /dev/null +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM SMMUv3 DebugFS Support + * + * Directory Structure: + * /sys/kernel/debug/iommu/arm_smmu_v3/ + * =E2=94=94=E2=94=80=E2=94=80 smmu/ + * =E2=94=9C=E2=94=80=E2=94=80 capabilities # SMMU feature capabili= ties and configuration + * + * The capabilities file provides detailed information about: + * - translation stage support (Stage1/Stage2) + * - System coherency, ATS, and PRI feature availability + * - Stream table size and command/event queue depths + * + * Copyright (C) 2026 HiSilicon Limited. + * Author: Qinxin Xia + */ + +#include +#include +#include +#include "arm-smmu-v3.h" + +static struct dentry *smmu_debugfs_root; +static DEFINE_MUTEX(arm_smmu_debugfs_lock); + +/** + * smmu_debugfs_capabilities_show() - Display SMMU capabilities + * @seq: seq_file to write to + * @unused: unused parameter + * + * Errors are reported via seq_puts, the function always returns 0 + */ +static int smmu_debugfs_capabilities_show(struct seq_file *seq, void *unus= ed) +{ + struct arm_smmu_device *smmu =3D seq->private; + + if (!smmu) { + seq_puts(seq, "SMMU not available\n"); + return 0; + } + + seq_puts(seq, "SMMUv3 Capabilities:\n"); + seq_printf(seq, " Stage1 Translation: %s\n", + smmu->features & ARM_SMMU_FEAT_TRANS_S1 ? "Yes" : "No"); + seq_printf(seq, " Stage2 Translation: %s\n", + smmu->features & ARM_SMMU_FEAT_TRANS_S2 ? "Yes" : "No"); + seq_printf(seq, " Coherent Walk: %s\n", + smmu->features & ARM_SMMU_FEAT_COHERENCY ? "Yes" : "No"); + seq_printf(seq, " ATS Support: %s\n", + smmu->features & ARM_SMMU_FEAT_ATS ? "Yes" : "No"); + seq_printf(seq, " PRI Support: %s\n", + smmu->features & ARM_SMMU_FEAT_PRI ? "Yes" : "No"); + seq_printf(seq, " Stream Table Size: %llu\n", 1ULL << smmu->sid_bits); + seq_printf(seq, " Command Queue Depth: %d\n", + 1 << smmu->cmdq.q.llq.max_n_shift); + seq_printf(seq, " Event Queue Depth: %d\n", + 1 << smmu->evtq.q.llq.max_n_shift); + + return 0; +} + +static int smmu_debugfs_capabilities_open(struct inode *inode, struct file= *file) +{ + struct arm_smmu_device *smmu =3D inode->i_private; + int ret; + + if (!smmu || !get_device(smmu->dev)) + return -ENODEV; + + ret =3D single_open(file, smmu_debugfs_capabilities_show, smmu); + if (ret) + put_device(smmu->dev); + + return ret; +} + +static int smmu_debugfs_capabilities_release(struct inode *inode, struct f= ile *file) +{ + struct seq_file *seq =3D file->private_data; + struct arm_smmu_device *smmu =3D seq->private; + + single_release(inode, file); + if (smmu) + put_device(smmu->dev); + + return 0; +} + +static const struct file_operations smmu_debugfs_capabilities_fops =3D { + .owner =3D THIS_MODULE, + .open =3D smmu_debugfs_capabilities_open, + .read =3D seq_read, + .llseek =3D seq_lseek, + .release =3D smmu_debugfs_capabilities_release, +}; + +/** + * arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device + * @smmu: SMMU device to setup debugfs for + * @name: SMMU device name + * + * This function creates the basic debugfs directory structure for an SMMU= device. + * + * Return: 0 on success, negative error code on failure + */ +int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name) +{ + struct arm_smmu_debugfs *debugfs; + struct dentry *smmu_dir; + + /* Create root directory if it doesn't exist */ + scoped_guard(mutex, &arm_smmu_debugfs_lock) { + if (!smmu_debugfs_root) { + /* Once created, it will not be removed */ + smmu_debugfs_root =3D debugfs_create_dir("arm_smmu_v3", + iommu_debugfs_dir); + if (IS_ERR(smmu_debugfs_root)) { + smmu_debugfs_root =3D NULL; + return -ENOMEM; + } + } + } + + /* Allocate debugfs structure */ + debugfs =3D kzalloc_obj(*debugfs); + if (!debugfs) + return -ENOMEM; + + /* Create SMMU instance directory */ + smmu_dir =3D debugfs_create_dir(name, smmu_debugfs_root); + if (IS_ERR(smmu_dir)) { + kfree(debugfs); + smmu->debugfs =3D NULL; + return PTR_ERR(smmu_dir); + } + + debugfs->smmu_dir =3D smmu_dir; + smmu->debugfs =3D debugfs; + + /* Create capabilities file */ + debugfs_create_file("capabilities", 0444, smmu_dir, smmu, + &smmu_debugfs_capabilities_fops); + + dev_dbg(smmu->dev, "debugfs initialized for %s\n", name); + return 0; +} + +/** + * arm_smmu_debugfs_remove() - Clean up debugfs entries for an SMMU device + * @smmu: SMMU device + * + * This function removes the debugfs directories created by setup. + */ +void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu) +{ + struct arm_smmu_debugfs *debugfs; + struct dentry *smmu_dir; + + scoped_guard(mutex, &arm_smmu_debugfs_lock) { + debugfs =3D smmu->debugfs; + if (!debugfs) + return; + + smmu_dir =3D debugfs->smmu_dir; + kfree(debugfs); + smmu->debugfs =3D NULL; + } + + /* Remove outside lock to avoid blocking on active VFS operations */ + debugfs_remove_recursive(smmu_dir); +} diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/ar= m/arm-smmu-v3/arm-smmu-v3.c index e8d7dbe495f0..929b8ead95b0 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -5469,6 +5469,7 @@ static int arm_smmu_device_probe(struct platform_devi= ce *pdev) resource_size_t ioaddr; struct arm_smmu_device *smmu; struct device *dev =3D &pdev->dev; + char name[32]; =20 smmu =3D devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); if (!smmu) @@ -5496,6 +5497,7 @@ static int arm_smmu_device_probe(struct platform_devi= ce *pdev) return -EINVAL; } ioaddr =3D res->start; + snprintf(name, sizeof(name), "smmu3.%pa", &ioaddr); =20 /* * Don't map the IMPLEMENTATION DEFINED regions, since they may contain @@ -5548,6 +5550,12 @@ static int arm_smmu_device_probe(struct platform_dev= ice *pdev) /* Check for RMRs and install bypass STEs if any */ arm_smmu_rmr_install_bypass_ste(smmu); =20 +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS + ret =3D arm_smmu_debugfs_setup(smmu, name); + if (ret) + dev_warn(dev, "Failed to create debugfs!\n"); +#endif + /* Reset the device */ ret =3D arm_smmu_device_reset(smmu); if (ret) @@ -5555,7 +5563,7 @@ static int arm_smmu_device_probe(struct platform_devi= ce *pdev) =20 /* And we're up. Go go go! */ ret =3D iommu_device_sysfs_add(&smmu->iommu, dev, NULL, - "smmu3.%pa", &ioaddr); + "%s", name); if (ret) goto err_disable; =20 @@ -5570,6 +5578,9 @@ static int arm_smmu_device_probe(struct platform_devi= ce *pdev) err_free_sysfs: iommu_device_sysfs_remove(&smmu->iommu); err_disable: +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS + arm_smmu_debugfs_remove(smmu); +#endif arm_smmu_device_disable(smmu); err_free_iopf: iopf_queue_free(smmu->evtq.iopf); @@ -5582,6 +5593,9 @@ static void arm_smmu_device_remove(struct platform_de= vice *pdev) =20 iommu_device_unregister(&smmu->iommu); iommu_device_sysfs_remove(&smmu->iommu); +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS + arm_smmu_debugfs_remove(smmu); +#endif arm_smmu_device_disable(smmu); iopf_queue_free(smmu->evtq.iopf); ida_destroy(&smmu->vmid_map); diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/ar= m/arm-smmu-v3/arm-smmu-v3.h index ef42df4753ec..8e1c19b6831c 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -820,6 +820,15 @@ struct arm_smmu_impl_ops { const struct iommu_user_data *user_data); }; =20 +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS +struct arm_smmu_debugfs { + struct dentry *smmu_dir; +}; + +int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name); +void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu); +#endif + /* An SMMUv3 instance */ struct arm_smmu_device { struct device *dev; @@ -890,6 +899,10 @@ struct arm_smmu_device { =20 struct rb_root streams; struct mutex streams_mutex; + +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS + struct arm_smmu_debugfs *debugfs; +#endif }; =20 struct arm_smmu_stream { --=20 2.33.0 From nobody Mon May 25 01:15:57 2026 Received: from canpmsgout08.his.huawei.com (canpmsgout08.his.huawei.com [113.46.200.223]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E035533B97B for ; Wed, 20 May 2026 06:37:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.223 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259046; cv=none; b=Indgk2fUZSte2lyOEMJ7eolo+jOhaU126tP79qzRUe/h0i5vc4pGSwhRZ0L0Q1dDISrP4/bcq2IA1nnWw0tn3H6FsyaFPpNO1le88NULHM5NQ2pU9wj6WItTwysy4geTQwflMDDoFmMJ4CsjeR89107wLT3SyIApNM2x7NXQvJw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259046; c=relaxed/simple; bh=vMHh8OXTHaHYXC4EputxpzkylZJd5ittKyjt+2GhsPY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Val+5SVqc3dVoqjluuvof6zC5tkmHXXPZa231FaUZVTcpbuT2kYAueHRr2uD7MVGcTxytSko68qsuZuzei1qvoKZJqWKLEYSKtLQNL8Dq6jXBVsA9fV+2tTY6T354B/x5C5/Rrj3VflISoG+61Rx2QHJJFCbaXQNBQNnNoSF91I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=e/ehfqYc; arc=none smtp.client-ip=113.46.200.223 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="e/ehfqYc" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=IMkepDCVc2TLY2VZbej5xOqxbCMgq8RcQd0nxJHbH2o=; b=e/ehfqYcuRj5vCkhJu+aFkoz6KYv3jLv2fDoFIQtEt73SO1JwX3M+SEtxaamrD55m0QphFpbY BgG+OFcQHH6rc2vpas0AFiUfJ8EigVHJwaUxqY4xOr5PKINa9FigAk7HPBeb7n7zpkUMYfX39Z1 C+R5q6eVm8GgT1I46IeRW5g= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout08.his.huawei.com (SkyGuard) with ESMTPS id 4gL1q33dCrzmV7Z; Wed, 20 May 2026 14:29:35 +0800 (CST) Received: from kwepemj200003.china.huawei.com (unknown [7.202.194.15]) by mail.maildlp.com (Postfix) with ESMTPS id 04C8940561; Wed, 20 May 2026 14:37:18 +0800 (CST) Received: from localhost.huawei.com (10.90.31.46) by kwepemj200003.china.huawei.com (7.202.194.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 20 May 2026 14:37:17 +0800 From: Qinxin Xia To: , , , CC: , , , , , , , , , Subject: [PATCH 2/5] iommu/arm-smmu-v3: Add register display to debugfs Date: Wed, 20 May 2026 14:37:08 +0800 Message-ID: <20260520063714.2440584-2-xiaqinxin@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com> References: <20260328101706.3448655-1-xiaqinxin@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To kwepemj200003.china.huawei.com (7.202.194.15) Add register display functionality to debugfs.This allows reading and displaying key SMMU register values including control registers and queue pointers. The registers file shows: - CR0, CR1, CR2 control registers - Command and Event queue pointers Signed-off-by: Qinxin Xia --- .../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/= iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c index 1fc2cd1651b4..a541476b7427 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c @@ -6,12 +6,17 @@ * /sys/kernel/debug/iommu/arm_smmu_v3/ * =E2=94=94=E2=94=80=E2=94=80 smmu/ * =E2=94=9C=E2=94=80=E2=94=80 capabilities # SMMU feature capabili= ties and configuration + * =E2=94=9C=E2=94=80=E2=94=80 registers # SMMU Key registers * * The capabilities file provides detailed information about: * - translation stage support (Stage1/Stage2) * - System coherency, ATS, and PRI feature availability * - Stream table size and command/event queue depths * + * The registers display provides crucial visibility into: + * - CR0, CR1, CR2 control registers + * - Command and Event queue pointers + * * Copyright (C) 2026 HiSilicon Limited. * Author: Qinxin Xia */ @@ -95,6 +100,80 @@ static const struct file_operations smmu_debugfs_capabi= lities_fops =3D { .release =3D smmu_debugfs_capabilities_release, }; =20 +/** + * smmu_debugfs_registers_show() - Display SMMU register values + * @seq: seq_file to write to + * @unused: unused parameter + * + * Errors are reported via seq_puts, the function always returns 0 + */ +static int smmu_debugfs_registers_show(struct seq_file *seq, void *unused) +{ + struct arm_smmu_device *smmu =3D seq->private; + void __iomem *base; + + if (!smmu || !smmu->base) { + seq_puts(seq, "SMMU not available\n"); + return 0; + } + + base =3D smmu->base; + + seq_puts(seq, "SMMUv3 Key Registers:\n"); + + /* 32-bit control registers */ + seq_printf(seq, "CR0: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR0)); + seq_printf(seq, "CR1: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR1)); + seq_printf(seq, "CR2: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR2)); + + /* 32-bit queue pointer registers */ + seq_printf(seq, "CMDQ_PROD: 0x%08x\n", + readl_relaxed(base + ARM_SMMU_CMDQ_PROD)); + seq_printf(seq, "CMDQ_CONS: 0x%08x\n", + readl_relaxed(base + ARM_SMMU_CMDQ_CONS)); + seq_printf(seq, "EVTQ_PROD: 0x%08x\n", + smmu->page1 ? readl_relaxed(smmu->page1 + ARM_SMMU_EVTQ_PROD) : 0); + seq_printf(seq, "EVTQ_CONS: 0x%08x\n", + smmu->page1 ? readl_relaxed(smmu->page1 + ARM_SMMU_EVTQ_CONS) : 0); + + return 0; +} + +static int smmu_debugfs_registers_open(struct inode *inode, struct file *f= ile) +{ + struct arm_smmu_device *smmu =3D inode->i_private; + int ret; + + if (!smmu || !get_device(smmu->dev)) + return -ENODEV; + + ret =3D single_open(file, smmu_debugfs_registers_show, smmu); + if (ret) + put_device(smmu->dev); + + return ret; +} + +static int smmu_debugfs_registers_release(struct inode *inode, struct file= *file) +{ + struct seq_file *seq =3D file->private_data; + struct arm_smmu_device *smmu =3D seq->private; + + single_release(inode, file); + if (smmu) + put_device(smmu->dev); + + return 0; +} + +static const struct file_operations smmu_debugfs_registers_fops =3D { + .owner =3D THIS_MODULE, + .open =3D smmu_debugfs_registers_open, + .read =3D seq_read, + .llseek =3D seq_lseek, + .release =3D smmu_debugfs_registers_release, +}; + /** * arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device * @smmu: SMMU device to setup debugfs for @@ -142,6 +221,9 @@ int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu= , const char *name) debugfs_create_file("capabilities", 0444, smmu_dir, smmu, &smmu_debugfs_capabilities_fops); =20 + debugfs_create_file("registers", 0444, smmu_dir, smmu, + &smmu_debugfs_registers_fops); + dev_dbg(smmu->dev, "debugfs initialized for %s\n", name); return 0; } --=20 2.33.0 From nobody Mon May 25 01:15:57 2026 Received: from canpmsgout08.his.huawei.com (canpmsgout08.his.huawei.com [113.46.200.223]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9FF9333A9E2 for ; Wed, 20 May 2026 06:37:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.223 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259047; cv=none; b=riLw/2DynJk2eHzu7FrvGBwvJrv9//6qDPnmLTf6o4YO6flJ2InaNSN8gk1MfPp8RGICMLIMNeb2eIYLhDHdaDjcHoCeQNfL1061CRftThpxTVfM65Glda6vZLSSDucEaKtqrjBcdB6YIQm6lOaG2ZziPu79tbVUd3N5KMD1u20= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259047; c=relaxed/simple; bh=i55YQez6SwPTc6r0xcjZ0eBlTjsv/woQzV7M1g5yyOk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=L3RsisDWGZJ12yEzNofRoLlpb5f4LqYaVHtArOj3L7JtNeei2dKOJDLkTsKs6VKiqqC8F2Y1FiXDZA0r5BP3y7bine1FRo9XHjfn4+Jd0bks39mY+E4VRJazAsRIO7H+CyOzbMkZx0ovQ/HmOZP+6K//N3OAsLN8seTs9+qJ6Is= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=3xsa1KGA; arc=none smtp.client-ip=113.46.200.223 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="3xsa1KGA" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=sbh0U2CJNS6rjWyK+D0W274Ocmy9rhlndaWq+7vgBUM=; b=3xsa1KGAoe0kiq/G5OjSoKFmVBQ+fv2AF8HkxXKxB7qDPf94rh0OrTHCIpVIqgmkaRL4UEcc2 JICC6S+W6zhZ7iIkrdLau/b1BdqinZLLNrm8/KvlXv9tLafUbvAyTLpyLkoO0h7k/W1ElcTk//g b0oBd0MGSgUdgtc6DonQ0GE= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout08.his.huawei.com (SkyGuard) with ESMTPS id 4gL1q442JjzmVD0; Wed, 20 May 2026 14:29:36 +0800 (CST) Received: from kwepemj200003.china.huawei.com (unknown [7.202.194.15]) by mail.maildlp.com (Postfix) with ESMTPS id 14B1C40572; Wed, 20 May 2026 14:37:19 +0800 (CST) Received: from localhost.huawei.com (10.90.31.46) by kwepemj200003.china.huawei.com (7.202.194.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 20 May 2026 14:37:18 +0800 From: Qinxin Xia To: , , , CC: , , , , , , , , , Subject: [PATCH 3/5] iommu/arm-smmu-v3: Add Stream Table Entry display to debugfs Date: Wed, 20 May 2026 14:37:09 +0800 Message-ID: <20260520063714.2440584-3-xiaqinxin@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com> References: <20260328101706.3448655-1-xiaqinxin@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To kwepemj200003.china.huawei.com (7.202.194.15) Add Stream Table Entry (STE) display functionality to debugfs. This allow inspecting STE contents for each device stream including: - STE validity and configuration - Stage 1 and Stage 2 context pointers - Raw STE data /sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/ =E2=94=94=E2=94=80=E2=94=80 / =E2=94=94=E2=94=80=E2=94=80=E2=94=80 ste Signed-off-by: Qinxin Xia --- .../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 235 ++++++++++++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 17 ++ 3 files changed, 261 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/= iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c index a541476b7427..a5866f34264f 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c @@ -7,6 +7,9 @@ * =E2=94=94=E2=94=80=E2=94=80 smmu/ * =E2=94=9C=E2=94=80=E2=94=80 capabilities # SMMU feature capabili= ties and configuration * =E2=94=9C=E2=94=80=E2=94=80 registers # SMMU Key registers + * =E2=94=9C=E2=94=80=E2=94=80 stream_table + * =E2=94=9C=E2=94=80=E2=94=80 / = # Stream ID + * =E2=94=9C=E2=94=80=E2=94=80 ste = # Stream Table Entry * * The capabilities file provides detailed information about: * - translation stage support (Stage1/Stage2) @@ -17,6 +20,11 @@ * - CR0, CR1, CR2 control registers * - Command and Event queue pointers * + * The STE Information Displayed: + * - STE validity and configuration + * - Stage 1 and Stage 2 context pointers + * - Raw STE data + * * Copyright (C) 2026 HiSilicon Limited. * Author: Qinxin Xia */ @@ -174,6 +182,231 @@ static const struct file_operations smmu_debugfs_regi= sters_fops =3D { .release =3D smmu_debugfs_registers_release, }; =20 +/** + * smmu_debugfs_ste_show() - Dump STE details to seq_file + * @seq: seq_file to write to + * @unused: unused parameter + * + * Errors are reported via seq_puts, the function always returns 0 + */ +static int smmu_debugfs_ste_show(struct seq_file *seq, void *unused) +{ + struct ste_context *ctx =3D seq->private; + struct arm_smmu_master *master =3D ctx->master; + struct arm_smmu_device *smmu; + struct arm_smmu_ste *ste; + u32 sid, cfg; + int i; + + if (!master) { + seq_puts(seq, "No SMMU master data\n"); + return 0; + } + + smmu =3D master->smmu; + guard(mutex)(&smmu->streams_mutex); + + sid =3D ctx->sid; + + if (!arm_smmu_sid_in_range(smmu, sid)) { + seq_printf(seq, "Invalid Stream ID: %u (max %u)\n", + sid, (1 << smmu->sid_bits) - 1); + return 0; + } + + ste =3D arm_smmu_get_step_for_sid(smmu, sid); + if (!ste) { + seq_printf(seq, "STE not available for SID %u\n", sid); + return 0; + } + + seq_printf(seq, "STE for Stream ID %u\n", sid); + seq_printf(seq, " Valid: %s\n", + le64_to_cpu(ste->data[0]) & STRTAB_STE_0_V ? "Yes" : "No"); + + seq_puts(seq, " Config: "); + + cfg =3D FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(ste->data[0])); + + switch (cfg) { + case STRTAB_STE_0_CFG_BYPASS: + seq_puts(seq, "BYPASS\n"); + break; + case STRTAB_STE_0_CFG_S1_TRANS: + seq_puts(seq, "only S1_TRANS\n"); + break; + case STRTAB_STE_0_CFG_S2_TRANS: + seq_puts(seq, "only S2_TRANS\n"); + break; + case STRTAB_STE_0_CFG_NESTED: + seq_puts(seq, "S1+S2_TRANS\n"); + break; + case STRTAB_STE_0_CFG_ABORT: + seq_puts(seq, "ABORT\n"); + break; + default: + seq_puts(seq, "UNKNOWN\n"); + } + + if (cfg =3D=3D STRTAB_STE_0_CFG_S1_TRANS || cfg =3D=3D STRTAB_STE_0_CFG_N= ESTED) { + seq_printf(seq, " S1ContextPtr: 0x%016llx\n", + le64_to_cpu(ste->data[0]) & STRTAB_STE_0_S1CTXPTR_MASK); + } + + if (cfg =3D=3D STRTAB_STE_0_CFG_S2_TRANS || cfg =3D=3D STRTAB_STE_0_CFG_N= ESTED) { + seq_printf(seq, " S2TTB: 0x%016llx\n", + le64_to_cpu(ste->data[3]) & STRTAB_STE_3_S2TTB_MASK); + } + + /* Display raw STE data */ + seq_puts(seq, " Raw Data:\n"); + for (i =3D 0; i < STRTAB_STE_DWORDS; i++) + seq_printf(seq, " STE[%d]: 0x%016llx\n", i, + le64_to_cpu(ste->data[i])); + + return 0; +} + +static int smmu_debugfs_ste_open(struct inode *inode, struct file *file) +{ + struct ste_context *ctx =3D inode->i_private; + int ret; + + if (!ctx || !get_device(ctx->master->dev)) + return -ENODEV; + + ret =3D single_open(file, smmu_debugfs_ste_show, ctx); + if (ret) + put_device(ctx->master->dev); + + return ret; +} + +static int smmu_debugfs_ste_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq =3D file->private_data; + struct ste_context *ctx =3D seq->private; + + single_release(inode, file); + if (ctx) + put_device(ctx->master->dev); + return 0; +} + +static const struct file_operations smmu_debugfs_ste_fops =3D { + .owner =3D THIS_MODULE, + .open =3D smmu_debugfs_ste_open, + .read =3D seq_read, + .llseek =3D seq_lseek, + .release =3D smmu_debugfs_ste_release, +}; + +/** + * arm_smmu_debugfs_create_stream_table() - Create debugfs entries for str= eam table + * @smmu: SMMU device + * @dev: device to create entries for + * + * Return: 0 on success, negative error code on failure + */ +int arm_smmu_debugfs_create_stream_table(struct arm_smmu_device *smmu, + struct device *dev) +{ + struct dentry *stream_dir, *dev_dir; + struct arm_smmu_master *master; + struct ste_context *ctx; + char name[64]; + u32 sid; + int i; + + if (!smmu->debugfs) + return -ENODEV; + + scoped_guard(mutex, &arm_smmu_debugfs_lock) { + if (!smmu->debugfs->stream_dir) { + stream_dir =3D debugfs_create_dir("stream_table", + smmu->debugfs->smmu_dir); + if (IS_ERR(stream_dir)) + return PTR_ERR(stream_dir); + + smmu->debugfs->stream_dir =3D stream_dir; + } else { + stream_dir =3D smmu->debugfs->stream_dir; + } + } + + master =3D dev_iommu_priv_get(dev); + if (!master || !master->num_streams) + return -ENODEV; + + for (i =3D 0; i < master->num_streams; i++) { + sid =3D master->streams[i].id; + snprintf(name, sizeof(name), "%u", sid); + dev_dir =3D debugfs_create_dir(name, stream_dir); + if (IS_ERR(dev_dir)) + continue; + + /* Create STE file */ + ctx =3D kzalloc_obj(*ctx); + if (!ctx) + continue; + + ctx->master =3D master; + ctx->sid =3D sid; + spin_lock(&smmu->debugfs->stream_lock); + list_add_tail(&ctx->node, &smmu->debugfs->stream_list); + spin_unlock(&smmu->debugfs->stream_lock); + debugfs_create_file("ste", 0444, dev_dir, ctx, + &smmu_debugfs_ste_fops); + } + + return 0; +} + +/** + * arm_smmu_debugfs_remove_stream_table() - Remove debugfs entries for str= eam table + * @smmu: SMMU device + * @dev: device to remove entries for + * + * This function removes the debugfs directories created by + * arm_smmu_debugfs_create_stream_table(). + */ +void arm_smmu_debugfs_remove_stream_table(struct arm_smmu_device *smmu, + struct device *dev) +{ + struct dentry *stream_dir, *dev_dir; + struct arm_smmu_master *master; + struct ste_context *ctx, *tmp; + char name[64]; + int i; + + /* Check if stream_table directory exists */ + if (!smmu->debugfs || !smmu->debugfs->stream_dir) + return; + + stream_dir =3D smmu->debugfs->stream_dir; + master =3D dev_iommu_priv_get(dev); + if (!master) + return; + + /* Remove directories for each stream ID */ + for (i =3D 0; i < master->num_streams; i++) { + snprintf(name, sizeof(name), "%u", master->streams[i].id); + dev_dir =3D debugfs_lookup(name, stream_dir); + debugfs_remove_recursive(dev_dir); + dput(dev_dir); + } + + /* Free stream context */ + spin_lock(&smmu->debugfs->stream_lock); + list_for_each_entry_safe(ctx, tmp, &smmu->debugfs->stream_list, node) { + if (ctx->master->dev =3D=3D dev) { + list_del(&ctx->node); + kfree(ctx); + } + } + spin_unlock(&smmu->debugfs->stream_lock); +} + /** * arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device * @smmu: SMMU device to setup debugfs for @@ -215,6 +448,8 @@ int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu= , const char *name) } =20 debugfs->smmu_dir =3D smmu_dir; + INIT_LIST_HEAD(&debugfs->stream_list); + spin_lock_init(&debugfs->stream_lock); smmu->debugfs =3D debugfs; =20 /* Create capabilities file */ diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/ar= m/arm-smmu-v3/arm-smmu-v3.c index 929b8ead95b0..ca0fa043c2ce 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2992,7 +2992,7 @@ static int arm_smmu_domain_finalise(struct arm_smmu_d= omain *smmu_domain, return 0; } =20 -static struct arm_smmu_ste * +struct arm_smmu_ste * arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) { struct arm_smmu_strtab_cfg *cfg =3D &smmu->strtab_cfg; @@ -4090,7 +4090,7 @@ struct arm_smmu_device *arm_smmu_get_by_fwnode(struct= fwnode_handle *fwnode) return dev ? dev_get_drvdata(dev) : NULL; } =20 -static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid) +bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid) { if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) return arm_smmu_strtab_l1_idx(sid) < smmu->strtab_cfg.l2.num_l1_ents; @@ -4269,6 +4269,10 @@ static struct iommu_device *arm_smmu_probe_device(st= ruct device *dev) pci_prepare_ats(to_pci_dev(dev), stu); } =20 +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS + arm_smmu_debugfs_create_stream_table(smmu, dev); +#endif + return &smmu->iommu; =20 err_free_master: @@ -4282,6 +4286,9 @@ static void arm_smmu_release_device(struct device *de= v) =20 WARN_ON(master->iopf_refcount); =20 +#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS + arm_smmu_debugfs_remove_stream_table(master->smmu, dev); +#endif arm_smmu_disable_pasid(master); arm_smmu_remove_master(master); if (arm_smmu_cdtab_allocated(&master->cd_table)) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/ar= m/arm-smmu-v3/arm-smmu-v3.h index 8e1c19b6831c..9c9be63dc9e2 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -821,12 +821,29 @@ struct arm_smmu_impl_ops { }; =20 #ifdef CONFIG_ARM_SMMU_V3_DEBUGFS +struct ste_context { + struct arm_smmu_master *master; + u32 sid; + struct list_head node; +}; + struct arm_smmu_debugfs { + struct list_head stream_list; + spinlock_t stream_lock; struct dentry *smmu_dir; + struct dentry *stream_dir; }; =20 int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name); void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu); +int arm_smmu_debugfs_create_stream_table(struct arm_smmu_device *smmu, + struct device *dev); +void arm_smmu_debugfs_remove_stream_table(struct arm_smmu_device *smmu, + struct device *dev); + +struct arm_smmu_ste * +arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid); +bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid); #endif =20 /* An SMMUv3 instance */ --=20 2.33.0 From nobody Mon May 25 01:15:57 2026 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CD8033A029 for ; Wed, 20 May 2026 06:37:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259050; cv=none; b=ZfpRRQtsQwVX6NrgjhN4wr5HCanUl0pZBfJfiJglG6E6yX8B3s0SBfvM4wsF0JLY0L1T5+EdiCptkpE0b9Y0GQvvEdcBVBB+ke1+gQdoYP0G46sV1qadlZWE3sHVNdTZ8ug8yR9wQZewSa/0FTDRCmc8e7HEDIFBhndg0F45uCQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259050; c=relaxed/simple; bh=id5nu2+5revVGV2X7GFUSfspCR6Al6e4oMBFp59uBPI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H3PnP+64irQNkYVU920CvM0AAKtO8uVQO2R/khZ3OajE+L7j5TnThtX5ahBZP00m6zkbQPz5RzOU5QP4Ka66FS7AIrAPcxlPDLIbNGjdg5ZpykWSDQCmZ5FO1Lrbgdj8QeOZy/2UZ71Mu0nptsq6o9pjLKdy/3AFv3t5cWoMttk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=DTUgcXX0; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="DTUgcXX0" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=Vu3EZBeWinYUHPBmY/X090V8/6NEcv7XCtOXv6H294Q=; b=DTUgcXX0QCOxzf8m0FRgEYq6mHvJ8fm5/LaunYVYwK8xC/eRMYpl+bJhsuFUryDpThYXxX4SD zD5E2giVkd242GleR1g//3guxL955J3f6aBVzlkV2nSgD1kadg92DnjwG042X0ideouW+DMHrsE PjSrMIPTDI/RKohWj9cLQ1I= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4gL1qt6q77z12LDX; Wed, 20 May 2026 14:30:18 +0800 (CST) Received: from kwepemj200003.china.huawei.com (unknown [7.202.194.15]) by mail.maildlp.com (Postfix) with ESMTPS id 307AB40537; Wed, 20 May 2026 14:37:20 +0800 (CST) Received: from localhost.huawei.com (10.90.31.46) by kwepemj200003.china.huawei.com (7.202.194.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 20 May 2026 14:37:19 +0800 From: Qinxin Xia To: , , , CC: , , , , , , , , , Subject: [PATCH 4/5] iommu/arm-smmu-v3: Add device symlink in stream table debugfs Date: Wed, 20 May 2026 14:37:10 +0800 Message-ID: <20260520063714.2440584-4-xiaqinxin@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com> References: <20260328101706.3448655-1-xiaqinxin@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To kwepemj200003.china.huawei.com (7.202.194.15) Add a symlink named under each stream table entry directory pointing to the sysfs directory of the actual device. This aids debugging by providing direct access to device attributes. /sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/ =E2=94=94=E2=94=80=E2=94=80 / =E2=94=9C=E2=94=80=E2=94=80=E2=94=80 ste =E2=94=94=E2=94=80=E2=94=80=E2=94=80 Signed-off-by: Qinxin Xia --- .../iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/= iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c index a5866f34264f..9babc7d640fd 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c @@ -10,6 +10,7 @@ * =E2=94=9C=E2=94=80=E2=94=80 stream_table * =E2=94=9C=E2=94=80=E2=94=80 / = # Stream ID * =E2=94=9C=E2=94=80=E2=94=80 ste = # Stream Table Entry + * =E2=94=9C=E2=94=80=E2=94=80 = # Symlink to device sysfs directory * * The capabilities file provides detailed information about: * - translation stage support (Stage1/Stage2) @@ -31,6 +32,7 @@ =20 #include #include +#include #include #include "arm-smmu-v3.h" =20 @@ -314,6 +316,7 @@ int arm_smmu_debugfs_create_stream_table(struct arm_smm= u_device *smmu, struct dentry *stream_dir, *dev_dir; struct arm_smmu_master *master; struct ste_context *ctx; + char *path =3D NULL, *full_path; char name[64]; u32 sid; int i; @@ -338,6 +341,9 @@ int arm_smmu_debugfs_create_stream_table(struct arm_smm= u_device *smmu, if (!master || !master->num_streams) return -ENODEV; =20 + /* Get device sysfs path once, reuse for all streams */ + path =3D kobject_get_path(&dev->kobj, GFP_KERNEL); + for (i =3D 0; i < master->num_streams; i++) { sid =3D master->streams[i].id; snprintf(name, sizeof(name), "%u", sid); @@ -357,8 +363,19 @@ int arm_smmu_debugfs_create_stream_table(struct arm_sm= mu_device *smmu, spin_unlock(&smmu->debugfs->stream_lock); debugfs_create_file("ste", 0444, dev_dir, ctx, &smmu_debugfs_ste_fops); + + /* Create a symlink to the device's sysfs directory */ + if (path) { + full_path =3D kasprintf(GFP_KERNEL, "/sys%s", path); + if (full_path) { + debugfs_create_symlink(dev_name(dev), dev_dir, + full_path); + kfree(full_path); + } + } } =20 + kfree(path); return 0; } =20 --=20 2.33.0 From nobody Mon May 25 01:15:57 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AD0E32C94A for ; Wed, 20 May 2026 06:37:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259050; cv=none; b=GVhDU63tZDk4oRBRGqPZFM2eaUXIpdo9rXZ5fNuJluyE2U46jB+uGEIncAxy7DipVixN7m6eQP4/M34ysTaZPa8EAfIF5+99Bk3G2V96PPJqFWC59L9IifCBg3JnMp9prvS/Yiv7RMEatoLPQI3XCv0I20jw9OpvJEvIql8bKnY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779259050; c=relaxed/simple; bh=Dr/4xDbrG510OQcjwBL+tFBVj+TL+p3PLRpuroJdcow=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iK2Kin4gZ8EzGTDxWcdL37B40fIT/mpfEekxycu9J1p/52wvV+G6YaBgGukQbWid4JcpRtixCDXkL6sI/mMYjsmEfYzEXgOapgaP3R311BeI1j4Ke/8Y1s4PafJutAOLYCSkwjVYYf/IhCWe4MMGIod7RRU/TwNso1tl4fVgyOc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=JP0H/hcb; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="JP0H/hcb" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=A+9GMhHowlViOnH7+R9rmivmHqr2sB1gmzk/fG1Uco0=; b=JP0H/hcbSFdYwsZD0y/WqrbQ/tzGa8skOHjGDlyMM26YfHsUUglbpIbKwyZp3qvRLTM/vFpTo 3HCy15p48E/Drxodqr2XwBNXeS97tlHjEveIXS+m62aOKUO8yxOEOfK+UDypixYU0bCkWRDf4gc v5gacV3Ab6oangMQznj6aY8= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4gL1qg5S4VzpT03; Wed, 20 May 2026 14:30:07 +0800 (CST) Received: from kwepemj200003.china.huawei.com (unknown [7.202.194.15]) by mail.maildlp.com (Postfix) with ESMTPS id 5915B4048F; Wed, 20 May 2026 14:37:21 +0800 (CST) Received: from localhost.huawei.com (10.90.31.46) by kwepemj200003.china.huawei.com (7.202.194.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 20 May 2026 14:37:20 +0800 From: Qinxin Xia To: , , , CC: , , , , , , , , , Subject: [PATCH 5/5] iommu/arm-smmu-v3: Add Context Descriptor display to debugfs Date: Wed, 20 May 2026 14:37:11 +0800 Message-ID: <20260520063714.2440584-5-xiaqinxin@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com> References: <20260328101706.3448655-1-xiaqinxin@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To kwepemj200003.china.huawei.com (7.202.194.15) Add Context Descriptor (CD) display functionality to debugfs. This allow inspecting CD contents for all Substream IDs including: - CD validity and translation parameters - TTBR0 and TCR configurations - Raw CD data /sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/ =E2=94=94=E2=94=80=E2=94=80 / =E2=94=9C=E2=94=80=E2=94=80=E2=94=80 ste =E2=94=9C=E2=94=80=E2=94=80=E2=94=80 cd =E2=94=94=E2=94=80=E2=94=80=E2=94=80 Signed-off-by: Qinxin Xia --- .../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/= iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c index 9babc7d640fd..567749de5537 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c @@ -10,6 +10,7 @@ * =E2=94=9C=E2=94=80=E2=94=80 stream_table * =E2=94=9C=E2=94=80=E2=94=80 / = # Stream ID * =E2=94=9C=E2=94=80=E2=94=80 ste = # Stream Table Entry + * =E2=94=9C=E2=94=80=E2=94=80 cd = # Context Descriptor * =E2=94=9C=E2=94=80=E2=94=80 = # Symlink to device sysfs directory * * The capabilities file provides detailed information about: @@ -26,6 +27,12 @@ * - Stage 1 and Stage 2 context pointers * - Raw STE data * + * CD Information Displayed: + * - T0SZ: Input address space size configuration + * - EPD0/EPD1: Stage 1 translation enable flags + * - TTBR0: Stage 1 translation table base address + * - Raw Data: Complete CD structure in hexadecimal format + * * Copyright (C) 2026 HiSilicon Limited. * Author: Qinxin Xia */ @@ -303,6 +310,97 @@ static const struct file_operations smmu_debugfs_ste_f= ops =3D { .release =3D smmu_debugfs_ste_release, }; =20 +/** + * smmu_debug_dump_cd() - Dump a single Context Descriptor + * @seq: seq_file to write to + * @cd: pointer to the Context Descriptor to dump + */ +static void smmu_debug_dump_cd(struct seq_file *seq, struct arm_smmu_cd *c= d) +{ + u64 data; + int i; + + /* CD 0 */ + data =3D le64_to_cpu(cd->data[0]); + seq_printf(seq, " T0SZ: 0x%llx\n", data & CTXDESC_CD_0_TCR_T0SZ); + seq_printf(seq, " EPD0: %s\n", data & CTXDESC_CD_0_TCR_EPD0 ? "Yes" : "N= o"); + seq_printf(seq, " EPD1: %s\n", data & CTXDESC_CD_0_TCR_EPD1 ? "Yes" : "N= o"); + + /* CD 1 */ + data =3D le64_to_cpu(cd->data[1]); + seq_printf(seq, " TTBR0: 0x%016llx\n", data & CTXDESC_CD_1_TTB0_MASK); + + /* Display raw CD data */ + seq_puts(seq, " Raw Data:\n"); + for (i =3D 0; i < CTXDESC_CD_DWORDS; i++) + seq_printf(seq, " CD[%d]: 0x%016llx\n", i, + le64_to_cpu(cd->data[i])); +} + +static int smmu_debugfs_cd_show(struct seq_file *seq, void *unused) +{ + struct device *dev =3D seq->private; + struct arm_smmu_master *master; + u32 max_ssids, ssid; + + guard(mutex)(&arm_smmu_asid_lock); + + master =3D dev_iommu_priv_get(dev); + if (!master) { + seq_puts(seq, "No master data\n"); + return 0; + } + + max_ssids =3D 1 << master->ssid_bits; + seq_printf(seq, "Context Descriptors for device (max SSIDs: %u):\n", + max_ssids); + + for (ssid =3D 0; ssid < max_ssids; ssid++) { + struct arm_smmu_cd *cd =3D arm_smmu_get_cd_ptr(master, ssid); + + if (cd && (le64_to_cpu(cd->data[0]) & CTXDESC_CD_0_V)) { + seq_printf(seq, "\n--- SSID %u ---\n", ssid); + smmu_debug_dump_cd(seq, cd); + } + } + + return 0; +} + +static int smmu_debugfs_cd_open(struct inode *inode, struct file *file) +{ + struct device *dev =3D inode->i_private; + int ret; + + if (!dev || !get_device(dev)) + return -ENODEV; + + ret =3D single_open(file, smmu_debugfs_cd_show, dev); + if (ret) + put_device(dev); + + return ret; +} + +static int smmu_debugfs_cd_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq =3D file->private_data; + struct device *dev =3D seq->private; + + single_release(inode, file); + if (dev) + put_device(dev); + return 0; +} + +static const struct file_operations smmu_debugfs_cd_fops =3D { + .owner =3D THIS_MODULE, + .open =3D smmu_debugfs_cd_open, + .read =3D seq_read, + .llseek =3D seq_lseek, + .release =3D smmu_debugfs_cd_release, +}; + /** * arm_smmu_debugfs_create_stream_table() - Create debugfs entries for str= eam table * @smmu: SMMU device @@ -373,6 +471,9 @@ int arm_smmu_debugfs_create_stream_table(struct arm_smm= u_device *smmu, kfree(full_path); } } + + /* Create CD file to dump all valid Context Descriptors */ + debugfs_create_file("cd", 0444, dev_dir, dev, &smmu_debugfs_cd_fops); } =20 kfree(path); --=20 2.33.0