diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index fee73f3d9480..fc7fd2412dee 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 vfio_virqfd-y := virqfd.o
 
-obj-$(CONFIG_VFIO) += vfio.o
+obj-$(CONFIG_VFIO) += vfio.o vfio_common.o
 obj-$(CONFIG_VFIO_VIRQFD) += vfio_virqfd.o
 obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 9c8efad3a859..926cff00146c 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -561,61 +561,6 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
 	return 0;
 }
 
-static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
-					   unsigned int count, uint32_t flags,
-					   void *data)
-{
-	/* DATA_NONE/DATA_BOOL enables loopback testing */
-	if (flags & VFIO_IRQ_SET_DATA_NONE) {
-		if (*ctx) {
-			if (count) {
-				eventfd_signal(*ctx, 1);
-			} else {
-				eventfd_ctx_put(*ctx);
-				*ctx = NULL;
-			}
-			return 0;
-		}
-	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
-		uint8_t trigger;
-
-		if (!count)
-			return -EINVAL;
-
-		trigger = *(uint8_t *)data;
-		if (trigger && *ctx)
-			eventfd_signal(*ctx, 1);
-
-		return 0;
-	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
-		int32_t fd;
-
-		if (!count)
-			return -EINVAL;
-
-		fd = *(int32_t *)data;
-		if (fd == -1) {
-			if (*ctx)
-				eventfd_ctx_put(*ctx);
-			*ctx = NULL;
-		} else if (fd >= 0) {
-			struct eventfd_ctx *efdctx;
-
-			efdctx = eventfd_ctx_fdget(fd);
-			if (IS_ERR(efdctx))
-				return PTR_ERR(efdctx);
-
-			if (*ctx)
-				eventfd_ctx_put(*ctx);
-
-			*ctx = efdctx;
-		}
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
 				    unsigned index, unsigned start,
 				    unsigned count, uint32_t flags, void *data)
@@ -623,8 +568,8 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
 	if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)
 		return -EINVAL;
 
-	return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,
-					       count, flags, data);
+	return vfio_set_ctx_trigger_single(&vdev->err_trigger,
+					   count, flags, data);
 }
 
 static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
@@ -634,8 +579,8 @@ static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
 	if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1)
 		return -EINVAL;
 
-	return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger,
-					       count, flags, data);
+	return vfio_set_ctx_trigger_single(&vdev->req_trigger,
+					   count, flags, data);
 }
 
 int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
diff --git a/drivers/vfio/vfio_common.c b/drivers/vfio/vfio_common.c
new file mode 100644
index 000000000000..b209d57c7312
--- /dev/null
+++ b/drivers/vfio/vfio_common.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Intel, Corp. All rights reserved.
+ * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson@redhat.com>
+ * VFIO common helper functions
+ */
+
+#include <linux/eventfd.h>
+#include <linux/vfio.h>
+
+/*
+ * Common helper to set single eventfd trigger
+ *
+ * @ctx [out]		: address of eventfd ctx to be written to
+ * @count [in]		: number of vectors (should be 1)
+ * @flags [in]		: VFIO IRQ flags
+ * @data [in]		: data from ioctl
+ */
+int vfio_set_ctx_trigger_single(struct eventfd_ctx **ctx,
+				unsigned int count, u32 flags,
+				void *data)
+{
+	/* DATA_NONE/DATA_BOOL enables loopback testing */
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		if (*ctx) {
+			if (count) {
+				eventfd_signal(*ctx, 1);
+			} else {
+				eventfd_ctx_put(*ctx);
+				*ctx = NULL;
+			}
+			return 0;
+		}
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		u8 trigger;
+
+		if (!count)
+			return -EINVAL;
+
+		trigger = *(uint8_t *)data;
+		if (trigger && *ctx)
+			eventfd_signal(*ctx, 1);
+
+		return 0;
+	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		s32 fd;
+
+		if (!count)
+			return -EINVAL;
+
+		fd = *(s32 *)data;
+		if (fd == -1) {
+			if (*ctx)
+				eventfd_ctx_put(*ctx);
+			*ctx = NULL;
+		} else if (fd >= 0) {
+			struct eventfd_ctx *efdctx;
+
+			efdctx = eventfd_ctx_fdget(fd);
+			if (IS_ERR(efdctx))
+				return PTR_ERR(efdctx);
+
+			if (*ctx)
+				eventfd_ctx_put(*ctx);
+
+			*ctx = efdctx;
+		}
+		return 0;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(vfio_set_ctx_trigger_single);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index ed5ca027eb49..aa7cb0e1b8b2 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -235,4 +235,8 @@ extern int vfio_virqfd_enable(void *opaque,
 			      void *data, struct virqfd **pvirqfd, int fd);
 extern void vfio_virqfd_disable(struct virqfd **pvirqfd);
 
+/* common lib functions */
+extern int vfio_set_ctx_trigger_single(struct eventfd_ctx **ctx,
+				       unsigned int count, u32 flags,
+				       void *data);
 #endif /* VFIO_H */
