[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.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>