Home | History | Annotate | Line # | Download | only in alpha
      1 /* $NetBSD: cpu.c,v 1.108 2024/03/06 07:22:45 thorpej Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1998, 1999, 2000, 2001, 2020 The NetBSD Foundation, Inc.
      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  */
     32 
     33 /*
     34  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
     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 (at) 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  */
     59 
     60 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     61 
     62 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.108 2024/03/06 07:22:45 thorpej Exp $");
     63 
     64 #include "opt_ddb.h"
     65 #include "opt_multiprocessor.h"
     66 
     67 #include <sys/param.h>
     68 #include <sys/systm.h>
     69 #include <sys/device.h>
     70 #include <sys/kmem.h>
     71 #include <sys/proc.h>
     72 #include <sys/atomic.h>
     73 #include <sys/cpu.h>
     74 #include <sys/sysctl.h>
     75 
     76 #include <uvm/uvm_extern.h>
     77 
     78 #include <machine/autoconf.h>
     79 #include <machine/cpuvar.h>
     80 #include <machine/rpb.h>
     81 #include <machine/prom.h>
     82 #include <machine/alpha.h>
     83 
     84 struct cpu_info cpu_info_primary __cacheline_aligned = {
     85 	.ci_curlwp = &lwp0,
     86 	.ci_flags  = CPUF_PRIMARY|CPUF_RUNNING,
     87 };
     88 struct cpu_info *cpu_info_list __read_mostly = &cpu_info_primary;
     89 
     90 #if defined(MULTIPROCESSOR)
     91 /*
     92  * Array of CPU info structures.  Must be statically-allocated because
     93  * curproc, etc. are used early.
     94  */
     95 struct cpu_info *cpu_info[ALPHA_MAXPROCS];
     96 
     97 /* Bitmask of CPUs booted, currently running, and paused. */
     98 volatile u_long cpus_booted __read_mostly;
     99 volatile u_long cpus_running __read_mostly;
    100 volatile u_long cpus_paused __read_mostly;
    101 
    102 void	cpu_boot_secondary(struct cpu_info *);
    103 #endif /* MULTIPROCESSOR */
    104 
    105 static void
    106 cpu_idle_default(void)
    107 {
    108 	/*
    109 	 * Default is to do nothing.  Platform code can overwrite
    110 	 * as needed.
    111 	 */
    112 }
    113 
    114 void
    115 cpu_idle_wtint(void)
    116 {
    117 	/*
    118 	 * Some PALcode versions implement the WTINT call to idle
    119 	 * in a low power mode.
    120 	 */
    121 	alpha_pal_wtint(0);
    122 }
    123 
    124 void	(*cpu_idle_fn)(void) __read_mostly = cpu_idle_default;
    125 
    126 /*
    127  * The Implementation Version and the Architecture Mask must be
    128  * consistent across all CPUs in the system, so we set it for the
    129  * primary and announce the AMASK extensions if they exist.
    130  *
    131  * Note, we invert the AMASK so that if a bit is set, it means "has
    132  * extension".
    133  */
    134 u_long	cpu_implver __read_mostly;
    135 u_long	cpu_amask __read_mostly;
    136 
    137 /* Definition of the driver for autoconfig. */
    138 static int	cpumatch(device_t, cfdata_t, void *);
    139 static void	cpuattach(device_t, device_t, void *);
    140 
    141 CFATTACH_DECL_NEW(cpu, sizeof(struct cpu_softc),
    142     cpumatch, cpuattach, NULL, NULL);
    143 
    144 static void	cpu_announce_extensions(struct cpu_info *);
    145 
    146 extern struct cfdriver cpu_cd;
    147 
    148 static const char * const lcaminor[] = {
    149 	"",
    150 	"21066", "21066",
    151 	"21068", "21068",
    152 	"21066A", "21068A",
    153 	NULL
    154 };
    155 
    156 const struct cputable_struct {
    157 	const char *cpu_evname;
    158 	const char *cpu_major_name;
    159 	const char * const *cpu_minor_names;
    160 } cpunametable[] = {
    161 [PCS_PROC_EV3]       ={	"EV3",		NULL,		NULL		},
    162 [PCS_PROC_EV4]       ={	"EV4",		"21064",	NULL		},
    163 [PCS_PROC_SIMULATION]={ "Sim",		NULL,		NULL		},
    164 [PCS_PROC_LCA4]      ={	"LCA4",		NULL,		lcaminor	},
    165 [PCS_PROC_EV5]       ={	"EV5",		"21164",	NULL		},
    166 [PCS_PROC_EV45]      ={	"EV45",		"21064A",	NULL		},
    167 [PCS_PROC_EV56]      ={	"EV56",		"21164A",	NULL		},
    168 [PCS_PROC_EV6]       ={	"EV6",		"21264",	NULL		},
    169 [PCS_PROC_PCA56]     ={	"PCA56",	"21164PC",	NULL		},
    170 [PCS_PROC_PCA57]     ={	"PCA57",	"21164PC"/*XXX*/,NULL		},
    171 [PCS_PROC_EV67]      ={	"EV67",		"21264A",	NULL		},
    172 [PCS_PROC_EV68CB]    ={	"EV68CB",	"21264C",	NULL		},
    173 [PCS_PROC_EV68AL]    ={	"EV68AL",	"21264B",	NULL		},
    174 [PCS_PROC_EV68CX]    ={	"EV68CX",	"21264D",	NULL		},
    175 [PCS_PROC_EV7]       ={	"EV7",		"21364",	NULL		},
    176 [PCS_PROC_EV79]      ={	"EV79",		NULL,		NULL		},
    177 [PCS_PROC_EV69]      ={	"EV69",		NULL,		NULL		},
    178 };
    179 
    180 static bool
    181 cpu_description(const struct cpu_softc * const sc,
    182     char * const buf, size_t const buflen)
    183 {
    184 	const char * const *s;
    185 	const char *ev;
    186 	int i;
    187 
    188 	const uint32_t major = sc->sc_major_type;
    189 	const uint32_t minor = sc->sc_minor_type;
    190 
    191 	if (major < __arraycount(cpunametable) &&
    192 	    (ev = cpunametable[major].cpu_evname) != NULL) {
    193 		s = cpunametable[major].cpu_minor_names;
    194 		for (i = 0; s != NULL && s[i] != NULL; i++) {
    195 			if (i == minor && strlen(s[i]) != 0) {
    196 				break;
    197 			}
    198 		}
    199 		if (s == NULL || s[i] == NULL) {
    200 			s = &cpunametable[major].cpu_major_name;
    201 			i = 0;
    202 			if (s[i] == NULL) {
    203 				s = NULL;
    204 			}
    205 		}
    206 
    207 		/*
    208 		 * Example strings:
    209 		 *
    210 		 *	Sim-0
    211 		 *	21068-3 (LCA4)		[uses minor table]
    212 		 *	21264C-5 (EV68CB)
    213 		 *	21164PC-1 (PCA56)
    214 		 */
    215 		if (s != NULL) {
    216 			snprintf(buf, buflen, "%s-%d (%s)", s[i], minor, ev);
    217 		} else {
    218 			snprintf(buf, buflen, "%s-%d", ev, minor);
    219 		}
    220 		return true;
    221 	}
    222 
    223 	snprintf(buf, buflen, "UNKNOWN CPU TYPE (%u:%u)", major, minor);
    224 	return false;
    225 }
    226 
    227 static int
    228 cpu_sysctl_model(SYSCTLFN_ARGS)
    229 {
    230 	struct sysctlnode node = *rnode;
    231 	const struct cpu_softc * const sc = node.sysctl_data;
    232 	char model[32];
    233 
    234 	cpu_description(sc, model, sizeof(model));
    235 	node.sysctl_data = model;
    236 	return sysctl_lookup(SYSCTLFN_CALL(&node));
    237 }
    238 
    239 static int
    240 cpu_sysctl_amask_bit(SYSCTLFN_ARGS, unsigned long const bit)
    241 {
    242 	struct sysctlnode node = *rnode;
    243 	const struct cpu_softc * const sc = node.sysctl_data;
    244 
    245 	bool result = (sc->sc_amask & bit) ? true : false;
    246 	node.sysctl_data = &result;
    247 	return sysctl_lookup(SYSCTLFN_CALL(&node));
    248 }
    249 
    250 static int
    251 cpu_sysctl_bwx(SYSCTLFN_ARGS)
    252 {
    253 	return cpu_sysctl_amask_bit(SYSCTLFN_CALL(rnode), ALPHA_AMASK_BWX);
    254 }
    255 
    256 static int
    257 cpu_sysctl_fix(SYSCTLFN_ARGS)
    258 {
    259 	return cpu_sysctl_amask_bit(SYSCTLFN_CALL(rnode), ALPHA_AMASK_FIX);
    260 }
    261 
    262 static int
    263 cpu_sysctl_cix(SYSCTLFN_ARGS)
    264 {
    265 	return cpu_sysctl_amask_bit(SYSCTLFN_CALL(rnode), ALPHA_AMASK_CIX);
    266 }
    267 
    268 static int
    269 cpu_sysctl_mvi(SYSCTLFN_ARGS)
    270 {
    271 	return cpu_sysctl_amask_bit(SYSCTLFN_CALL(rnode), ALPHA_AMASK_MVI);
    272 }
    273 
    274 static int
    275 cpu_sysctl_pat(SYSCTLFN_ARGS)
    276 {
    277 	return cpu_sysctl_amask_bit(SYSCTLFN_CALL(rnode), ALPHA_AMASK_PAT);
    278 }
    279 
    280 static int
    281 cpu_sysctl_pmi(SYSCTLFN_ARGS)
    282 {
    283 	return cpu_sysctl_amask_bit(SYSCTLFN_CALL(rnode), ALPHA_AMASK_PMI);
    284 }
    285 
    286 static int
    287 cpu_sysctl_primary(SYSCTLFN_ARGS)
    288 {
    289 	struct sysctlnode node = *rnode;
    290 	const struct cpu_softc * const sc = node.sysctl_data;
    291 
    292 	bool result = CPU_IS_PRIMARY(sc->sc_ci);
    293 	node.sysctl_data = &result;
    294 	return sysctl_lookup(SYSCTLFN_CALL(&node));
    295 }
    296 
    297 /*
    298  * The following is an attempt to map out how booting secondary CPUs
    299  * works.
    300  *
    301  * As we find processors during the autoconfiguration sequence, all
    302  * processors have idle stacks and PCBs created for them, including
    303  * the primary (although the primary idles on lwp0's PCB until its
    304  * idle PCB is created).
    305  *
    306  * Right before calling uvm_scheduler(), main() calls, on lwp0's
    307  * context, cpu_boot_secondary_processors().  This is our key to
    308  * actually spin up the additional processor's we've found.  We
    309  * run through our cpu_info[] array looking for secondary processors
    310  * with idle PCBs, and spin them up.
    311  *
    312  * The spinup involves switching the secondary processor to the
    313  * OSF/1 PALcode, setting the entry point to cpu_spinup_trampoline(),
    314  * and sending a "START" message to the secondary's console.
    315  *
    316  * Upon successful processor bootup, the cpu_spinup_trampoline will call
    317  * cpu_hatch(), which will print a message indicating that the processor
    318  * is running, and will set the "hatched" flag in its softc.  At the end
    319  * of cpu_hatch() is a spin-forever loop; we do not yet attempt to schedule
    320  * anything on secondary CPUs.
    321  */
    322 
    323 static int
    324 cpumatch(device_t parent, cfdata_t cfdata, void *aux)
    325 {
    326 	struct mainbus_attach_args *ma = aux;
    327 
    328 	/* make sure that we're looking for a CPU. */
    329 	if (strcmp(ma->ma_name, cpu_cd.cd_name) != 0)
    330 		return (0);
    331 
    332 	/* XXX CHECK SLOT? */
    333 	/* XXX CHECK PRIMARY? */
    334 
    335 	return (1);
    336 }
    337 
    338 static void
    339 cpuattach(device_t parent, device_t self, void *aux)
    340 {
    341 	struct cpu_softc * const sc = device_private(self);
    342 	const struct mainbus_attach_args * const ma = aux;
    343 	struct cpu_info *ci;
    344 	char model[32];
    345 
    346 	const bool primary = ma->ma_slot == hwrpb->rpb_primary_cpu_id;
    347 
    348 	sc->sc_dev = self;
    349 
    350 	const struct pcs * const p = LOCATE_PCS(hwrpb, ma->ma_slot);
    351 	sc->sc_major_type = PCS_CPU_MAJORTYPE(p);
    352 	sc->sc_minor_type = PCS_CPU_MINORTYPE(p);
    353 
    354 	const bool recognized = cpu_description(sc, model, sizeof(model));
    355 
    356 	aprint_normal(": ID %d%s, ", ma->ma_slot, primary ? " (primary)" : "");
    357 	if (recognized) {
    358 		aprint_normal("%s", model);
    359 	} else {
    360 		aprint_error("%s", model);
    361 	}
    362 
    363 	aprint_naive("\n");
    364 	aprint_normal("\n");
    365 
    366 	if (p->pcs_proc_var != 0) {
    367 		bool needcomma = false;
    368 		const char *vaxfp = "";
    369 		const char *ieeefp = "";
    370 		const char *pe = "";
    371 
    372 		if (p->pcs_proc_var & PCS_VAR_VAXFP) {
    373 			sc->sc_vax_fp = true;
    374 			vaxfp = "VAX FP support";
    375 			needcomma = true;
    376 		}
    377 		if (p->pcs_proc_var & PCS_VAR_IEEEFP) {
    378 			sc->sc_ieee_fp = true;
    379 			ieeefp = ", IEEE FP support";
    380 			if (!needcomma)
    381 				ieeefp += 2;
    382 			needcomma = true;
    383 		}
    384 		if (p->pcs_proc_var & PCS_VAR_PE) {
    385 			sc->sc_primary_eligible = true;
    386 			pe = ", Primary Eligible";
    387 			if (!needcomma)
    388 				pe += 2;
    389 			needcomma = true;
    390 		}
    391 		aprint_debug_dev(sc->sc_dev, "%s%s%s", vaxfp, ieeefp, pe);
    392 		if (p->pcs_proc_var & PCS_VAR_RESERVED)
    393 			aprint_debug("%sreserved bits: %#lx",
    394 			    needcomma ? ", " : "",
    395 			    p->pcs_proc_var & PCS_VAR_RESERVED);
    396 		aprint_debug("\n");
    397 	}
    398 
    399 	if (ma->ma_slot > ALPHA_WHAMI_MAXID) {
    400 		if (primary)
    401 			panic("cpu_attach: primary CPU ID too large");
    402 		aprint_error_dev(sc->sc_dev,
    403 		    "processor ID too large, ignoring\n");
    404 		return;
    405 	}
    406 
    407 	if (primary) {
    408 		ci = &cpu_info_primary;
    409 	} else {
    410 		/*
    411 		 * kmem_zalloc() will guarante cache line alignment for
    412 		 * all allocations >= CACHE_LINE_SIZE.
    413 		 */
    414 		ci = kmem_zalloc(sizeof(*ci), KM_SLEEP);
    415 		KASSERT(((uintptr_t)ci & (CACHE_LINE_SIZE - 1)) == 0);
    416 	}
    417 #if defined(MULTIPROCESSOR)
    418 	cpu_info[ma->ma_slot] = ci;
    419 #endif
    420 	ci->ci_cpuid = ma->ma_slot;
    421 	ci->ci_softc = sc;
    422 	ci->ci_pcc_freq = hwrpb->rpb_cc_freq;
    423 
    424 	sc->sc_ci = ci;
    425 
    426 #if defined(MULTIPROCESSOR)
    427 	/*
    428 	 * Make sure the processor is available for use.
    429 	 */
    430 	if ((p->pcs_flags & PCS_PA) == 0) {
    431 		if (primary)
    432 			panic("cpu_attach: primary not available?!");
    433 		aprint_normal_dev(sc->sc_dev,
    434 		    "processor not available for use\n");
    435 		return;
    436 	}
    437 
    438 	/* Make sure the processor has valid PALcode. */
    439 	if ((p->pcs_flags & PCS_PV) == 0) {
    440 		if (primary)
    441 			panic("cpu_attach: primary has invalid PALcode?!");
    442 		aprint_error_dev(sc->sc_dev, "PALcode not valid\n");
    443 		return;
    444 	}
    445 #endif /* MULTIPROCESSOR */
    446 
    447 	/*
    448 	 * If we're the primary CPU, no more work to do; we're already
    449 	 * running!
    450 	 */
    451 	if (primary) {
    452 		cpu_announce_extensions(ci);
    453 #if defined(MULTIPROCESSOR)
    454 		KASSERT(ci->ci_flags & CPUF_PRIMARY);
    455 		KASSERT(ci->ci_flags & CPUF_RUNNING);
    456 		atomic_or_ulong(&cpus_booted, (1UL << ma->ma_slot));
    457 		atomic_or_ulong(&cpus_running, (1UL << ma->ma_slot));
    458 #endif /* MULTIPROCESSOR */
    459 	} else {
    460 #if defined(MULTIPROCESSOR)
    461 		int error;
    462 
    463 		error = mi_cpu_attach(ci);
    464 		if (error != 0) {
    465 			aprint_error_dev(sc->sc_dev,
    466 			    "mi_cpu_attach failed with %d\n", error);
    467 			return;
    468 		}
    469 
    470 		/*
    471 		 * Boot the secondary processor.  It will announce its
    472 		 * extensions, and then spin until we tell it to go
    473 		 * on its merry way.
    474 		 */
    475 		cpu_boot_secondary(ci);
    476 
    477 		/*
    478 		 * Link the processor into the list.
    479 		 */
    480 		ci->ci_next = cpu_info_list->ci_next;
    481 		cpu_info_list->ci_next = ci;
    482 #else /* ! MULTIPROCESSOR */
    483 		aprint_normal_dev(sc->sc_dev, "processor off-line; "
    484 		    "multiprocessor support not present in kernel\n");
    485 #endif /* MULTIPROCESSOR */
    486 	}
    487 
    488 	evcnt_attach_dynamic(&sc->sc_evcnt_clock, EVCNT_TYPE_INTR,
    489 	    NULL, device_xname(sc->sc_dev), "clock");
    490 	evcnt_attach_dynamic(&sc->sc_evcnt_device, EVCNT_TYPE_INTR,
    491 	    NULL, device_xname(sc->sc_dev), "device");
    492 #if defined(MULTIPROCESSOR)
    493 	alpha_ipi_init(ci);
    494 #endif
    495 
    496 	struct sysctllog **log = &sc->sc_sysctllog;
    497 	const struct sysctlnode *rnode, *cnode;
    498 	int error;
    499 
    500 	error = sysctl_createv(log, 0, NULL, &rnode, CTLFLAG_PERMANENT,
    501 	    CTLTYPE_NODE, device_xname(sc->sc_dev),
    502 	    SYSCTL_DESCR("cpu properties"),
    503 	    NULL, 0,
    504 	    NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
    505 	if (error)
    506 		return;
    507 
    508 	error = sysctl_createv(log, 0, &rnode, &cnode,
    509 	    CTLFLAG_PERMANENT, CTLTYPE_STRING, "model",
    510 	    SYSCTL_DESCR("cpu model"),
    511 	    cpu_sysctl_model, 0,
    512 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    513 	if (error)
    514 		return;
    515 
    516 	error = sysctl_createv(log, 0, &rnode, &cnode,
    517 	    CTLFLAG_PERMANENT, CTLTYPE_INT, "major",
    518 	    SYSCTL_DESCR("cpu major type"),
    519 	    NULL, 0,
    520 	    &sc->sc_major_type, 0, CTL_CREATE, CTL_EOL);
    521 	if (error)
    522 		return;
    523 
    524 	error = sysctl_createv(log, 0, &rnode, &cnode,
    525 	    CTLFLAG_PERMANENT, CTLTYPE_INT, "minor",
    526 	    SYSCTL_DESCR("cpu minor type"),
    527 	    NULL, 0,
    528 	    &sc->sc_minor_type, 0, CTL_CREATE, CTL_EOL);
    529 	if (error)
    530 		return;
    531 
    532 	error = sysctl_createv(log, 0, &rnode, &cnode,
    533 	    CTLFLAG_PERMANENT, CTLTYPE_LONG, "implver",
    534 	    SYSCTL_DESCR("cpu implementation version"),
    535 	    NULL, 0,
    536 	    &sc->sc_implver, 0, CTL_CREATE, CTL_EOL);
    537 	if (error)
    538 		return;
    539 
    540 	error = sysctl_createv(log, 0, &rnode, &cnode,
    541 	    CTLFLAG_PERMANENT|CTLFLAG_HEX, CTLTYPE_LONG, "amask",
    542 	    SYSCTL_DESCR("architecture extensions mask"),
    543 	    NULL, 0,
    544 	    &sc->sc_amask, 0, CTL_CREATE, CTL_EOL);
    545 	if (error)
    546 		return;
    547 
    548 	error = sysctl_createv(log, 0, &rnode, &cnode,
    549 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "bwx",
    550 	    SYSCTL_DESCR("cpu supports BWX extension"),
    551 	    cpu_sysctl_bwx, 0,
    552 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    553 	if (error)
    554 		return;
    555 
    556 	error = sysctl_createv(log, 0, &rnode, &cnode,
    557 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "fix",
    558 	    SYSCTL_DESCR("cpu supports FIX extension"),
    559 	    cpu_sysctl_fix, 0,
    560 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    561 	if (error)
    562 		return;
    563 
    564 	error = sysctl_createv(log, 0, &rnode, &cnode,
    565 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "cix",
    566 	    SYSCTL_DESCR("cpu supports CIX extension"),
    567 	    cpu_sysctl_cix, 0,
    568 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    569 	if (error)
    570 		return;
    571 
    572 	error = sysctl_createv(log, 0, &rnode, &cnode,
    573 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "mvi",
    574 	    SYSCTL_DESCR("cpu supports MVI extension"),
    575 	    cpu_sysctl_mvi, 0,
    576 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    577 	if (error)
    578 		return;
    579 
    580 	error = sysctl_createv(log, 0, &rnode, &cnode,
    581 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "pat",
    582 	    SYSCTL_DESCR("cpu supports PAT extension"),
    583 	    cpu_sysctl_pat, 0,
    584 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    585 	if (error)
    586 		return;
    587 
    588 	error = sysctl_createv(log, 0, &rnode, &cnode,
    589 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "pmi",
    590 	    SYSCTL_DESCR("cpu supports PMI extension"),
    591 	    cpu_sysctl_pmi, 0,
    592 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    593 	if (error)
    594 		return;
    595 
    596 	error = sysctl_createv(log, 0, &rnode, &cnode,
    597 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "vax_fp",
    598 	    SYSCTL_DESCR("cpu supports VAX FP"),
    599 	    NULL, 0,
    600 	    &sc->sc_vax_fp, 0, CTL_CREATE, CTL_EOL);
    601 	if (error)
    602 		return;
    603 
    604 	error = sysctl_createv(log, 0, &rnode, &cnode,
    605 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "ieee_fp",
    606 	    SYSCTL_DESCR("cpu supports IEEE FP"),
    607 	    NULL, 0,
    608 	    &sc->sc_ieee_fp, 0, CTL_CREATE, CTL_EOL);
    609 	if (error)
    610 		return;
    611 
    612 	error = sysctl_createv(log, 0, &rnode, &cnode,
    613 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "primary_eligible",
    614 	    SYSCTL_DESCR("cpu is primary-eligible"),
    615 	    NULL, 0,
    616 	    &sc->sc_primary_eligible, 0, CTL_CREATE, CTL_EOL);
    617 	if (error)
    618 		return;
    619 
    620 	error = sysctl_createv(log, 0, &rnode, &cnode,
    621 	    CTLFLAG_PERMANENT, CTLTYPE_BOOL, "primary",
    622 	    SYSCTL_DESCR("cpu is the primary cpu"),
    623 	    cpu_sysctl_primary, 0,
    624 	    (void *)sc, 0, CTL_CREATE, CTL_EOL);
    625 	if (error)
    626 		return;
    627 
    628 	error = sysctl_createv(log, 0, &rnode, &cnode,
    629 	    CTLFLAG_PERMANENT, CTLTYPE_LONG, "cpu_id",
    630 	    SYSCTL_DESCR("hardware cpu ID"),
    631 	    NULL, 0,
    632 	    &sc->sc_ci->ci_cpuid, 0, CTL_CREATE, CTL_EOL);
    633 	if (error)
    634 		return;
    635 
    636 	error = sysctl_createv(log, 0, &rnode, &cnode,
    637 	    CTLFLAG_PERMANENT, CTLTYPE_LONG, "pcc_freq",
    638 	    SYSCTL_DESCR("PCC frequency"),
    639 	    NULL, 0,
    640 	    &sc->sc_ci->ci_pcc_freq, 0, CTL_CREATE, CTL_EOL);
    641 	if (error)
    642 		return;
    643 }
    644 
    645 static void
    646 cpu_announce_extensions(struct cpu_info *ci)
    647 {
    648 	u_long implver, amask = 0;
    649 	char bits[64];
    650 
    651 	implver = alpha_implver();
    652 	if (implver >= ALPHA_IMPLVER_EV5)
    653 		amask = (~alpha_amask(ALPHA_AMASK_ALL)) & ALPHA_AMASK_ALL;
    654 
    655 	ci->ci_softc->sc_implver = implver;
    656 	ci->ci_softc->sc_amask = amask;
    657 
    658 	if (ci->ci_cpuid == hwrpb->rpb_primary_cpu_id) {
    659 		cpu_implver = implver;
    660 		cpu_amask = amask;
    661 	} else {
    662 		if (implver < cpu_implver)
    663 			aprint_error_dev(ci->ci_softc->sc_dev,
    664 			    "WARNING: IMPLVER %lu < %lu\n",
    665 			    implver, cpu_implver);
    666 
    667 		/*
    668 		 * Cap the system architecture mask to the intersection
    669 		 * of features supported by all processors in the system.
    670 		 */
    671 		cpu_amask &= amask;
    672 	}
    673 
    674 	if (amask) {
    675 		snprintb(bits, sizeof(bits),
    676 		    ALPHA_AMASK_BITS, amask);
    677 		aprint_normal_dev(ci->ci_softc->sc_dev,
    678 		    "Architecture extensions: %s\n", bits);
    679 	}
    680 }
    681 
    682 #if defined(MULTIPROCESSOR)
    683 void
    684 cpu_boot_secondary_processors(void)
    685 {
    686 	struct cpu_info *ci;
    687 	u_long i;
    688 	bool did_patch = false;
    689 
    690 	for (i = 0; i < ALPHA_MAXPROCS; i++) {
    691 		ci = cpu_info[i];
    692 		if (ci == NULL || ci->ci_data.cpu_idlelwp == NULL)
    693 			continue;
    694 		if (CPU_IS_PRIMARY(ci))
    695 			continue;
    696 		if ((cpus_booted & (1UL << i)) == 0)
    697 			continue;
    698 
    699 		/* Patch MP-criticial kernel routines. */
    700 		if (did_patch == false) {
    701 			alpha_patch(true);
    702 			did_patch = true;
    703 		}
    704 
    705 		/*
    706 		 * Launch the processor.
    707 		 */
    708 		atomic_or_ulong(&ci->ci_flags, CPUF_RUNNING);
    709 		atomic_or_ulong(&cpus_running, (1U << i));
    710 	}
    711 }
    712 
    713 void
    714 cpu_boot_secondary(struct cpu_info *ci)
    715 {
    716 	long timeout;
    717 	struct pcs *pcsp, *primary_pcsp;
    718 	struct pcb *pcb;
    719 	u_long cpumask;
    720 
    721 	pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp);
    722 	primary_pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
    723 	pcsp = LOCATE_PCS(hwrpb, ci->ci_cpuid);
    724 	cpumask = (1UL << ci->ci_cpuid);
    725 
    726 	/*
    727 	 * Set up the PCS's HWPCB to match ours.
    728 	 */
    729 	memcpy(pcsp->pcs_hwpcb, &pcb->pcb_hw, sizeof(pcb->pcb_hw));
    730 
    731 	/*
    732 	 * Set up the HWRPB to restart the secondary processor
    733 	 * with our spin-up trampoline.
    734 	 */
    735 	hwrpb->rpb_restart = (uint64_t) cpu_spinup_trampoline;
    736 	hwrpb->rpb_restart_val = (uint64_t) ci;
    737 	hwrpb->rpb_checksum = hwrpb_checksum();
    738 
    739 	/*
    740 	 * Configure the CPU to start in OSF/1 PALcode by copying
    741 	 * the primary CPU's PALcode revision info to the secondary
    742 	 * CPUs PCS.
    743 	 */
    744 	memcpy(&pcsp->pcs_pal_rev, &primary_pcsp->pcs_pal_rev,
    745 	    sizeof(pcsp->pcs_pal_rev));
    746 	pcsp->pcs_flags |= (PCS_CV|PCS_RC);
    747 	pcsp->pcs_flags &= ~PCS_BIP;
    748 
    749 	/* Make sure the secondary console sees all this. */
    750 	alpha_mb();
    751 
    752 	/* Send a "START" command to the secondary CPU's console. */
    753 	if (cpu_iccb_send(ci->ci_cpuid, "START\r\n")) {
    754 		aprint_error_dev(ci->ci_softc->sc_dev,
    755 		    "unable to issue `START' command\n");
    756 		return;
    757 	}
    758 
    759 	/* Wait for the processor to boot. */
    760 	for (timeout = 10000; timeout != 0; timeout--) {
    761 		alpha_mb();
    762 		if (pcsp->pcs_flags & PCS_BIP)
    763 			break;
    764 		delay(1000);
    765 	}
    766 	if (timeout == 0)
    767 		aprint_error_dev(ci->ci_softc->sc_dev,
    768 		    "processor failed to boot\n");
    769 
    770 	/*
    771 	 * ...and now wait for verification that it's running kernel
    772 	 * code.
    773 	 */
    774 	for (timeout = 10000; timeout != 0; timeout--) {
    775 		alpha_mb();
    776 		if (cpus_booted & cpumask)
    777 			break;
    778 		delay(1000);
    779 	}
    780 	if (timeout == 0)
    781 		aprint_error_dev(ci->ci_softc->sc_dev,
    782 		    "processor failed to hatch\n");
    783 }
    784 
    785 void
    786 cpu_pause_resume(u_long cpu_id, int pause)
    787 {
    788 	u_long cpu_mask = (1UL << cpu_id);
    789 
    790 	if (pause) {
    791 		atomic_or_ulong(&cpus_paused, cpu_mask);
    792 		alpha_send_ipi(cpu_id, ALPHA_IPI_PAUSE);
    793 	} else
    794 		atomic_and_ulong(&cpus_paused, ~cpu_mask);
    795 }
    796 
    797 void
    798 cpu_pause_resume_all(int pause)
    799 {
    800 	struct cpu_info *ci, *self = curcpu();
    801 	CPU_INFO_ITERATOR cii;
    802 
    803 	for (CPU_INFO_FOREACH(cii, ci)) {
    804 		if (ci == self)
    805 			continue;
    806 		cpu_pause_resume(ci->ci_cpuid, pause);
    807 	}
    808 }
    809 
    810 void
    811 cpu_halt(void)
    812 {
    813 	struct cpu_info *ci = curcpu();
    814 	u_long cpu_id = cpu_number();
    815 	struct pcs *pcsp = LOCATE_PCS(hwrpb, cpu_id);
    816 
    817 	aprint_normal_dev(ci->ci_softc->sc_dev, "shutting down...\n");
    818 
    819 	pcsp->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ);
    820 	pcsp->pcs_flags |= PCS_HALT_STAY_HALTED;
    821 
    822 	atomic_and_ulong(&cpus_running, ~(1UL << cpu_id));
    823 	atomic_and_ulong(&cpus_booted, ~(1U << cpu_id));
    824 
    825 	alpha_pal_halt();
    826 	/* NOTREACHED */
    827 }
    828 
    829 void
    830 cpu_hatch(struct cpu_info *ci)
    831 {
    832 	u_long cpu_id = cpu_number();
    833 	u_long cpumask = (1UL << cpu_id);
    834 
    835 	/* pmap initialization for this processor. */
    836 	pmap_init_cpu(ci);
    837 
    838 	/* Initialize trap vectors for this processor. */
    839 	trap_init();
    840 
    841 	/* Yahoo!  We're running kernel code!  Announce it! */
    842 	cpu_announce_extensions(ci);
    843 
    844 	atomic_or_ulong(&cpus_booted, cpumask);
    845 
    846 	/*
    847 	 * Spin here until we're told we can start.
    848 	 */
    849 	while ((cpus_running & cpumask) == 0)
    850 		/* spin */ ;
    851 
    852 	/*
    853 	 * Invalidate the TLB and sync the I-stream before we
    854 	 * jump into the kernel proper.  We have to do this
    855 	 * because we haven't been getting IPIs while we've
    856 	 * been spinning.
    857 	 */
    858 	ALPHA_TBIA();
    859 	alpha_pal_imb();
    860 
    861 	if (alpha_use_cctr) {
    862 		cc_init_secondary(ci);
    863 	}
    864 
    865 	cpu_initclocks_secondary();
    866 }
    867 
    868 int
    869 cpu_iccb_send(long cpu_id, const char *msg)
    870 {
    871 	struct pcs *pcsp = LOCATE_PCS(hwrpb, cpu_id);
    872 	int timeout;
    873 	u_long cpumask = (1UL << cpu_id);
    874 
    875 	/* Wait for the ICCB to become available. */
    876 	for (timeout = 10000; timeout != 0; timeout--) {
    877 		alpha_mb();
    878 		if ((hwrpb->rpb_rxrdy & cpumask) == 0)
    879 			break;
    880 		delay(1000);
    881 	}
    882 	if (timeout == 0)
    883 		return (EIO);
    884 
    885 	/*
    886 	 * Copy the message into the ICCB, and tell the secondary console
    887 	 * that it's there.  Ensure the buffer is initialized before we
    888 	 * set the rxrdy bits, as a store-release.
    889 	 */
    890 	strcpy(pcsp->pcs_iccb.iccb_rxbuf, msg);
    891 	pcsp->pcs_iccb.iccb_rxlen = strlen(msg);
    892 	membar_release();
    893 	atomic_or_ulong(&hwrpb->rpb_rxrdy, cpumask);
    894 
    895 	/* Wait for the message to be received. */
    896 	for (timeout = 10000; timeout != 0; timeout--) {
    897 		alpha_mb();
    898 		if ((hwrpb->rpb_rxrdy & cpumask) == 0)
    899 			break;
    900 		delay(1000);
    901 	}
    902 	if (timeout == 0)
    903 		return (EIO);
    904 
    905 	return (0);
    906 }
    907 
    908 void
    909 cpu_iccb_receive(void)
    910 {
    911 #if 0	/* Don't bother... we don't get any important messages anyhow. */
    912 	uint64_t txrdy;
    913 	char *cp1, *cp2, buf[80];
    914 	struct pcs *pcsp;
    915 	u_int cnt;
    916 	long cpu_id;
    917 
    918 	txrdy = hwrpb->rpb_txrdy;
    919 
    920 	for (cpu_id = 0; cpu_id < hwrpb->rpb_pcs_cnt; cpu_id++) {
    921 		if (txrdy & (1UL << cpu_id)) {
    922 			pcsp = LOCATE_PCS(hwrpb, cpu_id);
    923 			printf("Inter-console message from CPU %lu "
    924 			    "HALT REASON = 0x%lx, FLAGS = 0x%lx\n",
    925 			    cpu_id, pcsp->pcs_halt_reason, pcsp->pcs_flags);
    926 
    927 			cnt = pcsp->pcs_iccb.iccb_txlen;
    928 			if (cnt >= 80) {
    929 				printf("Malformed inter-console message\n");
    930 				continue;
    931 			}
    932 			cp1 = pcsp->pcs_iccb.iccb_txbuf;
    933 			cp2 = buf;
    934 			while (cnt--) {
    935 				if (*cp1 != '\r' && *cp1 != '\n')
    936 					*cp2++ = *cp1;
    937 				cp1++;
    938 			}
    939 			*cp2 = '\0';
    940 			printf("Message from CPU %lu: %s\n", cpu_id, buf);
    941 		}
    942 	}
    943 #endif /* 0 */
    944 	hwrpb->rpb_txrdy = 0;
    945 	alpha_mb();
    946 }
    947 
    948 #if defined(DDB)
    949 
    950 #include <ddb/db_output.h>
    951 #include <machine/db_machdep.h>
    952 
    953 /*
    954  * Dump CPU information from DDB.
    955  */
    956 void
    957 cpu_debug_dump(void)
    958 {
    959 	struct cpu_info *ci;
    960 	CPU_INFO_ITERATOR cii;
    961 
    962 	db_printf("addr		dev	id	flags	ipis	curproc\n");
    963 	for (CPU_INFO_FOREACH(cii, ci)) {
    964 		db_printf("%p	%s	%lu	%lx	%lx	%p\n",
    965 		    ci,
    966 		    device_xname(ci->ci_softc->sc_dev),
    967 		    ci->ci_cpuid,
    968 		    ci->ci_flags,
    969 		    ci->ci_ipis,
    970 		    ci->ci_curlwp);
    971 	}
    972 }
    973 
    974 #endif /* DDB */
    975 
    976 #endif /* MULTIPROCESSOR */
    977