diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index b05e7cd..8af4c0b 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -230,8 +230,18 @@ struct kvm_arch_memory_slot {
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
+struct kvm_irq_ctrler {
+	int (*setup_vcpu)(struct kvm_vcpu *vcpu);
+	void (*teardown_vcpu)(struct kvm_vcpu *vcpu);
+	void (*free_ctrler)(struct kvm *kvm);
+	int (*hcall)(struct kvm_vcpu *vcpu, unsigned long req);
+	int (*ioctl)(struct kvm *kvm, unsigned int ioctl, unsigned long arg);
+};
+
 struct kvm_arch {
 	unsigned int lpid;
+	struct kvm_irq_ctrler *irq_ctrler;
+	void *irq_ctrler_private;
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	unsigned long hpt_virt;
 	struct revmap_entry *revmap;
@@ -260,7 +270,6 @@ struct kvm_arch {
 #ifdef CONFIG_PPC_BOOK3S_64
 	struct list_head spapr_tce_tables;
 	struct list_head rtas_tokens;
-	struct kvmppc_xics *xics;
 #endif
 };
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index f0fd22b..2308fff 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -130,12 +130,7 @@ extern long kvmppc_prepare_vrma(struct kvm *kvm,
 extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
 			struct kvm_memory_slot *memslot, unsigned long porder);
 extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
-extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
-extern int kvmppc_xics_ioctl(struct kvm *kvm, unsigned ioctl, unsigned long arg);
 extern int kvmppc_xics_create(struct kvm *kvm, struct kvm_irqchip_args *args);
-extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
-extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu);
-extern void kvmppc_xics_free(struct kvm *kvm);
 
 extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
 				struct kvm_create_spapr_tce *args);
@@ -275,15 +270,6 @@ static inline void kvm_linear_init(void)
 
 #endif
 
-#ifdef CONFIG_PPC_BOOK3S_64
-static inline int kvmppc_xics_enabled(struct kvm *kvm)
-{
-	return kvm->arch.xics != NULL;
-}
-#else
-static inline int kvmppc_xics_enabled(struct kvm *kvm) { return 0; }
-#endif
-
 static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index aa3a0db..8f09c36 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -532,8 +532,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 	case H_CPPR:
 	case H_EOI:
 	case H_IPI:
