]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sparc64/sparc64/mp_machdep.c
Upgrade Unbound to 1.6.6. More to follow.
[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(kernel_arena, PCPU_PAGES * PAGE_SIZE,
346             M_WAITOK | M_ZERO);
347         pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1;
348         pcpu_init(pc, cpuid, sizeof(*pc));
349         dpcpu_init((void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
350             M_WAITOK | M_ZERO), cpuid);
351         pc->pc_addr = va;
352         pc->pc_clock = clock;
353         pc->pc_impl = cpu_impl;
354         pc->pc_mid = mid;
355         pc->pc_node = node;
356
357         cache_init(pc);
358
359         CPU_SET(cpuid, &all_cpus);
360         intr_add_cpu(cpuid);
361 }
362
363 void
364 cpu_mp_announce(void)
365 {
366
367 }
368
369 static void
370 cpu_mp_unleash(void *v __unused)
371 {
372         volatile struct cpu_start_args *csa;
373         struct pcpu *pc;
374         register_t s;
375         vm_offset_t va;
376         vm_paddr_t pa;
377         u_int ctx_inc;
378         u_int ctx_min;
379         int i;
380
381         ctx_min = TLB_CTX_USER_MIN;
382         ctx_inc = (TLB_CTX_USER_MAX - 1) / mp_ncpus;
383         csa = &cpu_start_args;
384         csa->csa_count = mp_ncpus;
385         STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
386                 pc->pc_tlb_ctx = ctx_min;
387                 pc->pc_tlb_ctx_min = ctx_min;
388                 pc->pc_tlb_ctx_max = ctx_min + ctx_inc;
389                 ctx_min += ctx_inc;
390
391                 if (pc->pc_cpuid == curcpu)
392                         continue;
393                 KASSERT(pc->pc_idlethread != NULL,
394                     ("%s: idlethread", __func__));
395                 pc->pc_curthread = pc->pc_idlethread;
396                 pc->pc_curpcb = pc->pc_curthread->td_pcb;
397                 for (i = 0; i < PCPU_PAGES; i++) {
398                         va = pc->pc_addr + i * PAGE_SIZE;
399                         pa = pmap_kextract(va);
400                         if (pa == 0)
401                                 panic("%s: pmap_kextract", __func__);
402                         csa->csa_ttes[i].tte_vpn = TV_VPN(va, TS_8K);
403                         csa->csa_ttes[i].tte_data = TD_V | TD_8K | TD_PA(pa) |
404                             TD_L | TD_CP | TD_CV | TD_P | TD_W;
405                 }
406                 csa->csa_state = 0;
407                 csa->csa_pcpu = pc->pc_addr;
408                 csa->csa_mid = pc->pc_mid;
409                 s = intr_disable();
410                 while (csa->csa_state != CPU_BOOTSTRAP)
411                         ;
412                 intr_restore(s);
413         }
414
415         membar(StoreLoad);
416         csa->csa_count = 0;
417 }
418
419 void
420 cpu_mp_bootstrap(struct pcpu *pc)
421 {
422         volatile struct cpu_start_args *csa;
423
424         csa = &cpu_start_args;
425
426         /* Do CPU-specific initialization. */
427         if (pc->pc_impl >= CPU_IMPL_ULTRASPARCIII)
428                 cheetah_init(pc->pc_impl);
429         else if (pc->pc_impl == CPU_IMPL_SPARC64V)
430                 zeus_init(pc->pc_impl);
431
432         /*
433          * Enable the caches.  Note that his may include applying workarounds.
434          */
435         cache_enable(pc->pc_impl);
436
437         /*
438          * Clear (S)TICK timer(s) (including NPT) and ensure they are stopped.
439          */
440         tick_clear(pc->pc_impl);
441         tick_stop(pc->pc_impl);
442
443         /* Set the kernel context. */
444         pmap_set_kctx();
445
446         /* Lock the kernel TSB in the TLB if necessary. */
447         if (tsb_kernel_ldd_phys == 0)
448                 pmap_map_tsb();
449
450         /*
451          * Flush all non-locked TLB entries possibly left over by the
452          * firmware.
453          */
454         tlb_flush_nonlocked();
455
456         /*
457          * Enable interrupts.
458          * Note that the PIL we be lowered indirectly via sched_throw(NULL)
459          * when fake spinlock held by the idle thread eventually is released.
460          */
461         wrpr(pstate, 0, PSTATE_KERNEL);
462
463         smp_cpus++;
464         KASSERT(curthread != NULL, ("%s: curthread", __func__));
465         printf("SMP: AP CPU #%d Launched!\n", curcpu);
466
467         csa->csa_count--;
468         membar(StoreLoad);
469         csa->csa_state = CPU_BOOTSTRAP;
470         while (csa->csa_count != 0)
471                 ;
472
473         if (smp_cpus == mp_ncpus)
474                 atomic_store_rel_int(&smp_started, 1);
475
476         /* Start per-CPU event timers. */
477         cpu_initclocks_ap();
478
479         /* Ok, now enter the scheduler. */
480         sched_throw(NULL);
481 }
482
483 void
484 cpu_mp_shutdown(void)
485 {
486         cpuset_t cpus;
487         int i;
488
489         critical_enter();
490         shutdown_cpus = all_cpus;
491         CPU_CLR(PCPU_GET(cpuid), &shutdown_cpus);
492         cpus = shutdown_cpus;
493
494         /* XXX: Stop all the CPUs which aren't already. */
495         if (CPU_CMP(&stopped_cpus, &cpus)) {
496
497                 /* cpus is just a flat "on" mask without curcpu. */
498                 CPU_NAND(&cpus, &stopped_cpus);
499                 stop_cpus(cpus);
500         }
501         i = 0;
502         while (!CPU_EMPTY(&shutdown_cpus)) {
503                 if (i++ > 100000) {
504                         printf("timeout shutting down CPUs.\n");
505                         break;
506                 }
507         }
508         critical_exit();
509 }
510
511 static void
512 cpu_ipi_ast(struct trapframe *tf __unused)
513 {
514
515 }
516
517 static void
518 cpu_ipi_stop(struct trapframe *tf __unused)
519 {
520         u_int cpuid;
521
522         CTR2(KTR_SMP, "%s: stopped %d", __func__, curcpu);
523         sched_pin();
524         savectx(&stoppcbs[curcpu]);
525         cpuid = PCPU_GET(cpuid);
526         CPU_SET_ATOMIC(cpuid, &stopped_cpus);
527         while (!CPU_ISSET(cpuid, &started_cpus)) {
528                 if (CPU_ISSET(cpuid, &shutdown_cpus)) {
529                         CPU_CLR_ATOMIC(cpuid, &shutdown_cpus);
530                         (void)intr_disable();
531                         for (;;)
532                                 ;
533                 }
534         }
535         CPU_CLR_ATOMIC(cpuid, &started_cpus);
536         CPU_CLR_ATOMIC(cpuid, &stopped_cpus);
537         sched_unpin();
538         CTR2(KTR_SMP, "%s: restarted %d", __func__, curcpu);
539 }
540
541 static void
542 cpu_ipi_preempt(struct trapframe *tf __unused)
543 {
544
545         sched_preempt(curthread);
546 }
547
548 static void
549 cpu_ipi_hardclock(struct trapframe *tf)
550 {
551         struct trapframe *oldframe;
552         struct thread *td;
553
554         critical_enter();
555         td = curthread;
556         td->td_intr_nesting_level++;
557         oldframe = td->td_intr_frame;
558         td->td_intr_frame = tf;
559         hardclockintr();
560         td->td_intr_frame = oldframe;
561         td->td_intr_nesting_level--;
562         critical_exit();
563 }
564
565 static void
566 spitfire_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
567 {
568         u_int cpu;
569
570         while ((cpu = CPU_FFS(&cpus)) != 0) {
571                 cpu--;
572                 CPU_CLR(cpu, &cpus);
573                 spitfire_ipi_single(cpu, d0, d1, d2);
574         }
575 }
576
577 static void
578 spitfire_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
579 {
580         register_t s;
581         u_long ids;
582         u_int mid;
583         int i;
584
585         mtx_assert(&ipi_mtx, MA_OWNED);
586         KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__));
587         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_BUSY) == 0,
588             ("%s: outstanding dispatch", __func__));
589
590         mid = cpuid_to_mid[cpu];
591         for (i = 0; i < IPI_RETRIES; i++) {
592                 s = intr_disable();
593                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
594                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
595                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
596                 membar(Sync);
597                 stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT),
598                     ASI_SDB_INTR_W, 0);
599                 /*
600                  * Workaround for SpitFire erratum #54; do a dummy read
601                  * from a SDB internal register before the MEMBAR #Sync
602                  * for the write to ASI_SDB_INTR_W (requiring another
603                  * MEMBAR #Sync in order to make sure the write has
604                  * occurred before the load).
605                  */
606                 membar(Sync);
607                 (void)ldxa(AA_SDB_CNTL_HIGH, ASI_SDB_CONTROL_R);
608                 membar(Sync);
609                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
610                     IDR_BUSY) != 0)
611                         ;
612                 intr_restore(s);
613                 if ((ids & (IDR_BUSY | IDR_NACK)) == 0)
614                         return;
615         }
616         if (kdb_active != 0 || panicstr != NULL)
617                 printf("%s: couldn't send IPI to module 0x%u\n",
618                     __func__, mid);
619         else
620                 panic("%s: couldn't send IPI to module 0x%u",
621                     __func__, mid);
622 }
623
624 static void
625 cheetah_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
626 {
627         register_t s;
628         u_long ids;
629         u_int mid;
630         int i;
631
632         mtx_assert(&ipi_mtx, MA_OWNED);
633         KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__));
634         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
635             IDR_CHEETAH_ALL_BUSY) == 0,
636             ("%s: outstanding dispatch", __func__));
637
638         mid = cpuid_to_mid[cpu];
639         for (i = 0; i < IPI_RETRIES; i++) {
640                 s = intr_disable();
641                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
642                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
643                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
644                 membar(Sync);
645                 stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT),
646                     ASI_SDB_INTR_W, 0);
647                 membar(Sync);
648                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
649                     IDR_BUSY) != 0)
650                         ;
651                 intr_restore(s);
652                 if ((ids & (IDR_BUSY | IDR_NACK)) == 0)
653                         return;
654         }
655         if (kdb_active != 0 || panicstr != NULL)
656                 printf("%s: couldn't send IPI to module 0x%u\n",
657                     __func__, mid);
658         else
659                 panic("%s: couldn't send IPI to module 0x%u",
660                     __func__, mid);
661 }
662
663 static void
664 cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
665 {
666         register_t s;
667         u_long ids;
668         u_int bnp;
669         u_int cpu;
670         int i;
671
672         mtx_assert(&ipi_mtx, MA_OWNED);
673         KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__));
674         KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself",
675             __func__));
676         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
677             IDR_CHEETAH_ALL_BUSY) == 0,
678             ("%s: outstanding dispatch", __func__));
679
680         ids = 0;
681         for (i = 0; i < IPI_RETRIES * smp_cpus; i++) {
682                 s = intr_disable();
683                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
684                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
685                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
686                 membar(Sync);
687                 bnp = 0;
688                 for (cpu = 0; cpu < smp_cpus; cpu++) {
689                         if (CPU_ISSET(cpu, &cpus)) {
690                                 stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] <<
691                                     IDC_ITID_SHIFT) | bnp << IDC_BN_SHIFT,
692                                     ASI_SDB_INTR_W, 0);
693                                 membar(Sync);
694                                 bnp++;
695                                 if (bnp == IDR_CHEETAH_MAX_BN_PAIRS)
696                                         break;
697                         }
698                 }
699                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
700                     IDR_CHEETAH_ALL_BUSY) != 0)
701                         ;
702                 intr_restore(s);
703                 bnp = 0;
704                 for (cpu = 0; cpu < smp_cpus; cpu++) {
705                         if (CPU_ISSET(cpu, &cpus)) {
706                                 if ((ids & (IDR_NACK << (2 * bnp))) == 0)
707                                         CPU_CLR(cpu, &cpus);
708                                 bnp++;
709                         }
710                 }
711                 if (CPU_EMPTY(&cpus))
712                         return;
713         }
714         if (kdb_active != 0 || panicstr != NULL)
715                 printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n",
716                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
717         else
718                 panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)",
719                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
720 }
721
722 static void
723 jalapeno_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
724 {
725         register_t s;
726         u_long ids;
727         u_int busy, busynack, mid;
728         int i;
729
730         mtx_assert(&ipi_mtx, MA_OWNED);
731         KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__));
732         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
733             IDR_CHEETAH_ALL_BUSY) == 0,
734             ("%s: outstanding dispatch", __func__));
735
736         mid = cpuid_to_mid[cpu];
737         busy = IDR_BUSY << (2 * mid);
738         busynack = (IDR_BUSY | IDR_NACK) << (2 * mid);
739         for (i = 0; i < IPI_RETRIES; i++) {
740                 s = intr_disable();
741                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
742                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
743                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
744                 membar(Sync);
745                 stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT),
746                     ASI_SDB_INTR_W, 0);
747                 membar(Sync);
748                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
749                     busy) != 0)
750                         ;
751                 intr_restore(s);
752                 if ((ids & busynack) == 0)
753                         return;
754         }
755         if (kdb_active != 0 || panicstr != NULL)
756                 printf("%s: couldn't send IPI to module 0x%u\n",
757                     __func__, mid);
758         else
759                 panic("%s: couldn't send IPI to module 0x%u",
760                     __func__, mid);
761 }
762
763 static void
764 jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
765 {
766         register_t s;
767         u_long ids;
768         u_int cpu;
769         int i;
770
771         mtx_assert(&ipi_mtx, MA_OWNED);
772         KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__));
773         KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself",
774             __func__));
775         KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) &
776             IDR_CHEETAH_ALL_BUSY) == 0,
777             ("%s: outstanding dispatch", __func__));
778
779         ids = 0;
780         for (i = 0; i < IPI_RETRIES * smp_cpus; i++) {
781                 s = intr_disable();
782                 stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
783                 stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
784                 stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
785                 membar(Sync);
786                 for (cpu = 0; cpu < smp_cpus; cpu++) {
787                         if (CPU_ISSET(cpu, &cpus)) {
788                                 stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] <<
789                                     IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0);
790                                 membar(Sync);
791                         }
792                 }
793                 while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) &
794                     IDR_CHEETAH_ALL_BUSY) != 0)
795                         ;
796                 intr_restore(s);
797                 if ((ids &
798                     (IDR_CHEETAH_ALL_BUSY | IDR_CHEETAH_ALL_NACK)) == 0)
799                         return;
800                 for (cpu = 0; cpu < smp_cpus; cpu++)
801                         if (CPU_ISSET(cpu, &cpus))
802                                 if ((ids & (IDR_NACK <<
803                                     (2 * cpuid_to_mid[cpu]))) == 0)
804                                         CPU_CLR(cpu, &cpus);
805         }
806         if (kdb_active != 0 || panicstr != NULL)
807                 printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n",
808                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
809         else
810                 panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)",
811                     __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
812 }