lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 27 Mar 2013 18:51:34 -0500
From:	<suravee.suthikulpanit@....com>
To:	<iommu@...ts.linux-foundation.org>, <joro@...tes.org>
CC:	<linux-kernel@...r.kernel.org>,
	Suravee Suthikulpanit <suravee.suthikulpanit@....com>
Subject: [PATCH 2/3] iommu/amd: Add IOMMU event log injection interface for testing event flag decoding logic

From: Suravee Suthikulpanit <suravee.suthikulpanit@....com>

Add IOMMU event log injection interface for testing event flag decoding logic.
This interface allows users to specify device id, event flag, and event types via debugfs.

echo 0x300 > /sys/kernel/debug/amd-iommu-evninj/devid // (e.g. Bus:Dev.fun 3:0.0)
echo 0xfff > /sys/kernel/debug/amd-iommu-evninj/flags // (e.g. Specify flag value)
echo 2 > /sys/kernel/debug/amd-iommu-evninj/type      // (e.g. for IO_PAGE_FAULT event)

Once the event is injected, IOMMU driver will parse and print out the event information
in kernel log (dmesg) with the various information depending on the types of event and flag
specified.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@....com>
---
 drivers/iommu/Kconfig            |    9 ++++
 drivers/iommu/Makefile           |    1 +
 drivers/iommu/amd_iommu.c        |    7 ++-
 drivers/iommu/amd_iommu_inject.c |   99 ++++++++++++++++++++++++++++++++++++++
 drivers/iommu/amd_iommu_proto.h  |    9 ++++
 5 files changed, 123 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu_inject.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 5c514d07..c9787b9 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -64,6 +64,15 @@ config AMD_IOMMU_STATS
 	  information to userspace via debugfs.
 	  If unsure, say N.
 
+config AMD_IOMMU_EVENT_LOG_INJ
+	bool "Enable AMID IOMMU event injection interface via debugfs"
+	depends on AMD_IOMMU
+	select DEBUG_FS
+	---help---
+	  This option enables code in the AMD IOMMU driver to allow event log
+	  injection for testing IOMMU event log decoding logic via debugfs
+	  If unsure, say N.
+
 config AMD_IOMMU_V2
 	tristate "AMD IOMMU Version 2 driver"
 	depends on AMD_IOMMU && PROFILING
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index ef0e520..190eec5 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
+obj-$(CONFIG_AMD_IOMMU_EVENT_LOG_INJ) += amd_iommu_inject.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 477cfbb..30ac0cb 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -711,7 +711,7 @@ static void dump_command(unsigned long phys_addr)
 		pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]);
 }
 
-static void iommu_print_event(int type, int devid, int domid,
+void amd_iommu_print_event(int type, int devid, int domid,
 			      int flags, u64 address)
 {
 	pr_err("AMD-Vi: Event logged [");
@@ -799,7 +799,7 @@ retry:
 		goto retry;
 	}
 
-	iommu_print_event(type, devid, domid, flags, address);
+	amd_iommu_print_event(type, devid, domid, flags, address);
 
 	memset(__evt, 0, 4 * sizeof(u32));
 }
@@ -3288,6 +3288,9 @@ int __init amd_iommu_init_dma_ops(void)
 	else
 		pr_info("AMD-Vi: Lazy IO/TLB flushing enabled\n");
 
+#ifdef CONFIG_AMD_IOMMU_EVENT_LOG_INJ
+	amd_iommu_evninj_init();
+#endif
 	return 0;
 
 free_domains:
