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

Annotation of src/sys/arch/alpha/alpha/cpu.c, Revision 1.80.14.2

1.80.14.1  mjf         1: /* $NetBSD$ */
1.27      thorpej     2:
                      3: /*-
1.64      thorpej     4:  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
1.27      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:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
1.1       cgd        32:
                     33: /*
1.6       cgd        34:  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
1.1       cgd        35:  * All rights reserved.
                     36:  *
                     37:  * Author: Chris G. Demetriou
                     38:  *
                     39:  * Permission to use, copy, modify and distribute this software and
                     40:  * its documentation is hereby granted, provided that both the copyright
                     41:  * notice and this permission notice appear in all copies of the
                     42:  * software, derivative works or modified versions, and any portions
                     43:  * thereof, and that both notices appear in supporting documentation.
                     44:  *
                     45:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     46:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
                     47:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     48:  *
                     49:  * Carnegie Mellon requests users of this software to return to
                     50:  *
                     51:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     52:  *  School of Computer Science
                     53:  *  Carnegie Mellon University
                     54:  *  Pittsburgh PA 15213-3890
                     55:  *
                     56:  * any improvements or extensions that they make and grant Carnegie the
                     57:  * rights to redistribute these changes.
                     58:  */
1.20      cgd        59:
1.21      cgd        60: #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
                     61:
1.80.14.1  mjf        62: __KERNEL_RCSID(0, "$NetBSD$");
1.27      thorpej    63:
1.60      thorpej    64: #include "opt_ddb.h"
1.27      thorpej    65: #include "opt_multiprocessor.h"
1.1       cgd        66:
                     67: #include <sys/param.h>
1.10      cgd        68: #include <sys/systm.h>
1.1       cgd        69: #include <sys/device.h>
1.62      thorpej    70: #include <sys/malloc.h>
1.27      thorpej    71: #include <sys/proc.h>
                     72: #include <sys/user.h>
1.80.14.1  mjf        73: #include <sys/atomic.h>
                     74: #include <sys/cpu.h>
1.27      thorpej    75:
1.52      mrg        76: #include <uvm/uvm_extern.h>
1.1       cgd        77:
                     78: #include <machine/autoconf.h>
1.50      thorpej    79: #include <machine/cpuvar.h>
1.1       cgd        80: #include <machine/rpb.h>
1.27      thorpej    81: #include <machine/prom.h>
1.33      ross       82: #include <machine/alpha.h>
1.27      thorpej    83:
1.79      ad         84: struct cpu_info cpu_info_primary = {
                     85:        .ci_curlwp = &lwp0
                     86: };
1.61      thorpej    87: struct cpu_info *cpu_info_list = &cpu_info_primary;
                     88:
1.27      thorpej    89: #if defined(MULTIPROCESSOR)
1.34      thorpej    90: /*
                     91:  * Array of CPU info structures.  Must be statically-allocated because
                     92:  * curproc, etc. are used early.
                     93:  */
1.61      thorpej    94: struct cpu_info *cpu_info[ALPHA_MAXPROCS];
1.32      thorpej    95:
1.64      thorpej    96: /* Bitmask of CPUs booted, currently running, and paused. */
1.73      perry      97: volatile u_long cpus_booted;
                     98: volatile u_long cpus_running;
                     99: volatile u_long cpus_paused;
1.34      thorpej   100:
1.41      thorpej   101: void   cpu_boot_secondary __P((struct cpu_info *));
1.27      thorpej   102: #endif /* MULTIPROCESSOR */
1.1       cgd       103:
1.43      thorpej   104: /*
                    105:  * The Implementation Version and the Architecture Mask must be
                    106:  * consistent across all CPUs in the system, so we set it for the
                    107:  * primary and announce the AMASK extensions if they exist.
                    108:  *
                    109:  * Note, we invert the AMASK so that if a bit is set, it means "has
                    110:  * extension".
                    111:  */
                    112: u_long cpu_implver, cpu_amask;
                    113:
