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