diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index fbe018e..2ba53a1 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2107,6 +2107,39 @@ struct.  When creating an ICS, the argument struct further indicates
 the BUID (Bus Unit ID) and number of interrupt sources for the new
 ICS.
 
+4.80 KVM_IRQCHIP_GET_SOURCES
+
+Capability: KVM_CAP_SPAPR_XICS
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_irq_sources
+Returns: 0 on success, -1 on error
+
+Copies configuration and status information about a range of interrupt
+sources into a user-supplied buffer.  The argument struct gives the
+starting interrupt source number and the number of interrupt sources.
+All of the interrupt sources must be within the range of a single
+interrupt source controller (ICS).  The user buffer is an array of
+64-bit quantities, one per interrupt source, with (from the least-
+significant bit) 32 bits of interrupt server number, 8 bits of
+priority, and 1 bit each for a level-sensitive indicator, a masked
+indicator, and a pending indicator.
+
+4.81 KVM_IRQCHIP_SET_SOURCES
+
+Capability: KVM_CAP_SPAPR_XICS
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_irq_sources
+Returns: 0 on success, -1 on error
+
+Sets the configuration and status for a range of interrupt sources
+from information supplied in a user-supplied buffer.  The argument
+struct gives the starting interrupt source number and the number of
+interrupt sources.  All of the interrupt sources must be within the
+range of a single interrupt source controller (ICS).  The user buffer
+is formatted as for KVM_IRQCHIP_GET_SOURCES.
+
 
 5. The kvm_run structure
 ------------------------
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index 8314cd9..8071c7e 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -1066,6 +1066,88 @@ int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval)
 	return 0;
 }
 
+static int kvm_xics_get_sources(struct kvm *kvm, struct kvm_irq_sources *srcs)
+{
+	int ret = 0;
+	struct kvmppc_xics *xics = kvm->arch.xics;
+	struct kvmppc_ics *ics;
+	struct ics_irq_state *irqp;
+	u64 __user *ubufp;
+	u16 idx;
+	u64 val;
+	long int i;
+
+	ics = kvmppc_xics_find_ics(xics, srcs->irq, &idx);
+	if (!ics || idx + srcs->nr_irqs > ics->nr_irqs)
+		return -ENOENT;
+
+	irqp = &ics->irq_state[idx];
+	ubufp = srcs->irqbuf;
+	mutex_lock(&ics->lock);
+	for (i = 0; i < srcs->nr_irqs; ++i, ++irqp, ++ubufp) {
+		val = irqp->server;
+		if (irqp->priority == MASKED && irqp->saved_priority != MASKED)
+			val |= KVM_IRQ_MASKED | ((u64)irqp->saved_priority <<
+						 KVM_IRQ_PRIORITY_SHIFT);
+		else
+			val |= ((u64)irqp->priority << KVM_IRQ_PRIORITY_SHIFT);
+		if (irqp->asserted)
+			val |= KVM_IRQ_LEVEL_SENSITIVE | KVM_IRQ_PENDING;
+		else if (irqp->masked_pending || irqp->resend)
+			val |= KVM_IRQ_PENDING;
+		ret = -EFAULT;
+		if (__put_user(val, ubufp))
+			break;
+		ret = 0;
+	}
+	mutex_unlock(&ics->lock);
+	return ret;
+}
+
+static int kvm_xics_set_sources(struct kvm *kvm, struct kvm_irq_sources *srcs)
+{
+	int ret = 0;
+	struct kvmppc_xics *xics = kvm->arch.xics;
+	struct kvmppc_ics *ics;
+	struct ics_irq_state *irqp;
+	u64 __user *ubufp;
+	u16 idx;
+	u64 val;
+	long int i;
+
+	ics = kvmppc_xics_find_ics(xics, srcs->irq, &idx);
+	if (!ics || idx + srcs->nr_irqs > ics->nr_irqs)
+		return -ENOENT;
+
+	irqp = &ics->irq_state[idx];
+	ubufp = srcs->irqbuf;
+	for (i = 0; i < srcs->nr_irqs; ++i, ++irqp, ++ubufp) {
+		ret = -EFAULT;
+		if (__get_user(val, ubufp))
+			break;
+		ret = 0;
+
+		mutex_lock(&ics->lock);
+		irqp->server = val & KVM_IRQ_SERVER_MASK;
+		irqp->saved_priority = val >> KVM_IRQ_PRIORITY_SHIFT;
+		if (val & KVM_IRQ_MASKED)
+			irqp->priority = MASKED;
+		else
+			irqp->priority = irqp->saved_priority;
+		irqp->resend = 0;
+		irqp->masked_pending = 0;
+		irqp->asserted = 0;
+		if ((val & KVM_IRQ_PENDING) && (val & KVM_IRQ_LEVEL_SENSITIVE))
+			irqp->asserted = 1;
+		mutex_unlock(&ics->lock);
+
+		if (val & KVM_IRQ_PENDING)
+			icp_deliver_irq(xics, NULL, irqp->number);
+	}
+
+	return ret;
+}
+
 /* -- ioctls -- */
 
 static int kvm_vm_ioctl_create_icp(struct kvm *kvm,
@@ -1200,6 +1282,32 @@ int kvmppc_xics_ioctl(struct kvm *kvm, unsigned ioctl, unsigned long arg)
 		break;
 	}
 