1.1       cgd       114: /* Definition of the driver for autoconfig. */
1.16      cgd       115: static int     cpumatch(struct device *, struct cfdata *, void *);
1.1       cgd       116: static void    cpuattach(struct device *, struct device *, void *);
1.5       thorpej   117:
1.68      thorpej   118: CFATTACH_DECL(cpu, sizeof(struct cpu_softc),
                    119:     cpumatch, cpuattach, NULL, NULL);
1.5       thorpej   120:
1.64      thorpej   121: static void    cpu_announce_extensions(struct cpu_info *);
                    122:
1.23      thorpej   123: extern struct cfdriver cpu_cd;
1.1       cgd       124:
1.53      thorpej   125: static const char *lcaminor[] = {
1.26      ross      126:        "",
1.53      thorpej   127:        "21066", "21066",
                    128:        "21068", "21068",
                    129:        "21066A", "21068A", 0
1.26      ross      130: };
                    131:
                    132: struct cputable_struct {
                    133:        int     cpu_major_code;
1.53      thorpej   134:        const char *cpu_major_name;
                    135:        const char **cpu_minor_names;
1.26      ross      136: } cpunametable[] = {
1.48      thorpej   137:        { PCS_PROC_EV3,         "EV3",          NULL            },
1.53      thorpej   138:        { PCS_PROC_EV4,         "21064",        NULL            },
1.48      thorpej   139:        { PCS_PROC_SIMULATION,  "Sim",          NULL            },
1.26      ross      140:        { PCS_PROC_LCA4,        "LCA",          lcaminor        },
1.53      thorpej   141:        { PCS_PROC_EV5,         "21164",        NULL            },
                    142:        { PCS_PROC_EV45,        "21064A",       NULL            },
                    143:        { PCS_PROC_EV56,        "21164A",       NULL            },
                    144:        { PCS_PROC_EV6,         "21264",        NULL            },
                    145:        { PCS_PROC_PCA56,       "PCA56",        NULL            },
1.48      thorpej   146:        { PCS_PROC_PCA57,       "PCA57",        NULL            },
1.49      thorpej   147:        { PCS_PROC_EV67,        "21264A",       NULL            },
1.66      he        148:        { PCS_PROC_EV68CB,      "21264C",       NULL            },
                    149:        { PCS_PROC_EV68AL,      "21264B",       NULL            },
                    150:        { PCS_PROC_EV68CX,      "21264D",       NULL            },
1.26      ross      151: };
                    152:
1.27      thorpej   153: /*
                    154:  * The following is an attempt to map out how booting secondary CPUs
                    155:  * works.
                    156:  *
                    157:  * As we find processors during the autoconfiguration sequence, all
1.41      thorpej   158:  * processors have idle stacks and PCBs created for them, including
                    159:  * the primary (although the primary idles on proc0's PCB until its
                    160:  * idle PCB is created).
1.34      thorpej   161:  *
1.41      thorpej   162:  * Right before calling uvm_scheduler(), main() calls, on proc0's
                    163:  * context, cpu_boot_secondary_processors().  This is our key to
                    164:  * actually spin up the additional processor's we've found.  We
                    165:  * run through our cpu_info[] array looking for secondary processors
                    166:  * with idle PCBs, and spin them up.
                    167:  *
                    168:  * The spinup involves switching the secondary processor to the
                    169:  * OSF/1 PALcode, setting the entry point to cpu_spinup_trampoline(),
                    170:  * and sending a "START" message to the secondary's console.
1.27      thorpej   171:  *
                    172:  * Upon successful processor bootup, the cpu_spinup_trampoline will call
                    173:  * cpu_hatch(), which will print a message indicating that the processor
                    174:  * is running, and will set the "hatched" flag in its softc.  At the end
                    175:  * of cpu_hatch() is a spin-forever loop; we do not yet attempt to schedule
                    176:  * anything on secondary CPUs.
                    177:  */
                    178:
1.1       cgd       179: static int
                    180: cpumatch(parent, cfdata, aux)
                    181:        struct device *parent;
1.16      cgd       182:        struct cfdata *cfdata;
1.1       cgd       183:        void *aux;
                    184: {
1.24      thorpej   185:        struct mainbus_attach_args *ma = aux;
1.1       cgd       186:
                    187:        /* make sure that we're looking for a CPU. */
1.24      thorpej   188:        if (strcmp(ma->ma_name, cpu_cd.cd_name) != 0)
1.1       cgd       189:                return (0);
                    190:
1.18      cgd       191:        /* XXX CHECK SLOT? */
                    192:        /* XXX CHECK PRIMARY? */
                    193:
1.1       cgd       194:        return (1);
                    195: }
                    196:
                    197: static void
