All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Add debugfs info for the AMD IOMMU
@ 2018-01-26 23:52 ` Gary R Hook
  0 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu; +Cc: joro, linux-kernel

The following series creates a debugfs directory for AMD IOMMUs,
constructs a framework for additional entries, an online README,
and a method for dumping device table entries. Data is reported
in a default concise mode, but a verbose mode is enabled via a
filesystem entry.

This is the first of three patch series that will expose a number
of IOMMU registers.

---

Gary R Hook (5):
      iommu/amd - Add debugfs support
      iommu/amd - Add a 'verbose' switch for IOMMU debugfs
      iommu/amd - Add a README variable for the IOMMU debugfs
      iommu/amd - Expose the active IOMMU device table entries
      iommu/amd - Add a debugfs entry to specify a IOMMU device table entry


 drivers/iommu/Kconfig             |    9 +
 drivers/iommu/Makefile            |    2 
 drivers/iommu/amd_iommu_debugfs.c |  428 +++++++++++++++++++++++++++++++++++++
 drivers/iommu/amd_iommu_init.c    |    7 -
 drivers/iommu/amd_iommu_proto.h   |    6 +
 drivers/iommu/amd_iommu_types.h   |    3 
 6 files changed, 452 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu_debugfs.c

--

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 0/5] Add debugfs info for the AMD IOMMU
@ 2018-01-26 23:52 ` Gary R Hook
  0 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA

The following series creates a debugfs directory for AMD IOMMUs,
constructs a framework for additional entries, an online README,
and a method for dumping device table entries. Data is reported
in a default concise mode, but a verbose mode is enabled via a
filesystem entry.

This is the first of three patch series that will expose a number
of IOMMU registers.

---

Gary R Hook (5):
      iommu/amd - Add debugfs support
      iommu/amd - Add a 'verbose' switch for IOMMU debugfs
      iommu/amd - Add a README variable for the IOMMU debugfs
      iommu/amd - Expose the active IOMMU device table entries
      iommu/amd - Add a debugfs entry to specify a IOMMU device table entry


 drivers/iommu/Kconfig             |    9 +
 drivers/iommu/Makefile            |    2 
 drivers/iommu/amd_iommu_debugfs.c |  428 +++++++++++++++++++++++++++++++++++++
 drivers/iommu/amd_iommu_init.c    |    7 -
 drivers/iommu/amd_iommu_proto.h   |    6 +
 drivers/iommu/amd_iommu_types.h   |    3 
 6 files changed, 452 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu_debugfs.c

--

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/5] iommu/amd - Add debugfs support
  2018-01-26 23:52 ` Gary R Hook
@ 2018-01-26 23:52   ` Gary R Hook
  -1 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu; +Cc: joro, linux-kernel

Create the basic debugfs functions. Expose a count of IOMMU device
table entries that appear to be in use.

Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/iommu/Kconfig             |    9 +++
 drivers/iommu/Makefile            |    2 -
 drivers/iommu/amd_iommu_debugfs.c |  112 +++++++++++++++++++++++++++++++++++++
 drivers/iommu/amd_iommu_init.c    |    7 ++
 drivers/iommu/amd_iommu_proto.h   |    6 ++
 drivers/iommu/amd_iommu_types.h   |    3 +
 6 files changed, 136 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu_debugfs.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f3a21343e636..7753989b6be7 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -135,6 +135,15 @@ config AMD_IOMMU_V2
 	  hardware. Select this option if you want to use devices that support
 	  the PCI PRI and PASID interface.
 
+config AMD_IOMMU_DEBUG
+	bool "Expose AMD IOMMU internals in DebugFS"
+	depends on AMD_IOMMU && DEBUG_FS
+	default n
+	help
+	  With this option you can enable access to AMD IOMMU registers and
+	  data structures through debugfs. Select this to see information
+	  about the internal state of the device.
+
 # Intel IOMMU support
 config DMAR_TABLE
 	bool
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 1fb695854809..d9e9ed5f6cfc 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
new file mode 100644
index 000000000000..18f70934961d
--- /dev/null
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD IOMMU driver
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook <gary.hook@amd.com>
+ */
+
+#ifdef	CONFIG_DEBUG_FS
+
+#include <linux/pci.h>
+#include <linux/iommu.h>
+#include <linux/debugfs.h>
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
+
+/* DebugFS helpers */
+#define	OBUFP		(obuf + oboff)
+#define	OBUFLEN		obuflen
+#define	OBUFSPC		(OBUFLEN - oboff)
+#define	OSCNPRINTF(fmt, ...) \
+		scnprintf(OBUFP, OBUFSPC, fmt, ## __VA_ARGS__)
+
+static struct dentry *iommu_debugfs_dir;
+static DEFINE_RWLOCK(iommu_debugfs_lock);
+
+#define	MAX_NAME_LEN	20
+
+static unsigned int amd_iommu_count_valid_dtes(int start, int end)
+{
+	unsigned int n = 0;
+	int i;
+
+	/* Scan the DTE table from entry 'start' through entry 'end' for
+	 * active entries
+	 */
+	for (i = start ; i <= end ; i++)
+		if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
+		     || amd_iommu_dev_table[i].data[1])
+			n++;
+	return n;
+}
+
+static ssize_t amd_iommu_debugfs_dtecount_read(struct file *filp,
+					       char __user *ubuf,
+					       size_t count, loff_t *offp)
+{
+	struct amd_iommu *iommu = filp->private_data;
+	unsigned int obuflen = 512;
+	unsigned int oboff = 0;
+	unsigned int n;
+	ssize_t ret;
+	char *obuf;
+
+	if (!iommu)
+		return 0;
+
+	obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	n = amd_iommu_count_valid_dtes(0, 0xFFFF);
+	oboff += OSCNPRINTF("%d\n", n);
+
+	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
+	kfree(obuf);
+
+	return ret;
+}
+
+static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = amd_iommu_debugfs_dtecount_read,
+	.write = NULL,
+};
+
+void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
+{
+	char name[MAX_NAME_LEN + 1];
+	struct dentry *d_dte;
+	unsigned long flags;
+
+	if (!debugfs_initialized())
+		return;
+
+	write_lock_irqsave(&iommu_debugfs_lock, flags);
+	if (!iommu_debugfs_dir)
+		iommu_debugfs_dir = debugfs_create_dir("amd-iommu", NULL);
+	write_unlock_irqrestore(&iommu_debugfs_lock, flags);
+	if (!iommu_debugfs_dir)
+		goto err;
+
+	snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index);
+	iommu->debugfs_instance = debugfs_create_dir(name, iommu_debugfs_dir);
+	if (!iommu->debugfs_instance)
+		goto err;
+
+	d_dte = debugfs_create_file("count", 0400,
+				    iommu->debugfs_instance, iommu,
+				    &amd_iommu_debugfs_dtecount_ops);
+	if (!d_dte)
+		goto err;
+
+	return;
+
+err:
+	debugfs_remove_recursive(iommu->debugfs_instance);
+}
+
+#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 6fe2d0346073..43856c7f4ea1 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -89,6 +89,7 @@
 #define ACPI_DEVFLAG_ATSDIS             0x10000000
 
 #define LOOP_TIMEOUT	100000
