Commit | Line | Data |
---|---|---|
dca3793c | 1 | /* machdep.c 4.21 81/03/03 */ |
79821b2c BJ |
2 | |
3 | #include "../h/param.h" | |
4 | #include "../h/systm.h" | |
5 | #include "../h/dir.h" | |
6 | #include "../h/user.h" | |
7 | #include "../h/map.h" | |
8 | #include "../h/reg.h" | |
9 | #include "../h/mtpr.h" | |
10 | #include "../h/clock.h" | |
11 | #include "../h/pte.h" | |
12 | #include "../h/vm.h" | |
13 | #include "../h/proc.h" | |
14 | #include "../h/psl.h" | |
8ae22d0f | 15 | #include "../h/buf.h" |
f5eeaba8 | 16 | #include "../h/uba.h" |
0dc06be8 BJ |
17 | #include "../h/cons.h" |
18 | #include "../h/reboot.h" | |
2de46def | 19 | #include "../h/conf.h" |
8ae22d0f BJ |
20 | #include "../h/mem.h" |
21 | #include "../h/cpu.h" | |
c34926db BJ |
22 | #include "../h/inode.h" |
23 | #include "../h/file.h" | |
24 | #include "../h/text.h" | |
25 | #include "../h/clist.h" | |
26 | #include "../h/callout.h" | |
27 | #include "../h/cmap.h" | |
2de46def | 28 | #include <frame.h> |
79821b2c | 29 | |
2de46def BJ |
30 | int coresw = 0; |
31 | int printsw = 0; | |
32 | ||
dca3793c | 33 | char version[] = "VM/UNIX (Berkeley Version 4.21) 81/03/03 11:04:57 \n"; |
79821b2c BJ |
34 | int icode[] = |
35 | { | |
48575cec BJ |
36 | 0x9f19af9f, /* pushab [&"init",0]; pushab */ |
37 | 0x02dd09af, /* "/etc/init"; pushl $2 */ | |
79821b2c BJ |
38 | 0xbc5c5ed0, /* movl sp,ap; chmk */ |
39 | 0x2ffe110b, /* $exec; brb .; "/ */ | |
40 | 0x2f637465, /* etc/ */ | |
0dc06be8 BJ |
41 | 0x74696e69, /* init" */ |
42 | 0x00000000, /* \0\0\0"; 0 */ | |
79821b2c BJ |
43 | 0x00000014, /* [&"init", */ |
44 | 0x00000000, /* 0] */ | |
45 | }; | |
46 | int szicode = sizeof(icode); | |
79821b2c BJ |
47 | |
48 | /* | |
49 | * Machine-dependent startup code | |
50 | */ | |
51 | startup(firstaddr) | |
c34926db | 52 | int firstaddr; |
79821b2c BJ |
53 | { |
54 | register int unixsize; | |
a53ab6ba BJ |
55 | register int i; |
56 | register struct pte *pte; | |
c34926db | 57 | register caddr_t v; |
79821b2c | 58 | |
90f8d91f BJ |
59 | /* |
60 | * Initialize error message buffer (at end of core). | |
61 | */ | |
62 | maxmem -= CLSIZE; | |
63 | pte = msgbufmap; | |
64 | for (i = 0; i < CLSIZE; i++) | |
65 | *(int *)pte++ = PG_V | PG_KW | (maxmem + i); | |
66 | mtpr(TBIA, 1); | |
67 | ||
79821b2c BJ |
68 | /* |
69 | * Good {morning,afternoon,evening,night}. | |
70 | */ | |
90f8d91f BJ |
71 | printf(version); |
72 | printf("real mem = %d\n", ctob(maxmem)); | |
cf19cacc | 73 | |
79821b2c | 74 | /* |
c34926db BJ |
75 | * First determine how many buffers are reasonable. |
76 | * Current alg is 32 per megabyte, with min of 32. | |
77 | * We allocate 1/2 as many swap buffer headers as file i/o buffers. | |
79821b2c | 78 | */ |
c34926db | 79 | nbuf = (32 * physmem) / btoc(1024*1024); if (nbuf < 32) nbuf = 32; |
0a34b6fd | 80 | nswbuf = (nbuf / 2) &~ 1; /* force even */ |
a53ab6ba BJ |
81 | |
82 | /* | |
c34926db | 83 | * Allocate space for system data structures. |
a53ab6ba | 84 | */ |
c34926db BJ |
85 | v = (caddr_t)(0x80000000 | (firstaddr * NBPG)); |
86 | #define valloc(name, type, num) \ | |
87 | (name) = (type *)(v); (v) = (caddr_t)((name)+(num)) | |
88 | #define valloclim(name, type, num, lim) \ | |
89 | (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num))) | |
90 | valloc(buffers, char, BSIZE*nbuf); | |
91 | valloc(buf, struct buf, nbuf); | |
92 | valloc(swbuf, struct buf, nswbuf); | |
0a34b6fd BJ |
93 | valloc(swsize, short, nswbuf); /* note: nswbuf is even */ |
94 | valloc(swpf, int, nswbuf); | |
c34926db BJ |
95 | valloclim(inode, struct inode, ninode, inodeNINODE); |
96 | valloclim(file, struct file, nfile, fileNFILE); | |
97 | valloclim(proc, struct proc, nproc, procNPROC); | |
98 | valloclim(text, struct text, ntext, textNTEXT); | |
99 | valloc(cfree, struct cblock, nclist); | |
100 | valloc(callout, struct callout, ncallout); | |
233328fc BJ |
101 | valloc(swapmap, struct map, nswapmap = nproc * 2); |
102 | valloc(argmap, struct map, ARGMAPSIZE); | |
c34926db BJ |
103 | valloc(kernelmap, struct map, nproc); |
104 | ||
105 | /* | |
106 | * Now allocate space for core map | |
107 | */ | |
108 | ncmap = (physmem*NBPG - ((int)v &~ 0x80000000)) / | |
109 | (NBPG*CLSIZE + sizeof (struct cmap)); | |
110 | valloclim(cmap, struct cmap, ncmap, ecmap); | |
111 | ||
112 | /* | |
113 | * Clear allocated space, and make r/w entries | |
114 | * for the space in the kernel map. | |
115 | */ | |
0a34b6fd | 116 | unixsize = btoc((int)ecmap &~ 0x80000000); |
c34926db BJ |
117 | if (unixsize >= physmem - 8*UPAGES) |
118 | panic("no memory"); | |
119 | pte = &Sysmap[firstaddr]; | |
120 | for (i = firstaddr; i < unixsize; i++) { | |
121 | *(int *)(&Sysmap[i]) = PG_V | PG_KW | i; | |
122 | clearseg(i); | |
123 | } | |
a53ab6ba | 124 | mtpr(TBIA, 1); |
79821b2c BJ |
125 | |
126 | /* | |
233328fc BJ |
127 | * Initialize memory allocator and swap |
128 | * and user page table maps. | |
129 | * | |
130 | * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' | |
131 | * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. | |
79821b2c BJ |
132 | */ |
133 | meminit(unixsize, maxmem); | |
a53ab6ba | 134 | maxmem = freemem; |
79821b2c | 135 | printf("avail mem = %d\n", ctob(maxmem)); |
233328fc | 136 | rminit(kernelmap, USRPTSIZE, 1, "usrpt", nproc); |
cf19cacc BJ |
137 | |
138 | /* | |
139 | * Configure the system. | |
140 | */ | |
141 | configure(); | |
142 | ||
143 | /* | |
144 | * Clear restart inhibit flags. | |
145 | */ | |
146 | tocons(TXDB_CWSI); | |
147 | tocons(TXDB_CCSI); | |
79821b2c BJ |
148 | } |
149 | ||
150 | /* | |
151 | * set up a physical address | |
152 | * into users virtual address space. | |
153 | */ | |
154 | sysphys() | |
155 | { | |
156 | ||
157 | if(!suser()) | |
158 | return; | |
159 | u.u_error = EINVAL; | |
160 | } | |
161 | ||
162 | /* | |
b559a38a BJ |
163 | * Initialze the clock, based on the time base which is, e.g. |
164 | * from a filesystem. Base provides the time to within six months, | |
165 | * and the time of year clock provides the rest. | |
79821b2c | 166 | */ |
354a4341 | 167 | clkinit(base) |
b559a38a | 168 | time_t base; |
354a4341 | 169 | { |
b559a38a | 170 | register unsigned todr = mfpr(TODR); |
890f1888 | 171 | long deltat; |
b559a38a BJ |
172 | int year = YRREF; |
173 | ||
f4d57f63 | 174 | if (base < 5*SECYR) { |
e506b649 | 175 | printf("WARNING: preposterous time in file system"); |
aa94c536 | 176 | time = 6*SECYR + 186*SECDAY + SECDAY/2; |
cdc19302 BJ |
177 | clkset(); |
178 | goto check; | |
f4d57f63 | 179 | } |
b559a38a BJ |
180 | /* |
181 | * Have been told that VMS keeps time internally with base TODRZERO. | |
182 | * If this is correct, then this routine and VMS should maintain | |
183 | * the same date, and switching shouldn't be painful. | |
2de46def BJ |
184 | * (Unfortunately, VMS keeps local time, so when you run UNIX |
185 | * and VMS, VMS runs on GMT...). | |
b559a38a BJ |
186 | */ |
187 | if (todr < TODRZERO) { | |
188 | printf("WARNING: todr too small (battery backup failed?)"); | |
189 | time = base; | |
190 | /* | |
191 | * Believe the time in the file system for lack of | |
192 | * anything better, resetting the TODR. | |
193 | */ | |
194 | clkset(); | |
195 | goto check; | |
196 | } | |
197 | /* | |
198 | * Sneak to within 6 month of the time in the filesystem, | |
199 | * by starting with the time of the year suggested by the TODR, | |
200 | * and advancing through succesive years. Adding the number of | |
201 | * seconds in the current year takes us to the end of the current year | |
202 | * and then around into the next year to the same position. | |
203 | */ | |
204 | for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) { | |
205 | if (LEAPYEAR(year)) | |
206 | time += SECDAY; | |
207 | year++; | |
208 | } | |
354a4341 | 209 | |
b559a38a BJ |
210 | /* |
211 | * See if we gained/lost two or more days; | |
212 | * if so, assume something is amiss. | |
213 | */ | |
890f1888 BJ |
214 | deltat = time - base; |
215 | if (deltat < 0) | |
216 | deltat = -deltat; | |
b559a38a BJ |
217 | if (deltat < 2*SECDAY) |
218 | return; | |
219 | printf("WARNING: clock %s %d days", | |
220 | time < base ? "lost" : "gained", deltat / SECDAY); | |
221 | check: | |
222 | printf(" -- CHECK AND RESET THE DATE!\n"); | |
354a4341 BJ |
223 | } |
224 | ||
b559a38a BJ |
225 | /* |
226 | * Reset the TODR based on the time value; used when the TODR | |
227 | * has a preposterous value and also when the time is reset | |
228 | * by the stime system call. Also called when the TODR goes past | |
229 | * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) | |
230 | * to wrap the TODR around. | |
231 | */ | |
354a4341 BJ |
232 | clkset() |
233 | { | |
b559a38a BJ |
234 | int year = YRREF; |
235 | unsigned secyr; | |
236 | unsigned yrtime = time; | |
354a4341 | 237 | |
b559a38a BJ |
238 | /* |
239 | * Whittle the time down to an offset in the current year, | |
240 | * by subtracting off whole years as long as possible. | |
241 | */ | |
242 | for (;;) { | |
243 | secyr = SECYR; | |
244 | if (LEAPYEAR(year)) | |
245 | secyr += SECDAY; | |
246 | if (yrtime < secyr) | |
247 | break; | |
248 | yrtime -= secyr; | |
249 | year++; | |
250 | } | |
251 | mtpr(TODR, TODRZERO + yrtime*100); | |
354a4341 BJ |
252 | } |
253 | ||
79821b2c BJ |
254 | #ifdef PGINPROF |
255 | /* | |
256 | * Return the difference (in microseconds) | |
257 | * between the current time and a previous | |
258 | * time as represented by the arguments. | |
259 | * If there is a pending clock interrupt | |
260 | * which has not been serviced due to high | |
261 | * ipl, return error code. | |
262 | */ | |
263 | vmtime(otime, olbolt, oicr) | |
264 | register int otime, olbolt, oicr; | |
265 | { | |
266 | ||
267 | if (mfpr(ICCS)&ICCS_INT) | |
268 | return(-1); | |
269 | else | |
270 | return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr); | |
271 | } | |
272 | #endif | |
273 | ||
274 | /* | |
275 | * Send an interrupt to process | |
f815f998 BJ |
276 | * |
277 | * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION | |
278 | * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS. | |
79821b2c BJ |
279 | */ |
280 | sendsig(p, n) | |
858ecf0f | 281 | int (*p)(); |
79821b2c BJ |
282 | { |
283 | register int *usp, *regs; | |
284 | ||
285 | regs = u.u_ar0; | |
286 | usp = (int *)regs[SP]; | |
79821b2c BJ |
287 | usp -= 5; |
288 | if ((int)usp <= USRSTACK - ctob(u.u_ssize)) | |
81263dba | 289 | (void) grow((unsigned)usp); |
79821b2c | 290 | ; /* Avoid asm() label botch */ |
858ecf0f | 291 | #ifndef lint |
79821b2c BJ |
292 | asm("probew $3,$20,(r11)"); |
293 | asm("beql bad"); | |
858ecf0f BJ |
294 | #else |
295 | if (useracc((caddr_t)usp, 0x20, 1)) | |
296 | goto bad; | |
297 | #endif | |
79821b2c | 298 | *usp++ = n; |
dca3793c BJ |
299 | if (n == SIGILL || n == SIGFPE) { |
300 | *usp++ = u.u_code; | |
301 | u.u_code = 0; | |
302 | } else | |
303 | *usp++ = 0; | |
858ecf0f | 304 | *usp++ = (int)p; |
79821b2c BJ |
305 | *usp++ = regs[PC]; |
306 | *usp++ = regs[PS]; | |
307 | regs[SP] = (int)(usp - 5); | |
79821b2c BJ |
308 | regs[PS] &= ~(PSL_CM|PSL_FPD); |
309 | regs[PC] = (int)u.u_pcb.pcb_sigc; | |
310 | return; | |
311 | ||
79821b2c | 312 | asm("bad:"); |
79821b2c | 313 | bad: |
2e2312a9 | 314 | psignal(u.u_procp, SIGKILL); |
79821b2c BJ |
315 | } |
316 | ||
9a3561c2 BJ |
317 | dorti() |
318 | { | |
2de46def | 319 | struct frame frame; |
9a3561c2 BJ |
320 | register int sp; |
321 | register int reg, mask; | |
322 | extern int ipcreg[]; | |
9a3561c2 BJ |
323 | |
324 | (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame)); | |
325 | sp = u.u_ar0[FP] + sizeof (frame); | |
2de46def BJ |
326 | u.u_ar0[PC] = frame.fr_savpc; |
327 | u.u_ar0[FP] = frame.fr_savfp; | |
328 | u.u_ar0[AP] = frame.fr_savap; | |
329 | mask = frame.fr_mask; | |
9a3561c2 BJ |
330 | for (reg = 0; reg <= 11; reg++) { |
331 | if (mask&1) { | |
858ecf0f | 332 | u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp); |
9a3561c2 BJ |
333 | sp += 4; |
334 | } | |
335 | mask >>= 1; | |
336 | } | |
2de46def BJ |
337 | sp += frame.fr_spa; |
338 | u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw; | |
339 | if (frame.fr_s) | |
858ecf0f | 340 | sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff); |
9a3561c2 | 341 | /* phew, now the rei */ |
858ecf0f | 342 | u.u_ar0[PC] = fuword((caddr_t)sp); |
9a3561c2 | 343 | sp += 4; |
858ecf0f | 344 | u.u_ar0[PS] = fuword((caddr_t)sp); |
9a3561c2 BJ |
345 | sp += 4; |
346 | u.u_ar0[PS] |= PSL_CURMOD|PSL_PRVMOD; | |
347 | u.u_ar0[PS] &= ~PSL_USERCLR; | |
cdc19302 | 348 | u.u_ar0[SP] = (int)sp; |
9a3561c2 BJ |
349 | } |
350 | ||
79821b2c | 351 | /* |
dca3793c BJ |
352 | * Memenable enables the memory controlle corrected data reporting. |
353 | * This runs at regular intervals, turning on the interrupt. | |
354 | * The interrupt is turned off, per memory controller, when error | |
355 | * reporting occurs. Thus we report at most once per memintvl. | |
79821b2c | 356 | */ |
79821b2c BJ |
357 | int memintvl = MEMINTVL; |
358 | ||
dca3793c | 359 | memenable() |
79821b2c | 360 | { |
8ae22d0f BJ |
361 | register struct mcr *mcr; |
362 | register int m; | |
d96afe11 | 363 | |
8ae22d0f BJ |
364 | for (m = 0; m < nmcr; m++) { |
365 | mcr = mcraddr[m]; | |
366 | switch (cpu) { | |
367 | #if VAX780 | |
368 | case VAX_780: | |
dca3793c | 369 | M780_ENA(mcr); |
8ae22d0f | 370 | break; |
48575cec | 371 | #endif |
8ae22d0f BJ |
372 | #if VAX750 |
373 | case VAX_750: | |
dca3793c | 374 | M750_ENA(mcr); |
8ae22d0f | 375 | break; |
48575cec | 376 | #endif |
8ae22d0f | 377 | } |
dca3793c BJ |
378 | } |
379 | if (memintvl > 0) | |
380 | timeout(memenable, (caddr_t)0, memintvl); | |
381 | } | |
382 | ||
383 | /* | |
384 | * Memerr is the interrupt routine for corrected read data | |
385 | * interrupts. It looks to see which memory controllers have | |
386 | * unreported errors, reports them, and disables further | |
387 | * reporting for a time on those controller. | |
388 | */ | |
389 | memerr() | |
390 | { | |
391 | register struct mcr *mcr; | |
392 | register int m; | |
393 | ||
394 | for (m = 0; m < nmcr; m++) { | |
395 | mcr = mcraddr[m]; | |
8ae22d0f BJ |
396 | switch (cpu) { |
397 | #if VAX780 | |
398 | case VAX_780: | |
dca3793c BJ |
399 | if (M780_ERR(mcr)) { |
400 | printf("memerr mcr%d addr %x syn %x\n", | |
401 | m, M780_ADDR(mcr), M780_SYN(mcr)); | |
402 | M780_INH(mcr); | |
403 | } | |
8ae22d0f | 404 | break; |
d96afe11 | 405 | #endif |
8ae22d0f BJ |
406 | #if VAX750 |
407 | case VAX_750: | |
dca3793c BJ |
408 | if (M750_ERR(mcr)) { |
409 | printf("memerr mcr%d addr %x syn %x\n", | |
410 | m, M750_ADDR(mcr), M750_SYN(mcr)); | |
411 | M750_INH(mcr); | |
412 | } | |
8ae22d0f BJ |
413 | break; |
414 | #endif | |
415 | } | |
416 | } | |
79821b2c BJ |
417 | } |
418 | ||
419 | /* | |
420 | * Invalidate single all pte's in a cluster | |
421 | */ | |
422 | tbiscl(v) | |
423 | unsigned v; | |
424 | { | |
425 | register caddr_t addr; /* must be first reg var */ | |
426 | register int i; | |
427 | ||
428 | asm(".set TBIS,58"); | |
429 | addr = ptob(v); | |
430 | for (i = 0; i < CLSIZE; i++) { | |
431 | #ifdef lint | |
432 | mtpr(TBIS, addr); | |
433 | #else | |
434 | asm("mtpr r11,$TBIS"); | |
435 | #endif | |
436 | addr += NBPG; | |
437 | } | |
438 | } | |
b559a38a | 439 | |
0dc06be8 BJ |
440 | int waittime = -1; |
441 | ||
442 | boot(panic, arghowto) | |
443 | int panic, arghowto; | |
444 | { | |
445 | register int howto; /* r11 == how to boot */ | |
446 | register int devtype; /* r10 == major of root dev */ | |
447 | ||
448 | howto = arghowto; | |
cf19cacc | 449 | if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) { |
0dc06be8 BJ |
450 | waittime = 0; |
451 | update(); | |
87771f34 BJ |
452 | printf("syncing disks... "); |
453 | while (++waittime <= 5) | |
0dc06be8 | 454 | sleep((caddr_t)&lbolt, PZERO); |
87771f34 | 455 | printf("done\n"); |
0dc06be8 BJ |
456 | } |
457 | splx(0x1f); /* extreme priority */ | |
458 | devtype = major(rootdev); | |
2de46def BJ |
459 | if (howto&RB_HALT) { |
460 | printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n"); | |
461 | mtpr(IPL, 0x1f); | |
462 | for (;;) | |
463 | ; | |
464 | } else { | |
465 | if (panic == RB_PANIC) | |
466 | doadump(); | |
48575cec | 467 | tocons(TXDB_BOOT); |
2de46def | 468 | } |
e5a79c70 BJ |
469 | #if VAX750 |
470 | if (cpu == VAX_750) | |
471 | { asm("movl r11,r5"); } /* boot flags go in r5 */ | |
48575cec | 472 | #endif |
0dc06be8 BJ |
473 | for (;;) |
474 | asm("halt"); | |
858ecf0f BJ |
475 | #ifdef lint |
476 | printf("howto %d, devtype %d\n", howto, devtype); | |
477 | #endif | |
478 | /*NOTREACHED*/ | |
479 | } | |
480 | ||
481 | tocons(c) | |
482 | { | |
483 | ||
484 | while ((mfpr(TXCS)&TXCS_RDY) == 0) | |
485 | continue; | |
486 | mtpr(TXDB, c); | |
0dc06be8 | 487 | } |
2de46def BJ |
488 | |
489 | /* | |
490 | * Doadump comes here after turning off memory management and | |
491 | * getting on the dump stack, either when called above, or by | |
492 | * the auto-restart code. | |
493 | */ | |
494 | dumpsys() | |
495 | { | |
496 | ||
497 | if ((minor(dumpdev)&07) != 1) | |
498 | return; | |
499 | printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); | |
dca3793c BJ |
500 | printf("dump "); |
501 | switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { | |
502 | ||
503 | case ENXIO: | |
504 | printf("device bad\n"); | |
505 | break; | |
506 | ||
507 | case EFAULT: | |
508 | printf("device not ready\n"); | |
509 | break; | |
510 | ||
511 | case EINVAL: | |
512 | printf("area improper\n"); | |
513 | break; | |
514 | ||
515 | case EIO: | |
516 | printf("i/o error"); | |
517 | break; | |
518 | ||
519 | default: | |
520 | printf("succeeded"); | |
521 | break; | |
522 | } | |
2de46def | 523 | } |
a58c4eb5 | 524 | |
dca3793c BJ |
525 | /* |
526 | * Machine check error recovery code. | |
527 | * Print out the machine check frame and then give up. | |
528 | */ | |
a58c4eb5 BJ |
529 | char *mc780[] = { |
530 | "cp read", "ctrl str par", "cp tbuf par", "cp cache par", | |
531 | "cp rdtimo", "cp rds", "ucode lost", 0, | |
532 | 0, 0, "ib tbuf par", 0, | |
533 | "ib rds", "ib rd timo", 0, "ib cache par" | |
534 | }; | |
535 | ||
dca3793c BJ |
536 | /* |
537 | * Frame for a 780 | |
538 | */ | |
a58c4eb5 | 539 | struct mc780frame { |
dca3793c BJ |
540 | int mc8_bcnt; /* byte count == 28 */ |
541 | int mc8_summary; /* summary parameter (as above) */ | |
542 | int mc8_cpues; /* cpu error status */ | |
543 | int mc8_upc; /* micro pc */ | |
544 | int mc8_vaviba; /* va/viba register */ | |
545 | int mc8_dreg; /* d register */ | |
546 | int mc8_tber0; /* tbuf error reg 0 */ | |
547 | int mc8_tber1; /* tbuf error reg 1 */ | |
548 | int mc8_timo; /* timeout address divided by 4 */ | |
549 | int mc8_parity; /* parity */ | |
550 | int mc8_sbier; /* sbi error register */ | |
551 | int mc8_pc; /* trapped pc */ | |
552 | int mc8_psl; /* trapped psl */ | |
a78738a8 BJ |
553 | }; |
554 | struct mc750frame { | |
dca3793c BJ |
555 | int mc5_bcnt; /* byte count == 28 */ |
556 | int mc5_summary; /* summary parameter (as above) */ | |
557 | int mc5_va; /* virtual address register */ | |
558 | int mc5_errpc; /* error pc */ | |
a78738a8 | 559 | int mc5_mdr; |
dca3793c BJ |
560 | int mc5_svmode; /* saved mode register */ |
561 | int mc5_rdtimo; /* read lock timeout */ | |
562 | int mc5_tbgpar; /* tb group parity error register */ | |
563 | int mc5_cacherr; /* cache error register */ | |
564 | int mc5_buserr; /* bus error register */ | |
565 | int mc5_mcesr; /* machine check status register */ | |
566 | int mc5_pc; /* trapped pc */ | |
567 | int mc5_psl; /* trapped psl */ | |
a58c4eb5 BJ |
568 | }; |
569 | ||
a78738a8 BJ |
570 | machinecheck(cmcf) |
571 | caddr_t cmcf; | |
a58c4eb5 | 572 | { |
a78738a8 | 573 | register int type = ((struct mc780frame *)cmcf)->mc8_summary; |
a58c4eb5 BJ |
574 | |
575 | printf("machine check %x: %s%s\n", type, mc780[type&0xf], | |
576 | (type&0xf0) ? " abort" : " fault"); | |
a78738a8 BJ |
577 | switch (cpu) { |
578 | #if VAX780 | |
579 | case VAX_780: { | |
580 | register struct mc780frame *mcf = (struct mc780frame *)cmcf; | |
581 | register int sbifs; | |
582 | printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n", | |
583 | mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba, | |
584 | mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1); | |
585 | sbifs = mfpr(SBIFS); | |
586 | printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n", | |
587 | mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier, | |
588 | mcf->mc8_pc, mcf->mc8_psl, sbifs); | |
589 | /* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */ | |
590 | /* BOOK AND SHOULD BE PUT IN AN ``sbi.h'' */ | |
591 | mtpr(SBIFS, sbifs &~ 0x2000000); | |
592 | mtpr(SBIER, mfpr(SBIER) | 0x70c0); | |
593 | break; | |
594 | } | |
595 | #endif | |
596 | #if VAX750 | |
597 | case VAX_750: { | |
598 | register struct mc750frame *mcf = (struct mc750frame *)cmcf; | |
599 | printf("\tva %x errpc %x mdr %x smr %x tbgpar %x cacherr %x\n", | |
600 | mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode, | |
601 | mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr); | |
602 | printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n", | |
603 | mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, | |
604 | mfpr(MCSR)); | |
605 | mtpr(MCESR, 0xf); | |
606 | break; | |
607 | } | |
608 | #endif | |
609 | } | |
a58c4eb5 BJ |
610 | panic("mchk"); |
611 | } |