/* * This is used in working around bugs in thread reconfiguration * on POWER9 (at least up to Nimbus DD2.2) relating to transactional * memory and the way that XER[SO] is checkpointed. * This function forces the core into SMT4 in order by asking * all other threads not to stop, and sending a message to any * that are in a stop state. * Must be called with preemption disabled. */ void pnv_power9_force_smt4_catch(void) { int cpu, cpu0, thr; int awake_threads = 1; /* this thread is awake */ int poke_threads = 0; int need_awake = threads_per_core; cpu = smp_processor_id(); cpu0 = cpu & ~(threads_per_core - 1); for (thr = 0; thr < threads_per_core; ++thr) { if (cpu != cpu0 + thr) atomic_inc(&paca_ptrs[cpu0+thr]->dont_stop); } /* order setting dont_stop vs testing requested_psscr */ mb(); for (thr = 0; thr < threads_per_core; ++thr) { if (!paca_ptrs[cpu0+thr]->requested_psscr) ++awake_threads; else poke_threads |= (1 << thr); } /* If at least 3 threads are awake, the core is in SMT4 already */ if (awake_threads < need_awake) { /* We have to wake some threads; we'll use msgsnd */ for (thr = 0; thr < threads_per_core; ++thr) { if (poke_threads & (1 << thr)) { ppc_msgsnd_sync(); ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, paca_ptrs[cpu0+thr]->hw_cpu_id); } } /* now spin until at least 3 threads are awake */ do { for (thr = 0; thr < threads_per_core; ++thr) { if ((poke_threads & (1 << thr)) && !paca_ptrs[cpu0+thr]->requested_psscr) { ++awake_threads; poke_threads &= ~(1 << thr); } } } while (awake_threads < need_awake); } }
void doorbell_cause_ipi(int cpu, unsigned long data) { /* Order previous accesses vs. msgsnd, which is treated as a store */ mb(); ppc_msgsnd(PPC_DBELL, 0, data); }
void doorbell_cause_ipi(int cpu, unsigned long data) { ppc_msgsnd(PPC_DBELL, 0, data); }