Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-microblaze.git] / arch / powerpc / kvm / book3s_hv.c
index 829ff9b..2acb1c9 100644 (file)
@@ -59,6 +59,7 @@
 #include <asm/kvm_book3s.h>
 #include <asm/mmu_context.h>
 #include <asm/lppaca.h>
+#include <asm/pmc.h>
 #include <asm/processor.h>
 #include <asm/cputhreads.h>
 #include <asm/page.h>
@@ -1165,7 +1166,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                break;
 #endif
        case H_RANDOM:
-               if (!powernv_get_random_long(&vcpu->arch.regs.gpr[4]))
+               if (!arch_get_random_seed_long(&vcpu->arch.regs.gpr[4]))
                        ret = H_HARDWARE;
                break;
        case H_RPT_INVALIDATE:
@@ -1679,6 +1680,21 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
                        r = RESUME_GUEST;
                }
                break;
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       case BOOK3S_INTERRUPT_HV_SOFTPATCH:
+               /*
+                * This occurs for various TM-related instructions that
+                * we need to emulate on POWER9 DD2.2.  We have already
+                * handled the cases where the guest was in real-suspend
+                * mode and was transitioning to transactional state.
+                */
+               r = kvmhv_p9_tm_emulation(vcpu);
+               if (r != -1)
+                       break;
+               fallthrough; /* go to facility unavailable handler */
+#endif
+
        /*
         * This occurs if the guest (kernel or userspace), does something that
         * is prohibited by HFSCR.
@@ -1697,18 +1713,6 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
                }
                break;
 
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       case BOOK3S_INTERRUPT_HV_SOFTPATCH:
-               /*
-                * This occurs for various TM-related instructions that
-                * we need to emulate on POWER9 DD2.2.  We have already
-                * handled the cases where the guest was in real-suspend
-                * mode and was transitioning to transactional state.
-                */
-               r = kvmhv_p9_tm_emulation(vcpu);
-               break;
-#endif
-
        case BOOK3S_INTERRUPT_HV_RM_HARD:
                r = RESUME_PASSTHROUGH;
                break;
@@ -1727,6 +1731,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
 
 static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
 {
+       struct kvm_nested_guest *nested = vcpu->arch.nested;
        int r;
        int srcu_idx;
 
@@ -1811,9 +1816,41 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
                 * mode and was transitioning to transactional state.
                 */
                r = kvmhv_p9_tm_emulation(vcpu);
-               break;
+               if (r != -1)
+                       break;
+               fallthrough; /* go to facility unavailable handler */
 #endif
 
+       case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: {
+               u64 cause = vcpu->arch.hfscr >> 56;
+
+               /*
+                * Only pass HFU interrupts to the L1 if the facility is
+                * permitted but disabled by the L1's HFSCR, otherwise
+                * the interrupt does not make sense to the L1 so turn
+                * it into a HEAI.
+                */
+               if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) ||
+                                       (nested->hfscr & (1UL << cause))) {
+                       vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST;
+
+                       /*
+                        * If the fetch failed, return to guest and
+                        * try executing it again.
+                        */
+                       r = kvmppc_get_last_inst(vcpu, INST_GENERIC,
+                                                &vcpu->arch.emul_inst);
+                       if (r != EMULATE_DONE)
+                               r = RESUME_GUEST;
+                       else
+                               r = RESUME_HOST;
+               } else {
+                       r = RESUME_HOST;
+               }
+
+               break;
+       }
+
        case BOOK3S_INTERRUPT_HV_RM_HARD:
                vcpu->arch.trap = 0;
                r = RESUME_GUEST;
@@ -2684,6 +2721,7 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
        spin_lock_init(&vcpu->arch.vpa_update_lock);
        spin_lock_init(&vcpu->arch.tbacct_lock);
        vcpu->arch.busy_preempt = TB_NIL;
