]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/powerpc/kvm/book3s.c
KVM: PPC: Book3S HV: Native usage of the XIVE interrupt controller
[mirror_ubuntu-bionic-kernel.git] / arch / powerpc / kvm / book3s.c
index aedacefd961d1417923254d646e3ebcb62cf3fcb..cb8009cd688d4d746411893dc4f0771d87970c6f 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/kvm_book3s.h>
 #include <asm/mmu_context.h>
 #include <asm/page.h>
+#include <asm/xive.h>
 
 #include "book3s.h"
 #include "trace.h"
@@ -578,11 +579,14 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
                        break;
 #ifdef CONFIG_KVM_XICS
                case KVM_REG_PPC_ICP_STATE:
-                       if (!vcpu->arch.icp) {
+                       if (!vcpu->arch.icp && !vcpu->arch.xive_vcpu) {
                                r = -ENXIO;
                                break;
                        }
-                       *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu));
+                       if (xive_enabled())
+                               *val = get_reg_val(id, kvmppc_xive_get_icp(vcpu));
+                       else
+                               *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu));
                        break;
 #endif /* CONFIG_KVM_XICS */
                case KVM_REG_PPC_FSCR:
@@ -648,12 +652,14 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_KVM_XICS
                case KVM_REG_PPC_ICP_STATE:
-                       if (!vcpu->arch.icp) {
+                       if (!vcpu->arch.icp && !vcpu->arch.xive_vcpu) {
                                r = -ENXIO;
                                break;
                        }
-                       r = kvmppc_xics_set_icp(vcpu,
-                                               set_reg_val(id, *val));
+                       if (xive_enabled())
+                               r = kvmppc_xive_set_icp(vcpu, set_reg_val(id, *val));
+                       else
+                               r = kvmppc_xics_set_icp(vcpu, set_reg_val(id, *val));
                        break;
 #endif /* CONFIG_KVM_XICS */
                case KVM_REG_PPC_FSCR:
@@ -924,6 +930,50 @@ int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hcall)
        return kvm->arch.kvm_ops->hcall_implemented(hcall);
 }
 
+#ifdef CONFIG_KVM_XICS
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
+               bool line_status)
+{
+       if (xive_enabled())
+               return kvmppc_xive_set_irq(kvm, irq_source_id, irq, level,
+                                          line_status);
+       else
+               return kvmppc_xics_set_irq(kvm, irq_source_id, irq, level,
+                                          line_status);
+}
+
+int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry,
+                             struct kvm *kvm, int irq_source_id,
+                             int level, bool line_status)
+{
+       return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
+                          level, line_status);
+}
+static int kvmppc_book3s_set_irq(struct kvm_kernel_irq_routing_entry *e,
+                                struct kvm *kvm, int irq_source_id, int level,
+                                bool line_status)
+{
+       return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status);
+}
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+                   struct kvm_kernel_irq_routing_entry *entries, int gsi)
+{
+       entries->gsi = gsi;
+       entries->type = KVM_IRQ_ROUTING_IRQCHIP;
+       entries->set = kvmppc_book3s_set_irq;
+       entries->irqchip.irqchip = 0;
+       entries->irqchip.pin = gsi;
+       return 1;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
+{
+       return pin;
+}
+
+#endif /* CONFIG_KVM_XICS */
+
 static int kvmppc_book3s_init(void)
 {
        int r;
@@ -934,12 +984,25 @@ static int kvmppc_book3s_init(void)
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        r = kvmppc_book3s_init_pr();
 #endif
-       return r;
 
+#ifdef CONFIG_KVM_XICS
+#ifdef CONFIG_KVM_XIVE
+       if (xive_enabled()) {
+               kvmppc_xive_init_module();
+               kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS);
+       } else
+#endif
+               kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS);
+#endif
+       return r;
 }
 
 static void kvmppc_book3s_exit(void)
 {
+#ifdef CONFIG_KVM_XICS
+       if (xive_enabled())
+               kvmppc_xive_exit_module();
+#endif
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        kvmppc_book3s_exit_pr();
 #endif