1 /* $NetBSD: ka670.c,v 1.17 2017/05/22 16:46:15 ragge Exp $ */
2 /*
3 * Copyright (c) 1999 Ludd, University of Lule}, Sweden.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Ludd by Bertram Barth.
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, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: ka670.c,v 1.17 2017/05/22 16:46:15 ragge Exp $");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/cpu.h>
35 #include <sys/device.h>
36 #include <sys/kernel.h>
37
38 #include <machine/sid.h>
39 #include <machine/nexus.h>
40 #include <machine/vsbus.h>
41 #include <machine/ka670.h>
42 #include <machine/clock.h>
43
44 static void ka670_memerr(void);
45 static void ka670_conf(void);
46 static void ka670_attach_cpu(device_t);
47 static int ka670_mchk(void *);
48 static int ka670_cache_init(void); /* "int mapen" as argument? */
49
50 static const char * const ka670_devs[] = { "cpu", "sgec", "shac", "uba", NULL };
51
52 const struct cpu_dep ka670_calls = {
53 .cpu_mchk = ka670_mchk,
54 .cpu_memerr = ka670_memerr,
55 .cpu_conf = ka670_conf,
56 .cpu_gettime = generic_gettime,
57 .cpu_settime = generic_settime,
58 .cpu_vups = 8, /* 8 VUP */
59 .cpu_scbsz = 2, /* SCB pages */
60 .cpu_halt = generic_halt,
61 .cpu_reboot = generic_reboot,
62 .cpu_devs = ka670_devs,
63 .cpu_attach_cpu = ka670_attach_cpu,
64 };
65
66 #define KA670_MC_RESTART 0x00008000 /* Restart possible*/
67 #define KA670_PSL_FPDONE 0x00010000 /* First Part Done */
68
69 struct ka670_mcframe { /* Format of RigelMAX machine check frame: */
70 int mc670_bcnt; /* byte count, always 24 (0x18) */
71 int mc670_code; /* machine check type code and restart bit */
72 int mc670_addr; /* most recent (faulting?) virtual address */
73 int mc670_viba; /* contents of VIBA register */
74 int mc670_sisr; /* ICCS bit 6 and SISR bits 15:0 */
75 int mc670_istate; /* internal state */
76 int mc670_sc; /* shift count register */
77 int mc670_pc; /* trapped PC */
78 int mc670_psl; /* trapped PSL */
79 };
80
81 #if 0
82
83 /*
84 * This is not the mchk types on KA670.
85 */
86 static const char * const ka670_mctype[] = {
87 "no error (0)", /* Code 0: No error */
88 "FPA: protocol error", /* Code 1-5: FPA errors */
89 "FPA: illegal opcode",
90 "FPA: operand parity error",
91 "FPA: unknown status",
92 "FPA: result parity error",
93 "unused (6)", /* Code 6-7: Unused */
94 "unused (7)",
95 "MMU error (TLB miss)", /* Code 8-9: MMU errors */
96 "MMU error (TLB hit)",
97 "HW interrupt at unused IPL", /* Code 10: Interrupt error */
98 "MOVCx impossible state", /* Code 11-13: Microcode errors */
99 "undefined trap code (i-box)",
100 "undefined control store address",
101 "unused (14)", /* Code 14-15: Unused */
102 "unused (15)",
103 "PC tag or data parity error", /* Code 16: Cache error */
104 "data bus parity error", /* Code 17: Read error */
105 "data bus error (NXM)", /* Code 18: Write error */
106 "undefined data bus state", /* Code 19: Bus error */
107 };
108 #define MC670_MAX 19
109 #endif
110
111 static int ka670_error_count = 0;
112
113 int
ka670_mchk(void * addr)114 ka670_mchk(void *addr)
115 {
116 struct ka670_mcframe * const mcf = addr;
117
118 mtpr(0x00, PR_MCESR); /* Acknowledge the machine check */
119 printf("machine check %d (0x%x)\n", mcf->mc670_code, mcf->mc670_code);
120 printf("PC %x PSL %x\n", mcf->mc670_pc, mcf->mc670_psl);
121 if (++ka670_error_count > 10) {
122 printf("error_count exceeded: %d\n", ka670_error_count);
123 return (-1);
124 }
125
126 /*
127 * If either the Restart flag is set or the First-Part-Done flag
128 * is set, and the TRAP2 (double error) bit is not set, then the
129 * error is recoverable.
130 */
131 if (mfpr(PR_PCSTS) & KA670_PCS_TRAP2) {
132 printf("TRAP2 (double error) in ka670_mchk.\n");
133 panic("unrecoverable state in ka670_mchk.");
134 return (-1);
135 }
136 if ((mcf->mc670_code & KA670_MC_RESTART) ||
137 (mcf->mc670_psl & KA670_PSL_FPDONE)) {
138 printf("ka670_mchk: recovering from machine-check.\n");
139 ka670_cache_init(); /* reset caches */
140 return (0); /* go on; */
141 }
142
143 /*
144 * Unknown error state, panic/halt the machine!
145 */
146 printf("ka670_mchk: unknown error state!\n");
147 return (-1);
148 }
149
150 void
ka670_memerr(void)151 ka670_memerr(void)
152 {
153 char sbuf[256];
154
155 /*
156 * Don\'t know what to do here. So just print some messages
157 * and try to go on...
158 */
159
160 printf("memory error!\n");
161
162 snprintb(sbuf, sizeof(sbuf), KA670_PCSTS_BITS, mfpr(PR_PCSTS));
163 printf("primary cache status: %s\n", sbuf);
164
165 snprintb(sbuf, sizeof(sbuf), KA670_BCSTS_BITS, mfpr(PR_BCSTS));
166 printf("secondary cache status: %s\n", sbuf);
167 }
168
169 int
ka670_cache_init(void)170 ka670_cache_init(void)
171 {
172 int val;
173 #ifdef DEBUG
174 char sbuf[256];
175 #endif
176
177 mtpr(KA670_PCS_REFRESH, PR_PCSTS); /* disable primary cache */
178 val = mfpr(PR_PCSTS);
179 mtpr(val, PR_PCSTS); /* clear error flags */
180 mtpr(8, PR_BCCTL); /* disable backup cache */
181 mtpr(0, PR_BCFBTS); /* flush backup cache tag store */
182 mtpr(0, PR_BCFPTS); /* flush primary cache tag store */
183 mtpr(0x0e, PR_BCCTL); /* enable backup cache */
184 mtpr(KA670_PCS_FLUSH | KA670_PCS_REFRESH, PR_PCSTS); /* flush primary cache */
185 mtpr(KA670_PCS_ENABLE | KA670_PCS_REFRESH, PR_PCSTS); /* flush primary cache */
186
187 #ifdef DEBUG
188 snprintb(sbuf, sizeof(sbuf), KA670_PCSTS_BITS, mfpr(PR_PCSTS));
189 printf("primary cache status: %s\n", sbuf);
190
191 snprintb(sbuf, sizeof(sbuf), KA670_BCSTS_BITS, mfpr(PR_BCSTS));
192 printf("secondary cache status: %s\n", sbuf);
193 #endif
194
195 return (0);
196 }
197
198 void
ka670_conf(void)199 ka670_conf(void)
200 {
201
202 /*
203 * ka670_conf() gets called with MMU enabled, now it's save to
204 * init/reset the caches.
205 */
206 ka670_cache_init();
207
208 cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1);
209 }
210
211 void
ka670_attach_cpu(device_t self)212 ka670_attach_cpu(device_t self)
213 {
214 aprint_normal(
215 ": %s, Rigel (ucode rev %d), 2KB L1 cache, 128KB L2 cache\n",
216 "KA670",
217 vax_cpudata % 0377);
218 }
219