+       vcpu->arch.shregs.msr = MSR_ME;
        vcpu->arch.intr_msr = MSR_SF | MSR_ME;
 
        /*
@@ -2705,6 +2743,8 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
        if (cpu_has_feature(CPU_FTR_TM_COMP))
                vcpu->arch.hfscr |= HFSCR_TM;
 
+       vcpu->arch.hfscr_permitted = vcpu->arch.hfscr;
+
        kvmppc_mmu_book3s_hv_init(vcpu);
 
        vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
@@ -3727,7 +3767,6 @@ static void load_spr_state(struct kvm_vcpu *vcpu)
        mtspr(SPRN_EBBHR, vcpu->arch.ebbhr);
        mtspr(SPRN_EBBRR, vcpu->arch.ebbrr);
        mtspr(SPRN_BESCR, vcpu->arch.bescr);
-       mtspr(SPRN_WORT, vcpu->arch.wort);
        mtspr(SPRN_TIDR, vcpu->arch.tid);
        mtspr(SPRN_AMR, vcpu->arch.amr);
        mtspr(SPRN_UAMOR, vcpu->arch.uamor);
@@ -3754,7 +3793,6 @@ static void store_spr_state(struct kvm_vcpu *vcpu)
        vcpu->arch.ebbhr = mfspr(SPRN_EBBHR);
        vcpu->arch.ebbrr = mfspr(SPRN_EBBRR);
        vcpu->arch.bescr = mfspr(SPRN_BESCR);
-       vcpu->arch.wort = mfspr(SPRN_WORT);
        vcpu->arch.tid = mfspr(SPRN_TIDR);
        vcpu->arch.amr = mfspr(SPRN_AMR);
        vcpu->arch.uamor = mfspr(SPRN_UAMOR);
@@ -3786,7 +3824,6 @@ static void restore_p9_host_os_sprs(struct kvm_vcpu *vcpu,
                                    struct p9_host_os_sprs *host_os_sprs)
 {
        mtspr(SPRN_PSPB, 0);
-       mtspr(SPRN_WORT, 0);
        mtspr(SPRN_UAMOR, 0);
 
        mtspr(SPRN_DSCR, host_os_sprs->dscr);
@@ -3852,6 +3889,18 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
            cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
                kvmppc_restore_tm_hv(vcpu, vcpu->arch.shregs.msr, true);
 
+#ifdef CONFIG_PPC_PSERIES
+       if (kvmhv_on_pseries()) {
+               barrier();
+               if (vcpu->arch.vpa.pinned_addr) {
+                       struct lppaca *lp = vcpu->arch.vpa.pinned_addr;
+                       get_lppaca()->pmcregs_in_use = lp->pmcregs_in_use;
+               } else {
+                       get_lppaca()->pmcregs_in_use = 1;
+               }
+               barrier();
+       }
+#endif
        kvmhv_load_guest_pmu(vcpu);
 
        msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX);
@@ -3986,6 +4035,13 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
        save_pmu |= nesting_enabled(vcpu->kvm);
 
        kvmhv_save_guest_pmu(vcpu, save_pmu);
+#ifdef CONFIG_PPC_PSERIES
+       if (kvmhv_on_pseries()) {
+               barrier();
+               get_lppaca()->pmcregs_in_use = ppc_get_pmu_inuse();
+               barrier();
+       }
+#endif
 
        vc->entry_exit_map = 0x101;
        vc->in_guest = 0;
@@ -5340,6 +5396,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
        struct kvmppc_passthru_irqmap *pimap;
        struct irq_chip *chip;
        int i, rc = 0;
+       struct irq_data *host_data;
 
        if (!kvm_irq_bypass)
                return 1;
@@ -5367,7 +5424,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
         * what our real-mode EOI code does, or a XIVE interrupt
         */
        chip = irq_data_get_irq_chip(&desc->irq_data);
-       if (!chip || !(is_pnv_opal_msi(chip) || is_xive_irq(chip))) {
+       if (!chip || !is_pnv_opal_msi(chip)) {
                pr_warn("kvmppc_set_passthru_irq_hv: Could not assign IRQ map for (%d,%d)\n",
                        host_irq, guest_gsi);
                mutex_unlock(&kvm->lock);
@@ -5404,15 +5461,22 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
         * the KVM real mode handler.
         */
        smp_wmb();
-       irq_map->r_hwirq = desc->irq_data.hwirq;
+
+       /*
+        * The 'host_irq' number is mapped in the PCI-MSI domain but
+        * the underlying calls, which will EOI the interrupt in real
+        * mode, need an HW IRQ number mapped in the XICS IRQ domain.
+        */
+       host_data = irq_domain_get_irq_data(irq_get_default_host(), host_irq);
+       irq_map->r_hwirq = (unsigned int)irqd_to_hwirq(host_data);
 
        if (i == pimap->n_mapped)
                pimap->n_mapped++;
 
        if (xics_on_xive())
-               rc = kvmppc_xive_set_mapped(kvm, guest_gsi, desc);
+               rc = kvmppc_xive_set_mapped(kvm, guest_gsi, host_irq);
        else
-               kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq);
+               kvmppc_xics_set_mapped(kvm, guest_gsi, irq_map->r_hwirq);
        if (rc)
                irq_map->r_hwirq = 0;
 
@@ -5451,7 +5515,7 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
        }
 
        if (xics_on_xive())
-               rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, pimap->mapped[i].desc);
+               rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, host_irq);
        else
                kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq);