diff --git a/arch/powerpc/include/asm/book3s_errinjct.h b/arch/powerpc/include/asm/book3s_errinjct.h
index 35712be..75443ad 100644
--- a/arch/powerpc/include/asm/book3s_errinjct.h
+++ b/arch/powerpc/include/asm/book3s_errinjct.h
@@ -56,6 +56,25 @@ struct kvm_errinjct_token {
 	struct list_head list;
 };
 
+/* Argument buffer for various operations */
+struct kvm_errinjct_ioa_bus {
+	uint32_t addr;
+	uint32_t mask;
+	uint32_t cfg_addr;
+	uint32_t buid_hi;
+	uint32_t buid_lo;
+	uint32_t op;
+};
+
+struct kvm_errinjct_ioa_bus64 {
+	uint64_t addr;
+	uint64_t mask;
+	uint32_t cfg_addr;
+	uint32_t buid_hi;
+	uint32_t buid_lo;
+	uint32_t op;
+};
+
 int kvm_errinjct_register(int opcode, kvm_errinjct_func handler);
 int kvm_errinjct_unregister(int opcode);
 void kvmppc_errinjct_rtas(struct kvm_vcpu *vcpu,
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index d8ea670..d096b18 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_PCI)	+= pci.o pci-p5ioc2.o pci-ioda.o
 obj-$(CONFIG_EEH)	+= eeh-ioda.o eeh-powernv.o
 obj-$(CONFIG_KVM_EEH)	+= eeh-rtas.o
+obj-$(CONFIG_KVM_ERRINJCT)	+= errinjct.o
 obj-$(CONFIG_PPC_SCOM)	+= opal-xscom.o
 obj-$(CONFIG_MEMORY_FAILURE)	+= opal-memory-errors.o
