On Fri, 3 Feb 2017 03:20:48 PM Nicholas Piggin wrote: > On Fri, 3 Feb 2017 00:25:11 +1000 > Nicholas Piggin <npig...@gmail.com> wrote: > > > This goes with the previous NMI IPI series, and a new version of > > Alistair's opal API I posted to the skiboot list. > > And here is the incremental bit that is required for Alistair's > hardware implementation to work. > > If the opal broacast call fails with OPAL_PARTIAL, then we designate > a bouncer CPU on another core to send NMI IPIs back to our sibling > threads. > > Probably needs more discussion and testing about how to detect and > handle failure cases and future compatibility for different types of > restrictions, but at least it works in mambo.
Looking at the Mambo implementation you recently posted I couldn't see where OPAL_PARTIAL was returned. So I guess you have other Skiboot patches to test this path using Mambo? I'm wondering because they could be useful for testing the skiboot HW side as well... > > Of course the other option rather than doing this in Linux is call > into opal in the system reset handler and have it do the bouncing. > Something to consider before we finalise the API. That might not be such a bad idea. OPAL could queue up the threads it couldn't reset and then wait until opal_sreset_complete() is called from an eligible thread to reset the ones it couldn't do in the original call. I might try prototyping something like this when I get some time. One issue would be if there is only a single core in the system, but that's unlikely and I think that's probably something we can't support in any case as cores can't sreset threads on the same core, at least on P8. - Alistair > Thanks, > Nick > > --- > arch/powerpc/platforms/powernv/smp.c | 88 > +++++++++++++++++++++++++++++++++--- > 1 file changed, 82 insertions(+), 6 deletions(-) > > diff --git a/arch/powerpc/platforms/powernv/smp.c > b/arch/powerpc/platforms/powernv/smp.c > index f90555f75723..4241fda9df9e 100644 > --- a/arch/powerpc/platforms/powernv/smp.c > +++ b/arch/powerpc/platforms/powernv/smp.c > @@ -241,8 +241,32 @@ static int pnv_cpu_bootable(unsigned int nr) > return smp_generic_cpu_bootable(nr); > } > > +static int nmi_ipi_bounce_cpu; > +static int nmi_ipi_bounce_cpu_done; > +static int nmi_ipi_bounce_target_core; > +static int nmi_ipi_bounce_target_exclude; > + > int pnv_system_reset_exception(struct pt_regs *regs) > { > + smp_rmb(); > + if (nmi_ipi_bounce_cpu == smp_processor_id()) { > + int64_t rc; > + int c; > + > + for_each_online_cpu(c) { > + if (!cpumask_test_cpu(c, > cpu_sibling_mask(nmi_ipi_bounce_target_core))) > + continue; > + if (c == nmi_ipi_bounce_target_exclude) > + continue; > + rc = opal_signal_system_reset(c); > + if (rc != OPAL_SUCCESS) { > + nmi_ipi_bounce_cpu_done = -1; > + return 1; > + } > + } > + nmi_ipi_bounce_cpu_done = 1; > + } > + > if (smp_handle_nmi_ipi(regs)) > return 1; > return 0; > @@ -252,13 +276,65 @@ static int pnv_cause_nmi_ipi(int cpu) > { > int64_t rc; > > - rc = opal_signal_system_reset(cpu); > - if (rc == OPAL_SUCCESS) > - return 1; > + if (cpu >= 0) { > + rc = opal_signal_system_reset(cpu); > + if (rc == OPAL_SUCCESS) > + return 1; > + } else { > + /* > + * Test bounce behavior with broadcast IPI. > + */ > + rc = OPAL_PARTIAL; > + } > + if (rc == OPAL_PARTIAL) { > + int c; > > - /* > - * Don't cope with OPAL_PARTIAL yet (just punt to regular IPI) > - */ > + /* > + * Some platforms can not send NMI to sibling threads in > + * the same core. We can designate one inter-core target > + * to bounce NMIs back to our sibling threads. > + */ > + > + if (cpu >= 0) { > + /* > + * Don't support bouncing unicast NMIs yet (because > + * that would have to raise an NMI on an unrelated > + * CPU. Revisit this if callers start using unicast. > + */ > + return 0; > + } > + > + nmi_ipi_bounce_cpu = -1; > + nmi_ipi_bounce_cpu_done = 0; > + nmi_ipi_bounce_target_core = -1; > + nmi_ipi_bounce_target_exclude = -1; > + smp_wmb(); > + > + for_each_online_cpu(c) { > + if (cpumask_test_cpu(c, > cpu_sibling_mask(smp_processor_id()))) > + continue; > + > + if (nmi_ipi_bounce_cpu == -1) { > + nmi_ipi_bounce_cpu = c; > + nmi_ipi_bounce_target_core = smp_processor_id(); > + if (cpu == NMI_IPI_ALL_OTHERS) > + nmi_ipi_bounce_target_exclude = > smp_processor_id(); > + } > + > + rc = opal_signal_system_reset(c); > + if (rc != OPAL_SUCCESS) > + return 0; > + } > + > + if (nmi_ipi_bounce_cpu == -1) > + return 0; /* could not find a bouncer */ > + > + while (!nmi_ipi_bounce_cpu_done) > + cpu_relax(); > + > + if (nmi_ipi_bounce_cpu_done == 1) > + return 1; /* bounce worked */ > + } > > return 0; > } >