+
 /*
  * ACPI table definitions
  *
@@ -2720,6 +2721,7 @@ int __init amd_iommu_enable_faulting(void)
  */
 static int __init amd_iommu_init(void)
 {
+	struct amd_iommu *iommu;
 	int ret;
 
 	ret = iommu_go_to_state(IOMMU_INITIALIZED);
@@ -2729,14 +2731,15 @@ static int __init amd_iommu_init(void)
 			disable_iommus();
 			free_iommu_resources();
 		} else {
-			struct amd_iommu *iommu;
-
 			uninit_device_table_dma();
 			for_each_iommu(iommu)
 				iommu_flush_all_caches(iommu);
 		}
 	}
 
+	for_each_iommu(iommu)
+		amd_iommu_debugfs_setup(iommu);
+
 	return ret;
 }
 
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 640c286a0ab9..f2a978dbcff7 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -33,6 +33,12 @@ extern void amd_iommu_uninit_devices(void);
 extern void amd_iommu_init_notifier(void);
 extern int amd_iommu_init_api(void);
 
+#ifdef	CONFIG_DEBUG_FS
+extern void amd_iommu_debugfs_setup(struct amd_iommu *iommu);
+#else
+static inline void amd_iommu_debugfs_setup(struct amd_iommu *iommu) {}
+#endif
+
 /* Needed for interrupt remapping */
 extern int amd_iommu_prepare(void);
 extern int amd_iommu_enable(void);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 6a877ebd058b..43c008dc7ade 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -593,6 +593,9 @@ struct amd_iommu {
 
 	u32 flags;
 	volatile u64 __aligned(8) cmd_sem;
+
+	/* DebugFS Info */
+	struct dentry *debugfs_instance;
 };
 
 static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev)

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 1/5] iommu/amd - Add debugfs support
@ 2018-01-26 23:52   ` Gary R Hook
  0 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA

Create the basic debugfs functions. Expose a count of IOMMU device
table entries that appear to be in use.

Signed-off-by: Gary R Hook <gary.hook-5C7GfCeVMHo@public.gmane.org>
---
 drivers/iommu/Kconfig             |    9 +++
 drivers/iommu/Makefile            |    2 -
 drivers/iommu/amd_iommu_debugfs.c |  112 +++++++++++++++++++++++++++++++++++++
 drivers/iommu/amd_iommu_init.c    |    7 ++
 drivers/iommu/amd_iommu_proto.h   |    6 ++
 drivers/iommu/amd_iommu_types.h   |    3 +
 6 files changed, 136 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu_debugfs.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f3a21343e636..7753989b6be7 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -135,6 +135,15 @@ config AMD_IOMMU_V2
 	  hardware. Select this option if you want to use devices that support
 	  the PCI PRI and PASID interface.
 
+config AMD_IOMMU_DEBUG
+	bool "Expose AMD IOMMU internals in DebugFS"
+	depends on AMD_IOMMU && DEBUG_FS
+	default n
+	help
+	  With this option you can enable access to AMD IOMMU registers and
+	  data structures through debugfs. Select this to see information
+	  about the internal state of the device.
+
 # Intel IOMMU support
 config DMAR_TABLE
 	bool
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 1fb695854809..d9e9ed5f6cfc 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
new file mode 100644
index 000000000000..18f70934961d
--- /dev/null
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD IOMMU driver
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook <gary.hook-5C7GfCeVMHo@public.gmane.org>
+ */
+
+#ifdef	CONFIG_DEBUG_FS
+
+#include <linux/pci.h>
+#include <linux/iommu.h>
+#include <linux/debugfs.h>
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
+
+/* DebugFS helpers */
+#define	OBUFP		(obuf + oboff)
+#define	OBUFLEN		obuflen
+#define	OBUFSPC		(OBUFLEN - oboff)
+#define	OSCNPRINTF(fmt, ...) \
+		scnprintf(OBUFP, OBUFSPC, fmt, ## __VA_ARGS__)
+
+static struct dentry *iommu_debugfs_dir;
+static DEFINE_RWLOCK(iommu_debugfs_lock);
+
+#define	MAX_NAME_LEN	20
+
+static unsigned int amd_iommu_count_valid_dtes(int start, int end)
+{
+	unsigned int n = 0;
+	int i;
+
+	/* Scan the DTE table from entry 'start' through entry 'end' for
+	 * active entries
+	 */
+	for (i = start ; i <= end ; i++)
+		if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
+		     || amd_iommu_dev_table[i].data[1])
+			n++;
+	return n;
+}
+
+static ssize_t amd_iommu_debugfs_dtecount_read(struct file *filp,
+					       char __user *ubuf,
+					       size_t count, loff_t *offp)
+{
+	struct amd_iommu *iommu = filp->private_data;
+	unsigned int obuflen = 512;
+	unsigned int oboff = 0;
+	unsigned int n;
+	ssize_t ret;
+	char *obuf;
+
+	if (!iommu)
+		return 0;
+
+	obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	n = amd_iommu_count_valid_dtes(0, 0xFFFF);
+	oboff += OSCNPRINTF("%d\n", n);
+
+	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
+	kfree(obuf);
+
+	return ret;
+}
+
+static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = amd_iommu_debugfs_dtecount_read,
+	.write = NULL,
+};
+
+void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
+{
+	char name[MAX_NAME_LEN + 1];
+	struct dentry *d_dte;
+	unsigned long flags;
+
+	if (!debugfs_initialized())
+		return;
+
+	write_lock_irqsave(&iommu_debugfs_lock, flags);
+	if (!iommu_debugfs_dir)
+		iommu_debugfs_dir = debugfs_create_dir("amd-iommu", NULL);
+	write_unlock_irqrestore(&iommu_debugfs_lock, flags);
+	if (!iommu_debugfs_dir)
+		goto err;
+
+	snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index);
+	iommu->debugfs_instance = debugfs_create_dir(name, iommu_debugfs_dir);
+	if (!iommu->debugfs_instance)
+		goto err;
+
+	d_dte = debugfs_create_file("count", 0400,
+				    iommu->debugfs_instance, iommu,
+				    &amd_iommu_debugfs_dtecount_ops);
+	if (!d_dte)
+		goto err;
+
+	return;
+
+err:
+	debugfs_remove_recursive(iommu->debugfs_instance);
+}
+
+#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 6fe2d0346073..43856c7f4ea1 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -89,6 +89,7 @@
 #define ACPI_DEVFLAG_ATSDIS             0x10000000
 
 #define LOOP_TIMEOUT	100000
+
 /*
  * ACPI table definitions
  *
@@ -2720,6 +2721,7 @@ int __init amd_iommu_enable_faulting(void)
  */
 static int __init amd_iommu_init(void)
 {
+	struct amd_iommu *iommu;
 	int ret;
 
 	ret = iommu_go_to_state(IOMMU_INITIALIZED);
@@ -2729,14 +2731,15 @@ static int __init amd_iommu_init(void)
 			disable_iommus();
 			free_iommu_resources();
 		} else {
-			struct amd_iommu *iommu;
-
 			uninit_device_table_dma();
 			for_each_iommu(iommu)
 				iommu_flush_all_caches(iommu);
 		}
 	}
 
+	for_each_iommu(iommu)
+		amd_iommu_debugfs_setup(iommu);
+
 	return ret;
 }
 
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 640c286a0ab9..f2a978dbcff7 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -33,6 +33,12 @@ extern void amd_iommu_uninit_devices(void);
 extern void amd_iommu_init_notifier(void);
 extern int amd_iommu_init_api(void);
 
+#ifdef	CONFIG_DEBUG_FS
+extern void amd_iommu_debugfs_setup(struct amd_iommu *iommu);
+#else
+static inline void amd_iommu_debugfs_setup(struct amd_iommu *iommu) {}
+#endif
+
 /* Needed for interrupt remapping */
 extern int amd_iommu_prepare(void);
 extern int amd_iommu_enable(void);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 6a877ebd058b..43c008dc7ade 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -593,6 +593,9 @@ struct amd_iommu {
 
 	u32 flags;
 	volatile u64 __aligned(8) cmd_sem;
+
+	/* DebugFS Info */
+	struct dentry *debugfs_instance;
 };
 
 static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev)

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/5] iommu/amd - Add a 'verbose' switch for IOMMU debugfs
  2018-01-26 23:52 ` Gary R Hook
  (?)
  (?)
