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