Annotation of src/sys/arch/alpha/alpha/ipifuncs.c, Revision 1.25
1.25 ! thorpej 1: /* $NetBSD: ipifuncs.c,v 1.24 2001/01/19 18:51:17 thorpej Exp $ */
1.1 thorpej 2:
3: /*-
1.14 thorpej 4: * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
1.1 thorpej 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9: * NASA Ames Research Center.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
41:
1.25 ! thorpej 42: __KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.24 2001/01/19 18:51:17 thorpej Exp $");
1.1 thorpej 43:
44: /*
45: * Interprocessor interrupt handlers.
46: */
47:
48: #include <sys/param.h>
49: #include <sys/device.h>
50: #include <sys/systm.h>
1.23 thorpej 51: #include <sys/reboot.h>
1.1 thorpej 52:
1.13 mrg 53: #include <uvm/uvm_extern.h>
1.5 thorpej 54:
1.9 thorpej 55: #include <machine/atomic.h>
1.1 thorpej 56: #include <machine/alpha_cpu.h>
1.15 thorpej 57: #include <machine/alpha.h>
1.1 thorpej 58: #include <machine/cpu.h>
1.12 thorpej 59: #include <machine/cpuvar.h>
1.1 thorpej 60: #include <machine/intr.h>
61: #include <machine/rpb.h>
1.23 thorpej 62: #include <machine/prom.h>
1.1 thorpej 63:
1.23 thorpej 64: typedef void (*ipifunc_t)(struct cpu_info *, struct trapframe *);
1.22 thorpej 65:
1.23 thorpej 66: void alpha_ipi_halt(struct cpu_info *, struct trapframe *);
67: void alpha_ipi_tbia(struct cpu_info *, struct trapframe *);
68: void alpha_ipi_tbiap(struct cpu_info *, struct trapframe *);
69: void alpha_ipi_imb(struct cpu_info *, struct trapframe *);
70: void alpha_ipi_ast(struct cpu_info *, struct trapframe *);
71: void alpha_ipi_synch_fpu(struct cpu_info *, struct trapframe *);
72: void alpha_ipi_discard_fpu(struct cpu_info *, struct trapframe *);
73: void alpha_ipi_pause(struct cpu_info *, struct trapframe *);
1.1 thorpej 74:
1.5 thorpej 75: /*
76: * NOTE: This table must be kept in order with the bit definitions
77: * in <machine/intr.h>.
78: */
1.1 thorpej 79: ipifunc_t ipifuncs[ALPHA_NIPIS] = {
80: alpha_ipi_halt,
81: alpha_ipi_tbia,
82: alpha_ipi_tbiap,
1.5 thorpej 83: pmap_do_tlb_shootdown,
1.8 thorpej 84: alpha_ipi_imb,
1.7 thorpej 85: alpha_ipi_ast,
1.15 thorpej 86: alpha_ipi_synch_fpu,
87: alpha_ipi_discard_fpu,
1.16 thorpej 88: alpha_ipi_pause,
1.1 thorpej 89: };
1.20 thorpej 90:
91: const char *ipinames[ALPHA_NIPIS] = {
92: "halt ipi",
93: "tbia ipi",
94: "tbiap ipi",
95: "shootdown ipi",
96: "imb ipi",
97: "ast ipi",
98: "synch fpu ipi",
99: "discard fpu ipi",
100: "pause ipi",
101: };
102:
103: /*
104: * Initialize IPI state for a CPU.
105: *
106: * Note: the cpu_info softc pointer must be valid.
107: */
108: void
109: alpha_ipi_init(struct cpu_info *ci)
110: {
111: struct cpu_softc *sc = ci->ci_softc;
112: int i;
113:
114: evcnt_attach_dynamic(&sc->sc_evcnt_ipi, EVCNT_TYPE_INTR,
115: NULL, sc->sc_dev.dv_xname, "ipi");
116:
117: for (i = 0; i < ALPHA_NIPIS; i++) {
118: evcnt_attach_dynamic(&sc->sc_evcnt_which_ipi[i],
119: EVCNT_TYPE_INTR, NULL, sc->sc_dev.dv_xname,
120: ipinames[i]);
1.22 thorpej 121: }
122: }
123:
124: /*
125: * Process IPIs for a CPU.
126: */
127: void
1.23 thorpej 128: alpha_ipi_process(struct cpu_info *ci, struct trapframe *framep)
1.22 thorpej 129: {
130: struct cpu_softc *sc = ci->ci_softc;
131: u_long pending_ipis, bit;
132:
133: #ifdef DIAGNOSTIC
134: if (sc == NULL) {
135: /* XXX panic? */
136: printf("WARNING: no softc for ID %lu\n", ci->ci_cpuid);
137: return;
138: }
139: #endif
140:
141: pending_ipis = atomic_loadlatch_ulong(&ci->ci_ipis, 0);
142:
143: /*
144: * For various reasons, it is possible to have spurious calls
145: * to this routine, so just bail out now if there are none
146: * pending.
147: */
148: if (pending_ipis == 0)
149: return;
150:
151: sc->sc_evcnt_ipi.ev_count++;
152:
153: for (bit = 0; bit < ALPHA_NIPIS; bit++) {
154: if (pending_ipis & (1UL << bit)) {
155: sc->sc_evcnt_which_ipi[bit].ev_count++;
1.23 thorpej 156: (*ipifuncs[bit])(ci, framep);
1.22 thorpej 157: }
1.20 thorpej 158: }
159: }
1.1 thorpej 160:
161: /*
162: * Send an interprocessor interrupt.
163: */
164: void
1.14 thorpej 165: alpha_send_ipi(u_long cpu_id, u_long ipimask)
1.1 thorpej 166: {
167:
168: #ifdef DIAGNOSTIC
1.4 thorpej 169: if (cpu_id >= hwrpb->rpb_pcs_cnt ||
1.12 thorpej 170: cpu_info[cpu_id].ci_softc == NULL)
1.19 thorpej 171: panic("alpha_send_ipi: bogus cpu_id");
172: if (((1UL << cpu_id) & cpus_running) == 0)
173: panic("alpha_send_ipi: CPU %ld not running", cpu_id);
1.1 thorpej 174: #endif
175:
1.10 thorpej 176: atomic_setbits_ulong(&cpu_info[cpu_id].ci_ipis, ipimask);
1.1 thorpej 177: alpha_pal_wripir(cpu_id);
178: }
179:
1.5 thorpej 180: /*
181: * Broadcast an IPI to all but ourselves.
182: */
183: void
1.14 thorpej 184: alpha_broadcast_ipi(u_long ipimask)
185: {
186: u_long i, cpu_id = cpu_number();
1.19 thorpej 187: u_long cpumask;
188:
1.21 sommerfe 189: cpumask = cpus_running & ~(1UL << cpu_id);
1.14 thorpej 190:
191: for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
1.19 thorpej 192: if ((cpumask & (1UL << i)) == 0)
1.14 thorpej 193: continue;
194: alpha_send_ipi(i, ipimask);
195: }
196: }
197:
198: /*
199: * Send an IPI to all in the list but ourselves.
200: */
201: void
202: alpha_multicast_ipi(u_long cpumask, u_long ipimask)
1.5 thorpej 203: {
204: u_long i;
205:
1.19 thorpej 206: cpumask &= cpus_running;
1.14 thorpej 207: cpumask &= ~(1UL << cpu_number());
208: if (cpumask == 0)
209: return;
210:
1.5 thorpej 211: for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
1.19 thorpej 212: if ((cpumask & (1UL << i)) == 0)
1.5 thorpej 213: continue;
214: alpha_send_ipi(i, ipimask);
215: }
216: }
217:
1.1 thorpej 218: void
1.23 thorpej 219: alpha_ipi_halt(struct cpu_info *ci, struct trapframe *framep)
1.1 thorpej 220: {
1.23 thorpej 221: u_long cpu_id = ci->ci_cpuid;
222: u_long wait_mask = (1UL << cpu_id);
1.2 thorpej 223:
224: /* Disable interrupts. */
225: (void) splhigh();
226:
1.23 thorpej 227: if (cpu_id != hwrpb->rpb_primary_cpu_id) {
228: /*
229: * If we're not the primary, we just halt now.
230: */
231: cpu_halt();
232: }
233:
234: /*
235: * We're the primary. We need to wait for all the other
236: * secondary CPUs to halt, then we can drop back to the
237: * console.
238: */
239: printf("%s: waiting for secondary CPUs to halt...\n",
240: ci->ci_softc->sc_dev.dv_xname);
241: alpha_mb();
242: for (;;) {
243: alpha_mb();
244: if (cpus_running == wait_mask)
245: break;
246: delay(1000);
247: }
248:
249: prom_halt(boothowto & RB_HALT);
1.2 thorpej 250: /* NOTREACHED */
1.1 thorpej 251: }
252:
253: void
1.23 thorpej 254: alpha_ipi_tbia(struct cpu_info *ci, struct trapframe *framep)
1.1 thorpej 255: {
256:
1.5 thorpej 257: /* If we're doing a TBIA, we don't need to do a TBIAP or a SHOOTDOWN. */
1.23 thorpej 258: atomic_clearbits_ulong(&ci->ci_ipis,
1.5 thorpej 259: ALPHA_IPI_TBIAP|ALPHA_IPI_SHOOTDOWN);
1.17 thorpej 260:
1.23 thorpej 261: pmap_tlb_shootdown_q_drain(ci->ci_cpuid, TRUE);
1.1 thorpej 262:
263: ALPHA_TBIA();
264: }
265:
266: void
1.23 thorpej 267: alpha_ipi_tbiap(struct cpu_info *ci, struct trapframe *framep)
1.1 thorpej 268: {
1.5 thorpej 269:
270: /* Can't clear SHOOTDOWN here; might have PG_ASM mappings. */
1.17 thorpej 271:
1.23 thorpej 272: pmap_tlb_shootdown_q_drain(ci->ci_cpuid, FALSE);
1.1 thorpej 273:
274: ALPHA_TBIAP();
1.8 thorpej 275: }
276:
277: void
1.23 thorpej 278: alpha_ipi_imb(struct cpu_info *ci, struct trapframe *framep)
1.8 thorpej 279: {
280:
281: alpha_pal_imb();
1.7 thorpej 282: }
283:
284: void
1.23 thorpej 285: alpha_ipi_ast(struct cpu_info *ci, struct trapframe *framep)
1.7 thorpej 286: {
287:
1.24 thorpej 288: if (ci->ci_curproc != NULL)
289: aston(ci->ci_curproc);
1.15 thorpej 290: }
291:
292: void
1.23 thorpej 293: alpha_ipi_synch_fpu(struct cpu_info *ci, struct trapframe *framep)
1.15 thorpej 294: {
295:
1.25 ! thorpej 296: if (ci->ci_flags & CPUF_FPUSAVE)
! 297: return;
1.23 thorpej 298: fpusave_cpu(ci, 1);
1.15 thorpej 299: }
300:
301: void
1.23 thorpej 302: alpha_ipi_discard_fpu(struct cpu_info *ci, struct trapframe *framep)
1.15 thorpej 303: {
304:
1.25 ! thorpej 305: if (ci->ci_flags & CPUF_FPUSAVE)
! 306: return;
1.23 thorpej 307: fpusave_cpu(ci, 0);
1.16 thorpej 308: }
309:
310: void
1.23 thorpej 311: alpha_ipi_pause(struct cpu_info *ci, struct trapframe *framep)
1.16 thorpej 312: {
1.23 thorpej 313: u_long cpumask = (1UL << ci->ci_cpuid);
1.16 thorpej 314: int s;
315:
1.23 thorpej 316: s = splhigh();
1.16 thorpej 317:
1.23 thorpej 318: /* Point debuggers at our trapframe for register state. */
319: ci->ci_db_regs = framep;
1.16 thorpej 320:
1.23 thorpej 321: atomic_setbits_ulong(&ci->ci_flags, CPUF_PAUSED);
1.16 thorpej 322:
323: /* Spin with interrupts disabled until we're resumed. */
1.19 thorpej 324: do {
325: alpha_mb();
326: } while (cpus_paused & cpumask);
1.16 thorpej 327:
1.23 thorpej 328: atomic_clearbits_ulong(&ci->ci_flags, CPUF_PAUSED);
329:
330: ci->ci_db_regs = NULL;
1.16 thorpej 331:
332: splx(s);
1.23 thorpej 333:
334: /* Do an IMB on the way out, in case the kernel text was changed. */
335: alpha_pal_imb();
1.1 thorpej 336: }
CVSweb <webmaster@jp.NetBSD.org>