1.50      thorpej   198: cpuattach(parent, self, aux)
1.1       cgd       199:        struct device *parent;
1.50      thorpej   200:        struct device *self;
1.1       cgd       201:        void *aux;
                    202: {
1.50      thorpej   203:        struct cpu_softc *sc = (void *) self;
1.24      thorpej   204:        struct mainbus_attach_args *ma = aux;
1.26      ross      205:        int i;
1.53      thorpej   206:        const char **s;
1.43      thorpej   207:        struct pcs *p;
1.19      mycroft   208: #ifdef DEBUG
1.14      cgd       209:        int needcomma;
1.19      mycroft   210: #endif
1.2       cgd       211:        u_int32_t major, minor;
1.46      thorpej   212:        struct cpu_info *ci;
1.1       cgd       213:
1.25      ross      214:        p = LOCATE_PCS(hwrpb, ma->ma_slot);
                    215:        major = PCS_CPU_MAJORTYPE(p);
                    216:        minor = PCS_CPU_MINORTYPE(p);
1.14      cgd       217:
1.24      thorpej   218:        printf(": ID %d%s, ", ma->ma_slot,
                    219:            ma->ma_slot == hwrpb->rpb_primary_cpu_id ? " (primary)" : "");
1.18      cgd       220:
1.26      ross      221:        for(i = 0; i < sizeof cpunametable / sizeof cpunametable[0]; ++i) {
                    222:                if (cpunametable[i].cpu_major_code == major) {
1.36      ross      223:                        printf("%s-%d", cpunametable[i].cpu_major_name, minor);
1.26      ross      224:                        s = cpunametable[i].cpu_minor_names;
                    225:                        for(i = 0; s && s[i]; ++i) {
1.39      ross      226:                                if (i == minor && strlen(s[i]) != 0) {
1.26      ross      227:                                        printf(" (%s)\n", s[i]);
                    228:                                        goto recognized;
                    229:                                }
                    230:                        }
                    231:                        goto recognized;
1.14      cgd       232:                }
1.26      ross      233:        }
1.53      thorpej   234:        printf("UNKNOWN CPU TYPE (%d:%d)", major, minor);
1.4       cgd       235:
1.26      ross      236: recognized:
1.53      thorpej   237:        printf("\n");
1.2       cgd       238:
1.18      cgd       239: #ifdef DEBUG
1.2       cgd       240:        if (p->pcs_proc_var != 0) {
1.51      sommerfe  241:                printf("%s: ", sc->sc_dev.dv_xname);
1.2       cgd       242:
                    243:                needcomma = 0;
                    244:                if (p->pcs_proc_var & PCS_VAR_VAXFP) {
1.12      christos  245:                        printf("VAX FP support");
1.2       cgd       246:                        needcomma = 1;
                    247:                }
                    248:                if (p->pcs_proc_var & PCS_VAR_IEEEFP) {
1.12      christos  249:                        printf("%sIEEE FP support", needcomma ? ", " : "");
1.2       cgd       250:                        needcomma = 1;
                    251:                }
1.8       cgd       252:                if (p->pcs_proc_var & PCS_VAR_PE) {
1.12      christos  253:                        printf("%sPrimary Eligible", needcomma ? ", " : "");
1.3       cgd       254:                        needcomma = 1;
                    255:                }
1.2       cgd       256:                if (p->pcs_proc_var & PCS_VAR_RESERVED)
1.12      christos  257:                        printf("%sreserved bits: 0x%lx", needcomma ? ", " : "",
1.2       cgd       258:                            p->pcs_proc_var & PCS_VAR_RESERVED);
1.12      christos  259:                printf("\n");
1.2       cgd       260:        }
1.18      cgd       261: #endif
1.3       cgd       262:
1.27      thorpej   263:        if (ma->ma_slot > ALPHA_WHAMI_MAXID) {
1.46      thorpej   264:                if (ma->ma_slot == hwrpb->rpb_primary_cpu_id)
                    265:                        panic("cpu_attach: primary CPU ID too large");
1.50      thorpej   266:                printf("%s: procssor ID too large, ignoring\n",
                    267:                    sc->sc_dev.dv_xname);
1.27      thorpej   268:                return;
                    269:        }
                    270:
1.62      thorpej   271:        if (ma->ma_slot == hwrpb->rpb_primary_cpu_id)
1.61      thorpej   272:                ci = &cpu_info_primary;
                    273:        else {
                    274:                ci = malloc(sizeof(*ci), M_DEVBUF, M_WAITOK);
                    275:                memset(ci, 0, sizeof(*ci));
                    276:        }
1.62      thorpej   277: #if defined(MULTIPROCESSOR)
                    278:        cpu_info[ma->ma_slot] = ci;
1.46      thorpej   279: #endif
1.34      thorpej   280:        ci->ci_cpuid = ma->ma_slot;
1.62      thorpej   281:        ci->ci_softc = sc;
1.76      tsutsui   282:        ci->ci_pcc_freq = hwrpb->rpb_cc_freq;
1.27      thorpej   283:
1.4       cgd       284:        /*
1.14      cgd       285:         * Though we could (should?) attach the LCA cpus' PCI
1.4       cgd       286:         * bus here there is no good reason to do so, and
                    287:         * the bus attachment code is easier to understand
                    288:         * and more compact if done the 'normal' way.
                    289:         */
1.27      thorpej   290:
                    291: #if defined(MULTIPROCESSOR)
                    292:        /*
1.41      thorpej   293:         * Make sure the processor is available for use.
1.27      thorpej   294:         */
1.41      thorpej   295:        if ((p->pcs_flags & PCS_PA) == 0) {
                    296:                if (ma->ma_slot == hwrpb->rpb_primary_cpu_id)
                    297:                        panic("cpu_attach: primary not available?!");
1.50      thorpej   298:                printf("%s: processor not available for use\n",
                    299:                    sc->sc_dev.dv_xname);
1.41      thorpej   300:                return;
                    301:        }
1.32      thorpej   302:
1.41      thorpej   303:        /* Make sure the processor has valid PALcode. */
                    304:        if ((p->pcs_flags & PCS_PV) == 0) {
                    305:                if (ma->ma_slot == hwrpb->rpb_primary_cpu_id)
                    306:                        panic("cpu_attach: primary has invalid PALcode?!");
1.50      thorpej   307:                printf("%s: PALcode not valid\n", sc->sc_dev.dv_xname);
1.27      thorpej   308:                return;
                    309:        }
1.64      thorpej   310: #endif /* MULTIPROCESSOR */
1.41      thorpej   311:
                    312:        /*
                    313:         * If we're the primary CPU, no more work to do; we're already
                    314:         * running!
                    315:         */
                    316:        if (ma->ma_slot == hwrpb->rpb_primary_cpu_id) {
1.64      thorpej   317:                cpu_announce_extensions(ci);
                    318: #if defined(MULTIPROCESSOR)
1.61      thorpej   319:                ci->ci_flags |= CPUF_PRIMARY|CPUF_RUNNING;
1.80.14.1  mjf       320:                atomic_or_ulong(&cpus_booted, (1UL << ma->ma_slot));
                    321:                atomic_or_ulong(&cpus_running, (1UL << ma->ma_slot));
1.64      thorpej   322: #endif /* MULTIPROCESSOR */
                    323:        } else {
                    324: #if defined(MULTIPROCESSOR)
1.74      yamt      325:                int error;
                    326:
                    327:                error = mi_cpu_attach(ci);
                    328:                if (error != 0) {
                    329:                        aprint_error("%s: mi_cpu_attach failed with %d\n",
                    330:                            sc->sc_dev.dv_xname, error);
                    331:                        return;
                    332:                }
                    333:
1.64      thorpej   334:                /*
                    335:                 * Boot the secondary processor.  It will announce its
                    336:                 * extensions, and then spin until we tell it to go
                    337:                 * on its merry way.
                    338:                 */
                    339:                cpu_boot_secondary(ci);
                    340: #else /* ! MULTIPROCESSOR */
                    341:                printf("%s: processor off-line; multiprocessor support "
                    342:                    "not present in kernel\n", sc->sc_dev.dv_xname);
                    343: #endif /* MULTIPROCESSOR */
1.41      thorpej   344:        }
1.50      thorpej   345:
                    346:        evcnt_attach_dynamic(&sc->sc_evcnt_clock, EVCNT_TYPE_INTR,
                    347:            NULL, sc->sc_dev.dv_xname, "clock");
                    348:        evcnt_attach_dynamic(&sc->sc_evcnt_device, EVCNT_TYPE_INTR,
                    349:            NULL, sc->sc_dev.dv_xname, "device");
                    350: #if defined(MULTIPROCESSOR)
1.58      thorpej   351:        alpha_ipi_init(ci);
1.50      thorpej   352: #endif
1.27      thorpej   353: }
                    354:
1.64      thorpej   355: static void
                    356: cpu_announce_extensions(struct cpu_info *ci)
                    357: {
1.71      chs       358:        u_long implver, amask = 0;
1.64      thorpej   359:        char bits[64];
                    360:
                    361:        implver = alpha_implver();
                    362:        if (implver >= ALPHA_IMPLVER_EV5)
                    363:                amask = (~alpha_amask(ALPHA_AMASK_ALL)) & ALPHA_AMASK_ALL;
                    364:
                    365:        if (ci->ci_cpuid == hwrpb->rpb_primary_cpu_id) {
                    366:                cpu_implver = implver;
                    367:                cpu_amask = amask;
                    368:        } else {
                    369:                if (implver < cpu_implver)
                    370:                        printf("%s: WARNING: IMPLVER %lu < %lu\n",
                    371:                            ci->ci_softc->sc_dev.dv_xname,
                    372:                            implver, cpu_implver);
                    373:
                    374:                /*
                    375:                 * Cap the system architecture mask to the intersection
                    376:                 * of features supported by all processors in the system.
                    377:                 */
                    378:                cpu_amask &= amask;
                    379:        }
                    380:
                    381:        if (amask)
                    382:                printf("%s: Architecture extensions: %s\n",
                    383:                    ci->ci_softc->sc_dev.dv_xname, bitmask_snprintf(cpu_amask,
                    384:                    ALPHA_AMASK_BITS, bits, sizeof(bits)));
                    385: }
                    386:
1.27      thorpej   387: #if defined(MULTIPROCESSOR)
                    388: void
1.64      thorpej   389: cpu_boot_secondary_processors(void)
1.41      thorpej   390: {
                    391:        struct cpu_info *ci;
                    392:        u_long i;
1.80      ad        393:        bool did_patch = false;
1.41      thorpej   394:
                    395:        for (i = 0; i < ALPHA_MAXPROCS; i++) {
1.61      thorpej   396:                ci = cpu_info[i];
1.75      mhitch    397:                if (ci == NULL || ci->ci_data.cpu_idlelwp == NULL)
1.41      thorpej   398:                        continue;
                    399:                if (ci->ci_flags & CPUF_PRIMARY)
                    400:                        continue;
1.64      thorpej   401:                if ((cpus_booted & (1UL << i)) == 0)
                    402:                        continue;
1.41      thorpej   403:
1.80      ad        404:                /* Patch MP-criticial kernel routines. */
                    405:                if (did_patch == false) {
                    406:                        alpha_patch(true);
                    407:                        did_patch = true;
                    408:                }
                    409:
1.64      thorpej   410:                /*
                    411:                 * Link the processor into the list, and launch it.
                    412:                 */
                    413:                ci->ci_next = cpu_info_list->ci_next;
                    414:                cpu_info_list->ci_next = ci;
1.80.14.1  mjf       415:                atomic_or_ulong(&ci->ci_flags, CPUF_RUNNING);
                    416:                atomic_or_ulong(&cpus_running, (1U << i));
1.41      thorpej   417:        }
                    418: }
                    419:
                    420: void