diff --git a/arch/powerpc/platforms/powernv/errinjct.c b/arch/powerpc/platforms/powernv/errinjct.c
new file mode 100644
index 0000000..ccc7853
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/errinjct.c
@@ -0,0 +1,215 @@
+/*
+ * Backend for error injection implemented on PowerNV platform.
+ *
+ * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+
+#include <asm/uaccess.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/eeh.h>
+#include <asm/kvm_book3s.h>
+#include <asm/kvm_ppc.h>
+#include <asm/book3s_errinjct.h>
+#include <asm/hvcall.h>
+#include <asm/msi_bitmap.h>
+#include <asm/opal.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+static int powernv_errinjct_ioa(struct kvm_vcpu *vcpu, rtas_arg_t buf)
+{
+	struct OpalErrinjct ej;
+	struct kvm_errinjct_ioa_bus args;
+	struct eeh_vfio_pci_addr addr;
+	struct eeh_pe *pe;
+	struct pnv_phb *phb;
+	long rc;
+	int ret = 0;
+
+	/* Word aligned buffer */
+	if (buf & 0x3) {
+		ret = -3;
+		goto out;
+	}
+
+	/* Copy over argument */
+	ret = kvm_read_guest(vcpu->kvm, buf, &args, sizeof(args));
+	if (ret) {
+		pr_warn("%s: Can't copyover arguments (%d)\n",
+			__func__, ret);
+		ret = -3;
+		goto out;
+	}
+
+	/*
+	 * Sanity check on operation. We don't support optional
+	 * operation (20) and last one (21) for now.
+	 */
+	if (args.op < 0 || args.op > 21) {
+		ret = -3;
+		goto out;
+	} else if (args.op >= 20) {
+		ret = -1;
+		goto out;
+	}
+
+	/*
+	 * Only do error injection on passthrou PE. It's notable
+	 * the "cfg_addr" is guest PE address
+	 */
+	addr.kvm = vcpu->kvm;
+	addr.buid_hi = args.buid_hi;
+	addr.buid_lo = args.buid_lo;
+	addr.pe_addr = args.cfg_addr;
+	pe = eeh_vfio_pe_get(&addr);
+	if (!pe) {
+		pr_warn("%s: Can't find passed PE (%08x-%08x-%08x)\n",
+			__func__, args.buid_hi, args.buid_lo, args.cfg_addr);
+		ret = -3;
+		goto out;
+	}
+
+	/*
+	 * Calling to OPAL API. We need host PE address
+	 * and PHB host BUID.
+	 */
+	phb = pe->phb->private_data;
+
+	ej.type		= OpalErrinjctTypeIoaBusError;
+	ej.ioa.addr	= args.addr;
+	ej.ioa.mask	= args.mask;
+	ej.ioa.phb_id	= phb->opal_id;
+	ej.ioa.pe	= pe->addr;
+	ej.ioa.function	=  args.op;
+	rc = opal_err_injct(&ej);
+	if (rc != OPAL_SUCCESS) {
+		pr_warn("%s: OPAL API returns %ld\n", __func__, rc);
+		ret = -1;
+		goto out;
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int powernv_errinjct_ioa64(struct kvm_vcpu *vcpu, rtas_arg_t buf)
+{
+	struct OpalErrinjct ej;
+	struct kvm_errinjct_ioa_bus64 args;
+	struct eeh_vfio_pci_addr addr;
+	struct eeh_pe *pe;
+	struct pnv_phb *phb;
+	long rc;
+	int ret = 0;
+
+	/* Double word aligned buffer */
+	if (buf & 0x7) {
+		ret = -3;
+		goto out;
+	}
+
+	/* Copy over argument */
+	ret = kvm_read_guest(vcpu->kvm, buf, &args, sizeof(args));
+	if (ret) {
+		pr_warn("%s: Can't copyover arguments (%d)\n",
+			__func__, ret);
+		ret = -3;
+		goto out;
+	}
+
+	/*
+	 * Sanity check on operation. We don't support optional
+	 * operation (20) and last one (21) for now.
+	 */
+	if (args.op < 0 || args.op > 21) {
+		ret = -3;
+		goto out;
+	} else if (args.op >= 20) {
+		ret = -1;
+		goto out;
+	}
+
+	/*
+	 * Only do error injection on passthrou PE. It's notable
+	 * that "cfg_addr" is guest PE address
+	 */
+	addr.kvm = vcpu->kvm;
+	addr.buid_hi = args.buid_hi;
+	addr.buid_lo = args.buid_lo;
+	addr.pe_addr = args.cfg_addr;
+	pe = eeh_vfio_pe_get(&addr);
+	if (!pe) {
+		pr_warn("%s: Can't find passed PE (%08x-%08x-%08x)\n",
+			__func__, args.buid_hi, args.buid_lo, args.cfg_addr);
+		ret = -3;
+		goto out;
+	}
+
+	/*
+	 * Calling to OPAL API. We need host PE address
+	 * and PHB host BUID.
+	 */
+	phb = pe->phb->private_data;
+
+	ej.type		  = OpalErrinjctTypeIoaBusError64;
+	ej.ioa64.addr	  = args.addr;
+	ej.ioa64.mask	  = args.mask;
+	ej.ioa64.phb_id	  = phb->opal_id;
+	ej.ioa64.pe	  = pe->addr;
+	ej.ioa64.function =  args.op;
+	rc = opal_err_injct(&ej);
+	if (rc != OPAL_SUCCESS) {
+		pr_warn("%s: OPAL API returns %ld\n", __func__, rc);
+		ret = -1;
+		goto out;
+	}
+
+	/* Success */
+	ret = 0;
+out:
+	return ret;
+}
+
+static struct kvm_errinjct_handler handlers[] = {
+	{ .opcode  = kvm_errinjct_ioa_bus_error,
+	  .handler = powernv_errinjct_ioa
+	},
+	{ .opcode  = kvm_errinjct_ioa_bus_error_64,
+	  .handler = powernv_errinjct_ioa64
+	}
+};
+
+static int __init powernv_errinjct_init(void)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(handlers); i++) {
+		ret = kvm_errinjct_register(handlers[i].opcode,
+					    handlers[i].handler);
+		if (ret) {
+			pr_warn("%s: Failure registering handler %d (%d)\n",
+				__func__, handlers[i].opcode, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+module_init(powernv_errinjct_init);