-		if (kvmppc_xics_enabled(vcpu->kvm)) {
-			ret = kvmppc_xics_hcall(vcpu, req);
+		if (vcpu->kvm->arch.irq_ctrler) {
+			ret = vcpu->kvm->arch.irq_ctrler->hcall(vcpu, req);
 			break;
 		} /* fallthrough */
 	default:
@@ -894,9 +894,9 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
 	spin_lock_init(&vcpu->arch.tbacct_lock);
 	vcpu->arch.busy_preempt = TB_NIL;
 
-	/* Create the XICS */
-	if (kvmppc_xics_enabled(kvm)) {
-		err = kvmppc_xics_create_icp(vcpu);
+	/* Create the interrupt-controller-specific state */
+	if (kvm->arch.irq_ctrler) {
+		err = kvm->arch.irq_ctrler->setup_vcpu(vcpu);
 		if (err < 0)
 			goto free_vcpu;
 	}
@@ -952,8 +952,8 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 		kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.vpa.pinned_addr);
 	spin_unlock(&vcpu->arch.vpa_update_lock);
 	kvm_vcpu_uninit(vcpu);
-	if (kvmppc_xics_enabled(vcpu->kvm))
-		kvmppc_xics_free_icp(vcpu);
+	if (vcpu->kvm->arch.irq_ctrler)
+		vcpu->kvm->arch.irq_ctrler->teardown_vcpu(vcpu);
 	kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
 
@@ -1899,8 +1899,8 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 
 	kvmppc_rtas_tokens_free(kvm);
 
-	if (kvmppc_xics_enabled(kvm))
-		kvmppc_xics_free(kvm);
+	if (kvm->arch.irq_ctrler)
+		kvm->arch.irq_ctrler->free_ctrler(kvm);
 
 	kvmppc_free_hpt(kvm);
 	WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 9b2237f..0c84242 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1069,9 +1069,9 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
 	if (err < 0)
 		goto uninit_vcpu;
 
-	/* Create the XICS */
-	if (kvmppc_xics_enabled(kvm)) {
-		err = kvmppc_xics_create_icp(vcpu);
+	/* Create the interrupt-controller-specific vcpu state */
+	if (kvm->arch.irq_ctrler) {
+		err = kvm->arch.irq_ctrler->setup_vcpu(vcpu);
 		if (err < 0)
 			goto free_vcpu;
 	}
@@ -1092,8 +1092,8 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
 
-	if (kvmppc_xics_enabled(vcpu->kvm))
-		kvmppc_xics_free_icp(vcpu);
+	if (vcpu->kvm->arch.irq_ctrler)
+		vcpu->kvm->arch.irq_ctrler->teardown_vcpu(vcpu);
 	free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
 	kvm_vcpu_uninit(vcpu);
 	kfree(vcpu_book3s->shadow_vcpu);
@@ -1313,8 +1313,8 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 #ifdef CONFIG_PPC64
 	WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
 #endif
-	if (kvmppc_xics_enabled(kvm))
-		kvmppc_xics_free(kvm);
+	if (kvm->arch.irq_ctrler)
+		kvm->arch.irq_ctrler->free_ctrler(kvm);
 
 }
 
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
index 94cec5b..c423b51 100644
--- a/arch/powerpc/kvm/book3s_pr_papr.c
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
@@ -229,7 +229,11 @@ static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
 
 static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
 {
-	long rc = kvmppc_xics_hcall(vcpu, cmd);
+	long rc;
+
+	if (!vcpu->kvm->arch.irq_ctrler)
+		return EMULATE_FAIL;
+	rc = vcpu->kvm->arch.irq_ctrler->hcall(vcpu, cmd);
 	if (rc == H_TOO_HARD)
 		return EMULATE_FAIL;
 	kvmppc_set_gpr(vcpu, 3, rc);
@@ -259,9 +263,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
 	case H_CPPR:
 	case H_EOI:
 	case H_IPI:
-		if (kvmppc_xics_enabled(vcpu->kvm))
-			return kvmppc_h_pr_xics_hcall(vcpu, cmd);
-		break;
+		return kvmppc_h_pr_xics_hcall(vcpu, cmd);
 	case H_RTAS:
 		if (list_empty(&vcpu->kvm->arch.rtas_tokens))
 			return RESUME_HOST;
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index 7749060..2312b56 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -115,7 +115,7 @@ static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
 
 int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority)
 {
-	struct kvmppc_xics *xics = kvm->arch.xics;
+	struct kvmppc_xics *xics = kvm->arch.irq_ctrler_private;
 	struct kvmppc_icp *icp;
 	struct kvmppc_ics *ics;
 	struct ics_irq_state *state;
@@ -158,7 +158,7 @@ int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority)
 
 int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server, u32 *priority)
 {
-	struct kvmppc_xics *xics = kvm->arch.xics;
+	struct kvmppc_xics *xics = kvm->arch.irq_ctrler_private;
 	struct kvmppc_ics *ics;
 	struct ics_irq_state *state;
 	u16 src;
@@ -514,7 +514,7 @@ static noinline int h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
 			  unsigned long mfrr)
 {
         union kvmppc_icp_state old_state, new_state;
-	struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
+	struct kvmppc_xics *xics = vcpu->kvm->arch.irq_ctrler_private;
 	struct kvmppc_icp *icp;
 	u32 reject;
 	bool resend;
@@ -582,7 +582,7 @@ static noinline int h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
 static noinline void h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
 {
 	union kvmppc_icp_state old_state, new_state;
-	struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
+	struct kvmppc_xics *xics = vcpu->kvm->arch.irq_ctrler_private;
 	struct kvmppc_icp *icp = vcpu->arch.icp;
 	u32 reject;
 
@@ -638,7 +638,7 @@ static noinline void h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
 
 static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
 {
-	struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
+	struct kvmppc_xics *xics = vcpu->kvm->arch.irq_ctrler_private;
 	struct kvmppc_icp *icp = vcpu->arch.icp;
 	struct kvmppc_ics *ics;
 	struct ics_irq_state *state;
@@ -686,13 +686,13 @@ static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
 	return H_SUCCESS;
 }
 
-int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
+static int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, unsigned long req)
 {
 	unsigned long res;
 	int rc = H_SUCCESS;
 
 	/* Check if we have an ICP */
-	if (!vcpu->arch.icp || !vcpu->kvm->arch.xics)
+	if (!vcpu->arch.icp || !vcpu->kvm->arch.irq_ctrler_private)
 		return H_HARDWARE;
 
 	switch (req) {
@@ -838,7 +838,7 @@ static struct kvmppc_ics *kvmppc_xics_create_ics(struct kvmppc_xics *xics,
 	return xics->ics[icsid];
 }
 
-int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu)
+static int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_icp *icp;
 
@@ -856,7 +856,7 @@ int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
+static void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->arch.icp)
 		return;
@@ -864,9 +864,9 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
 	vcpu->arch.icp = NULL;
 }
 