1.64      thorpej   421: cpu_boot_secondary(struct cpu_info *ci)
1.27      thorpej   422: {
                    423:        long timeout;
                    424:        struct pcs *pcsp, *primary_pcsp;
                    425:        struct pcb *pcb;
1.32      thorpej   426:        u_long cpumask;
1.27      thorpej   427:
1.75      mhitch    428:        pcb = &ci->ci_data.cpu_idlelwp->l_addr->u_pcb;
1.27      thorpej   429:        primary_pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
1.34      thorpej   430:        pcsp = LOCATE_PCS(hwrpb, ci->ci_cpuid);
                    431:        cpumask = (1UL << ci->ci_cpuid);
1.27      thorpej   432:
1.34      thorpej   433:        /*
1.41      thorpej   434:         * Set up the PCS's HWPCB to match ours.
1.34      thorpej   435:         */
                    436:        memcpy(pcsp->pcs_hwpcb, &pcb->pcb_hw, sizeof(pcb->pcb_hw));
1.27      thorpej   437:
1.34      thorpej   438:        /*
                    439:         * Set up the HWRPB to restart the secondary processor
                    440:         * with our spin-up trampoline.
                    441:         */
                    442:        hwrpb->rpb_restart = (u_int64_t) cpu_spinup_trampoline;
                    443:        hwrpb->rpb_restart_val = (u_int64_t) ci;
                    444:        hwrpb->rpb_checksum = hwrpb_checksum();
                    445:
                    446:        /*
                    447:         * Configure the CPU to start in OSF/1 PALcode by copying
                    448:         * the primary CPU's PALcode revision info to the secondary
                    449:         * CPUs PCS.
                    450:         */
                    451:        memcpy(&pcsp->pcs_pal_rev, &primary_pcsp->pcs_pal_rev,
                    452:            sizeof(pcsp->pcs_pal_rev));
                    453:        pcsp->pcs_flags |= (PCS_CV|PCS_RC);
                    454:        pcsp->pcs_flags &= ~PCS_BIP;
                    455:
                    456:        /* Make sure the secondary console sees all this. */
                    457:        alpha_mb();
                    458:
                    459:        /* Send a "START" command to the secondary CPU's console. */
                    460:        if (cpu_iccb_send(ci->ci_cpuid, "START\r\n")) {
                    461:                printf("%s: unable to issue `START' command\n",
1.50      thorpej   462:                    ci->ci_softc->sc_dev.dv_xname);
1.34      thorpej   463:                return;
                    464:        }
1.27      thorpej   465:
1.34      thorpej   466:        /* Wait for the processor to boot. */
                    467:        for (timeout = 10000; timeout != 0; timeout--) {
1.27      thorpej   468:                alpha_mb();
1.34      thorpej   469:                if (pcsp->pcs_flags & PCS_BIP)
                    470:                        break;
                    471:                delay(1000);
                    472:        }
                    473:        if (timeout == 0)
1.50      thorpej   474:                printf("%s: processor failed to boot\n",
                    475:                    ci->ci_softc->sc_dev.dv_xname);
1.27      thorpej   476:
1.34      thorpej   477:        /*
                    478:         * ...and now wait for verification that it's running kernel
                    479:         * code.
                    480:         */
                    481:        for (timeout = 10000; timeout != 0; timeout--) {
                    482:                alpha_mb();
1.64      thorpej   483:                if (cpus_booted & cpumask)
1.34      thorpej   484:                        break;
                    485:                delay(1000);
1.27      thorpej   486:        }
1.34      thorpej   487:        if (timeout == 0)
1.50      thorpej   488:                printf("%s: processor failed to hatch\n",
                    489:                    ci->ci_softc->sc_dev.dv_xname);
1.54      thorpej   490: }
                    491:
                    492: void
                    493: cpu_pause_resume(u_long cpu_id, int pause)
                    494: {
                    495:        u_long cpu_mask = (1UL << cpu_id);
                    496:
                    497:        if (pause) {
1.80.14.1  mjf       498:                atomic_or_ulong(&cpus_paused, cpu_mask);
1.54      thorpej   499:                alpha_send_ipi(cpu_id, ALPHA_IPI_PAUSE);
                    500:        } else
1.80.14.1  mjf       501:                atomic_and_ulong(&cpus_paused, ~cpu_mask);
1.54      thorpej   502: }
                    503:
                    504: void
                    505: cpu_pause_resume_all(int pause)
                    506: {
1.61      thorpej   507:        struct cpu_info *ci, *self = curcpu();
                    508:        CPU_INFO_ITERATOR cii;
1.54      thorpej   509:
1.61      thorpej   510:        for (CPU_INFO_FOREACH(cii, ci)) {
                    511:                if (ci == self)
1.54      thorpej   512:                        continue;
1.61      thorpej   513:                cpu_pause_resume(ci->ci_cpuid, pause);
1.54      thorpej   514:        }
1.27      thorpej   515: }
                    516:
                    517: void