@ 2018-01-26 23:52 ` Gary R Hook
  -1 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu; +Cc: joro, linux-kernel

Enable more descriptive debugfs output via a 'verbose' variable.

Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/iommu/amd_iommu_debugfs.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
index 18f70934961d..c449f3a7452c 100644
--- a/drivers/iommu/amd_iommu_debugfs.c
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -27,6 +27,8 @@ static DEFINE_RWLOCK(iommu_debugfs_lock);
 
 #define	MAX_NAME_LEN	20
 
+static unsigned int amd_iommu_verbose;
+
 static unsigned int amd_iommu_count_valid_dtes(int start, int end)
 {
 	unsigned int n = 0;
@@ -61,7 +63,10 @@ static ssize_t amd_iommu_debugfs_dtecount_read(struct file *filp,
 		return -ENOMEM;
 
 	n = amd_iommu_count_valid_dtes(0, 0xFFFF);
-	oboff += OSCNPRINTF("%d\n", n);
+	if (amd_iommu_verbose)
+		oboff += OSCNPRINTF("# DTEs:  %d\n", n);
+	else
+		oboff += OSCNPRINTF("%d\n", n);
 
 	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
 	kfree(obuf);
@@ -79,6 +84,7 @@ static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
 void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 {
 	char name[MAX_NAME_LEN + 1];
+	struct dentry *d_verbose;
 	struct dentry *d_dte;
 	unsigned long flags;
 
@@ -97,6 +103,12 @@ void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 	if (!iommu->debugfs_instance)
 		goto err;
 
+	d_verbose = debugfs_create_u32("verbose", 0600,
+				       iommu->debugfs_instance,
+				       &amd_iommu_verbose);
+	if (!d_verbose)
+		goto err;
+
 	d_dte = debugfs_create_file("count", 0400,
 				    iommu->debugfs_instance, iommu,
 				    &amd_iommu_debugfs_dtecount_ops);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/5] iommu/amd - Add a README variable for the IOMMU debugfs
  2018-01-26 23:52 ` Gary R Hook
                   ` (2 preceding siblings ...)
  (?)
@ 2018-01-26 23:52 ` Gary R Hook
  -1 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu; +Cc: joro, linux-kernel

Provide help text via a filesystem entry

Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/iommu/amd_iommu_debugfs.c |   31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
index c449f3a7452c..5066d3976912 100644
--- a/drivers/iommu/amd_iommu_debugfs.c
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -81,6 +81,31 @@ static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
 	.write = NULL,
 };
 