-void kvmppc_xics_free(struct kvm *kvm)
+static void kvmppc_xics_free(struct kvm *kvm)
 {
-	struct kvmppc_xics *xics = kvm->arch.xics;
+	struct kvmppc_xics *xics = kvm->arch.irq_ctrler_private;
 	int i;
 
 	if (!xics)
@@ -877,7 +877,7 @@ void kvmppc_xics_free(struct kvm *kvm)
 	debugfs_remove(xics->dentry);
 
 	if (xics->kvm) {
-		xics->kvm->arch.xics = NULL;
+		xics->kvm->arch.irq_ctrler_private = NULL;
 		xics->kvm = NULL;
 	}
 
@@ -891,7 +891,7 @@ void kvmppc_xics_free(struct kvm *kvm)
 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_xics *xics = kvm->arch.irq_ctrler_private;
 	struct kvmppc_ics *ics;
 	struct ics_irq_state *irqp;
 	u64 __user *ubufp;
@@ -941,7 +941,7 @@ static int kvm_xics_get_sources(struct kvm *kvm, struct kvm_irq_sources *srcs)
 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_xics *xics = kvm->arch.irq_ctrler_private;
 	struct kvmppc_ics *ics;
 	struct ics_irq_state *irqp;
 	u64 __user *ubufp;
@@ -999,39 +999,13 @@ static int kvm_xics_set_sources(struct kvm *kvm, struct kvm_irq_sources *srcs)
 
 /* -- ioctls -- */
 
-int kvmppc_xics_create(struct kvm *kvm, struct kvm_irqchip_args *args)
-{
-	struct kvmppc_xics *xics;
-	int rc = 0;
-
-	mutex_lock(&kvm->lock);
-
-	/* Already there ? */
-	if (kvm->arch.xics)
-		return -EEXIST;
-
-	xics = kzalloc(sizeof(*xics), GFP_KERNEL);
-	if (!xics) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	xics->kvm = kvm;
-	kvm->arch.xics = xics;
-	xics_debugfs_init(xics);
-
-out:
-	mutex_unlock(&kvm->lock);
-	return rc;
-}
-
 static int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args)
 {
 	struct kvmppc_xics *xics;
 
 	/* locking against multiple callers? */
 
-	xics = kvm->arch.xics;
+	xics = kvm->arch.irq_ctrler_private;
 	if (!xics)
 		return -ENODEV;
 
@@ -1048,7 +1022,7 @@ static int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args)
 	return 0;
 }
 
-int kvmppc_xics_ioctl(struct kvm *kvm, unsigned ioctl, unsigned long arg)
+static int kvmppc_xics_ioctl(struct kvm *kvm, unsigned ioctl, unsigned long arg)
 {
 	void __user *argp = (void __user *)arg;
 	int rc;
@@ -1099,3 +1073,38 @@ int kvmppc_xics_ioctl(struct kvm *kvm, unsigned ioctl, unsigned long arg)
 
 	return rc;
 }
+
+static struct kvm_irq_ctrler xics_ctrler = {
+	.setup_vcpu = kvmppc_xics_create_icp,
+	.teardown_vcpu = kvmppc_xics_free_icp,
+	.free_ctrler = kvmppc_xics_free,
+	.hcall = kvmppc_xics_hcall,
+	.ioctl = kvmppc_xics_ioctl,
+};
+
+int kvmppc_xics_create(struct kvm *kvm, struct kvm_irqchip_args *args)
+{
+	struct kvmppc_xics *xics;
+	int rc = 0;
+
+	mutex_lock(&kvm->lock);
+
+	/* Already there ? */
+	if (kvm->arch.irq_ctrler)
+		return -EEXIST;
+
+	xics = kzalloc(sizeof(*xics), GFP_KERNEL);
+	if (!xics) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	xics->kvm = kvm;
+	kvm->arch.irq_ctrler = &xics_ctrler;
+	kvm->arch.irq_ctrler_private = xics;
+	xics_debugfs_init(xics);
+
+out:
+	mutex_unlock(&kvm->lock);
+	return rc;
+}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 3bcc030..e429839 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -1009,8 +1009,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		struct kvm *kvm = filp->private_data;
 
 		r = -ENOTTY;
-		if (kvmppc_xics_enabled(kvm))
-			r = kvmppc_xics_ioctl(kvm, ioctl, arg);
+		if (kvm->arch.irq_ctrler)
+			r = kvm->arch.irq_ctrler->ioctl(kvm, ioctl, arg);
 		break;
 	}
 	case KVM_CREATE_IRQCHIP_ARGS: {
