Message ID | 1538127963-15645-21-git-send-email-paulus@ozlabs.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: PPC: Book3S HV: Nested HV virtualization | expand |
On Fri, Sep 28, 2018 at 07:45:50PM +1000, Paul Mackerras wrote: > This adds code to call the H_IPI and H_EOI hypercalls when we are > running as a nested hypervisor (i.e. without the CPU_FTR_HVMODE cpu > feature) and we would otherwise access the XICS interrupt controller > directly or via an OPAL call. > > Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> > --- > arch/powerpc/kvm/book3s_hv.c | 7 +++++- > arch/powerpc/kvm/book3s_hv_builtin.c | 44 +++++++++++++++++++++++++++++------- > arch/powerpc/kvm/book3s_hv_rm_xics.c | 8 +++++++ > 3 files changed, 50 insertions(+), 9 deletions(-) > > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 60adf47..8d2f91f 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -173,6 +173,10 @@ static bool kvmppc_ipi_thread(int cpu) > { > unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); > > + /* If we're a nested hypervisor, fall back to ordinary IPIs for now */ > + if (kvmhv_on_pseries()) > + return false; > + > /* On POWER9 we can use msgsnd to IPI any cpu */ > if (cpu_has_feature(CPU_FTR_ARCH_300)) { > msg |= get_hard_smp_processor_id(cpu); > @@ -5164,7 +5168,8 @@ static int kvmppc_book3s_init_hv(void) > * indirectly, via OPAL. > */ > #ifdef CONFIG_SMP > - if (!xive_enabled() && !local_paca->kvm_hstate.xics_phys) { > + if (!xive_enabled() && !kvmhv_on_pseries() && > + !local_paca->kvm_hstate.xics_phys) { > struct device_node *np; > > np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); > diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c > index ccfea5b..a71e2fc 100644 > --- a/arch/powerpc/kvm/book3s_hv_builtin.c > +++ b/arch/powerpc/kvm/book3s_hv_builtin.c > @@ -231,6 +231,15 @@ void kvmhv_rm_send_ipi(int cpu) > void __iomem *xics_phys; > unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); > > + /* For a nested hypervisor, use the XICS via hcall */ > + if (kvmhv_on_pseries()) { > + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; > + > + plpar_hcall_raw(H_IPI, retbuf, get_hard_smp_processor_id(cpu), > + IPI_PRIORITY); > + return; > + } > + > /* On POWER9 we can use msgsnd for any destination cpu. */ > if (cpu_has_feature(CPU_FTR_ARCH_300)) { > msg |= get_hard_smp_processor_id(cpu); > @@ -460,12 +469,19 @@ static long kvmppc_read_one_intr(bool *again) > return 1; > > /* Now read the interrupt from the ICP */ > - xics_phys = local_paca->kvm_hstate.xics_phys; > - rc = 0; > - if (!xics_phys) > - rc = opal_int_get_xirr(&xirr, false); > - else > - xirr = __raw_rm_readl(xics_phys + XICS_XIRR); > + if (kvmhv_on_pseries()) { > + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; > + > + rc = plpar_hcall_raw(H_XIRR, retbuf, 0xFF); > + xirr = cpu_to_be32(retbuf[0]); > + } else { > + xics_phys = local_paca->kvm_hstate.xics_phys; > + rc = 0; > + if (!xics_phys) > + rc = opal_int_get_xirr(&xirr, false); > + else > + xirr = __raw_rm_readl(xics_phys + XICS_XIRR); > + } > if (rc < 0) > return 1; > > @@ -494,7 +510,13 @@ static long kvmppc_read_one_intr(bool *again) > */ > if (xisr == XICS_IPI) { > rc = 0; > - if (xics_phys) { > + if (kvmhv_on_pseries()) { > + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; > + > + plpar_hcall_raw(H_IPI, retbuf, > + hard_smp_processor_id(), 0xff); > + plpar_hcall_raw(H_EOI, retbuf, h_xirr); > + } else if (xics_phys) { > __raw_rm_writeb(0xff, xics_phys + XICS_MFRR); > __raw_rm_writel(xirr, xics_phys + XICS_XIRR); > } else { > @@ -520,7 +542,13 @@ static long kvmppc_read_one_intr(bool *again) > /* We raced with the host, > * we need to resend that IPI, bummer > */ > - if (xics_phys) > + if (kvmhv_on_pseries()) { > + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; > + > + plpar_hcall_raw(H_IPI, retbuf, > + hard_smp_processor_id(), > + IPI_PRIORITY); > + } else if (xics_phys) > __raw_rm_writeb(IPI_PRIORITY, > xics_phys + XICS_MFRR); > else > diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c > index 8b9f356..b3f5786 100644 > --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c > +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c > @@ -767,6 +767,14 @@ static void icp_eoi(struct irq_chip *c, u32 hwirq, __be32 xirr, bool *again) > void __iomem *xics_phys; > int64_t rc; > > + if (kvmhv_on_pseries()) { > + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; > + > + iosync(); > + plpar_hcall_raw(H_EOI, retbuf, hwirq); > + return; > + } > + > rc = pnv_opal_pci_msi_eoi(c, hwirq); > > if (rc)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 60adf47..8d2f91f 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -173,6 +173,10 @@ static bool kvmppc_ipi_thread(int cpu) { unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); + /* If we're a nested hypervisor, fall back to ordinary IPIs for now */ + if (kvmhv_on_pseries()) + return false; + /* On POWER9 we can use msgsnd to IPI any cpu */ if (cpu_has_feature(CPU_FTR_ARCH_300)) { msg |= get_hard_smp_processor_id(cpu); @@ -5164,7 +5168,8 @@ static int kvmppc_book3s_init_hv(void) * indirectly, via OPAL. */ #ifdef CONFIG_SMP - if (!xive_enabled() && !local_paca->kvm_hstate.xics_phys) { + if (!xive_enabled() && !kvmhv_on_pseries() && + !local_paca->kvm_hstate.xics_phys) { struct device_node *np; np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index ccfea5b..a71e2fc 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -231,6 +231,15 @@ void kvmhv_rm_send_ipi(int cpu) void __iomem *xics_phys; unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); + /* For a nested hypervisor, use the XICS via hcall */ + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + plpar_hcall_raw(H_IPI, retbuf, get_hard_smp_processor_id(cpu), + IPI_PRIORITY); + return; + } + /* On POWER9 we can use msgsnd for any destination cpu. */ if (cpu_has_feature(CPU_FTR_ARCH_300)) { msg |= get_hard_smp_processor_id(cpu); @@ -460,12 +469,19 @@ static long kvmppc_read_one_intr(bool *again) return 1; /* Now read the interrupt from the ICP */ - xics_phys = local_paca->kvm_hstate.xics_phys; - rc = 0; - if (!xics_phys) - rc = opal_int_get_xirr(&xirr, false); - else - xirr = __raw_rm_readl(xics_phys + XICS_XIRR); + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + rc = plpar_hcall_raw(H_XIRR, retbuf, 0xFF); + xirr = cpu_to_be32(retbuf[0]); + } else { + xics_phys = local_paca->kvm_hstate.xics_phys; + rc = 0; + if (!xics_phys) + rc = opal_int_get_xirr(&xirr, false); + else + xirr = __raw_rm_readl(xics_phys + XICS_XIRR); + } if (rc < 0) return 1; @@ -494,7 +510,13 @@ static long kvmppc_read_one_intr(bool *again) */ if (xisr == XICS_IPI) { rc = 0; - if (xics_phys) { + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + plpar_hcall_raw(H_IPI, retbuf, + hard_smp_processor_id(), 0xff); + plpar_hcall_raw(H_EOI, retbuf, h_xirr); + } else if (xics_phys) { __raw_rm_writeb(0xff, xics_phys + XICS_MFRR); __raw_rm_writel(xirr, xics_phys + XICS_XIRR); } else { @@ -520,7 +542,13 @@ static long kvmppc_read_one_intr(bool *again) /* We raced with the host, * we need to resend that IPI, bummer */ - if (xics_phys) + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + plpar_hcall_raw(H_IPI, retbuf, + hard_smp_processor_id(), + IPI_PRIORITY); + } else if (xics_phys) __raw_rm_writeb(IPI_PRIORITY, xics_phys + XICS_MFRR); else diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index 8b9f356..b3f5786 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c @@ -767,6 +767,14 @@ static void icp_eoi(struct irq_chip *c, u32 hwirq, __be32 xirr, bool *again) void __iomem *xics_phys; int64_t rc; + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + iosync(); + plpar_hcall_raw(H_EOI, retbuf, hwirq); + return; + } + rc = pnv_opal_pci_msi_eoi(c, hwirq); if (rc)
This adds code to call the H_IPI and H_EOI hypercalls when we are running as a nested hypervisor (i.e. without the CPU_FTR_HVMODE cpu feature) and we would otherwise access the XICS interrupt controller directly or via an OPAL call. Signed-off-by: Paul Mackerras <paulus@ozlabs.org> --- arch/powerpc/kvm/book3s_hv.c | 7 +++++- arch/powerpc/kvm/book3s_hv_builtin.c | 44 +++++++++++++++++++++++++++++------- arch/powerpc/kvm/book3s_hv_rm_xics.c | 8 +++++++ 3 files changed, 50 insertions(+), 9 deletions(-)