Home | History | Annotate | Line # | Download | only in alpha
      1 /* $NetBSD: dec_kn8ae.c,v 1.45 2025/03/09 01:06:42 thorpej Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1997 by Matthew Jacob
      5  * NASA AMES Research Center.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice immediately at the beginning of the file, without modification,
     13  *    this list of conditions, and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  * SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     34 
     35 __KERNEL_RCSID(0, "$NetBSD: dec_kn8ae.c,v 1.45 2025/03/09 01:06:42 thorpej Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/device.h>
     40 #include <sys/lwp.h>
     41 
     42 #include <machine/rpb.h>
     43 #include <machine/autoconf.h>
     44 #include <machine/cpuconf.h>
     45 #include <machine/frame.h>
     46 #include <machine/alpha.h>
     47 #include <machine/logout.h>
     48 
     49 #include <dev/pci/pcivar.h>
     50 
     51 #include <alpha/tlsb/tlsbreg.h>
     52 #include <alpha/tlsb/tlsbvar.h>
     53 #include <alpha/tlsb/kftxxreg.h>
     54 #include <alpha/tlsb/kftxxvar.h>
     55 
     56 #define	KV(_addr)	((void *)ALPHA_PHYS_TO_K0SEG((_addr)))
     57 
     58 void dec_kn8ae_init(void);
     59 void dec_kn8ae_cons_init(void);
     60 static void dec_kn8ae_device_register(device_t, void *);
     61 
     62 static void dec_kn8ae_mcheck_handler
     63 (unsigned long, struct trapframe *, unsigned long, unsigned long);
     64 
     65 const struct alpha_variation_table dec_kn8ae_variations[] = {
     66 	{ 0, "AlphaServer 8400" },
     67 	{ 0, NULL },
     68 };
     69 
     70 void
     71 dec_kn8ae_init(void)
     72 {
     73 	uint64_t variation;
     74 
     75 	platform.family = "AlphaServer 8400";
     76 
     77 	if ((platform.model = alpha_dsr_sysname()) == NULL) {
     78 		variation = hwrpb->rpb_variation & SV_ST_MASK;
     79 		if ((platform.model = alpha_variation_name(variation,
     80 		    dec_kn8ae_variations)) == NULL)
     81 			platform.model = alpha_unknown_sysname();
     82 	}
     83 
     84 	platform.iobus = "tlsb";
     85 	platform.cons_init = dec_kn8ae_cons_init;
     86 	platform.device_register = dec_kn8ae_device_register;
     87 	platform.mcheck_handler = dec_kn8ae_mcheck_handler;
     88 }
     89 
     90 void
     91 dec_kn8ae_cons_init(void)
     92 {
     93 
     94 	/*
     95 	 * Info to retain:
     96 	 *
     97 	 *	The AXP 8X00 seems to encode the
     98 	 *	type of console in the ctb_type field,
     99 	 *	not the ctb_term_type field.
    100 	 *
    101 	 *	XXX Not Type 4 CTB?
    102 	 */
    103 }
    104 
    105 /* #define	BDEBUG	1 */
    106 static void
    107 dec_kn8ae_device_register(device_t dev, void *aux)
    108 {
    109 	static device_t primarydev;
    110 	struct bootdev_data *b = bootdev_data;
    111 
    112 	if (booted_device != NULL || b == NULL) {
    113 		return;
    114 	}
    115 
    116 	if (primarydev == NULL) {
    117 		if (device_is_a(dev, "dwlpx")) {
    118 			struct kft_dev_attach_args *ka = aux;
    119 
    120 			if (b->bus == ka->ka_hosenum) {
    121 				primarydev = dev;
    122 #ifdef BDEBUG
    123 				printf("\nprimarydev = %s\n",
    124 				    device_xname(dev));
    125 #endif
    126 			}
    127 		}
    128 		return;
    129 	}
    130 
    131 	pci_find_bootdev(primarydev, dev, aux);
    132 }
    133 
    134 /*
    135  * KN8AE Machine Check Handlers.
    136  */
    137 void kn8ae_harderr(unsigned long, unsigned long,
    138     unsigned long, struct trapframe *);
    139 
    140 static void kn8ae_softerr(unsigned long, unsigned long,
    141     unsigned long, struct trapframe *);
    142 
    143 void kn8ae_mcheck(unsigned long, unsigned long,
    144     unsigned long, struct trapframe *);
    145 
    146 /*
    147  * Support routine for clearing errors
    148  */
    149 static void clear_tlsb_ebits(int);
    150 
    151 static void
    152 clear_tlsb_ebits(int cpuonly)
    153 {
    154 	int node;
    155 	uint32_t tldev;
    156 
    157 	for (node = 0; node <= TLSB_NODE_MAX; ++node) {
    158 		if ((tlsb_found & (1 << node)) == 0)
    159 			continue;
    160 		tldev = TLSB_GET_NODEREG(node, TLDEV);
    161 		if (tldev == 0) {
    162 			/* "cannot happen" */
    163 			continue;
    164 		}
    165 		/*
    166 		 * Registers to clear for all nodes.
    167 		 */
    168 		if (TLSB_GET_NODEREG(node, TLBER) &
    169 		    (TLBER_UDE|TLBER_CWDE|TLBER_CRDE)) {
    170 			TLSB_PUT_NODEREG(node, TLESR0,
    171 			    TLSB_GET_NODEREG(node, TLESR0));
    172 			TLSB_PUT_NODEREG(node, TLESR1,
    173 			    TLSB_GET_NODEREG(node, TLESR1));
    174 			TLSB_PUT_NODEREG(node, TLESR2,
    175 			    TLSB_GET_NODEREG(node, TLESR2));
    176 			TLSB_PUT_NODEREG(node, TLESR3,
    177 			    TLSB_GET_NODEREG(node, TLESR3));
    178 		}
    179 		TLSB_PUT_NODEREG(node, TLBER,
    180 		    TLSB_GET_NODEREG(node, TLBER));
    181 		TLSB_PUT_NODEREG(node, TLFADR0,
    182 		    TLSB_GET_NODEREG(node, TLFADR0));
    183 		TLSB_PUT_NODEREG(node, TLFADR1,
    184 		    TLSB_GET_NODEREG(node, TLFADR1));
    185 
    186 		if (TLDEV_ISCPU(tldev)) {
    187 			TLSB_PUT_NODEREG(node, TLEPAERR,
    188 			    TLSB_GET_NODEREG(node, TLEPAERR));
    189 			TLSB_PUT_NODEREG(node, TLEPDERR,
    190 			    TLSB_GET_NODEREG(node, TLEPDERR));
    191 			TLSB_PUT_NODEREG(node, TLEPMERR,
    192 			    TLSB_GET_NODEREG(node, TLEPMERR));
    193 			continue;
    194 		}
    195 		/*
    196 		 * If we're only doing CPU nodes, or this was a memory
    197 		 * node, we're done. Onwards.
    198 		 */
    199 		if (cpuonly || TLDEV_ISMEM(tldev)) {
    200 			continue;
    201 		}
    202 
    203 		TLSB_PUT_NODEREG(node, KFT_ICCNSE,
    204 		    TLSB_GET_NODEREG(node, KFT_ICCNSE));
    205 		TLSB_PUT_NODEREG(node, KFT_IDPNSE0,
    206 		    TLSB_GET_NODEREG(node, KFT_IDPNSE0));
    207 		TLSB_PUT_NODEREG(node, KFT_IDPNSE1,
    208 		    TLSB_GET_NODEREG(node, KFT_IDPNSE1));
    209 		if (TLDEV_DTYPE(tldev) == TLDEV_DTYPE_KFTHA) {
    210 			TLSB_PUT_NODEREG(node, KFT_IDPNSE2,
    211 			    TLSB_GET_NODEREG(node, KFT_IDPNSE2));
    212 			TLSB_PUT_NODEREG(node, KFT_IDPNSE3,
    213 			    TLSB_GET_NODEREG(node, KFT_IDPNSE3));
    214 		}
    215 		/*
    216 		 * Digital Unix cleares the Mailbox Transaction Register
    217 		 * here. I don't think we should because we aren't using
    218 		 * mailboxes yet, and the tech manual makes dire warnings
    219 		 * about *not* rewriting this register.
    220 		 */
    221 	}
    222 }
    223 
    224 /*
    225  * System Corrected Errors.
    226  */
    227 static const char *fmt1 = "        %-25s = 0x%l016x\n";
    228 
    229 void
    230 kn8ae_harderr(unsigned long mces, unsigned long type, unsigned long logout, struct trapframe *framep)
    231 {
    232 	int whami, cpuwerr, dof_cnt;
    233 	mc_hdr_ev5 *hdr;
    234 	mc_cc_ev5 *mptr;
    235 	struct tlsb_mchk_fatal *ptr;
    236 
    237 	hdr = (mc_hdr_ev5 *) logout;
    238 	mptr = (mc_cc_ev5 *) (logout + sizeof (*hdr));
    239 	ptr = (struct tlsb_mchk_fatal *)
    240 		(logout + sizeof (*hdr) + sizeof (*mptr));
    241 	whami = alpha_pal_whami();
    242 
    243 	printf("kn8ae: CPU ID %d system correctable error\n", whami);
    244 
    245 	printf("    Machine Check Code 0x%lx\n", hdr->mcheck_code);
    246 	printf(fmt1, "EI Status", mptr->ei_stat);
    247 	printf(fmt1, "EI Address", mptr->ei_addr);
    248 	printf(fmt1, "Fill Syndrome", mptr->fill_syndrome);
    249 	printf(fmt1, "Interrupt Status Reg.", mptr->isr);
    250 	printf("\n");
    251 	dof_cnt = (ptr->rsvdheader & 0xffffffff00000000) >> 32;
    252 	cpuwerr = ptr->rsvdheader & 0xffff;
    253 
    254 	printf(fmt1, "CPU W/Error.", cpuwerr);
    255 	printf(fmt1, "DOF Count.", dof_cnt);
    256 	printf(fmt1, "TLDEV", ptr->tldev);
    257 	printf(fmt1, "TLSB Bus Error", ptr->tlber);
    258 	printf(fmt1, "TLSB CNR", ptr->tlcnr);
    259 	printf(fmt1, "TLSB VID", ptr->tlvid);
    260 	printf(fmt1, "TLSB Error Syndrome 0", ptr->tlesr0);
    261 	printf(fmt1, "TLSB Error Syndrome 1", ptr->tlesr1);
    262 	printf(fmt1, "TLSB Error Syndrome 2", ptr->tlesr2);
    263 	printf(fmt1, "TLSB Error Syndrome 3", ptr->tlesr3);
    264 	printf(fmt1, "TLSB LEP_AERR", ptr->tlepaerr);
    265 	printf(fmt1, "TLSB MODCONF", ptr->tlmodconfig);
    266 	printf(fmt1, "TLSB LEP_MERR", ptr->tlepmerr);
    267 	printf(fmt1, "TLSB LEP_DERR", ptr->tlepderr);
    268 	printf(fmt1, "TLSB INTRMASK0", ptr->tlintrmask0);
    269 	printf(fmt1, "TLSB INTRMASK1", ptr->tlintrmask1);
    270 	printf(fmt1, "TLSB INTRSUM0", ptr->tlintrsum0);
    271 	printf(fmt1, "TLSB INTRSUM1", ptr->tlintrsum1);
    272 	printf(fmt1, "TLSB VMG", ptr->tlep_vmg);
    273 
    274 	/* CLEAN UP */
    275 	/*
    276 	 * Here's what Digital Unix says to do-
    277 	 *
    278 	 * 1. Log the ECC error that got us here
    279 	 *
    280 	 * 2. Turn off error reporting
    281 	 *
    282 	 * 3. Attempt to have CPU read bad memory location (specified by the
    283 	 *    tlfadr reg of the TIOP or TMEM (depending on type of error,
    284 	 *    see upcoming code branches) and write data back to location.
    285 	 *
    286 	 * 4. When the CPU attempts to read the location, another 620 interrupt
    287 	 *    should occur for the CPU at which instant PAL will scrub the
    288 	 *    location. Then the o.s. scrub routine finishes. If the PAL scrubs
    289 	 *    the location then the scrubbed flag should be 0 (this is what we
    290 	 *    expect).
    291 	 *
    292 	 *    If it's a 1 then the alpha_scrub_long routine did the scrub.
    293 	 *
    294 	 * 5. We renable correctable error logging and continue
    295 	 */
    296 	printf("WARNING THIS IS NOT DONE YET YOU MAY GET DATA CORRUPTION");
    297 	clear_tlsb_ebits(0);
    298 	/*
    299 	 * Clear error by rewriting register.
    300 	 */
    301 	alpha_pal_wrmces(mces);
    302 }
    303 
    304 /*
    305  *  Processor Corrected Errors- BCACHE ECC errors.
    306  */
    307 
    308 static void
    309 kn8ae_softerr(unsigned long mces, unsigned long type, unsigned long logout, struct trapframe *framep)
    310 {
    311 	int whami, cpuwerr, dof_cnt;
    312 	mc_hdr_ev5 *hdr;
    313 	mc_cc_ev5 *mptr;
    314 	struct tlsb_mchk_soft *ptr;
    315 
    316 	hdr = (mc_hdr_ev5 *) logout;
    317 	mptr = (mc_cc_ev5 *) (logout + sizeof (*hdr));
    318 	ptr = (struct tlsb_mchk_soft *)
    319 		(logout + sizeof (*hdr) + sizeof (*mptr));
    320 	whami = alpha_pal_whami();
    321 
    322 	printf("kn8ae: CPU ID %d processor correctable error\n", whami);
    323 	printf("    Machine Check Code 0x%lx\n", hdr->mcheck_code);
    324 	printf(fmt1, "EI Status", mptr->ei_stat);
    325 	printf(fmt1, "EI Address", mptr->ei_addr);
    326 	printf(fmt1, "Fill Syndrome", mptr->fill_syndrome);
    327 	printf(fmt1, "Interrupt Status Reg.", mptr->isr);
    328 	printf("\n");
    329 	dof_cnt = (ptr->rsvdheader & 0xffffffff00000000) >> 32;
    330 	cpuwerr = ptr->rsvdheader & 0xffff;
    331 
    332 	printf(fmt1, "CPU W/Error.", cpuwerr);
    333 	printf(fmt1, "DOF Count.", dof_cnt);
    334 	printf(fmt1, "TLDEV", ptr->tldev);
    335 	printf(fmt1, "TLSB Bus Error", ptr->tlber);
    336 	printf(fmt1, "TLSB Error Syndrome 0", ptr->tlesr0);
    337 	printf(fmt1, "TLSB Error Syndrome 1", ptr->tlesr1);
    338 	printf(fmt1, "TLSB Error Syndrome 2", ptr->tlesr2);
    339 	printf(fmt1, "TLSB Error Syndrome 3", ptr->tlesr3);
    340 
    341 	/*
    342 	 * Clear TLSB bits on all CPU TLSB nodes.
    343 	 */
    344 	clear_tlsb_ebits(1);
    345 
    346 	/*
    347 	 * Clear error by rewriting register.
    348 	 */
    349 	alpha_pal_wrmces(mces);
    350 }
    351 
    352 /*
    353  * KN8AE specific machine check handler
    354  */
    355 
    356 void
    357 kn8ae_mcheck(unsigned long mces, unsigned long type, unsigned long logout, struct trapframe *framep)
    358 {
    359 	struct mchkinfo *mcp;
    360 	struct tlsb_mchk_fatal mcs[TLSB_NODE_MAX+1], *ptr;
    361 	mc_hdr_ev5 *hdr;
    362 	mc_uc_ev5 *mptr;
    363 
    364 	/*
    365 	 * If we expected a machine check, just go handle it in common code.
    366 	 */
    367 	mcp = &curcpu()->ci_mcinfo;
    368 	if (mcp->mc_expected) {
    369 		machine_check(mces, framep, type, logout);
    370 		return;
    371 	}
    372 
    373 	ptr = NULL;
    374 	memset(mcs, 0, sizeof (mcs));
    375 
    376 	hdr = (mc_hdr_ev5 *) logout;
    377 	mptr = (mc_uc_ev5 *) (logout + sizeof (*hdr));
    378 
    379 	/*
    380 	 * If detected by the system, we print out some TLASER registers.
    381 	 */
    382 	if (type == ALPHA_SYS_MCHECK) {
    383 #if	0
    384 		int get_lsb_regs = 0;
    385 		int get_dwlpx_regs = 0;
    386 #endif
    387 
    388 		ptr = (struct tlsb_mchk_fatal *)
    389 		    (logout + sizeof (*hdr) + sizeof (*mptr));
    390 
    391 #if	0
    392 		if (ptr->tlepaerr & TLEPAERR_WSPC_RD) {
    393 			get_dwlpx_regs++;
    394 		}
    395 		if ((ptr->tlepaerr & TLEPAERR_IBOX_TMO) &&
    396 		    (mptr->ic_perr_stat & EV5_IC_PERR_IBOXTMO) &&
    397 		    (ptr->tlepderr & TLEPDERR_GBTMO)) {
    398 			get_dwlpx_regs++;
    399 		}
    400 #endif
    401 	} else {
    402 		/*
    403 		 * We have a processor machine check- which doesn't
    404 		 * have information with it about any TLSB related
    405 		 * failures.
    406 		 */
    407 	}
    408 
    409 	/*
    410 	 * Now we can finally print some stuff...
    411 	 */
    412 	ev5_logout_print(hdr, mptr);
    413 	if (type == ALPHA_SYS_MCHECK) {
    414 		if (ptr->tlepaerr & TLEPAERR_WSPC_RD) {
    415 			printf("\tWSPC READ error\n");
    416 		}
    417 		if ((ptr->tlepaerr & TLEPAERR_IBOX_TMO) &&
    418 		    (mptr->ic_perr_stat & EV5_IC_PERR_IBOXTMO) &&
    419 		    (ptr->tlepderr & TLEPDERR_GBTMO)) {
    420 			printf ("\tWSPC IBOX timeout detected\n");
    421 		}
    422 #ifdef	DIAGNOSTIC
    423 		printf(fmt1, "TLDEV", ptr->tldev);
    424 		printf(fmt1, "TLSB Bus Error", ptr->tlber);
    425 		printf(fmt1, "TLSB CNR", ptr->tlcnr);
    426 		printf(fmt1, "TLSB VID", ptr->tlvid);
    427 		printf(fmt1, "TLSB Error Syndrome 0", ptr->tlesr0);
    428 		printf(fmt1, "TLSB Error Syndrome 1", ptr->tlesr1);
    429 		printf(fmt1, "TLSB Error Syndrome 2", ptr->tlesr2);
    430 		printf(fmt1, "TLSB Error Syndrome 3", ptr->tlesr3);
    431 		printf(fmt1, "TLSB LEP_AERR", ptr->tlepaerr);
    432 		printf(fmt1, "TLSB MODCONF", ptr->tlmodconfig);
    433 		printf(fmt1, "TLSB LEP_MERR", ptr->tlepmerr);
    434 		printf(fmt1, "TLSB LEP_DERR", ptr->tlepderr);
    435 		printf(fmt1, "TLSB INTRMASK0", ptr->tlintrmask0);
    436 		printf(fmt1, "TLSB INTRMASK1", ptr->tlintrmask1);
    437 		printf(fmt1, "TLSB INTRSUM0", ptr->tlintrsum0);
    438 		printf(fmt1, "TLSB INTRSUM1", ptr->tlintrsum1);
    439 		printf(fmt1, "TLSB VMG", ptr->tlep_vmg);
    440 #endif
    441 	} else {
    442 	}
    443 
    444 	/*
    445 	 * Now that we've printed all sorts of useful information
    446 	 * and have decided that we really can't do any more to
    447 	 * respond to the error, go on to the common code for
    448 	 * final disposition. Usually this means that we die.
    449 	 */
    450 	clear_tlsb_ebits(0);
    451 
    452 	machine_check(mces, framep, type, logout);
    453 }
    454 
    455 static void
    456 dec_kn8ae_mcheck_handler(unsigned long mces, struct trapframe *framep, unsigned long vector, unsigned long param)
    457 {
    458 	switch (vector) {
    459 	case ALPHA_SYS_ERROR:
    460 		kn8ae_harderr(mces, vector, param, framep);
    461 		break;
    462 
    463 	case ALPHA_PROC_ERROR:
    464 		kn8ae_softerr(mces, vector, param, framep);
    465 		break;
    466 
    467 	case ALPHA_SYS_MCHECK:
    468 	case ALPHA_PROC_MCHECK:
    469 		kn8ae_mcheck(mces, vector, param, framep);
    470 		break;
    471 	default:
    472 		printf("KN8AE_MCHECK: unknown check vector 0x%lx\n", vector);
    473 		machine_check(mces, framep, vector, param);
    474 		break;
    475 	}
    476 }
    477