+static char readmetext[] =
+"count                   Count of active devices\n"
+"verbose                 Provide additional descriptive text\n"
+"\n";
+
+static ssize_t amd_iommu_debugfs_readme_read(struct file *filp,
+				      char __user *ubuf,
+				      size_t count, loff_t *offp)
+{
+	ssize_t ret;
+
+	ret = simple_read_from_buffer(ubuf, count, offp,
+				      readmetext, strlen(readmetext));
+
+	return ret;
+}
+
+
+static const struct file_operations amd_iommu_debugfs_readme_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = amd_iommu_debugfs_readme_read,
+	.write = NULL,
+};
+
 void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 {
 	char name[MAX_NAME_LEN + 1];
@@ -115,6 +140,12 @@ void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 	if (!d_dte)
 		goto err;
 
+	d_dte = debugfs_create_file("README", 0400,
+				    iommu->debugfs_instance, iommu,
+				    &amd_iommu_debugfs_readme_ops);
+	if (!d_dte)
+		goto err;
+
 	return;
 
 err:

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/5] iommu/amd - Expose the active IOMMU device table entries
  2018-01-26 23:52 ` Gary R Hook
@ 2018-01-26 23:52   ` Gary R Hook
  -1 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu; +Cc: joro, linux-kernel

Add a debugfs entry to dump the active device table entries from
the IOMMU's table. 'Active' is determined by non-default values
in the first and second long words of the DTE. Aside from IOMMU
devices, this output should list every device reported by lspci.

Use arrays to store DTE bit field definitions for debugfs printing
in verbose mode

Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/iommu/amd_iommu_debugfs.c |  182 +++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
index 5066d3976912..87840ae9889d 100644
--- a/drivers/iommu/amd_iommu_debugfs.c
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -22,6 +22,16 @@
 #define	OSCNPRINTF(fmt, ...) \
 		scnprintf(OBUFP, OBUFSPC, fmt, ## __VA_ARGS__)
 
+#define	MAX_PCI_ID	0xFFFF
+
+#define	PRINTDTE(i)	OSCNPRINTF("%02x:%02x:%x - " \
+				   "%016llx %016llx %016llx %016llx\n", \
+				   PCI_BUS_NUM(i), PCI_SLOT(i), PCI_FUNC(i), \
+				   amd_iommu_dev_table[i].data[0], \
+				   amd_iommu_dev_table[i].data[1], \
+				   amd_iommu_dev_table[i].data[2], \
+				   amd_iommu_dev_table[i].data[3])
+
 static struct dentry *iommu_debugfs_dir;
 static DEFINE_RWLOCK(iommu_debugfs_lock);
 
@@ -81,9 +91,174 @@ static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
 	.write = NULL,
 };
 
+struct bits {
+	uint bit;
+	uint len;
+	char *lbl;
+	char *note;
+};
+
+static struct bits dte_lft[] = {
+	{  0, 1, "V:", "[0]" },
+	{  1, 1, "TV:", "[1]" },
+	{  7, 2, "Host Access Dirty:", "[8:7]" },
+	{  9, 3, "Paging Mode:", "[11:9]" },
+	{ 52, 1, "PPR:", "[52]" },
+	{ 53, 1, "GPRP:", "[53]" },
+	{ 54, 1, "GIoV:", "[54]" },
+	{ 55, 1, "GV:", "[55]" },
+	{ 56, 2, "GLX:", "[57:56]" },
+	{ 61, 1, "IR:", "[61]" },
+	{ 62, 1, "IW:", "[62]" },
+	{ 96, 1, "I:", "[96]" },
+	{ 97, 1, "SE:", "[97]" },
+	{ 98, 1, "SA:", "[98]" },
+	{ 99, 2, "IOCtl:", "[100:99]" },
+};
+static uint lftlen = sizeof(dte_lft) / sizeof(struct bits);
+
+static struct bits dte_rght[] = {
+	{ 101, 1, "Cache:", "[101]" },
+	{ 102, 1, "SD:", "[102]" },
+	{ 103, 1, "EX  :", "[103]" },
+	{ 104, 2, "SysMgt:", "[105:104]" },
+	{ 128, 1, "IV:", "[128]" },
+	{ 129, 4, "IntTabLen:", "[132:129]" },
+	{ 133, 1, "IG:", "[133]" },
+	{ 184, 1, "InitPass:", "[184]" },
+	{ 185, 1, "EIntPass:", "[185]" },
+	{ 186, 1, "NMIPass:", "[186]" },
+	{ 188, 2, "IntClt:", "[189:188]" },
+	{ 190, 1, "Lint0Pass:", "[190]" },
+	{ 191, 1, "Lint1Pass:", "[191]" },
+	{ 246, 1, "AttrV:", "[246]" },
+	{ 247, 1, "Mode0FC:", "[247]" },
+};
+static uint rghtlen = sizeof(dte_rght) / sizeof(struct bits);
+
+#define	DTE_BIT(ds, p, n)	((ds[p/64] >> (p%64)) & ((1ULL<<n) - 1))
+
+static void amd_iommu_print_dte_verbose(int devidx, char **buf,
+					unsigned int *buflen,
+					unsigned int *offset)
+{
+	u64 *dte = amd_iommu_dev_table[devidx].data;
+	u64 part1, part2, part3;
+	unsigned int obuflen = *buflen;
+	unsigned int oboff = *offset;
+	struct bits *lft, *rght;
+	char *obuf = *buf;
+	uint max;
+	int j;
+
+	max = lftlen > rghtlen ? lftlen : rghtlen;
+
+	for (j = 0; j < max ; j++) {
+		lft = &dte_lft[j];
+		if (j < lftlen)
+			oboff += OSCNPRINTF("%-19s%3llx %*s", lft->lbl,
+					    DTE_BIT(dte, lft->bit, lft->len),
+					    (j < rghtlen) ? -16 : 1,
+					    lft->note);
+		else
+			oboff += OSCNPRINTF("%38s", "");
+
+		rght = &dte_rght[j];
+		if (j < rghtlen)
+			oboff += OSCNPRINTF("    %-19s%3llx %s\n", rght->lbl,
+					    DTE_BIT(dte, rght->bit, rght->len),
+					    rght->note);
+		else
+			oboff += OSCNPRINTF("\n");
+	}
+
+	oboff += OSCNPRINTF("%-28s:         %4llx %s\n", "Domain ID",
+			    DTE_BIT(dte, 64, 16), "[79:64]");
+	oboff += OSCNPRINTF("%-28s:         %4llx %s\n", "Snoop Attribute",
+			    DTE_BIT(dte, 248, 8), "[255:248]");
+	oboff += OSCNPRINTF("%-28s: %12llx %s\n", "Page Table Root Pointer",
+			    DTE_BIT(dte, 12, 40) << 12, "[51:12]");
+	oboff += OSCNPRINTF("%-28s: %12llx %s\n",
+			    "Interrupt Table Root Pointer",
+			    DTE_BIT(dte, 134, 46) << 6, "[179:134]");
+
+	part1 = DTE_BIT(dte, 107, 21) << 19;
+	part2 = DTE_BIT(dte, 80, 16) << 3;
+	part3 = DTE_BIT(dte, 58, 3);
+	oboff += OSCNPRINTF("%-28s: %12llx %s\n\n",
+			    "Guest CR3 Table Root Pointer",
+			    (part1 | part2 | part3) << 12,
+			    "[127:107][95:80][60:58]");
+
+	*buflen = obuflen;
+	*offset = oboff;
+	*buf = obuf;
+}
+
+static ssize_t amd_iommu_debugfs_dte_read(struct file *filp,
+					  char __user *ubuf,
+					  size_t count, loff_t *offp)
+{
+	struct amd_iommu *iommu = filp->private_data;
+	unsigned int obuflen;
+	unsigned int oboff = 0;
+	unsigned int istart, iend;
+	ssize_t ret;
+	u32 i, n;
+	char *obuf;
+
+	if (!iommu)
+		return 0;
+
+	/* Count the number of valid entries in the device table */
+	istart = 0;
+	iend = MAX_PCI_ID;
+	n = amd_iommu_count_valid_dtes(istart, iend);
+	if (amd_iommu_verbose)
+		obuflen = n * 2048;
+	else
+		obuflen = n * 80;
+
+	obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	for (i = istart ; i <= iend ; i++)
+		if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
+		     || amd_iommu_dev_table[i].data[1]) {
+			if (amd_iommu_verbose) {
+				oboff += OSCNPRINTF("Device %02x:%02x.%x\n",
+						    PCI_BUS_NUM(i),
+						    PCI_SLOT(i),
+						    PCI_FUNC(i));
+				amd_iommu_print_dte_verbose(i, &obuf,
+							    &obuflen, &oboff);
+			} else {
+				oboff += PRINTDTE(i);
+			}
+		}
+
+	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
+	kfree(obuf);
+
+	return ret;
+}
+
+static const struct file_operations amd_iommu_debugfs_dte_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = amd_iommu_debugfs_dte_read,
+	.write = NULL,
+};
+
 static char readmetext[] =