diff --git a/drivers/iommu/amd_iommu_inject.c b/drivers/iommu/amd_iommu_inject.c
new file mode 100644
index 0000000..b431b5f
--- /dev/null
+++ b/drivers/iommu/amd_iommu_inject.c
@@ -0,0 +1,99 @@
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#include "amd_iommu_types.h"
+#include "amd_iommu_proto.h"
+
+#define TMPBUFSIZE 50
+
+/*
+ * ERROR Injection Stuff
+ */
+
+static struct dentry *evninj_dir;
+static struct dentry *evninj_dentry_devid;
+static struct dentry *evninj_dentry_domid;
+static struct dentry *evninj_dentry_addr;
+static struct dentry *evninj_dentry_flags;
+static struct dentry *evninj_dentry_type;
+
+static uint32_t evninj_devid;
+static uint32_t evninj_domid;
+static uint64_t evninj_addr;
+static uint32_t evninj_flags;
+static uint32_t evninj_type;
+
+DEFINE_RAW_SPINLOCK(evninj_lock);
+
+static ssize_t evninj_read_type(struct file *file, char __user *buf,
+			  size_t count, loff_t *offset)
+{
+	char tmpbuf[TMPBUFSIZE];
+	size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%u\n", evninj_type);
+	if (maxlen > TMPBUFSIZE)
+		maxlen = TMPBUFSIZE;
+	return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen);
+}
+
+static ssize_t evninj_write_type(struct file *file, const char __user *buf,
+			   size_t count, loff_t *offset)
+{
+	char tmpbuf[TMPBUFSIZE];
+	unsigned long flags;
+	int ret;
+
+	if (*offset)
+		return -EINVAL;
+
+	if (!count)
+		return 0;
+
+	if (count > TMPBUFSIZE - 1)
+		return -EINVAL;
+
+	memset(tmpbuf, 0x0, TMPBUFSIZE);
+
+	if (copy_from_user(tmpbuf, buf, count))
+		return -EFAULT;
+
+	raw_spin_lock_irqsave(&evninj_lock, flags);
+	ret = kstrtouint(tmpbuf, 0, &evninj_type);
+	raw_spin_unlock_irqrestore(&evninj_lock, flags);
+
+	if (ret != 0)
+		return -EINVAL;
+
+	amd_iommu_print_event(evninj_type, evninj_devid, evninj_domid,
+			      evninj_flags, evninj_addr);
+
+	return count;
+}
+
+static const struct file_operations evninj_type_ops = {
+	.read  = &evninj_read_type,
+	.write = &evninj_write_type,
+};
+
+int amd_iommu_evninj_init(void)
+{
+	evninj_dir = debugfs_create_dir("amd-iommu-evninj", NULL);
+	if (evninj_dir == NULL)
+		return -EINVAL;
+
+	pr_info("AMD-Vi: IOMMU event injection enabled.\n");
+
+	/* Log inject stuff */
+	evninj_dentry_devid = debugfs_create_u32("devid", 0744,
+		evninj_dir, &evninj_devid);
+	evninj_dentry_domid = debugfs_create_u32("domid", 0744,
+		evninj_dir, &evninj_domid);
+	evninj_dentry_addr  = debugfs_create_u64("addr" , 0744,
+		evninj_dir, &evninj_addr);
+	evninj_dentry_flags = debugfs_create_u32("flags", 0744,
+		evninj_dir, &evninj_flags);
+	evninj_dentry_type  = debugfs_create_file("type", 0744,
+		evninj_dir, NULL, &evninj_type_ops);
+	return 0;
+}
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index c294961..8eb9340 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -31,6 +31,9 @@ extern int amd_iommu_init_devices(void);
 extern void amd_iommu_uninit_devices(void);
 extern void amd_iommu_init_notifier(void);
 extern void amd_iommu_init_api(void);
+extern void amd_iommu_print_event(int type, int devid,
+	int domid, int flags, u64 address);
+
 
 /* Needed for interrupt remapping */
 extern int amd_iommu_supported(void);
@@ -69,6 +72,12 @@ static inline void amd_iommu_stats_init(void) { }
 
 #endif /* !CONFIG_AMD_IOMMU_STATS */
 
+#ifdef CONFIG_AMD_IOMMU_EVENT_LOG_INJ
+
+extern int amd_iommu_evninj_init(void);
+
+#endif /* CONFIG_AMD_IOMMU_EVENT_LOG_INJ */
+
 static inline bool is_rd890_iommu(struct pci_dev *pdev)
 {
 	return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
-- 
1.7.10.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