diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 8382c5834335..2b672e2164dc 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -19,6 +19,7 @@
 #include <linux/vfio.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
+#include <linux/cpuset.h>
 
 #include "vfio_pci_priv.h"
 
@@ -675,6 +676,54 @@ static int vfio_pci_set_intx_trigger(struct vfio_pci_core_device *vdev,
 	return 0;
 }
 
+static int vfio_pci_set_msi_affinity(struct vfio_pci_core_device *vdev,
+				     unsigned int ctx_index, unsigned int count,
+				     uint32_t *cpus)
+{
+	struct vfio_pci_irq_ctx *ctx;
+	cpumask_var_t allowed_mask;
+	cpumask_var_t irq_mask;
+	unsigned int i;
+	int err = 0;
+
+	ctx = vfio_irq_ctx_get(vdev, ctx_index);
+	if (!ctx)
+		return -EINVAL;
+
+	if (!alloc_cpumask_var(&allowed_mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	if (!zalloc_cpumask_var(&irq_mask, GFP_KERNEL)) {
+		err = -ENOMEM;
+		goto finish;
+	}
+
+	cpuset_cpus_allowed(current, allowed_mask);
+
+	for (i = 0; i < count; i++) {
+		if (cpus[i] >= nr_cpumask_bits ||
+		    !cpumask_test_cpu(cpus[i], allowed_mask)) {
+			err = -EPERM;
+			goto finish2;
+		}
+		__cpumask_set_cpu(cpus[i], irq_mask);
+	}
+
+	/* need at least 1 online cpu in the mask */
+	if (!cpumask_intersects(irq_mask, cpu_online_mask)) {
+		err = -EPERM;
+		goto finish2;
+	}
+
+	err = irq_set_affinity(ctx->producer.irq, irq_mask);
+
+finish2:
+	free_cpumask_var(irq_mask);
+finish:
+	free_cpumask_var(allowed_mask);
+	return err;
+}
+
 static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev,
 				    unsigned index, unsigned start,
 				    unsigned count, uint32_t flags, void *data)
@@ -691,6 +740,9 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev,
 	if (!(irq_is(vdev, index) || is_irq_none(vdev)))
 		return -EINVAL;
 
+	if (flags & VFIO_IRQ_SET_DATA_AFFINITY)
+		return vfio_pci_set_msi_affinity(vdev, start, count, data);
+
 	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
 		int32_t *fds = data;
 		int ret;
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index e97d796a54fb..5469a6f85822 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1489,7 +1489,6 @@ int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs,
 	minsz = offsetofend(struct vfio_irq_set, count);
 
 	if ((hdr->argsz < minsz) || (hdr->index >= max_irq_type) ||
-	    (hdr->count >= (U32_MAX - hdr->start)) ||
 	    (hdr->flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
 				VFIO_IRQ_SET_ACTION_TYPE_MASK)))
 		return -EINVAL;
@@ -1497,9 +1496,19 @@ int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs,
 	if (data_size)
 		*data_size = 0;
 
-	if (hdr->start >= num_irqs || hdr->start + hdr->count > num_irqs)
+	if (hdr->start >= num_irqs)
 		return -EINVAL;
 
+	/* For DATA_AFFINITY count is the number of cpu index */
+	if (hdr->flags & VFIO_IRQ_SET_DATA_AFFINITY) {
+		if (hdr->count > nr_cpumask_bits)
+			return -EINVAL;
+	} else {
+		if ((hdr->count >= (U32_MAX - hdr->start)) ||
+		    (hdr->start + hdr->count > num_irqs))
+			return -EINVAL;
+	}
+
 	switch (hdr->flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
 	case VFIO_IRQ_SET_DATA_NONE:
 		size = 0;
@@ -1510,6 +1519,9 @@ int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs,
 	case VFIO_IRQ_SET_DATA_EVENTFD:
 		size = sizeof(int32_t);
 		break;
+	case VFIO_IRQ_SET_DATA_AFFINITY:
+		size = sizeof(uint32_t);
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 2b68e6cdf190..af9405060401 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -548,7 +548,8 @@ struct vfio_irq_info {
  *
  * Set signaling, masking, and unmasking of interrupts.  Caller provides
  * struct vfio_irq_set with all fields set.  'start' and 'count' indicate
- * the range of subindexes being specified.
+ * the range of subindexes being specified, except for DATA_AFFINITY as
+ * explained below.
  *
  * The DATA flags specify the type of data provided.  If DATA_NONE, the
  * operation performs the specified action immediately on the specified
@@ -580,6 +581,11 @@ struct vfio_irq_info {
  *
  * Note that ACTION_[UN]MASK specify user->kernel signaling (irqfds) while
  * ACTION_TRIGGER specifies kernel->user signaling.
+ *
+ * DATA_AFFINITY specifies the affinity for an interrupt vector. It must be set
+ * with ACTION_TRIGGER in 'flags'. The 'start' field is the device interrupt
+ * vector. The variable-length 'data' is an array of CPU index encoded as __u32,
+ * the number of entries in the array is given by the 'count' field.
  */
 struct vfio_irq_set {
 	__u32	argsz;
@@ -587,6 +593,7 @@ struct vfio_irq_set {
 #define VFIO_IRQ_SET_DATA_NONE		(1 << 0) /* Data not present */
 #define VFIO_IRQ_SET_DATA_BOOL		(1 << 1) /* Data is bool (u8) */
 #define VFIO_IRQ_SET_DATA_EVENTFD	(1 << 2) /* Data is eventfd (s32) */
+#define VFIO_IRQ_SET_DATA_AFFINITY	(1 << 6) /* Data is cpu index (u32) */
 #define VFIO_IRQ_SET_ACTION_MASK	(1 << 3) /* Mask interrupt */
 #define VFIO_IRQ_SET_ACTION_UNMASK	(1 << 4) /* Unmask interrupt */
 #define VFIO_IRQ_SET_ACTION_TRIGGER	(1 << 5) /* Trigger interrupt */
@@ -599,7 +606,8 @@ struct vfio_irq_set {
 
 #define VFIO_IRQ_SET_DATA_TYPE_MASK	(VFIO_IRQ_SET_DATA_NONE | \
 					 VFIO_IRQ_SET_DATA_BOOL | \
-					 VFIO_IRQ_SET_DATA_EVENTFD)
+					 VFIO_IRQ_SET_DATA_EVENTFD | \
+					 VFIO_IRQ_SET_DATA_AFFINITY)
 #define VFIO_IRQ_SET_ACTION_TYPE_MASK	(VFIO_IRQ_SET_ACTION_MASK | \
 					 VFIO_IRQ_SET_ACTION_UNMASK | \
 					 VFIO_IRQ_SET_ACTION_TRIGGER)
