diff --git a/builtin-debug.c b/builtin-debug.c
index 4ae51d20..e39e2d09 100644
--- a/builtin-debug.c
+++ b/builtin-debug.c
@@ -5,6 +5,7 @@
 #include <kvm/parse-options.h>
 #include <kvm/kvm-ipc.h>
 #include <kvm/read-write.h>
+#include <kvm/virtio-iommu.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -17,6 +18,7 @@ static int nmi = -1;
 static bool dump;
 static const char *instance_name;
 static const char *sysrq;
+static const char *iommu;
 
 static const char * const debug_usage[] = {
 	"lkvm debug [--all] [-n name] [-d] [-m vcpu]",
@@ -28,6 +30,7 @@ static const struct option debug_options[] = {
 	OPT_BOOLEAN('d', "dump", &dump, "Generate a debug dump from guest"),
 	OPT_INTEGER('m', "nmi", &nmi, "Generate NMI on VCPU"),
 	OPT_STRING('s', "sysrq", &sysrq, "sysrq", "Inject a sysrq"),
+	OPT_STRING('i', "iommu", &iommu, "params", "Debug virtual IOMMU"),
 	OPT_GROUP("Instance options:"),
 	OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
 	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
@@ -68,11 +71,14 @@ static int do_debug(const char *name, int sock)
 		cmd.sysrq = sysrq[0];
 	}
 
+	if (iommu && !viommu_parse_debug_string(iommu, &cmd.iommu))
+		cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_IOMMU;
+
 	r = kvm_ipc__send_msg(sock, KVM_IPC_DEBUG, sizeof(cmd), (u8 *)&cmd);
 	if (r < 0)
 		return r;
 
-	if (!dump)
+	if (!(cmd.dbg_type & KVM_DEBUG_CMD_DUMP_MASK))
 		return 0;
 
 	do {
diff --git a/include/kvm/builtin-debug.h b/include/kvm/builtin-debug.h
index efa02684..cd2155ae 100644
--- a/include/kvm/builtin-debug.h
+++ b/include/kvm/builtin-debug.h
@@ -2,16 +2,22 @@
 #define KVM__DEBUG_H
 
 #include <kvm/util.h>
+#include <kvm/iommu.h>
 #include <linux/types.h>
 
 #define KVM_DEBUG_CMD_TYPE_DUMP	(1 << 0)
 #define KVM_DEBUG_CMD_TYPE_NMI	(1 << 1)
 #define KVM_DEBUG_CMD_TYPE_SYSRQ (1 << 2)
+#define KVM_DEBUG_CMD_TYPE_IOMMU (1 << 3)
+
+#define KVM_DEBUG_CMD_DUMP_MASK \
+	(KVM_DEBUG_CMD_TYPE_IOMMU | KVM_DEBUG_CMD_TYPE_DUMP)
 
 struct debug_cmd_params {
 	u32 dbg_type;
 	u32 cpu;
 	char sysrq;
+	struct iommu_debug_params iommu;
 };
 
 int kvm_cmd_debug(int argc, const char **argv, const char *prefix);
diff --git a/include/kvm/iommu.h b/include/kvm/iommu.h
index 45a20f3b..60857fa5 100644
--- a/include/kvm/iommu.h
+++ b/include/kvm/iommu.h
@@ -1,6 +1,7 @@
 #ifndef KVM_IOMMU_H
 #define KVM_IOMMU_H
 
+#include <stdbool.h>
 #include <stdlib.h>
 
 #include "devices.h"
@@ -10,6 +11,10 @@
 #define IOMMU_PROT_WRITE	0x2
 #define IOMMU_PROT_EXEC		0x4
 
+struct iommu_debug_params {
+	bool				print_enabled;
+};
+
 /*
  * Test if mapping is present. If not, return an error but do not report it to
  * stderr
diff --git a/include/kvm/virtio-iommu.h b/include/kvm/virtio-iommu.h
index 5532c82b..c9e36fb6 100644
--- a/include/kvm/virtio-iommu.h
+++ b/include/kvm/virtio-iommu.h
@@ -7,4 +7,9 @@ const struct iommu_properties *viommu_get_properties(void *dev);
 void *viommu_register(struct kvm *kvm, struct iommu_properties *props);
 void viommu_unregister(struct kvm *kvm, void *cookie);
 
+struct iommu_debug_params;
+
+int viommu_parse_debug_string(const char *options, struct iommu_debug_params *);
+int viommu_debug(int fd, struct iommu_debug_params *);
+
 #endif
diff --git a/kvm-ipc.c b/kvm-ipc.c
index e07ad105..a8b56543 100644
--- a/kvm-ipc.c
+++ b/kvm-ipc.c
@@ -14,6 +14,7 @@
 #include "kvm/strbuf.h"
 #include "kvm/kvm-cpu.h"
 #include "kvm/8250-serial.h"
+#include "kvm/virtio-iommu.h"
 
 struct kvm_ipc_head {
 	u32 type;
@@ -424,31 +425,35 @@ static void handle_debug(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
 		pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1);
 	}
 
-	if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
-		return;
+	if (dbg_type & KVM_DEBUG_CMD_TYPE_IOMMU)
+		viommu_debug(fd, &params->iommu);
 
-	for (i = 0; i < kvm->nrcpus; i++) {
-		struct kvm_cpu *cpu = kvm->cpus[i];
+	if (dbg_type & KVM_DEBUG_CMD_TYPE_DUMP) {
+		for (i = 0; i < kvm->nrcpus; i++) {
+			struct kvm_cpu *cpu = kvm->cpus[i];
 
-		if (!cpu)
-			continue;
+			if (!cpu)
+				continue;
 
-		printout_done = 0;
+			printout_done = 0;
+
+			kvm_cpu__set_debug_fd(fd);
+			pthread_kill(cpu->thread, SIGUSR1);
+			/*
+			 * Wait for the vCPU to dump state before signalling
+			 * the next thread. Since this is debug code it does
+			 * not matter that we are burning CPU time a bit:
+			 */
+			while (!printout_done)
+				sleep(0);
+		}
 
-		kvm_cpu__set_debug_fd(fd);
-		pthread_kill(cpu->thread, SIGUSR1);
-		/*
-		 * Wait for the vCPU to dump state before signalling
-		 * the next thread. Since this is debug code it does
-		 * not matter that we are burning CPU time a bit:
-		 */
-		while (!printout_done)
-			sleep(0);
+		serial8250__inject_sysrq(kvm, 'p');
 	}
 
-	close(fd);
-
-	serial8250__inject_sysrq(kvm, 'p');
+	if (dbg_type & KVM_DEBUG_CMD_DUMP_MASK)
+		/* builtin-debug is reading, signal EOT */
+		close(fd);
 }
 
 int kvm_ipc__init(struct kvm *kvm)
diff --git a/virtio/iommu.c b/virtio/iommu.c
index 2e5a23ee..5973cef1 100644
--- a/virtio/iommu.c
+++ b/virtio/iommu.c
@@ -620,3 +620,17 @@ void viommu_unregister(struct kvm *kvm, void *viommu)
 {
 	free(viommu);
 }
+
+int viommu_parse_debug_string(const char *cmdline, struct iommu_debug_params *params)
+{
+	/* show instances numbers */
+	/* send command to instance */
+	/* - dump mappings */
+	/* - statistics */
+	return -ENOSYS;
+}
+
+int viommu_debug(int sock, struct iommu_debug_params *params)
+{
+	return -ENOSYS;
+}
