1 /*
2 * Copyright (c) 1986, 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)ka860.c 7.4 (Berkeley) 12/16/90
8 */
9
10 #if VAX8600
11
12 /*
13 * VAX 8600 specific routines.
14 */
15
16 #include "sys/param.h"
17
18 #include "../include/cpu.h"
19 #include "../include/mtpr.h"
20
21 /*
22 * 8600 memory register (MERG) bit definitions
23 */
24 #define M8600_ICRD 0x400 /* inhibit crd interrupts */
25 #define M8600_TB_ERR 0xf00 /* translation buffer error mask */
26
27 /*
28 * MDECC register
29 */
30 #define M8600_ADDR_PE 0x080000 /* address parity error */
31 #define M8600_DBL_ERR 0x100000 /* data double bit error */
32 #define M8600_SNG_ERR 0x200000 /* data single bit error */
33 #define M8600_BDT_ERR 0x400000 /* bad data error */
34
35 /*
36 * ESPA register is used to address scratch pad registers in the Ebox.
37 * To access a register in the scratch pad, write the ESPA with the address
38 * and then read the ESPD register.
39 *
40 * NOTE: In assmebly code, the mfpr instruction that reads the ESPD
41 * register must immedately follow the mtpr instruction that setup
42 * the ESPA register -- per the VENUS processor register spec.
43 *
44 * The scratchpad registers that are supplied for a single bit ECC
45 * error are:
46 */
47 #define SPAD_MSTAT1 0x25 /* scratch pad mstat1 register */
48 #define SPAD_MSTAT2 0x26 /* scratch pad mstat2 register */
49 #define SPAD_MDECC 0x27 /* scratch pad mdecc register */
50 #define SPAD_MEAR 0x2a /* scratch pad mear register */
51
52 #define M8600_MEMERR(mdecc) ((mdecc) & 0x780000)
53 #define M8600_HRDERR(mdecc) ((mdecc) & 0x580000)
54 #define M8600_SYN(mdecc) (((mdecc) >> 9) & 0x3f)
55 #define M8600_ADDR(mear) ((mear) & 0x3ffffffc)
56 #define M8600_ARRAY(mear) (((mear) >> 22) & 0x0f)
57
58 #define M8600_MDECC_BITS \
59 "\20\27BAD_DT_ERR\26SNG_BIT_ERR\25DBL_BIT_ERR\24ADDR_PE"
60
61 #define M8600_MSTAT1_BITS "\20\30CPR_PE_A\27CPR_PE_B\26ABUS_DT_PE\
62 \25ABUS_CTL_MSK_PE\24ABUS_ADR_PE\23ABUS_C/A_CYCLE\22ABUS_ADP_1\21ABUS_ADP_0\
63 \20TB_MISS\17BLK_HIT\16C0_TAG_MISS\15CHE_MISS\14TB_VAL_ERR\13TB_PTE_B_PE\
64 \12TB_PTE_A_PE\11TB_TAG_PE\10WR_DT_PE_B3\7WR_DT_PE_B2\6WR_DT_PE_B1\
65 \5WR_DT_PE_B0\4CHE_RD_DT_PE\3CHE_SEL\2ANY_REFL\1CP_BW_CHE_DT_PE"
66
67 #define M8600_MSTAT2_BITS "\20\20CP_BYT_WR\17ABUS_BD_DT_CODE\10MULT_ERR\
68 \7CHE_TAG_PE\6CHE_TAG_W_PE\5CHE_WRTN_BIT\4NXM\3CP-IO_BUF_ERR\2MBOX_LOCK"
69
70 /* enable CRD reports */
ka860_memenable()71 ka860_memenable()
72 {
73
74 mtpr(MERG, mfpr(MERG) & ~M8600_ICRD);
75 }
76
77 /* log CRD errors */
ka860_memerr()78 ka860_memerr()
79 {
80 register int reg11; /* known to be r11 below */
81 int mdecc, mear, mstat1, mstat2, array;
82
83 /*
84 * Scratchpad registers in the Ebox must be read by
85 * storing their ID number in ESPA and then immediately
86 * reading ESPD's contents with no other intervening
87 * machine instructions!
88 *
89 * The asm's below have a number of constants which
90 * are defined correctly above and in mtpr.h.
91 */
92 #ifdef lint
93 reg11 = 0;
94 #else
95 asm("mtpr $0x27,$0x4e; mfpr $0x4f,r11");
96 #endif
97 mdecc = reg11; /* must acknowledge interrupt? */
98 if (M8600_MEMERR(mdecc)) {
99 asm("mtpr $0x2a,$0x4e; mfpr $0x4f,r11");
100 mear = reg11;
101 asm("mtpr $0x25,$0x4e; mfpr $0x4f,r11");
102 mstat1 = reg11;
103 asm("mtpr $0x26,$0x4e; mfpr $0x4f,r11");
104 mstat2 = reg11;
105 array = M8600_ARRAY(mear);
106
107 printf("mcr0: ecc error, addr %x (array %d) syn %x\n",
108 M8600_ADDR(mear), array, M8600_SYN(mdecc));
109 printf("\tMSTAT1 = %b\n\tMSTAT2 = %b\n",
110 mstat1, M8600_MSTAT1_BITS,
111 mstat2, M8600_MSTAT2_BITS);
112 mtpr(EHSR, 0);
113 mtpr(MERG, mfpr(MERG) | M8600_ICRD);
114 }
115 }
116
117 #define NMC8600 7
118 char *mc8600[] = {
119 "unkn type", "fbox error", "ebox error", "ibox error",
120 "mbox error", "tbuf error", "mbox 1D error"
121 };
122 /* codes for above */
123 #define MC_FBOX 1
124 #define MC_EBOX 2
125 #define MC_IBOX 3
126 #define MC_MBOX 4
127 #define MC_TBUF 5
128 #define MC_MBOX1D 6
129
130 /* error bits */
131 #define MBOX_FE 0x8000 /* Mbox fatal error */
132 #define FBOX_SERV 0x10000000 /* Fbox service error */
133 #define IBOX_ERR 0x2000 /* Ibox error */
134 #define EBOX_ERR 0x1e00 /* Ebox error */
135 #define MBOX_1D 0x81d0000 /* Mbox 1D error */
136 #define EDP_PE 0x200
137
138 struct mc8600frame {
139 int mc86_bcnt; /* byte count == 0x58 */
140 int mc86_ehmsts;
141 int mc86_evmqsav;
142 int mc86_ebcs;
143 int mc86_edpsr;
144 int mc86_cslint;
145 int mc86_ibesr;
146 int mc86_ebxwd1;
147 int mc86_ebxwd2;
148 int mc86_ivasav;
149 int mc86_vibasav;
150 int mc86_esasav;
151 int mc86_isasav;
152 int mc86_cpc;
153 int mc86_mstat1;
154 int mc86_mstat2;
155 int mc86_mdecc;
156 int mc86_merg;
157 int mc86_cshctl;
158 int mc86_mear;
159 int mc86_medr;
160 int mc86_accs;
161 int mc86_cses;
162 int mc86_pc; /* trapped pc */
163 int mc86_psl; /* trapped psl */
164 };
165
166 /* machine check */
ka860_mchk(cmcf)167 ka860_mchk(cmcf)
168 caddr_t cmcf;
169 {
170 register struct mc8600frame *mcf = (struct mc8600frame *)cmcf;
171 register int type;
172
173 if (mcf->mc86_ebcs & MBOX_FE)
174 mcf->mc86_ehmsts |= MC_MBOX;
175 else if (mcf->mc86_ehmsts & FBOX_SERV)
176 mcf->mc86_ehmsts |= MC_FBOX;
177 else if (mcf->mc86_ebcs & EBOX_ERR) {
178 if (mcf->mc86_ebcs & EDP_PE)
179 mcf->mc86_ehmsts |= MC_MBOX;
180 else
181 mcf->mc86_ehmsts |= MC_EBOX;
182 } else if (mcf->mc86_ehmsts & IBOX_ERR)
183 mcf->mc86_ehmsts |= MC_IBOX;
184 else if (mcf->mc86_mstat1 & M8600_TB_ERR)
185 mcf->mc86_ehmsts |= MC_TBUF;
186 else if ((mcf->mc86_cslint & MBOX_1D) == MBOX_1D)
187 mcf->mc86_ehmsts |= MC_MBOX1D;
188
189 type = mcf->mc86_ehmsts & 0x7;
190 printf("machine check %x: %s\n", type,
191 type < NMC8600 ? mc8600[type] : "???");
192 printf("\tehm.sts %x evmqsav %x ebcs %x edpsr %x cslint %x\n",
193 mcf->mc86_ehmsts, mcf->mc86_evmqsav, mcf->mc86_ebcs,
194 mcf->mc86_edpsr, mcf->mc86_cslint);
195 printf("\tibesr %x ebxwd %x %x ivasav %x vibasav %x\n",
196 mcf->mc86_ibesr, mcf->mc86_ebxwd1, mcf->mc86_ebxwd2,
197 mcf->mc86_ivasav, mcf->mc86_vibasav);
198 printf("\tesasav %x isasav %x cpc %x mstat %x %x mdecc %x\n",
199 mcf->mc86_esasav, mcf->mc86_isasav, mcf->mc86_cpc,
200 mcf->mc86_mstat1, mcf->mc86_mstat2, mcf->mc86_mdecc);
201 printf("\tmerg %x cshctl %x mear %x medr %x accs %x cses %x\n",
202 mcf->mc86_merg, mcf->mc86_cshctl, mcf->mc86_mear,
203 mcf->mc86_medr, mcf->mc86_accs, mcf->mc86_cses);
204 printf("\tpc %x psl %x\n", mcf->mc86_pc, mcf->mc86_psl);
205 mtpr(EHSR, 0);
206 return (MCHK_PANIC);
207 }
208 #endif
209