cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

err_ev6.c (7973B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *	linux/arch/alpha/kernel/err_ev6.c
      4 *
      5 *	Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
      6 *
      7 *	Error handling code supporting Alpha systems
      8 */
      9
     10#include <linux/sched.h>
     11
     12#include <asm/io.h>
     13#include <asm/irq_regs.h>
     14#include <asm/hwrpb.h>
     15#include <asm/smp.h>
     16#include <asm/err_common.h>
     17#include <asm/err_ev6.h>
     18
     19#include "err_impl.h"
     20#include "proto.h"
     21
     22static int
     23ev6_parse_ibox(u64 i_stat, int print)
     24{
     25	int status = MCHK_DISPOSITION_REPORT;
     26
     27#define EV6__I_STAT__PAR	(1UL << 29)
     28#define EV6__I_STAT__ERRMASK	(EV6__I_STAT__PAR)
     29
     30	if (!(i_stat & EV6__I_STAT__ERRMASK))
     31		return MCHK_DISPOSITION_UNKNOWN_ERROR;
     32
     33	if (!print)
     34		return status;
     35
     36	if (i_stat & EV6__I_STAT__PAR)
     37		printk("%s    Icache parity error\n", err_print_prefix);
     38
     39	return status;
     40}
     41
     42static int
     43ev6_parse_mbox(u64 mm_stat, u64 d_stat, u64 c_stat, int print)
     44{
     45	int status = MCHK_DISPOSITION_REPORT;
     46
     47#define EV6__MM_STAT__DC_TAG_PERR	(1UL << 10)
     48#define EV6__MM_STAT__ERRMASK		(EV6__MM_STAT__DC_TAG_PERR)
     49#define EV6__D_STAT__TPERR_P0		(1UL << 0)
     50#define EV6__D_STAT__TPERR_P1		(1UL << 1)
     51#define EV6__D_STAT__ECC_ERR_ST		(1UL << 2)
     52#define EV6__D_STAT__ECC_ERR_LD		(1UL << 3)
     53#define EV6__D_STAT__SEO		(1UL << 4)
     54#define EV6__D_STAT__ERRMASK		(EV6__D_STAT__TPERR_P0 |	\
     55                                         EV6__D_STAT__TPERR_P1 | 	\
     56                                         EV6__D_STAT__ECC_ERR_ST | 	\
     57                                         EV6__D_STAT__ECC_ERR_LD | 	\
     58                                         EV6__D_STAT__SEO)
     59
     60	if (!(d_stat & EV6__D_STAT__ERRMASK) && 
     61	    !(mm_stat & EV6__MM_STAT__ERRMASK))
     62		return MCHK_DISPOSITION_UNKNOWN_ERROR;
     63
     64	if (!print)
     65		return status;
     66
     67	if (mm_stat & EV6__MM_STAT__DC_TAG_PERR)
     68		printk("%s    Dcache tag parity error on probe\n",
     69		       err_print_prefix);
     70	if (d_stat & EV6__D_STAT__TPERR_P0)
     71		printk("%s    Dcache tag parity error - pipe 0\n",
     72		       err_print_prefix);
     73	if (d_stat & EV6__D_STAT__TPERR_P1)
     74		printk("%s    Dcache tag parity error - pipe 1\n",
     75		       err_print_prefix);
     76	if (d_stat & EV6__D_STAT__ECC_ERR_ST)
     77		printk("%s    ECC error occurred on a store\n", 
     78		       err_print_prefix);
     79	if (d_stat & EV6__D_STAT__ECC_ERR_LD)
     80		printk("%s    ECC error occurred on a %s load\n",
     81		       err_print_prefix,
     82		       c_stat ? "" : "speculative ");
     83	if (d_stat & EV6__D_STAT__SEO)
     84		printk("%s    Dcache second error\n", err_print_prefix);
     85
     86	return status;
     87}
     88
     89static int
     90ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn, 
     91	       u64 c_stat, u64 c_sts, int print)
     92{
     93	static const char * const sourcename[] = {
     94		"UNKNOWN", "UNKNOWN", "UNKNOWN",
     95		"MEMORY", "BCACHE", "DCACHE",
     96		"BCACHE PROBE", "BCACHE PROBE"
     97	};
     98	static const char * const streamname[] = { "D", "I" };
     99	static const char * const bitsname[] = { "SINGLE", "DOUBLE" };
    100	int status = MCHK_DISPOSITION_REPORT;
    101	int source = -1, stream = -1, bits = -1;
    102
    103#define EV6__C_STAT__BC_PERR		(0x01)
    104#define EV6__C_STAT__DC_PERR		(0x02)
    105#define EV6__C_STAT__DSTREAM_MEM_ERR	(0x03)
    106#define EV6__C_STAT__DSTREAM_BC_ERR	(0x04)
    107#define EV6__C_STAT__DSTREAM_DC_ERR	(0x05)
    108#define EV6__C_STAT__PROBE_BC_ERR0	(0x06)	/* both 6 and 7 indicate... */
    109#define EV6__C_STAT__PROBE_BC_ERR1	(0x07)	/* ...probe bc error.       */
    110#define EV6__C_STAT__ISTREAM_MEM_ERR	(0x0B)
    111#define EV6__C_STAT__ISTREAM_BC_ERR	(0x0C)
    112#define EV6__C_STAT__DSTREAM_MEM_DBL	(0x13)
    113#define EV6__C_STAT__DSTREAM_BC_DBL	(0x14)
    114#define EV6__C_STAT__ISTREAM_MEM_DBL	(0x1B)
    115#define EV6__C_STAT__ISTREAM_BC_DBL	(0x1C)
    116#define EV6__C_STAT__SOURCE_MEMORY	(0x03)
    117#define EV6__C_STAT__SOURCE_BCACHE	(0x04)
    118#define EV6__C_STAT__SOURCE__S		(0)
    119#define EV6__C_STAT__SOURCE__M 		(0x07)
    120#define EV6__C_STAT__ISTREAM__S		(3)
    121#define EV6__C_STAT__ISTREAM__M		(0x01)
    122#define EV6__C_STAT__DOUBLE__S		(4)
    123#define EV6__C_STAT__DOUBLE__M		(0x01)
    124#define EV6__C_STAT__ERRMASK		(0x1F)
    125#define EV6__C_STS__SHARED		(1 << 0)
    126#define EV6__C_STS__DIRTY		(1 << 1)
    127#define EV6__C_STS__VALID		(1 << 2)
    128#define EV6__C_STS__PARITY		(1 << 3)
    129
    130	if (!(c_stat & EV6__C_STAT__ERRMASK))
    131		return MCHK_DISPOSITION_UNKNOWN_ERROR;
    132
    133	if (!print)
    134		return status;
    135
    136	source = EXTRACT(c_stat, EV6__C_STAT__SOURCE);
    137	stream = EXTRACT(c_stat, EV6__C_STAT__ISTREAM);
    138	bits = EXTRACT(c_stat, EV6__C_STAT__DOUBLE);
    139
    140	if (c_stat & EV6__C_STAT__BC_PERR) {
    141		printk("%s    Bcache tag parity error\n", err_print_prefix);
    142		source = -1;
    143	}
    144
    145	if (c_stat & EV6__C_STAT__DC_PERR) {
    146		printk("%s    Dcache tag parity error\n", err_print_prefix);
    147		source = -1;
    148	}
    149
    150	if (c_stat == EV6__C_STAT__PROBE_BC_ERR0 ||
    151	    c_stat == EV6__C_STAT__PROBE_BC_ERR1) {
    152		printk("%s    Bcache single-bit error on a probe hit\n",
    153		       err_print_prefix);
    154		source = -1;
    155	}
    156
    157	if (source != -1) 
    158		printk("%s    %s-STREAM %s-BIT ECC error from %s\n",
    159		       err_print_prefix,
    160		       streamname[stream], bitsname[bits], sourcename[source]);
    161
    162	printk("%s    Address: 0x%016llx\n"
    163	         "    Syndrome[upper.lower]: %02llx.%02llx\n",
    164	       err_print_prefix,
    165	       c_addr,
    166	       c2_syn, c1_syn);
    167
    168	if (source == EV6__C_STAT__SOURCE_MEMORY ||
    169	    source == EV6__C_STAT__SOURCE_BCACHE) 
    170		printk("%s    Block status: %s%s%s%s\n",
    171		       err_print_prefix,
    172		       (c_sts & EV6__C_STS__SHARED) ? "SHARED " : "",
    173		       (c_sts & EV6__C_STS__DIRTY)  ? "DIRTY "  : "",
    174		       (c_sts & EV6__C_STS__VALID)  ? "VALID "  : "",
    175		       (c_sts & EV6__C_STS__PARITY) ? "PARITY " : "");
    176		
    177	return status;
    178}
    179
    180void
    181ev6_register_error_handlers(void)
    182{
    183	/* None right now. */
    184}
    185
    186int
    187ev6_process_logout_frame(struct el_common *mchk_header, int print)
    188{
    189	struct el_common_EV6_mcheck *ev6mchk = 
    190		(struct el_common_EV6_mcheck *)mchk_header;
    191	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
    192
    193	status |= ev6_parse_ibox(ev6mchk->I_STAT, print);
    194	status |= ev6_parse_mbox(ev6mchk->MM_STAT, ev6mchk->DC_STAT, 
    195				 ev6mchk->C_STAT, print);
    196	status |= ev6_parse_cbox(ev6mchk->C_ADDR, ev6mchk->DC1_SYNDROME,
    197				 ev6mchk->DC0_SYNDROME, ev6mchk->C_STAT,
    198				 ev6mchk->C_STS, print);
    199
    200	if (!print)
    201		return status;
    202
    203	if (status != MCHK_DISPOSITION_DISMISS) {
    204		char *saved_err_prefix = err_print_prefix;
    205
    206		/*
    207		 * Dump some additional information from the frame
    208		 */
    209		printk("%s    EXC_ADDR: 0x%016lx   IER_CM: 0x%016lx"
    210		            "   ISUM: 0x%016lx\n"
    211		         "    PAL_BASE: 0x%016lx   I_CTL:  0x%016lx"
    212		            "   PCTX: 0x%016lx\n",
    213		       err_print_prefix,
    214		       ev6mchk->EXC_ADDR, ev6mchk->IER_CM, ev6mchk->ISUM,
    215		       ev6mchk->PAL_BASE, ev6mchk->I_CTL, ev6mchk->PCTX);
    216
    217		if (status == MCHK_DISPOSITION_UNKNOWN_ERROR) {
    218			printk("%s    UNKNOWN error, frame follows:\n",
    219			       err_print_prefix);
    220		} else {
    221			/* had decode -- downgrade print level for frame */
    222			err_print_prefix = KERN_NOTICE;
    223		}
    224
    225		mchk_dump_logout_frame(mchk_header);
    226
    227		err_print_prefix = saved_err_prefix;
    228	}
    229
    230	return status;
    231}
    232
    233void
    234ev6_machine_check(unsigned long vector, unsigned long la_ptr)
    235{
    236	struct el_common *mchk_header = (struct el_common *)la_ptr;
    237
    238	/*
    239	 * Sync the processor
    240	 */
    241	mb();
    242	draina();
    243
    244	/*
    245	 * Parse the logout frame without printing first. If the only error(s)
    246	 * found are have a disposition of "dismiss", then just dismiss them
    247	 * and don't print any message
    248	 */
    249	if (ev6_process_logout_frame(mchk_header, 0) != 
    250	    MCHK_DISPOSITION_DISMISS) {
    251		char *saved_err_prefix = err_print_prefix;
    252		err_print_prefix = KERN_CRIT;
    253
    254		/*
    255		 * Either a nondismissable error was detected or no
    256		 * recognized error was detected  in the logout frame 
    257		 * -- report the error in either case
    258		 */
    259		printk("%s*CPU %s Error (Vector 0x%x) reported on CPU %d:\n", 
    260		       err_print_prefix,
    261		       (vector == SCB_Q_PROCERR)?"Correctable":"Uncorrectable",
    262		       (unsigned int)vector, (int)smp_processor_id());
    263		
    264		ev6_process_logout_frame(mchk_header, 1);
    265		dik_show_regs(get_irq_regs(), NULL);
    266
    267		err_print_prefix = saved_err_prefix;
    268	}
    269
    270	/* 
    271	 * Release the logout frame 
    272	 */
    273	wrmces(0x7);
    274	mb();
    275}
    276