+"devicetable             Print active entries in the device table\n"
 "count                   Count of active devices\n"
 "verbose                 Provide additional descriptive text\n"
+"\n"
+"                        Dumping the Device Table\n"
+"The device table is scanned for entries that appear to be active. The\n"
+"default range is from 0 to 0xFFFF, and only active entries will be reported\n"
 "\n";
 
 static ssize_t amd_iommu_debugfs_readme_read(struct file *filp,
@@ -134,6 +309,13 @@ void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 	if (!d_verbose)
 		goto err;
 
+	/* Device Table Entries */
+	d_dte = debugfs_create_file("devicetable", 0400,
+				    iommu->debugfs_instance, iommu,
+				    &amd_iommu_debugfs_dte_ops);
+	if (!d_dte)
+		goto err;
+
 	d_dte = debugfs_create_file("count", 0400,
 				    iommu->debugfs_instance, iommu,
 				    &amd_iommu_debugfs_dtecount_ops);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/5] iommu/amd - Expose the active IOMMU device table entries
@ 2018-01-26 23:52   ` Gary R Hook
  0 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA

Add a debugfs entry to dump the active device table entries from
the IOMMU's table. 'Active' is determined by non-default values
in the first and second long words of the DTE. Aside from IOMMU
devices, this output should list every device reported by lspci.

Use arrays to store DTE bit field definitions for debugfs printing
in verbose mode

Signed-off-by: Gary R Hook <gary.hook-5C7GfCeVMHo@public.gmane.org>
---
 drivers/iommu/amd_iommu_debugfs.c |  182 +++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
index 5066d3976912..87840ae9889d 100644
--- a/drivers/iommu/amd_iommu_debugfs.c
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -22,6 +22,16 @@
 #define	OSCNPRINTF(fmt, ...) \
 		scnprintf(OBUFP, OBUFSPC, fmt, ## __VA_ARGS__)
 
+#define	MAX_PCI_ID	0xFFFF
+
+#define	PRINTDTE(i)	OSCNPRINTF("%02x:%02x:%x - " \
+				   "%016llx %016llx %016llx %016llx\n", \
+				   PCI_BUS_NUM(i), PCI_SLOT(i), PCI_FUNC(i), \
+				   amd_iommu_dev_table[i].data[0], \
+				   amd_iommu_dev_table[i].data[1], \
+				   amd_iommu_dev_table[i].data[2], \
+				   amd_iommu_dev_table[i].data[3])
+
 static struct dentry *iommu_debugfs_dir;
 static DEFINE_RWLOCK(iommu_debugfs_lock);
 
@@ -81,9 +91,174 @@ static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
 	.write = NULL,
 };
 
+struct bits {
+	uint bit;
+	uint len;
+	char *lbl;
+	char *note;
+};
+
+static struct bits dte_lft[] = {
+	{  0, 1, "V:", "[0]" },
+	{  1, 1, "TV:", "[1]" },
+	{  7, 2, "Host Access Dirty:", "[8:7]" },
+	{  9, 3, "Paging Mode:", "[11:9]" },
+	{ 52, 1, "PPR:", "[52]" },
+	{ 53, 1, "GPRP:", "[53]" },
+	{ 54, 1, "GIoV:", "[54]" },
+	{ 55, 1, "GV:", "[55]" },
+	{ 56, 2, "GLX:", "[57:56]" },
+	{ 61, 1, "IR:", "[61]" },
+	{ 62, 1, "IW:", "[62]" },
+	{ 96, 1, "I:", "[96]" },
+	{ 97, 1, "SE:", "[97]" },
+	{ 98, 1, "SA:", "[98]" },
+	{ 99, 2, "IOCtl:", "[100:99]" },
+};
+static uint lftlen = sizeof(dte_lft) / sizeof(struct bits);
+
+static struct bits dte_rght[] = {
+	{ 101, 1, "Cache:", "[101]" },
+	{ 102, 1, "SD:", "[102]" },
+	{ 103, 1, "EX  :", "[103]" },
+	{ 104, 2, "SysMgt:", "[105:104]" },
+	{ 128, 1, "IV:", "[128]" },
+	{ 129, 4, "IntTabLen:", "[132:129]" },
+	{ 133, 1, "IG:", "[133]" },
+	{ 184, 1, "InitPass:", "[184]" },
+	{ 185, 1, "EIntPass:", "[185]" },
+	{ 186, 1, "NMIPass:", "[186]" },
+	{ 188, 2, "IntClt:", "[189:188]" },
+	{ 190, 1, "Lint0Pass:", "[190]" },
+	{ 191, 1, "Lint1Pass:", "[191]" },
+	{ 246, 1, "AttrV:", "[246]" },
+	{ 247, 1, "Mode0FC:", "[247]" },
+};
+static uint rghtlen = sizeof(dte_rght) / sizeof(struct bits);
+
+#define	DTE_BIT(ds, p, n)	((ds[p/64] >> (p%64)) & ((1ULL<<n) - 1))
+
+static void amd_iommu_print_dte_verbose(int devidx, char **buf,
+					unsigned int *buflen,
+					unsigned int *offset)
+{
+	u64 *dte = amd_iommu_dev_table[devidx].data;
+	u64 part1, part2, part3;
+	unsigned int obuflen = *buflen;
+	unsigned int oboff = *offset;
+	struct bits *lft, *rght;
+	char *obuf = *buf;
+	uint max;
+	int j;
+
+	max = lftlen > rghtlen ? lftlen : rghtlen;
+
+	for (j = 0; j < max ; j++) {
+		lft = &dte_lft[j];
+		if (j < lftlen)
+			oboff += OSCNPRINTF("%-19s%3llx %*s", lft->lbl,
+					    DTE_BIT(dte, lft->bit, lft->len),
+					    (j < rghtlen) ? -16 : 1,
+					    lft->note);
+		else
+			oboff += OSCNPRINTF("%38s", "");
+
+		rght = &dte_rght[j];
+		if (j < rghtlen)
+			oboff += OSCNPRINTF("    %-19s%3llx %s\n", rght->lbl,
+					    DTE_BIT(dte, rght->bit, rght->len),
+					    rght->note);
+		else
+			oboff += OSCNPRINTF("\n");
+	}
+
+	oboff += OSCNPRINTF("%-28s:         %4llx %s\n", "Domain ID",
+			    DTE_BIT(dte, 64, 16), "[79:64]");
+	oboff += OSCNPRINTF("%-28s:         %4llx %s\n", "Snoop Attribute",
+			    DTE_BIT(dte, 248, 8), "[255:248]");
+	oboff += OSCNPRINTF("%-28s: %12llx %s\n", "Page Table Root Pointer",
+			    DTE_BIT(dte, 12, 40) << 12, "[51:12]");
+	oboff += OSCNPRINTF("%-28s: %12llx %s\n",
+			    "Interrupt Table Root Pointer",
+			    DTE_BIT(dte, 134, 46) << 6, "[179:134]");
+
+	part1 = DTE_BIT(dte, 107, 21) << 19;
+	part2 = DTE_BIT(dte, 80, 16) << 3;
+	part3 = DTE_BIT(dte, 58, 3);
+	oboff += OSCNPRINTF("%-28s: %12llx %s\n\n",
+			    "Guest CR3 Table Root Pointer",
+			    (part1 | part2 | part3) << 12,
+			    "[127:107][95:80][60:58]");
+
+	*buflen = obuflen;
+	*offset = oboff;
+	*buf = obuf;
+}
+
+static ssize_t amd_iommu_debugfs_dte_read(struct file *filp,
+					  char __user *ubuf,
+					  size_t count, loff_t *offp)
+{
+	struct amd_iommu *iommu = filp->private_data;
+	unsigned int obuflen;
+	unsigned int oboff = 0;
+	unsigned int istart, iend;
+	ssize_t ret;
+	u32 i, n;
+	char *obuf;
+
+	if (!iommu)
+		return 0;
+
+	/* Count the number of valid entries in the device table */
+	istart = 0;
+	iend = MAX_PCI_ID;
+	n = amd_iommu_count_valid_dtes(istart, iend);
+	if (amd_iommu_verbose)
+		obuflen = n * 2048;
+	else
+		obuflen = n * 80;
+
+	obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	for (i = istart ; i <= iend ; i++)
+		if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
+		     || amd_iommu_dev_table[i].data[1]) {
+			if (amd_iommu_verbose) {
+				oboff += OSCNPRINTF("Device %02x:%02x.%x\n",
+						    PCI_BUS_NUM(i),
+						    PCI_SLOT(i),
+						    PCI_FUNC(i));
+				amd_iommu_print_dte_verbose(i, &obuf,
+							    &obuflen, &oboff);
+			} else {
+				oboff += PRINTDTE(i);
+			}
+		}
+
+	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
+	kfree(obuf);
+
+	return ret;
+}
+
+static const struct file_operations amd_iommu_debugfs_dte_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = amd_iommu_debugfs_dte_read,
+	.write = NULL,
+};
+
 static char readmetext[] =
+"devicetable             Print active entries in the device table\n"
 "count                   Count of active devices\n"
 "verbose                 Provide additional descriptive text\n"
+"\n"
+"                        Dumping the Device Table\n"
+"The device table is scanned for entries that appear to be active. The\n"
+"default range is from 0 to 0xFFFF, and only active entries will be reported\n"
 "\n";
 
 static ssize_t amd_iommu_debugfs_readme_read(struct file *filp,
@@ -134,6 +309,13 @@ void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 	if (!d_verbose)
 		goto err;
 
+	/* Device Table Entries */
+	d_dte = debugfs_create_file("devicetable", 0400,
+				    iommu->debugfs_instance, iommu,
+				    &amd_iommu_debugfs_dte_ops);
+	if (!d_dte)
+		goto err;
+
 	d_dte = debugfs_create_file("count", 0400,
 				    iommu->debugfs_instance, iommu,
 				    &amd_iommu_debugfs_dtecount_ops);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/5] iommu/amd - Add a debugfs entry to specify a IOMMU device table entry
  2018-01-26 23:52 ` Gary R Hook
                   ` (4 preceding siblings ...)
  (?)
@ 2018-01-26 23:52 ` Gary R Hook
  -1 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-26 23:52 UTC (permalink / raw)
  To: iommu; +Cc: joro, linux-kernel

