[BACK]Return to ipifuncs.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / alpha / alpha

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>