1.60      thorpej   518: cpu_halt(void)
1.32      thorpej   519: {
1.60      thorpej   520:        struct cpu_info *ci = curcpu();
                    521:        u_long cpu_id = cpu_number();
                    522:        struct pcs *pcsp = LOCATE_PCS(hwrpb, cpu_id);
1.32      thorpej   523:
1.60      thorpej   524:        printf("%s: shutting down...\n", ci->ci_softc->sc_dev.dv_xname);
1.32      thorpej   525:
1.60      thorpej   526:        pcsp->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ);
                    527:        pcsp->pcs_flags |= PCS_HALT_STAY_HALTED;
1.32      thorpej   528:
1.80.14.1  mjf       529:        atomic_and_ulong(&cpus_running, ~(1UL << cpu_id));
                    530:        atomic_and_ulong(&cpus_booted, ~(1U << cpu_id));
1.32      thorpej   531:
1.60      thorpej   532:        alpha_pal_halt();
                    533:        /* NOTREACHED */
1.32      thorpej   534: }
                    535:
                    536: void
1.64      thorpej   537: cpu_hatch(struct cpu_info *ci)
1.27      thorpej   538: {
1.55      thorpej   539:        u_long cpu_id = cpu_number();
                    540:        u_long cpumask = (1UL << cpu_id);
1.34      thorpej   541:
1.41      thorpej   542:        /* Mark the kernel pmap active on this processor. */
1.80.14.1  mjf       543:        atomic_or_ulong(&pmap_kernel()->pm_cpus, cpumask);
1.27      thorpej   544:
                    545:        /* Initialize trap vectors for this processor. */
                    546:        trap_init();
                    547:
                    548:        /* Yahoo!  We're running kernel code!  Announce it! */
1.64      thorpej   549:        cpu_announce_extensions(ci);
                    550:
1.80.14.1  mjf       551:        atomic_or_ulong(&cpus_booted, cpumask);
1.64      thorpej   552:
                    553:        /*
                    554:         * Spin here until we're told we can start.
                    555:         */
                    556:        while ((cpus_running & cpumask) == 0)
                    557:                /* spin */ ;
                    558:
                    559:        /*
                    560:         * Invalidate the TLB and sync the I-stream before we
                    561:         * jump into the kernel proper.  We have to do this
                    562:         * beacause we haven't been getting IPIs while we've
                    563:         * been spinning.
                    564:         */
                    565:        ALPHA_TBIA();
                    566:        alpha_pal_imb();
1.63      sommerfe  567:
1.76      tsutsui   568:        cc_calibrate_cpu(ci);
1.27      thorpej   569: }
                    570:
                    571: int
1.64      thorpej   572: cpu_iccb_send(long cpu_id, const char *msg)
1.27      thorpej   573: {
                    574:        struct pcs *pcsp = LOCATE_PCS(hwrpb, cpu_id);
                    575:        int timeout;
                    576:        u_long cpumask = (1UL << cpu_id);
                    577:
                    578:        /* Wait for the ICCB to become available. */
                    579:        for (timeout = 10000; timeout != 0; timeout--) {
                    580:                alpha_mb();
                    581:                if ((hwrpb->rpb_rxrdy & cpumask) == 0)
                    582:                        break;
                    583:                delay(1000);
                    584:        }
                    585:        if (timeout == 0)
                    586:                return (EIO);
                    587:
                    588:        /*
                    589:         * Copy the message into the ICCB, and tell the secondary console
1.80.14.1  mjf       590:         * that it's there.
1.27      thorpej   591:         */
                    592:        strcpy(pcsp->pcs_iccb.iccb_rxbuf, msg);
                    593:        pcsp->pcs_iccb.iccb_rxlen = strlen(msg);
1.80.14.1  mjf       594:        atomic_or_ulong(&hwrpb->rpb_rxrdy, cpumask);
                    595:        membar_sync();
1.27      thorpej   596:
                    597:        /* Wait for the message to be received. */
                    598:        for (timeout = 10000; timeout != 0; timeout--) {
                    599:                alpha_mb();
                    600:                if ((hwrpb->rpb_rxrdy & cpumask) == 0)
                    601:                        break;
                    602:                delay(1000);
                    603:        }
                    604:        if (timeout == 0)
                    605:                return (EIO);
                    606:
                    607:        return (0);
                    608: }
                    609:
                    610: void