+	case KVM_IRQCHIP_GET_SOURCES: {
+		struct kvm_irq_sources sources;
+
+		rc = -EFAULT;
+		if (copy_from_user(&sources, argp, sizeof(sources)))
+			break;
+		if (!access_ok(VERIFY_WRITE, sources.irqbuf,
+			       sources.nr_irqs * sizeof(u64)))
+			break;
+		rc = kvm_xics_get_sources(kvm, &sources);
+		break;
+	}
+
+	case KVM_IRQCHIP_SET_SOURCES: {
+		struct kvm_irq_sources sources;
+
+		rc = -EFAULT;
+		if (copy_from_user(&sources, argp, sizeof(sources)))
+			break;
+		if (!access_ok(VERIFY_READ, sources.irqbuf,
+			       sources.nr_irqs * sizeof(u64)))
+			break;
+		rc = kvm_xics_set_sources(kvm, &sources);
+		break;
+	}
+
 	default:
 		rc = -ENOTTY;
 		break;
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 90b5b5c..0d443d4 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -955,7 +955,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		r = kvm_vm_ioctl_rtas_define_token(kvm, argp);
 		break;
 	}
-	case KVM_IRQ_LINE: {
+	case KVM_IRQ_LINE:
+	case KVM_IRQCHIP_GET_SOURCES:
+	case KVM_IRQCHIP_SET_SOURCES: {
 		struct kvm *kvm = filp->private_data;
 
 		r = -ENOTTY;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 8674d32..edcf78d 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -779,6 +779,21 @@ struct kvm_msi {
 	__u8  pad[16];
 };
 
+struct kvm_irq_sources {
+	__u32 irq;
+	__u32 nr_irqs;
+	__u64 __user *irqbuf;
+};
+
+/* irqbuf entries are laid out like this: */
+#define KVM_IRQ_SERVER_SHIFT	0
+#define KVM_IRQ_SERVER_MASK	0xffffffffULL
+#define KVM_IRQ_PRIORITY_SHIFT	32
+#define KVM_IRQ_PRIORITY_MASK	0xff
+#define KVM_IRQ_LEVEL_SENSITIVE	(1ULL << 40)
+#define KVM_IRQ_MASKED		(1ULL << 41)
+#define KVM_IRQ_PENDING		(1ULL << 42)
+
 /*
  * ioctls for VM fds
  */
@@ -867,6 +882,8 @@ struct kvm_s390_ucas_mapping {
 #ifdef __KVM_HAVE_IRQCHIP_ARGS
 #define KVM_CREATE_IRQCHIP_ARGS   _IOW(KVMIO,  0xab, struct kvm_irqchip_args)
 #endif
+#define KVM_IRQCHIP_GET_SOURCES	  _IOW(KVMIO,  0xac, struct kvm_irq_sources)
+#define KVM_IRQCHIP_SET_SOURCES	  _IOW(KVMIO,  0xad, struct kvm_irq_sources)
 
 /*
  * ioctls for vcpu fds
