]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sparc64/sparc64/mp_machdep.c
bitset: rename confusing macro NAND to ANDNOT
[FreeBSD/FreeBSD.git] / sys / sparc64 / sparc64 / mp_machdep.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Berkeley Software Design Inc's name may not be used to endorse or
15  *    promote products derived from this software without specific prior
16  *    written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * from BSDI: locore.s,v 1.36.2.15 1999/08/23 22:34:41 cp Exp
31  */
32 /*-
33  * Copyright (c) 2002 Jake Burkholder.
34  * Copyright (c) 2007 - 2010 Marius Strobl <marius@FreeBSD.org>
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  */
58
59 #include <sys/cdefs.h>
60 __FBSDID("$FreeBSD$");
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/lock.h>
65 #include <sys/kdb.h>
66 #include <sys/kernel.h>
67 #include <sys/ktr.h>
68 #include <sys/mutex.h>
69 #include <sys/pcpu.h>
70 #include <sys/proc.h>
71 #include <sys/sched.h>
72 #include <sys/smp.h>
73
74 #include <vm/vm.h>
75 #include <vm/vm_param.h>
76 #include <vm/pmap.h>
77 #include <vm/vm_kern.h>
78 #include <vm/vm_extern.h>
79 #include <vm/vm_map.h>
80
81 #include <dev/ofw/openfirm.h>
82
83 #include <machine/asi.h>
84 #include <machine/atomic.h>
85 #include <machine/bus.h>
86 #include <machine/cpu.h>
87 #include <machine/cpufunc.h>
88 #include <machine/md_var.h>
89 #include <machine/metadata.h>
90 #include <machine/ofw_machdep.h>
91 #include <machine/pcb.h>
92 #include <machine/smp.h>
93 #include <machine/tick.h>
94 #include <machine/tlb.h>
95 #include <machine/tsb.h>
96 #include <machine/tte.h>
97 #include <machine/ver.h>
98
99 #define SUNW_STARTCPU           "SUNW,start-cpu"
100 #define SUNW_STOPSELF           "SUNW,stop-self"
101
102 static ih_func_t cpu_ipi_ast;
103 static ih_func_t cpu_ipi_hardclock;
104 static ih_func_t cpu_ipi_preempt;
105 static ih_func_t cpu_ipi_stop;
106
107 /*
108  * Argument area used to pass data to non-boot processors as they start up.
109  * This must be statically initialized with a known invalid CPU module ID,
110  * since the other processors will use it before the boot CPU enters the
111  * kernel.
112  */
113 struct  cpu_start_args cpu_start_args = { 0, -1, -1, 0, 0, 0 };
114 struct  ipi_cache_args ipi_cache_args;
115 struct  ipi_rd_args ipi_rd_args;
116 struct  ipi_tlb_args ipi_tlb_args;
117 struct  pcb stoppcbs[MAXCPU];
118
119 struct  mtx ipi_mtx;
120
121 cpu_ipi_selected_t *cpu_ipi_selected;
122 cpu_ipi_single_t *cpu_ipi_single;
123
124 static u_int cpuid_to_mid[MAXCPU];
125 static u_int cpuids = 1;
126 static volatile cpuset_t shutdown_cpus;
127 static char ipi_pbuf[CPUSETBUFSIZ];
128 static vm_offset_t mp_tramp;
129
130 static void ap_count(phandle_t node, u_int mid, u_int cpu_impl);
131 static void ap_start(phandle_t node, u_int mid, u_int cpu_impl);
132 static void cpu_mp_unleash(void *v);
133 static void foreach_ap(phandle_t node, void (*func)(phandle_t node,
134     u_int mid, u_int cpu_impl));
135 static void sun4u_startcpu(phandle_t cpu, void *func, u_long arg);
136
137 static cpu_ipi_selected_t cheetah_ipi_selected;
138 static cpu_ipi_single_t cheetah_ipi_single;
139 static cpu_ipi_selected_t jalapeno_ipi_selected;
140 static cpu_ipi_single_t jalapeno_ipi_single;
141 static cpu_ipi_selected_t spitfire_ipi_selected;
142 static cpu_ipi_single_t spitfire_ipi_single;
143
144 SYSINIT(cpu_mp_unleash, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
145
146 void
147 mp_init(void)
148 {
149         struct tte *tp;
150         int i;
151
152         mp_tramp = (vm_offset_t)OF_claim(NULL, PAGE_SIZE, PAGE_SIZE);
153         if (mp_tramp == (vm_offset_t)-1)
154                 panic("%s", __func__);
155         bcopy(mp_tramp_code, (void *)mp_tramp, mp_tramp_code_len);
156         *(vm_offset_t *)(mp_tramp + mp_tramp_tlb_slots) = kernel_tlb_slots;
157         *(vm_offset_t *)(mp_tramp + mp_tramp_func) = (vm_offset_t)mp_startup;
158         tp = (struct tte *)(mp_tramp + mp_tramp_code_len);
159         for (i = 0; i < kernel_tlb_slots; i++) {
160                 tp[i].tte_vpn = TV_VPN(kernel_tlbs[i].te_va, TS_4M);
161                 tp[i].tte_data = TD_V | TD_4M | TD_PA(kernel_tlbs[i].te_pa) |
162                     TD_L | TD_CP | TD_CV | TD_P | TD_W;
163         }
164         for (i = 0; i < PAGE_SIZE; i += sizeof(vm_offset_t))
165                 flush(mp_tramp + i);
166 }
167
168 static void
169 foreach_ap(phandle_t node, void (*func)(phandle_t node, u_int mid,
170     u_int cpu_impl))
171 {
172         static char type[sizeof("cpu")];
173         phandle_t child;
174         uint32_t cpu_impl, portid;
175
176         /* There's no need to traverse the whole OFW tree twice. */
177         if (mp_maxid > 0 && cpuids > mp_maxid)
178                 return;
179
180         for (; node != 0; node = OF_peer(node)) {
181                 child = OF_child(node);
182                 if (child > 0)
183                         foreach_ap(child, func);
184                 else {
185                         if (OF_getprop(node, "device_type", type,
186                             sizeof(type)) <= 0)
187                                 continue;
188                         if (strcmp(type, "cpu") != 0)
189                                 continue;
190                         if (OF_getprop(node, "implementation#", &cpu_impl,
191                             sizeof(cpu_impl)) <= 0)
192                                 panic("%s: couldn't determine CPU "
193                                     "implementation", __func__);
194                         if (OF_getprop(node, cpu_portid_prop(cpu_impl),
195                             &portid, sizeof(portid)) <= 0)
196                                 panic("%s: couldn't determine CPU port ID",
197                                     __func__);
198                         if (portid == PCPU_GET(mid))
199                                 continue;
200                         (*func)(node, portid, cpu_impl);
201                 }
202         }
203 }
204
205 /*
206  * Probe for other CPUs.
207  */
208 void
209 cpu_mp_setmaxid(void)
210 {
211
212         CPU_SETOF(curcpu, &all_cpus);
213         mp_ncpus = 1;
214
215         foreach_ap(OF_child(OF_peer(0)), ap_count);
216         mp_ncpus = MIN(mp_ncpus, MAXCPU);
217         mp_maxid = mp_ncpus - 1;
218 }
219
220 static void
221 ap_count(phandle_t node __unused, u_int mid __unused, u_int cpu_impl __unused)
222 {
223
224         mp_ncpus++;
225 }
226
227 int
228 cpu_mp_probe(void)
229 {
230
231         return (mp_maxid > 0);
232 }
233
234 struct cpu_group *
235 cpu_topo(void)
236 {
237
238         return (smp_topo_none());
239 }
240
241 static void
242 sun4u_startcpu(phandle_t cpu, void *func, u_long arg)
243 {
244         static struct {
245                 cell_t  name;
246                 cell_t  nargs;
247                 cell_t  nreturns;
248                 cell_t  cpu;
249                 cell_t  func;
250                 cell_t  arg;
251         } args = {
252                 (cell_t)SUNW_STARTCPU,
253                 3,
254         };
255
256         args.cpu = cpu;
257         args.func = (cell_t)func;
258         args.arg = (cell_t)arg;
259         ofw_entry(&args);
260 }
261
262 /*
263  * Fire up any non-boot processors.
264  */
265 void
266 cpu_mp_start(void)
267 {
268         u_int cpu_impl, isjbus;
269
270         mtx_init(&ipi_mtx, "ipi", NULL, MTX_SPIN);
271
272         isjbus = 0;
273         cpu_impl = PCPU_GET(impl);
274         if (cpu_impl == CPU_IMPL_ULTRASPARCIIIi ||
275             cpu_impl == CPU_IMPL_ULTRASPARCIIIip) {
276                 isjbus = 1;
277                 cpu_ipi_selected = jalapeno_ipi_selected;
278                 cpu_ipi_single = jalapeno_ipi_single;
279         } else if (cpu_impl == CPU_IMPL_SPARC64V ||
280             cpu_impl >= CPU_IMPL_ULTRASPARCIII) {
281                 cpu_ipi_selected = cheetah_ipi_selected;
282                 cpu_ipi_single = cheetah_ipi_single;
283         } else {
284                 cpu_ipi_selected = spitfire_ipi_selected;
285                 cpu_ipi_single = spitfire_ipi_single;
286         }
287
288         intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL);
289         intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action,
290             -1, NULL, NULL);
291         intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL);
292         intr_setup(PIL_PREEMPT, cpu_ipi_preempt, -1, NULL, NULL);
293         intr_setup(PIL_HARDCLOCK, cpu_ipi_hardclock, -1, NULL, NULL);
294
295         cpuid_to_mid[curcpu] = PCPU_GET(mid);
296
297         foreach_ap(OF_child(OF_peer(0)), ap_start);
298         KASSERT(!isjbus || mp_ncpus <= IDR_JALAPENO_MAX_BN_PAIRS,
299             ("%s: can only IPI a maximum of %d JBus-CPUs",
300             __func__, IDR_JALAPENO_MAX_BN_PAIRS));
301 }
302
303 static void
304 ap_start(phandle_t node, u_int mid, u_int cpu_impl)
305 {
306         volatile struct cpu_start_args *csa;
307         struct pcpu *pc;
308         register_t s;
309         vm_offset_t va;
310         u_int cpuid;
311         uint32_t clock;
312
313         if (cpuids > mp_maxid)
314                 return;
315
316         if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) <= 0)
317                 panic("%s: couldn't determine CPU frequency", __func__);
318         if (clock != PCPU_GET(clock))
319                 tick_et_use_stick = 1;
320
321         csa = &cpu_start_args;
322         csa->csa_state = 0;
323         sun4u_startcpu(node, (void *)mp_tramp, 0);
324         s = intr_disable();
325         while (csa->csa_state != CPU_TICKSYNC)
326                 ;
327         membar(StoreLoad);
328         csa->csa_tick = rd(tick);
329         if (cpu_impl == CPU_IMPL_SPARC64V ||
330             cpu_impl >= CPU_IMPL_ULTRASPARCIII) {
331                 while (csa->csa_state != CPU_STICKSYNC)
332                         ;
333                 membar(StoreLoad);
334                 csa->csa_stick = rdstick();
335         }
336         while (csa->csa_state != CPU_INIT)
337                 ;
338         csa->csa_tick = csa->csa_stick = 0;
339         intr_restore(s);
340
341         cpuid = cpuids++;
342         cpuid_to_mid[cpuid] = mid;
343         cpu_identify(csa->csa_ver, clock, cpuid);
344
345         va = kmem_malloc(PCPU_PAGES * PAGE_SIZE, M_WAITOK | M_ZERO);
346         pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1;
347         pcpu_init(pc, cpuid, sizeof(*pc));
348         dpcpu_init((void *)kmem_malloc(DPCPU_SIZE, M_WAITOK | M_ZERO), cpuid);
349         pc->pc_addr = va;
350         pc->pc_clock = clock;
351         pc->pc_impl = cpu_impl;
352         pc->pc_mid = mid;
353         pc->pc_node = node;
354
355         cache_init(pc);
356
357         CPU_SET(cpuid, &all_cpus);
358         intr_add_cpu(cpuid);
359 }
360
361 void
362 cpu_mp_announce(void)
363 {
364
365 }
366
367 static void
368 cpu_mp_unleash(void *v __unused)
369 {
370         volatile struct cpu_start_args *csa;
371         struct pcpu *pc;
372         register_t s;
373         vm_offset_t va;
374         vm_paddr_t pa;
375         u_int ctx_inc;
376         u_int ctx_min;
377         int i;
378
379         ctx_min = TLB_CTX_USER_MIN;
380         ctx_inc = (TLB_CTX_USER_MAX - 1) / mp_ncpus;
381         csa = &cpu_start_args;
382         csa->csa_count = mp_ncpus;
383         STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
384                 pc->pc_tlb_ctx = ctx_min;
385                 pc->pc_tlb_ctx_min = ctx_min;
386                 pc->pc_tlb_ctx_max = ctx_min + ctx_inc;
387                 ctx_min += ctx_inc;
388
389                 if (pc->pc_cpuid == curcpu)
390                         continue;
391                 KASSERT(pc->pc_idlethread != NULL,
392                     ("%s: idlethread", __func__));
393                 pc->pc_curthread = pc->pc_idlethread;
394                 pc->pc_curpcb = pc->pc_curthread->td_pcb;
395                 for (i = 0; i < PCPU_PAGES; i++) {
396                         va = pc->pc_addr + i * PAGE_SIZE;
397                         pa = pmap_kextract(va);
398                         if (pa == 0)
399                                 panic("%s: pmap_kextract", __func__);
400                         csa->csa_ttes[i].tte_vpn = TV_VPN(va, TS_8K);
401                         csa->csa_ttes[i].tte_data = TD_V | TD_8K | TD_PA(pa) |
402                             TD_L | TD_CP | TD_CV | TD_P | TD_W;
403                 }
404                 csa->csa_state = 0;
405                 csa->csa_pcpu = pc->pc_addr;
406                 csa->csa_mid = pc->pc_mid;
407                 s = intr_disable();
408                 while (csa->csa_state != CPU_BOOTSTRAP)
409                         ;
410                 intr_restore(s);
411         }
412
413         membar(StoreLoad);
414         csa->csa_count = 0;
415 }
416
417 void
418 cpu_mp_bootstrap(struct pcpu *pc)
419 {
420         volatile struct cpu_start_args *csa;
421
422         csa = &cpu_start_args;
423
424         /* Do CPU-specific initialization. */
425         if (pc->pc_impl >= CPU_IMPL_ULTRASPARCIII)
426                 cheetah_init(pc->pc_impl);
427         else if (pc->pc_impl == CPU_IMPL_SPARC64V)
428                 zeus_init(pc->pc_impl);
429
430         /*
431          * Enable the caches.  Note that his may include applying workarounds.
432          */
433         cache_enable(pc->pc_impl);
434
435         /*
436          * Clear (S)TICK timer(s) (including NPT) and ensure they are stopped.
437          */
438         tick_clear(pc->pc_impl);
439         tick_stop(pc->pc_impl);
440
441         /* Set the kernel context. */
442         pmap_set_kctx();
443
444         /* Lock the kernel TSB in the TLB if necessary. */
445         if (tsb_kernel_ldd_phys == 0)
446                 pmap_map_tsb();
447
448         /*
449          * Flush all non-locked TLB entries possibly left over by the
450          * firmware.
451          */
452         tlb_flush_nonlocked();
453
454         /*
455          * Enable interrupts.
456          * Note that the PIL we be lowered indirectly via sched_throw(NULL)
457          * when fake spinlock held by the idle thread eventually is released.
458          */
459         wrpr(pstate, 0, PSTATE_KERNEL);
460
461         smp_cpus++;
462         KASSERT(curthread != NULL, ("%s: curthread", __func__));
463         printf("SMP: AP CPU #%d Launched!\n", curcpu);
464
465         csa->csa_count--;
466         membar(StoreLoad);
467         csa->csa_state = CPU_BOOTSTRAP;
468         while (csa->csa_count != 0)
469                 ;
470
471         if (smp_cpus == mp_ncpus)
472                 atomic_store_rel_int(&smp_started, 1);
473
474         /* Start per-CPU event timers. */
475         cpu_initclocks_ap();
476
477         /* Ok, now enter the scheduler. */
478         sched_throw(NULL);
479 }
480
481 void
482 cpu_mp_shutdown(void)
483 {
484         cpuset_t cpus;
485         int i;
486
487         critical_enter();
488         shutdown_cpus = all_cpus;
489         CPU_CLR(PCPU_GET(cpuid), &shutdown_cpus);
490         cpus = shutdown_cpus;
491
492         /* XXX: Stop all the CPUs which aren't already. */
493         if (CPU_CMP(&stopped_cpus, &cpus)) {
494
495                 /* cpus is just a flat "on" mask without curcpu. */
496                 CPU_ANDNOT(&cpus, &stopped_cpus);
497                 stop_cpus(cpus);
498         }
499         i = 0;
500         while (!CPU_EMPTY(&shutdown_cpus)) {
501                 if (i++ > 100000) {
502                         printf("timeout shutting down CPUs.\n");
503                         break;
504                 }
505         }
506         critical_exit();
507 }
508
509 static void
510 cpu_ipi_ast(struct trapframe *tf __unused)
511 {
512
513 }
514
515 static void
516 cpu_ipi_stop(struct trapframe *tf __unused)
517 {
518         u_int cpuid;
519
520         CTR2(KTR_SMP, "%s: stopped %d", __func__, curcpu);
521         sched_pin();
522         savectx(&stoppcbs[curcpu]);
523         cpuid = PCPU_GET(cpuid);
524         CPU_SET_ATOMIC(cpuid, &stopped_cpus);
525         while (!CPU_ISSET(cpuid, &started_cpus)) {
526                 if (CPU_ISSET(cpuid, &shutdown_cpus)) {
527                         CPU_CLR_ATOMIC(cpuid, &shutdown_cpus);
528                         (void)intr_disable();
529                         for (;;)
530                                 ;
531                 }
532         }
533         CPU_CLR_ATOMIC(cpuid, &started_cpus);
534         CPU_CLR_ATOMIC(cpuid, &stopped_cpus);
535         sched_unpin();
536         CTR2(KTR_SMP, "%s: restarted %d", __func__, curcpu);
537 }
538
539 static void
540 cpu_ipi_preempt(struct trapframe *tf __unused)
541 {
542
543         sched_preempt(curthread);
544 }
545
546 static void
547 cpu_ipi_hardclock(struct trapframe *tf)
548 {
549         struct trapframe *oldframe;
550         struct thread *td;
551
552         critical_enter();
553         td = curthread;
554         td->td_intr_nesting_level++;
555         oldframe = td->td_intr_frame;
556         td->td_intr_frame = tf;
557         hardclockintr();
558         td->td_intr_frame = oldframe;
559         td->td_intr_nesting_level--;
560         critical_exit();
561 }
562
563 static void
564 spitfire_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
565 {
566         u_int cpu;
567
568         while ((cpu = CPU_FFS(&cpus)) != 0) {
569                 cpu--;
570                 CPU_CLR(cpu, &cpus);
571                 spitfire_ipi_single(cpu, d0, d1, d2);
572         }
573 }
574
575 static void
576 spitfire_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
577 {
578         register_t s;
579         u_long ids;
580         u_int mid;
581         int i;
582
583         mtx_assert(&ipi_mtx, MA_OWNED);
584         KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__));
585         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_BUSY) == 0,
586             ("%s: outstanding dispatch", __func__));
587
588         mid = cpuid_to_mid[cpu];
589         for (i = 0; i < IPI_RETRIES; i++) {
590                 s = intr_disable();
591                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
592                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
593                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
594                 membar(Sync);
595                 stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT),
596                     ASI_SDB_INTR_W, 0);
597                 /*
598                  * Workaround for SpitFire erratum #54; do a dummy read
599                  * from a SDB internal register before the MEMBAR #Sync
600                  * for the write to ASI_SDB_INTR_W (requiring another
601                  * MEMBAR #Sync in order to make sure the write has
602                  * occurred before the load).
603                  */
604                 membar(Sync);
605                 (void)ldxa(AA_SDB_CNTL_HIGH, ASI_SDB_CONTROL_R);
606                 membar(Sync);
607                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
608                     IDR_BUSY) != 0)
609                         ;
610                 intr_restore(s);
611                 if ((ids & (IDR_BUSY | IDR_NACK)) == 0)
612                         return;
613         }
614         if (kdb_active != 0 || panicstr != NULL)
615                 printf("%s: couldn't send IPI to module 0x%u\n",
616                     __func__, mid);
617         else
618                 panic("%s: couldn't send IPI to module 0x%u",
619                     __func__, mid);
620 }
621
622 static void
623 cheetah_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
624 {
625         register_t s;
626         u_long ids;
627         u_int mid;
628         int i;
629
630         mtx_assert(&ipi_mtx, MA_OWNED);
631         KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__));
632         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
633             IDR_CHEETAH_ALL_BUSY) == 0,
634             ("%s: outstanding dispatch", __func__));
635
636         mid = cpuid_to_mid[cpu];
637         for (i = 0; i < IPI_RETRIES; i++) {
638                 s = intr_disable();
639                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
640                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
641                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
642                 membar(Sync);
643                 stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT),
644                     ASI_SDB_INTR_W, 0);
645                 membar(Sync);
646                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
647                     IDR_BUSY) != 0)
648                         ;
649                 intr_restore(s);
650                 if ((ids & (IDR_BUSY | IDR_NACK)) == 0)
651                         return;
652         }
653         if (kdb_active != 0 || panicstr != NULL)
654                 printf("%s: couldn't send IPI to module 0x%u\n",
655                     __func__, mid);
656         else
657                 panic("%s: couldn't send IPI to module 0x%u",
658                     __func__, mid);
659 }
660
661 static void
662 cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
663 {
664         register_t s;
665         u_long ids;
666         u_int bnp;
667         u_int cpu;
668         int i;
669
670         mtx_assert(&ipi_mtx, MA_OWNED);
671         KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__));
672         KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself",
673             __func__));
674         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
675             IDR_CHEETAH_ALL_BUSY) == 0,
676             ("%s: outstanding dispatch", __func__));
677
678         ids = 0;
679         for (i = 0; i < IPI_RETRIES * smp_cpus; i++) {
680                 s = intr_disable();
681                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
682                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
683                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
684                 membar(Sync);
685                 bnp = 0;
686                 for (cpu = 0; cpu < smp_cpus; cpu++) {
687                         if (CPU_ISSET(cpu, &cpus)) {
688                                 stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] <<
689                                     IDC_ITID_SHIFT) | bnp << IDC_BN_SHIFT,
690                                     ASI_SDB_INTR_W, 0);
691                                 membar(Sync);
692                                 bnp++;
693                                 if (bnp == IDR_CHEETAH_MAX_BN_PAIRS)
694                                         break;
695                         }
696                 }
697                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
698                     IDR_CHEETAH_ALL_BUSY) != 0)
699                         ;
700                 intr_restore(s);
701                 bnp = 0;
702                 for (cpu = 0; cpu < smp_cpus; cpu++) {
703                         if (CPU_ISSET(cpu, &cpus)) {
704                                 if ((ids & (IDR_NACK << (2 * bnp))) == 0)
705                                         CPU_CLR(cpu, &cpus);
706                                 bnp++;
707                         }
708                 }
709                 if (CPU_EMPTY(&cpus))
710                         return;
711         }
712         if (kdb_active != 0 || panicstr != NULL)
713                 printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n",
714                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
715         else
716                 panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)",
717                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
718 }
719
720 static void
721 jalapeno_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
722 {
723         register_t s;
724         u_long ids;
725         u_int busy, busynack, mid;
726         int i;
727
728         mtx_assert(&ipi_mtx, MA_OWNED);
729         KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__));
730         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
731             IDR_CHEETAH_ALL_BUSY) == 0,
732             ("%s: outstanding dispatch", __func__));
733
734         mid = cpuid_to_mid[cpu];
735         busy = IDR_BUSY << (2 * mid);
736         busynack = (IDR_BUSY | IDR_NACK) << (2 * mid);
737         for (i = 0; i < IPI_RETRIES; i++) {
738                 s = intr_disable();
739                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
740                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
741                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
742                 membar(Sync);
743                 stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT),
744                     ASI_SDB_INTR_W, 0);
745                 membar(Sync);
746                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
747                     busy) != 0)
748                         ;
749                 intr_restore(s);
750                 if ((ids & busynack) == 0)
751                         return;
752         }
753         if (kdb_active != 0 || panicstr != NULL)
754                 printf("%s: couldn't send IPI to module 0x%u\n",
755                     __func__, mid);
756         else
757                 panic("%s: couldn't send IPI to module 0x%u",
758                     __func__, mid);
759 }
760
761 static void
762 jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
763 {
764         register_t s;
765         u_long ids;
766         u_int cpu;
767         int i;
768
769         mtx_assert(&ipi_mtx, MA_OWNED);
770         KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__));
771         KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself",
772             __func__));
773         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
774             IDR_CHEETAH_ALL_BUSY) == 0,
775             ("%s: outstanding dispatch", __func__));
776
777         ids = 0;
778         for (i = 0; i < IPI_RETRIES * smp_cpus; i++) {
779                 s = intr_disable();
780                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
781                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
782                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
783                 membar(Sync);
784                 for (cpu = 0; cpu < smp_cpus; cpu++) {
785                         if (CPU_ISSET(cpu, &cpus)) {
786                                 stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] <<
787                                     IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0);
788                                 membar(Sync);
789                         }
790                 }
791                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
792                     IDR_CHEETAH_ALL_BUSY) != 0)
793                         ;
794                 intr_restore(s);
795                 if ((ids &
796                     (IDR_CHEETAH_ALL_BUSY | IDR_CHEETAH_ALL_NACK)) == 0)
797                         return;
798                 for (cpu = 0; cpu < smp_cpus; cpu++)
799                         if (CPU_ISSET(cpu, &cpus))
800                                 if ((ids & (IDR_NACK <<
801                                     (2 * cpuid_to_mid[cpu]))) == 0)
802                                         CPU_CLR(cpu, &cpus);
803         }
804         if (kdb_active != 0 || panicstr != NULL)
805                 printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n",
806                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
807         else
808                 panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)",
809                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
810 }