1.64      thorpej   611: cpu_iccb_receive(void)
1.27      thorpej   612: {
1.28      thorpej   613: #if 0  /* Don't bother... we don't get any important messages anyhow. */
1.27      thorpej   614:        u_int64_t txrdy;
                    615:        char *cp1, *cp2, buf[80];
                    616:        struct pcs *pcsp;
                    617:        u_int cnt;
                    618:        long cpu_id;
                    619:
                    620:        txrdy = hwrpb->rpb_txrdy;
                    621:
                    622:        for (cpu_id = 0; cpu_id < hwrpb->rpb_pcs_cnt; cpu_id++) {
                    623:                if (txrdy & (1UL << cpu_id)) {
                    624:                        pcsp = LOCATE_PCS(hwrpb, cpu_id);
                    625:                        printf("Inter-console message from CPU %lu "
                    626:                            "HALT REASON = 0x%lx, FLAGS = 0x%lx\n",
                    627:                            cpu_id, pcsp->pcs_halt_reason, pcsp->pcs_flags);
                    628:
                    629:                        cnt = pcsp->pcs_iccb.iccb_txlen;
                    630:                        if (cnt >= 80) {
                    631:                                printf("Malformed inter-console message\n");
                    632:                                continue;
                    633:                        }
                    634:                        cp1 = pcsp->pcs_iccb.iccb_txbuf;
                    635:                        cp2 = buf;
                    636:                        while (cnt--) {
                    637:                                if (*cp1 != '\r' && *cp1 != '\n')
                    638:                                        *cp2++ = *cp1;
                    639:                                cp1++;
                    640:                        }
                    641:                        *cp2 = '\0';
                    642:                        printf("Message from CPU %lu: %s\n", cpu_id, buf);
                    643:                }
                    644:        }
1.28      thorpej   645: #endif /* 0 */
1.27      thorpej   646:        hwrpb->rpb_txrdy = 0;
                    647:        alpha_mb();
1.1       cgd       648: }
1.60      thorpej   649:
                    650: #if defined(DDB)
                    651:
                    652: #include <ddb/db_output.h>
                    653: #include <machine/db_machdep.h>
                    654:
                    655: /*
                    656:  * Dump CPU information from DDB.
                    657:  */
                    658: void
                    659: cpu_debug_dump(void)
                    660: {
                    661:        struct cpu_info *ci;
1.61      thorpej   662:        CPU_INFO_ITERATOR cii;
1.60      thorpej   663:
                    664:        db_printf("addr         dev     id      flags   ipis    curproc         fpcurproc\n");
1.61      thorpej   665:        for (CPU_INFO_FOREACH(cii, ci)) {
1.60      thorpej   666:                db_printf("%p   %s      %lu     %lx     %lx     %p      %p\n",
                    667:                    ci,
                    668:                    ci->ci_softc->sc_dev.dv_xname,
                    669:                    ci->ci_cpuid,
                    670:                    ci->ci_flags,
                    671:                    ci->ci_ipis,
1.69      thorpej   672:                    ci->ci_curlwp,
                    673:                    ci->ci_fpcurlwp);
1.60      thorpej   674:        }
                    675: }
                    676:
                    677: #endif /* DDB */
                    678:
1.27      thorpej   679: #endif /* MULTIPROCESSOR */

CVSweb <webmaster@jp.NetBSD.org>