Annotation of src/sys/arch/alpha/alpha/ipifuncs.c, Revision 1.33.18.1
1.33.18.1! yamt 1: /* $NetBSD: ipifuncs.c,v 1.33 2003/02/05 12:16:42 nakayama Exp $ */
1.1 thorpej 2:
3: /*-
1.26 thorpej 4: * Copyright (c) 1998, 1999, 2000, 2001 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.33.18.1! yamt 42: __KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.33 2003/02/05 12:16:42 nakayama Exp $");
1.1 thorpej 43:
44: /*
45: * Interprocessor interrupt handlers.
46: */
47:
48: #include <sys/param.h>
49: #include <sys/device.h>
1.31 chs 50: #include <sys/proc.h>
1.1 thorpej 51: #include <sys/systm.h>
1.23 thorpej 52: #include <sys/reboot.h>
1.1 thorpej 53:
1.13 mrg 54: #include <uvm/uvm_extern.h>
1.5 thorpej 55:
1.9 thorpej 56: #include <machine/atomic.h>
1.1 thorpej 57: #include <machine/alpha_cpu.h>
1.15 thorpej 58: #include <machine/alpha.h>
1.1 thorpej 59: #include <machine/cpu.h>
1.12 thorpej 60: #include <machine/cpuvar.h>
1.1 thorpej 61: #include <machine/intr.h>
62: #include <machine/rpb.h>
1.23 thorpej 63: #include <machine/prom.h>
1.1 thorpej 64:
1.23 thorpej 65: typedef void (*ipifunc_t)(struct cpu_info *, struct trapframe *);
1.22 thorpej 66:
1.23 thorpej 67: void alpha_ipi_halt(struct cpu_info *, struct trapframe *);
1.33 nakayama 68: void alpha_ipi_microset(struct cpu_info *, struct trapframe *);
1.23 thorpej 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,
1.33 nakayama 81: alpha_ipi_microset,
1.5 thorpej 82: pmap_do_tlb_shootdown,
1.8 thorpej 83: alpha_ipi_imb,
1.7 thorpej 84: alpha_ipi_ast,
1.15 thorpej 85: alpha_ipi_synch_fpu,
86: alpha_ipi_discard_fpu,
1.16 thorpej 87: alpha_ipi_pause,
1.26 thorpej 88: pmap_do_reactivate,
1.1 thorpej 89: };
1.20 thorpej 90:
91: const char *ipinames[ALPHA_NIPIS] = {
92: "halt ipi",
1.28 thorpej 93: "microset ipi",
1.20 thorpej 94: "shootdown ipi",
95: "imb ipi",
96: "ast ipi",
97: "synch fpu ipi",
98: "discard fpu ipi",
99: "pause ipi",
1.26 thorpej 100: "pmap reactivate ipi",
1.20 thorpej 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.27 thorpej 170: cpu_info[cpu_id] == 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.27 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: {
1.29 thorpej 186: struct cpu_info *ci;
187: CPU_INFO_ITERATOR cii;
188: u_long cpu_id = cpu_number();
1.19 thorpej 189: u_long cpumask;
190:
1.21 sommerfe 191: cpumask = cpus_running & ~(1UL << cpu_id);
1.14 thorpej 192:
1.29 thorpej 193: for (CPU_INFO_FOREACH(cii, ci)) {
194: if ((cpumask & (1UL << ci->ci_cpuid)) == 0)
1.14 thorpej 195: continue;
1.29 thorpej 196: alpha_send_ipi(ci->ci_cpuid, ipimask);
1.14 thorpej 197: }
198: }
199:
200: /*
201: * Send an IPI to all in the list but ourselves.
202: */
203: void
204: alpha_multicast_ipi(u_long cpumask, u_long ipimask)
1.5 thorpej 205: {
1.29 thorpej 206: struct cpu_info *ci;
207: CPU_INFO_ITERATOR cii;
1.5 thorpej 208:
1.19 thorpej 209: cpumask &= cpus_running;
1.14 thorpej 210: cpumask &= ~(1UL << cpu_number());
211: if (cpumask == 0)
212: return;
213:
1.29 thorpej 214: for (CPU_INFO_FOREACH(cii, ci)) {
215: if ((cpumask & (1UL << ci->ci_cpuid)) == 0)
1.5 thorpej 216: continue;
1.29 thorpej 217: alpha_send_ipi(ci->ci_cpuid, ipimask);
1.5 thorpej 218: }
219: }
220:
1.1 thorpej 221: void
1.23 thorpej 222: alpha_ipi_halt(struct cpu_info *ci, struct trapframe *framep)
1.1 thorpej 223: {
1.23 thorpej 224: u_long cpu_id = ci->ci_cpuid;
225: u_long wait_mask = (1UL << cpu_id);
1.2 thorpej 226:
227: /* Disable interrupts. */
228: (void) splhigh();
229:
1.23 thorpej 230: if (cpu_id != hwrpb->rpb_primary_cpu_id) {
231: /*
232: * If we're not the primary, we just halt now.
233: */
234: cpu_halt();
235: }
236:
237: /*
238: * We're the primary. We need to wait for all the other
239: * secondary CPUs to halt, then we can drop back to the
240: * console.
241: */
242: printf("%s: waiting for secondary CPUs to halt...\n",
243: ci->ci_softc->sc_dev.dv_xname);
244: alpha_mb();
245: for (;;) {
246: alpha_mb();
247: if (cpus_running == wait_mask)
248: break;
249: delay(1000);
250: }
251:
252: prom_halt(boothowto & RB_HALT);
1.2 thorpej 253: /* NOTREACHED */
1.33 nakayama 254: }
255:
256: void
257: alpha_ipi_microset(struct cpu_info *ci, struct trapframe *framep)
258: {
259:
260: cc_microset(ci);
1.8 thorpej 261: }
262:
263: void
1.23 thorpej 264: alpha_ipi_imb(struct cpu_info *ci, struct trapframe *framep)
1.8 thorpej 265: {
266:
267: alpha_pal_imb();
1.7 thorpej 268: }
269:
270: void
1.23 thorpej 271: alpha_ipi_ast(struct cpu_info *ci, struct trapframe *framep)
1.7 thorpej 272: {
273:
1.32 thorpej 274: if (ci->ci_curlwp != NULL)
1.33.18.1! yamt 275: aston(ci->ci_curlwp);
1.15 thorpej 276: }
277:
278: void
1.23 thorpej 279: alpha_ipi_synch_fpu(struct cpu_info *ci, struct trapframe *framep)
1.15 thorpej 280: {
281:
1.25 thorpej 282: if (ci->ci_flags & CPUF_FPUSAVE)
283: return;
1.23 thorpej 284: fpusave_cpu(ci, 1);
1.15 thorpej 285: }
286:
287: void
1.23 thorpej 288: alpha_ipi_discard_fpu(struct cpu_info *ci, struct trapframe *framep)
1.15 thorpej 289: {
290:
1.25 thorpej 291: if (ci->ci_flags & CPUF_FPUSAVE)
292: return;
1.23 thorpej 293: fpusave_cpu(ci, 0);
1.16 thorpej 294: }
295:
296: void
1.23 thorpej 297: alpha_ipi_pause(struct cpu_info *ci, struct trapframe *framep)
1.16 thorpej 298: {
1.23 thorpej 299: u_long cpumask = (1UL << ci->ci_cpuid);
1.16 thorpej 300: int s;
301:
1.23 thorpej 302: s = splhigh();
1.16 thorpej 303:
1.23 thorpej 304: /* Point debuggers at our trapframe for register state. */
305: ci->ci_db_regs = framep;
1.16 thorpej 306:
1.23 thorpej 307: atomic_setbits_ulong(&ci->ci_flags, CPUF_PAUSED);
1.16 thorpej 308:
309: /* Spin with interrupts disabled until we're resumed. */
1.19 thorpej 310: do {
311: alpha_mb();
312: } while (cpus_paused & cpumask);
1.16 thorpej 313:
1.23 thorpej 314: atomic_clearbits_ulong(&ci->ci_flags, CPUF_PAUSED);
315:
316: ci->ci_db_regs = NULL;
1.16 thorpej 317:
318: splx(s);
1.23 thorpej 319:
320: /* Do an IMB on the way out, in case the kernel text was changed. */
321: alpha_pal_imb();
1.1 thorpej 322: }
CVSweb <webmaster@jp.NetBSD.org>