Initially (at boot) the device table values dumped are all of the
active devices.  Add a devid debugfs file to allow the user to select a
single device table entry to dump (active or not). Let any devid value
greater than the maximum allowable PCI ID (0xFFFF) restore the
behavior to that effective at boot.

Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/iommu/amd_iommu_debugfs.c |  127 ++++++++++++++++++++++++++++++++-----
 1 file changed, 109 insertions(+), 18 deletions(-)

diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
index 87840ae9889d..efb666873daa 100644
--- a/drivers/iommu/amd_iommu_debugfs.c
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -38,6 +38,7 @@ static DEFINE_RWLOCK(iommu_debugfs_lock);
 #define	MAX_NAME_LEN	20
 
 static unsigned int amd_iommu_verbose;
+static unsigned int amd_iommu_devid = ~0;
 
 static unsigned int amd_iommu_count_valid_dtes(int start, int end)
 {
@@ -91,6 +92,72 @@ static const struct file_operations amd_iommu_debugfs_dtecount_ops = {
 	.write = NULL,
 };
 
+static ssize_t amd_iommu_debugfs_devid_read(struct file *filp,
+					    char __user *ubuf,
+					    size_t count, loff_t *offp)
+{
+	struct amd_iommu *iommu = filp->private_data;
+	unsigned int obuflen = 512;
+	unsigned int oboff = 0;
+	ssize_t ret;
+	char *obuf;
+
+	if (!iommu)
+		return 0;
+
+	obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	if (amd_iommu_verbose)
+		oboff += OSCNPRINTF("%02x:%02x.%x 0x%04x %u\n",
+				    PCI_BUS_NUM(amd_iommu_devid),
+				    PCI_SLOT(amd_iommu_devid),
+				    PCI_FUNC(amd_iommu_devid),
+				    amd_iommu_devid, amd_iommu_devid);
+	else
+		oboff += OSCNPRINTF("%u\n", amd_iommu_devid);
+
+	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
+	kfree(obuf);
+
+	return ret;
+}
+
+static ssize_t amd_iommu_debugfs_devid_write(struct file *filp,
+					    const char __user *ubuf,
+					    size_t count, loff_t *offp)
+{
+	unsigned int pci_id, pci_slot, pci_func;
+	unsigned int obuflen = 80;
+	ssize_t ret;
+	char *obuf;
+	int n;
+
+	obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	ret = simple_write_to_buffer(obuf, OBUFLEN, offp, ubuf, count);
+
+	if (strnchr(obuf, OBUFLEN, ':')) {
+		n = sscanf(obuf, "%x:%x.%x", &pci_id, &pci_slot, &pci_func);
+		if (n == 3)
+			amd_iommu_devid = PCI_DEVID(pci_id, PCI_DEVFN(pci_slot, pci_func));
+	} else
+		n = kstrtouint(obuf, 0, &amd_iommu_devid);
+	kfree(obuf);
+
+	return ret;
+}
+
+static const struct file_operations amd_iommu_debugfs_devid_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = amd_iommu_debugfs_devid_read,
+	.write = amd_iommu_debugfs_devid_write,
+};
+
 struct bits {
 	uint bit;
 	uint len;
@@ -211,9 +278,13 @@ static ssize_t amd_iommu_debugfs_dte_read(struct file *filp,
 		return 0;
 
 	/* Count the number of valid entries in the device table */
-	istart = 0;
-	iend = MAX_PCI_ID;
-	n = amd_iommu_count_valid_dtes(istart, iend);
+	if (amd_iommu_devid > MAX_PCI_ID) {
+		istart = 0;
+		iend = MAX_PCI_ID;
+		n = amd_iommu_count_valid_dtes(istart, iend);
+	} else {
+		n = 1;
+	}
 	if (amd_iommu_verbose)
 		obuflen = n * 2048;
 	else
@@ -223,20 +294,29 @@ static ssize_t amd_iommu_debugfs_dte_read(struct file *filp,
 	if (!obuf)
 		return -ENOMEM;
 
-	for (i = istart ; i <= iend ; i++)
-		if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
-		     || amd_iommu_dev_table[i].data[1]) {
-			if (amd_iommu_verbose) {
-				oboff += OSCNPRINTF("Device %02x:%02x.%x\n",
-						    PCI_BUS_NUM(i),
-						    PCI_SLOT(i),
-						    PCI_FUNC(i));
-				amd_iommu_print_dte_verbose(i, &obuf,
-							    &obuflen, &oboff);
-			} else {
-				oboff += PRINTDTE(i);
+	if (amd_iommu_devid > MAX_PCI_ID) {
+		for (i = istart ; i <= iend ; i++)
+			if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
+			     || amd_iommu_dev_table[i].data[1]) {
+				if (amd_iommu_verbose) {
+					oboff += OSCNPRINTF("Device %02x:%02x.%x\n",
+							    PCI_BUS_NUM(i),
+							    PCI_SLOT(i),
+							    PCI_FUNC(i));
+					amd_iommu_print_dte_verbose(i, &obuf,
+								    &obuflen,
+								    &oboff);
+				} else {
+					oboff += PRINTDTE(i);
+				}
 			}
-		}
+	} else {
+		i = amd_iommu_devid;
+		if (amd_iommu_verbose)
+			amd_iommu_print_dte_verbose(i, &obuf, &obuflen, &oboff);
+		else
+			oboff += PRINTDTE(i);
+	}
 
 	ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
 	kfree(obuf);
@@ -253,12 +333,17 @@ static const struct file_operations amd_iommu_debugfs_dte_ops = {
 
 static char readmetext[] =
 "devicetable             Print active entries in the device table\n"
+"devid                   Controls which device IDs are printed\n"
 "count                   Count of active devices\n"
 "verbose                 Provide additional descriptive text\n"
 "\n"
 "                        Dumping the Device Table\n"
-"The device table is scanned for entries that appear to be active. The\n"
-"default range is from 0 to 0xFFFF, and only active entries will be reported\n"
+"The device table is scanned for entries that appear to be active.\n"
+"The default (initial) range is from 0 to 0xFFFF, represented by a devid\n"
+"value greater than 0xFFFF, and only active entries will be reported.\n"
+"If devid is set to a specific value, only that device entry will be\n"
+"displayed (active or not). devid may be specified as ##:##:#, a decimal\n"
+"value, or a hex value.\n"
 "\n";
 
 static ssize_t amd_iommu_debugfs_readme_read(struct file *filp,
@@ -322,6 +407,12 @@ void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
 	if (!d_dte)
 		goto err;
 
+	d_dte = debugfs_create_file("devid", 0400,
+				    iommu->debugfs_instance, iommu,
+				    &amd_iommu_debugfs_devid_ops);
+	if (!d_dte)
+		goto err;
+
 	d_dte = debugfs_create_file("README", 0400,
 				    iommu->debugfs_instance, iommu,
 				    &amd_iommu_debugfs_readme_ops);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/5] iommu/amd - Add debugfs support
  2018-01-26 23:52   ` Gary R Hook
  (?)
@ 2018-01-27  0:00   ` Borislav Petkov
  2018-01-29 19:05     ` Gary R Hook
  -1 siblings, 1 reply; 11+ messages in thread
From: Borislav Petkov @ 2018-01-27  0:00 UTC (permalink / raw)
  To: Gary R Hook; +Cc: iommu, joro, linux-kernel

On Fri, Jan 26, 2018 at 05:52:15PM -0600, Gary R Hook wrote:
> Create the basic debugfs functions. Expose a count of IOMMU device
> table entries that appear to be in use.
> 
> Signed-off-by: Gary R Hook <gary.hook@amd.com>
> ---
>  drivers/iommu/Kconfig             |    9 +++
>  drivers/iommu/Makefile            |    2 -
>  drivers/iommu/amd_iommu_debugfs.c |  112 +++++++++++++++++++++++++++++++++++++
>  drivers/iommu/amd_iommu_init.c    |    7 ++
>  drivers/iommu/amd_iommu_proto.h   |    6 ++
>  drivers/iommu/amd_iommu_types.h   |    3 +
>  6 files changed, 136 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/iommu/amd_iommu_debugfs.c
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index f3a21343e636..7753989b6be7 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -135,6 +135,15 @@ config AMD_IOMMU_V2
>  	  hardware. Select this option if you want to use devices that support
>  	  the PCI PRI and PASID interface.
>  
> +config AMD_IOMMU_DEBUG
> +	bool "Expose AMD IOMMU internals in DebugFS"
> +	depends on AMD_IOMMU && DEBUG_FS
> +	default n
> +	help
> +	  With this option you can enable access to AMD IOMMU registers and
> +	  data structures through debugfs. Select this to see information
> +	  about the internal state of the device.
> +
>  # Intel IOMMU support
>  config DMAR_TABLE
>  	bool
> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> index 1fb695854809..d9e9ed5f6cfc 100644
> --- a/drivers/iommu/Makefile
> +++ b/drivers/iommu/Makefile
> @@ -9,7 +9,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
>  obj-$(CONFIG_IOMMU_IOVA) += iova.o
>  obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
>  obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
> -obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
> +obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_debugfs.o

That looks like it needs to be:

obj-$(CONFIG_AMD_IOMMU_DEBUG) += amd_iommu_debugfs.o

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/5] iommu/amd - Add debugfs support
  2018-01-27  0:00   ` Borislav Petkov
@ 2018-01-29 19:05     ` Gary R Hook
  0 siblings, 0 replies; 11+ messages in thread
From: Gary R Hook @ 2018-01-29 19:05 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: iommu, joro, linux-kernel

On 01/26/2018 06:00 PM, Borislav Petkov wrote:
> On Fri, Jan 26, 2018 at 05:52:15PM -0600, Gary R Hook wrote:
>> --- a/drivers/iommu/Kconfig
>> +++ b/drivers/iommu/Kconfig
>> @@ -135,6 +135,15 @@ config AMD_IOMMU_V2
>>   	  hardware. Select this option if you want to use devices that support
>>   	  the PCI PRI and PASID interface.
>>   
>> +config AMD_IOMMU_DEBUG
>> +	bool "Expose AMD IOMMU internals in DebugFS"
>> +	depends on AMD_IOMMU && DEBUG_FS
>> +	default n
>> +	help
>> +	  With this option you can enable access to AMD IOMMU registers and
>> +	  data structures through debugfs. Select this to see information
>> +	  about the internal state of the device.
>> +
>>   # Intel IOMMU support
>>   config DMAR_TABLE
>>   	bool
>> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
>> index 1fb695854809..d9e9ed5f6cfc 100644
>> --- a/drivers/iommu/Makefile
>> +++ b/drivers/iommu/Makefile
>> @@ -9,7 +9,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
>>   obj-$(CONFIG_IOMMU_IOVA) += iova.o
>>   obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
>>   obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
>> -obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
>> +obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_debugfs.o
> 
> That looks like it needs to be:
> 
> obj-$(CONFIG_AMD_IOMMU_DEBUG) += amd_iommu_debugfs.o

Of course. Thanks, Boris. I'll get that in v2.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-01-29 19:05 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-26 23:52 [PATCH 0/5] Add debugfs info for the AMD IOMMU Gary R Hook
2018-01-26 23:52 ` Gary R Hook
2018-01-26 23:52 ` [PATCH 1/5] iommu/amd - Add debugfs support Gary R Hook
2018-01-26 23:52   ` Gary R Hook
2018-01-27  0:00   ` Borislav Petkov
2018-01-29 19:05     ` Gary R Hook
2018-01-26 23:52 ` [PATCH 2/5] iommu/amd - Add a 'verbose' switch for IOMMU debugfs Gary R Hook
2018-01-26 23:52 ` [PATCH 3/5] iommu/amd - Add a README variable for the " Gary R Hook
2018-01-26 23:52 ` [PATCH 4/5] iommu/amd - Expose the active IOMMU device table entries Gary R Hook
2018-01-26 23:52   ` Gary R Hook
2018-01-26 23:52 ` [PATCH 5/5] iommu/amd - Add a debugfs entry to specify a IOMMU device table entry Gary R Hook

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.