platform.S revision 8017:2d68a6a11e44
1/*
2 * Copyright (c) 2003, 2004, 2005
3 * The Regents of The University of Michigan
4 * All Rights Reserved
5 *
6 * This code is part of the M5 simulator, developed by Nathan Binkert,
7 * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
8 * from Ron Dreslinski, Dave Greene, Lisa Hsu, Ali Saidi, and Andrew
9 * Schultz.
10 *
11 * Permission is granted to use, copy, create derivative works and
12 * redistribute this software and such derivative works for any
13 * purpose, so long as the copyright notice above, this grant of
14 * permission, and the disclaimer below appear in all copies made; and
15 * so long as the name of The University of Michigan is not used in
16 * any advertising or publicity pertaining to the use or distribution
17 * of this software without specific, written prior authorization.
18 *
19 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
20 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
21 * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
25 * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
26 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
27 * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
28 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
29 * DAMAGES.
30 */
31
32/*
33 * Copyright 1993 Hewlett-Packard Development Company, L.P.
34 *
35 * Permission is hereby granted, free of charge, to any person
36 * obtaining a copy of this software and associated documentation
37 * files (the "Software"), to deal in the Software without
38 * restriction, including without limitation the rights to use, copy,
39 * modify, merge, publish, distribute, sublicense, and/or sell copies
40 * of the Software, and to permit persons to whom the Software is
41 * furnished to do so, subject to the following conditions:
42 *
43 * The above copyright notice and this permission notice shall be
44 * included in all copies or substantial portions of the Software.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
50 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
51 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53 * SOFTWARE.
54 */
55
56#define max_cpuid 1
57#define hw_rei_spe hw_rei
58
59#include "ev5_defs.h"
60#include "ev5_impure.h"
61#include "ev5_alpha_defs.h"
62#include "ev5_paldef.h"
63#include "ev5_osfalpha_defs.h"
64#include "fromHudsonMacros.h"
65#include "fromHudsonOsf.h"
66#include "dc21164FromGasSources.h"
67#include "cserve.h"
68#include "tlaser.h"
69
70#define pt_entInt pt_entint
71#define pt_entArith pt_entarith
72#define mchk_size ((mchk_cpu_base + 7  + 8) &0xfff8)
73#define mchk_flag CNS_Q_FLAG
74#define mchk_sys_base 56
75#define mchk_cpu_base (CNS_Q_LD_LOCK + 8)
76#define mchk_offsets CNS_Q_EXC_ADDR
77#define mchk_mchk_code 8
78#define mchk_ic_perr_stat CNS_Q_ICPERR_STAT
79#define mchk_dc_perr_stat CNS_Q_DCPERR_STAT
80#define mchk_sc_addr CNS_Q_SC_ADDR
81#define mchk_sc_stat CNS_Q_SC_STAT
82#define mchk_ei_addr CNS_Q_EI_ADDR
83#define mchk_bc_tag_addr CNS_Q_BC_TAG_ADDR
84#define mchk_fill_syn CNS_Q_FILL_SYN
85#define mchk_ei_stat CNS_Q_EI_STAT
86#define mchk_exc_addr CNS_Q_EXC_ADDR
87#define mchk_ld_lock CNS_Q_LD_LOCK
88#define osfpcb_q_Ksp pcb_q_ksp
89#define pal_impure_common_size ((0x200 + 7) & 0xfff8)
90
91#if defined(BIG_TSUNAMI)
92#define MAXPROC         0x3f
93#define IPIQ_addr       0x800
94#define IPIQ_shift      0
95#define IPIR_addr       0x840
96#define IPIR_shift      0
97#define RTC_addr        0x880
98#define RTC_shift       0
99#define DIR_addr        0xa2
100#elif defined(TSUNAMI)
101#define MAXPROC         0x3
102#define IPIQ_addr       0x080
103#define IPIQ_shift      12
104#define IPIR_addr       0x080
105#define IPIR_shift      8
106#define RTC_addr        0x080
107#define RTC_shift       4
108#define DIR_addr        0xa0
109#elif defined(TLASER)
110#define MAXPROC         0xf
111#else
112#error Must define BIG_TSUNAMI, TSUNAMI, or TLASER
113#endif
114
115#define ALIGN_BLOCK \
116        .align 5
117
118#define ALIGN_BRANCH \
119        .align 3
120
121#define EXPORT(_x)	\
122        .align 5;	\
123        .globl _x;	\
124_x:
125
126// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
127// XXX the following is 'made up'
128// XXX bugnion
129
130// XXX bugnion not sure how to align 'quad'
131#define ALIGN_QUAD \
132        .align  3
133
134#define ALIGN_128 \
135        .align  7
136
137
138#define GET_IMPURE(_r) mfpr _r,pt_impure
139#define GET_ADDR(_r1,_off,_r2)  lda _r1,_off(_r2)
140
141
142#define BIT(_x) (1<<(_x))
143
144
145// System specific code - beh model version
146//
147//
148// Entry points
149//	SYS_CFLUSH - Cache flush
150//	SYS_CSERVE - Console service
151//	SYS_WRIPIR - interprocessor interrupts
152//	SYS_HALT_INTERRUPT - Halt interrupt
153//	SYS_PASSIVE_RELEASE - Interrupt, passive release
154//	SYS_INTERRUPT - Interrupt
155//	SYS_RESET - Reset
156//	SYS_ENTER_CONSOLE
157//
158//
159// Macro to read TLINTRSUMx
160//
161// Based on the CPU_NUMBER, read either the TLINTRSUM0 or TLINTRSUM1 register
162//
163// Assumed register usage:
164//   rsum TLINTRSUMx contents
165//   raddr node space address
166//   scratch scratch register
167//
168#define Read_TLINTRSUMx(_rsum, _raddr, _scratch)	                  \
169    nop;                                                                  \
170    mfpr  _scratch, pt_whami;      /* Get our whami (VID) */              \
171    extbl _scratch, 1, _scratch;   /* shift down to bit 0 */              \
172    lda	  _raddr, 0xff88(zero);    /* Get base node space address bits */ \
173    sll	  _raddr, 24, _raddr;      /* Shift up to proper position */      \
174    srl	  _scratch, 1, _rsum;      /* Shift off the cpu number */         \
175    sll   _rsum, 22, _rsum;        /* Get our node offset */		  \
176    addq  _raddr, _rsum, _raddr;   /* Get our base node space address */  \
177    blbs  _scratch, 1f;                                                   \
178    lda	  _raddr, 0x1180(_raddr);                                         \
179    br	  r31, 2f;                                                        \
1801:  lda	  _raddr, 0x11c0(_raddr);                                         \
1812:  ldl_p _rsum, 0(_raddr)         /* read the right tlintrsum reg */
182
183//
184// Macro to write TLINTRSUMx
185//
186//  Based on the CPU_NUMBER, write either the TLINTRSUM0 or TLINTRSUM1 register
187//
188// Assumed register usage:
189//   rsum TLINTRSUMx write data
190//   raddr node space address
191//   scratch scratch register
192//
193#define Write_TLINTRSUMx(_rsum,_raddr,_whami)                              \
194    nop;                                                                   \
195    mfpr  _whami, pt_whami;       /* Get our whami (VID) */                \
196    extbl _whami, 1, _whami;      /* shift down to bit 0 */                \
197    lda   _raddr, 0xff88(zero);   /* Get base node space address bits */   \
198    sll   _raddr, 24, _raddr;     /* Shift up to proper position */        \
199    blbs  _whami, 1f;                                                      \
200    lda   _raddr, 0x1180(_raddr);                                          \
201    br    zero, 2f;                                                        \
2021:  lda   _raddr, 0x11c0(_raddr);                                          \
2032:  srl	  _whami, 1, _whami;      /* Get our node offset */                \
204    addq  _raddr, _whami, _raddr; /* Get our base node space address */    \
205    mb;                                                                    \
206    stq_p _rsum, 0(_raddr);       /* write the right tlintrsum reg */      \
207    ldq_p _rsum, 0(_raddr);       /* dummy read to tlintrsum */            \
208    bis   _rsum, _rsum, _rsum     /* needed to complete the ldqp above */
209
210
211//
212// Macro to determine highest priority TIOP Node ID from interrupt pending mask
213//
214// Assumed register usage:
215//  rmask - TLINTRSUMx contents, shifted to isolate IOx bits
216//  rid - TLSB Node ID of highest TIOP
217//
218#define Intr_Find_TIOP(_rmask,_rid)              \
219    srl  _rmask,3,_rid;    /* check IOP8 */      \
220    blbc _rid,1f;          /* not IOP8 */        \
221    lda  _rid,8(zero);     /* IOP8 */            \
222    br   zero,6f;                                \
2231:  srl  _rmask,3,_rid;    /* check IOP7 */      \
224    blbc _rid, 2f;         /* not IOP7 */        \
225    lda  _rid, 7(r31);     /* IOP7 */            \
226    br   r31, 6f;                                \
2272:  srl  _rmask, 2, _rid;  /* check IOP6 */      \
228    blbc _rid, 3f;         /* not IOP6 */        \
229    lda  _rid, 6(r31);     /* IOP6 */            \
230    br   r31, 6f;                                \
2313:  srl  _rmask, 1, _rid;  /* check IOP5 */      \
232    blbc _rid, 4f;         /* not IOP5 */        \
233    lda  _rid, 5(r31);     /* IOP5 */            \
234    br   r31, 6f;                                \
2354:  srl  _rmask, 0, _rid;  /* check IOP4 */      \
236    blbc _rid, 5f;         /* not IOP4 */        \
237    lda  r14, 4(r31);      /* IOP4 */            \
238    br   r31, 6f;                                \
2395:  lda  r14, 0(r31);      /* passive release */ \
2406:
241
242//
243// Macro to calculate base node space address for given node id
244//
245// Assumed register usage:
246//  rid - TLSB node id
247//  raddr - base node space address
248#define Get_TLSB_Node_Address(_rid,_raddr)  \
249    sll  _rid, 22, _rid;                    \
250    lda  _raddr, 0xff88(zero);              \
251    sll  _raddr, 24, _raddr;                \
252    addq _raddr, _rid, _raddr
253
254
255#define OSFmchk_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg)     \
256    lda   _rs1, tlep_##_tlepreg(zero);                             \
257    or    _rs1, _nodebase, _rs1;                                   \
258    ldl_p _rs1, 0(_rs1);                                           \
259    stl_p _rs, mchk_##_tlepreg(_rlog)   /* store in frame */
260
261#define OSFmchk_TLEPstore(_tlepreg) \
262    OSFmchk_TLEPstore_1(r14,r8,r4,r13,_tlepreg)
263
264#define OSFcrd_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) 		\
265        lda	_rs1, tlep_##_tlepreg(zero);				\
266        or	_rs1, _nodebase, _rs1;  				\
267        ldl_p	_rs1, 0(_rs1);						\
268        stl_p	_rs, mchk_crd_##_tlepreg(_rlog)
269
270#define OSFcrd_TLEPstore_tlsb_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) 	\
271        lda	_rs1, tlsb_##_tlepreg(zero);				\
272        or	_rs1, _nodebase, _rs1;  				\
273        ldl_p	_rs1, 0(_rs1);						\
274        stl_p	_rs,mchk_crd_##_tlepreg(_rlog)
275
276#define OSFcrd_TLEPstore_tlsb_clr_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) 	\
277        lda	_rs1,tlsb_##_tlepreg(zero);				\
278        or	_rs1, _nodebase,_rs1;  					\
279        ldl_p	_rs1, 0(_rs1);						\
280        stl_p	_rs, mchk_crd_##_tlepreg(_rlog);			\
281        stl_p   _rs, 0(_rs1)
282
283#define OSFcrd_TLEPstore(_tlepreg) \
284    OSFcrd_TLEPstore_1(r14,r8,r4,r13,_tlepreg)
285#define OSFcrd_TLEPstore_tlsb(_tlepreg) \
286    OSFcrd_TLEPstore_tlsb_1(r14,r8,r4,r13,_tlepreg)
287#define OSFcrd_TLEPstore_tlsb_clr(_tlepreg) \
288    OSFcrd_TLEPstore_tlsb_clr_1(r14,r8,r4,r13,_tlepreg)
289
290
291#define save_pcia_intr(_irq)                                            \
292    and   r13, 0xf, r25;            /* isolate low 4 bits */            \
293    addq  r14, 4, r14;              /* format the TIOP Node id field */ \
294    sll   r14, 4, r14;              /* shift the TIOP Node id */        \
295    or    r14, r25, r10;            /* merge Node id/hose/HPC */        \
296    mfpr  r14, pt14;                /* get saved value */               \
297    extbl r14, _irq, r25;           /* confirm none outstanding */      \
298    bne   r25, sys_machine_check_while_in_pal;                          \
299    insbl r10, _irq, r10;           /* align new info */                \
300    or    r14, r10, r14;            /* merge info */                    \
301    mtpr  r14, pt14;                /* save it */                       \
302    bic   r13, 0xf, r13             /* clear low 4 bits of vector */
303
304
305// wripir - PALcode for wripir instruction
306// R16 has the processor number.
307//
308        ALIGN_BLOCK
309EXPORT(sys_wripir)
310    //
311    // Convert the processor number to a CPU mask
312    //
313    and   r16, MAXPROC, r14	// mask the top stuff: MAXPROC+1 CPUs supported
314    bis   r31, 0x1, r16		// get a one
315    sll   r16, r14, r14		// shift the bit to the right place
316#if defined(TSUNAMI) || defined(BIG_TSUNAMI)
317    sll   r14,IPIQ_shift,r14
318#endif
319
320
321    //
322    // Build the Broadcast Space base address
323    //
324#if defined(TSUNAMI) || defined(BIG_TSUNAMI)
325    lda   r16,0xf01(r31)
326    sll   r16,32,r16
327    ldah  r13,0xa0(r31)
328    sll   r13,8,r13
329    bis   r16,r13,r16
330    lda   r16,IPIQ_addr(r16)
331#elif defined(TLASER)
332    lda   r13, 0xff8e(r31)	// Load the upper address bits
333    sll   r13, 24, r13		// shift them to the top
334#endif
335
336    //
337    // Send out the IP Intr
338    //
339#if defined(TSUNAMI) || defined(BIG_TSUNAMI)
340    stq_p r14, 0(r16)		// Tsunami MISC Register
341#elif defined(TLASER)
342    stq_p r14, 0x40(r13)	// Write to TLIPINTR reg
343#endif
344    wmb				// Push out the store
345    hw_rei
346
347
348// cflush - PALcode for CFLUSH instruction
349//
350// SYS_CFLUSH
351// Entry:
352//	R16 - contains the PFN of the page to be flushed
353//
354// Function:
355//	Flush all Dstream caches of 1 entire page
356//
357//
358        ALIGN_BLOCK
359EXPORT(sys_cflush)
360
361//      #convert pfn to addr, and clean off <63:20>
362//      #sll	r16, <page_offset_size_bits>+<63-20>>, r12
363        sll	r16, page_offset_size_bits+(63-20),r12
364
365//      #ldah	r13,<<1@22>+32768>@-16(r31)// + xxx<31:16>
366//      # stolen from srcmax code. XXX bugnion
367        lda	r13, 0x10(r31)				   // assume 16Mbytes of cache
368        sll	r13, 20, r13				   // convert to bytes
369
370
371        srl	r12, 63-20, r12	// shift back to normal position
372        xor	r12, r13, r12		// xor addr<18>
373
374        or	r31, 8192/(32*8), r13	// get count of loads
375        nop
376
377cflush_loop:
378        subq	r13, 1, r13		// decr counter
379        mfpr    r25, ev5__intid         // Fetch level of interruptor
380
381        ldq_p	r31, 32*0(r12)		// do a load
382        ldq_p	r31, 32*1(r12)		// do next load
383
384        ldq_p	r31, 32*2(r12)		// do next load
385        ldq_p	r31, 32*3(r12)		// do next load
386
387        ldq_p	r31, 32*4(r12)		// do next load
388        ldq_p	r31, 32*5(r12)		// do next load
389
390        ldq_p	r31, 32*6(r12)		// do next load
391        ldq_p	r31, 32*7(r12)		// do next load
392
393        mfpr    r14, ev5__ipl           // Fetch current level
394        lda	r12, (32*8)(r12)	// skip to next cache block addr
395
396        cmple   r25, r14, r25           // R25 = 1 if intid .less than or eql ipl
397        beq	r25, 1f		// if any int's pending, re-queue CFLUSH -- need to check for hlt interrupt???
398
399        bne	r13, cflush_loop 	// loop till done
400        hw_rei				// back to user
401
402        ALIGN_BRANCH
4031:					// Here if interrupted
404        mfpr	r12, exc_addr
405        subq	r12, 4, r12		// Backup PC to point to CFLUSH
406
407        mtpr	r12, exc_addr
408        nop
409
410        mfpr	r31, pt0		// Pad exc_addr write
411        hw_rei
412
413
414        ALIGN_BLOCK
415//
416// sys_cserve - PALcode for CSERVE instruction
417//
418// Function:
419//	Various functions for private use of console software
420//
421//	option selector in r0
422//	arguments in r16....
423//
424//
425//	r0 = 0	unknown
426//
427//	r0 = 1	ldq_p
428//	r0 = 2	stq_p
429//		args, are as for normal STQ_P/LDQ_P in VMS PAL
430//
431//	r0 = 3	dump_tb's
432//	r16 = detination PA to dump tb's to.
433//
434//	r0<0> = 1, success
435//	r0<0> = 0, failure, or option not supported
436//	r0<63:1> = (generally 0, but may be function dependent)
437//	r0 - load data on ldq_p
438//
439//
440EXPORT(sys_cserve)
441
442        /* taken from scrmax */
443        cmpeq	r18, CSERVE_K_RD_IMPURE, r0
444        bne	r0, Sys_Cserve_Rd_Impure
445
446        cmpeq	r18, CSERVE_K_JTOPAL, r0
447        bne	r0, Sys_Cserve_Jtopal
448        call_pal        0
449
450        or	r31, r31, r0
451        hw_rei				// and back we go
452
453Sys_Cserve_Rd_Impure:
454        mfpr	r0, pt_impure		// Get base of impure scratch area.
455        hw_rei
456
457        ALIGN_BRANCH
458
459Sys_Cserve_Jtopal:
460        bic	a0, 3, t8		// Clear out low 2 bits of address
461        bis	t8, 1, t8		// Or in PAL mode bit
462        mtpr    t8,exc_addr
463        hw_rei
464
465        // ldq_p
466        ALIGN_QUAD
4671:
468        ldq_p	r0,0(r17)		// get the data
469        nop				// pad palshadow write
470
471        hw_rei				// and back we go
472
473
474        // stq_p
475        ALIGN_QUAD
4762:
477        stq_p	r18, 0(r17)		// store the data
478        lda     r0,17(r31) // bogus
479        hw_rei				// and back we go
480
481
482        ALIGN_QUAD
483csrv_callback:
484        ldq	r16, 0(r17)		// restore r16
485        ldq	r17, 8(r17)		// restore r17
486        lda	r0, hlt_c_callback(r31)
487        br	r31, sys_enter_console
488
489
490csrv_identify:
491        mfpr	r0, pal_base
492        ldq_p	r0, 8(r0)
493        hw_rei
494
495
496// dump tb's
497        ALIGN_QUAD
4980:
499        // DTB PTEs - 64 entries
500        addq	r31, 64, r0		// initialize loop counter
501        nop
502
5031:	mfpr	r12, ev5__dtb_pte_temp	// read out next pte to temp
504        mfpr	r12, ev5__dtb_pte	// read out next pte to reg file
505
506        subq	r0, 1, r0		// decrement loop counter
507        nop				// Pad - no Mbox instr in cycle after mfpr
508
509        stq_p	r12, 0(r16)		// store out PTE
510        addq	r16, 8 ,r16		// increment pointer
511
512        bne	r0, 1b
513
514        ALIGN_BRANCH
515        // ITB PTEs - 48 entries
516        addq	r31, 48, r0		// initialize loop counter
517        nop
518
5192:	mfpr	r12, ev5__itb_pte_temp	// read out next pte to temp
520        mfpr	r12, ev5__itb_pte	// read out next pte to reg file
521
522        subq	r0, 1, r0		// decrement loop counter
523        nop				//
524
525        stq_p	r12, 0(r16)		// store out PTE
526        addq	r16, 8 ,r16		// increment pointer
527
528        bne	r0, 2b
529        or	r31, 1, r0		// set success
530
531        hw_rei				// and back we go
532
533
534//
535// SYS_INTERRUPT  - Interrupt processing code
536//
537//	Current state:
538//		Stack is pushed
539//		ps, sp and gp are updated
540//		r12, r14 - available
541//		r13 - INTID (new EV5 IPL)
542//		r25 - ISR
543//		r16, r17, r18 - available
544//
545//
546EXPORT(sys_interrupt)
547    cmpeq  r13, 31, r12			// Check for level 31 interrupt
548    bne    r12, sys_int_mchk_or_crd	// machine check or crd
549
550    cmpeq  r13, 30, r12			// Check for level 30 interrupt
551    bne    r12, sys_int_powerfail	// powerfail
552
553    cmpeq  r13, 29, r12			// Check for level 29 interrupt
554    bne    r12, sys_int_perf_cnt	// performance counters
555
556    cmpeq  r13, 23, r12			// Check for level 23 interrupt
557    bne    r12, sys_int_23 		// IPI in Tsunami
558
559    cmpeq  r13, 22, r12			// Check for level 22 interrupt
560    bne    r12, sys_int_22 		// timer interrupt
561
562    cmpeq  r13, 21, r12			// Check for level 21 interrupt
563    bne    r12, sys_int_21	 	// I/O
564
565    cmpeq  r13, 20, r12			// Check for level 20 interrupt
566    bne    r12, sys_int_20		// system error interrupt
567                                        // (might be corrected)
568
569    mfpr   r14, exc_addr		// ooops, something is wrong
570    br     r31, pal_pal_bug_check_from_int
571
572
573//
574//sys_int_2*
575//	Routines to handle device interrupts at IPL 23-20.
576//	System specific method to ack/clear the interrupt, detect passive
577//      release, detect interprocessor (22),  interval clock (22),  corrected
578//	system error (20)
579//
580//	Current state:
581//		Stack is pushed
582//		ps, sp and gp are updated
583//		r12, r14 - available
584//		r13 - INTID (new EV5 IPL)
585//		r25 - ISR
586//
587//	On exit:
588//		Interrupt has been ack'd/cleared
589//		a0/r16 - signals IO device interrupt
590//		a1/r17 - contains interrupt vector
591//		exit to ent_int address
592//
593//
594
595#if defined(TSUNAMI) || defined(BIG_TSUNAMI)
596        ALIGN_BRANCH
597sys_int_23:
598        or      r31,0,r16                        // IPI interrupt A0 = 0
599        lda     r12,0xf01(r31)                   // build up an address for the MISC register
600        sll     r12,16,r12
601        lda     r12,0xa000(r12)
602        sll     r12,16,r12
603        lda     r12,IPIR_addr(r12)
604
605        mfpr    r10, pt_whami                   // get CPU ID
606        extbl	r10, 1, r10		        // Isolate just whami bits
607        or      r31,0x1,r14                     // load r14 with bit to clear
608        sll     r14,r10,r14                     // left shift by CPU ID
609        sll     r14,IPIR_shift,r14
610        stq_p   r14, 0(r12)                     // clear the ipi interrupt
611
612        br	r31, pal_post_interrupt		// Notify the OS
613
614
615        ALIGN_BRANCH
616sys_int_22:
617        or      r31,1,r16                       // a0 means it is a clock interrupt
618        lda     r12,0xf01(r31)                  // build up an address for the MISC register
619        sll     r12,16,r12
620        lda     r12,0xa000(r12)
621        sll     r12,16,r12
622        lda     r12,RTC_addr(r12)
623
624        mfpr    r10, pt_whami                   // get CPU ID
625        extbl	r10, 1, r10		        // Isolate just whami bits
626        or      r31,0x1,r14                     // load r14 with bit to clear
627        sll     r14,r10,r14                     // left shift by CPU ID
628        sll     r14,RTC_shift,r14               // put the bits in the right position
629        stq_p   r14, 0(r12)                     // clear the rtc interrupt
630
631        br	r31, pal_post_interrupt		// Tell the OS
632
633
634        ALIGN_BRANCH
635sys_int_20:
636        Read_TLINTRSUMx(r13,r10,r14)		// read the right TLINTRSUMx
637        srl	r13, 12, r13			// shift down to examine IPL15
638
639        Intr_Find_TIOP(r13,r14)
640        beq	r14, 1f
641
642        Get_TLSB_Node_Address(r14,r10)
643        lda	r10, 0xa40(r10)	// Get base TLILID address
644
645        ldl_p	r13, 0(r10)			// Read the TLILID register
646        bne	r13, pal_post_dev_interrupt
647        beq	r13, 1f
648
649        and	r13, 0x3, r10			// check for PCIA bits
650        beq	r10, pal_post_dev_interrupt	// done if nothing set
651        save_pcia_intr(1)
652        br	r31, pal_post_dev_interrupt	//
653
6541:	lda	r16, osfint_c_passrel(r31)	// passive release
655        br	r31, pal_post_interrupt		//
656
657
658        ALIGN_BRANCH
659sys_int_21:
660
661    lda     r12,0xf01(r31)                // calculate DIRn address
662    sll     r12,32,r12
663    ldah    r13,DIR_addr(r31)
664    sll	    r13,8,r13
665    bis	    r12,r13,r12
666
667    mfpr    r13, pt_whami                   // get CPU ID
668    extbl   r13, 1, r13		            // Isolate just whami bits
669
670#ifdef BIG_TSUNAMI
671    sll     r13,4,r13
672    or      r12,r13,r12
673#else
674    lda     r12,0x0080(r12)
675    and     r13,0x1,r14                     // grab LSB and shift left 6
676    sll     r14,6,r14
677    and     r13,0x2,r10                     // grabl LSB+1 and shift left 9
678    sll     r10,9,r10
679
680    mskbl   r12,0,r12                       // calculate DIRn address
681    lda     r13,0x280(r31)
682    bis     r12,r13,r12
683    or      r12,r14,r12
684    or      r12,r10,r12
685#endif
686
687    ldq_p    r13, 0(r12)                     // read DIRn
688
689    or      r31,1,r14                       // set bit 55 (ISA Interrupt)
690    sll     r14,55,r14
691
692    and     r13, r14, r14                    // check if bit 55 is set
693    lda     r16,0x900(r31)                  // load offset for normal into r13
694    beq     r14, normal_int                 // if not compute the vector normally
695
696    lda     r16,0x800(r31)                  // replace with offset for pic
697    lda     r12,0xf01(r31)                   // build an addr to access PIC
698    sll     r12,32,r12                        // at f01fc000000
699    ldah    r13,0xfc(r31)
700    sll	    r13,8,r13
701    bis	    r12,r13,r12
702    ldq_p    r13,0x0020(r12)                   // read PIC1 ISR for interrupting dev
703
704normal_int:
705    //ctlz    r13,r14                          // count the number of leading zeros
706    // EV5 doesn't have ctlz, but we do, so lets use it
707    .byte 0x4e
708    .byte 0x06
709    .byte 0xed
710    .byte 0x73
711    lda     r10,63(r31)
712    subq    r10,r14,r17                     // subtract from
713
714    lda	    r13,0x10(r31)
715    mulq    r17,r13,r17                    // compute 0x900 + (0x10 * Highest DIRn-bit)
716    addq    r17,r16,r17
717
718    or      r31,3,r16                       // a0 means it is a I/O interrupt
719
720    br      r31, pal_post_interrupt
721
722#elif defined(TLASER)
723        ALIGN_BRANCH
724sys_int_23:
725        Read_TLINTRSUMx(r13,r10,r14)		// read the right TLINTRSUMx
726        srl	r13, 22, r13			// shift down to examine IPL17
727
728        Intr_Find_TIOP(r13,r14)
729        beq	r14, 1f
730
731        Get_TLSB_Node_Address(r14,r10)
732        lda	r10, 0xac0(r10)	// Get base TLILID address
733
734        ldl_p	r13, 0(r10)			// Read the TLILID register
735        bne	r13, pal_post_dev_interrupt
736
7371:	lda	r16, osfint_c_passrel(r31)	// passive release
738        br	r31, pal_post_interrupt		//
739
740
741        ALIGN_BRANCH
742sys_int_22:
743        Read_TLINTRSUMx(r13,r10,r14)		// read the right TLINTRSUMx
744        srl	r13, 6, r14			// check the Intim bit
745
746        blbs	r14, tlep_intim			// go service Intim
747        srl	r13, 5, r14			// check the IP Int bit
748
749        blbs	r14, tlep_ipint			// go service IP Int
750        srl	r13, 17, r13			// shift down to examine IPL16
751
752        Intr_Find_TIOP(r13,r14)
753        beq	r14, 1f
754
755        Get_TLSB_Node_Address(r14,r10)
756        lda	r10, 0xa80(r10)	// Get base TLILID address
757
758        ldl_p	r13, 0(r10)			// Read the TLILID register
759        bne	r13, pal_post_dev_interrupt
760        beq	r13, 1f
761
762        and	r13, 0x3, r10			// check for PCIA bits
763        beq	r10, pal_post_dev_interrupt	// done if nothing set
764        save_pcia_intr(2)
765        br	r31, pal_post_dev_interrupt	//
766
7671:	lda	r16, osfint_c_passrel(r31)	// passive release
768        br	r31, pal_post_interrupt		//
769
770
771        ALIGN_BRANCH
772sys_int_21:
773        Read_TLINTRSUMx(r13,r10,r14)		// read the right TLINTRSUMx
774        srl	r13, 12, r13			// shift down to examine IPL15
775
776        Intr_Find_TIOP(r13,r14)
777        beq	r14, 1f
778
779        Get_TLSB_Node_Address(r14,r10)
780        lda	r10, 0xa40(r10)	// Get base TLILID address
781
782        ldl_p	r13, 0(r10)			// Read the TLILID register
783        bne	r13, pal_post_dev_interrupt
784        beq	r13, 1f
785
786        and	r13, 0x3, r10			// check for PCIA bits
787        beq	r10, pal_post_dev_interrupt	// done if nothing set
788        save_pcia_intr(1)
789        br	r31, pal_post_dev_interrupt	//
790
7911:	lda	r16, osfint_c_passrel(r31)	// passive release
792        br	r31, pal_post_interrupt		//
793
794
795        ALIGN_BRANCH
796sys_int_20:
797        lda	r13, 1(r31)			// Duart0 bit
798        Write_TLINTRSUMx(r13,r10,r14)		// clear the duart0 bit
799
800        Read_TLINTRSUMx(r13,r10,r14)		// read the right TLINTRSUMx
801        blbs	r13, tlep_uart0			// go service UART int
802
803        srl	r13, 7, r13			// shift down to examine IPL14
804        Intr_Find_TIOP(r13,r14)
805
806        beq	r14, tlep_ecc			// Branch if not IPL14
807        Get_TLSB_Node_Address(r14,r10)
808
809        lda	r10, 0xa00(r10)	                // Get base TLILID0 address
810        ldl_p	r13, 0(r10)			// Read the TLILID register
811
812        bne	r13, pal_post_dev_interrupt
813        beq	r13, 1f
814
815        and	r13, 0x3, r10			// check for PCIA bits
816        beq	r10, pal_post_dev_interrupt	// done if nothing set
817        save_pcia_intr(0)
818        br	r31, pal_post_dev_interrupt	//
8191:	lda	r16, osfint_c_passrel(r31)	// passive release
820        br	r31, pal_post_interrupt		//
821
822
823        ALIGN_BRANCH
824tlep_intim:
825        lda	r13, 0xffb(r31)			// get upper GBUS address bits
826        sll	r13, 28, r13			// shift up to top
827
828        lda	r13, (0x300)(r13)  // full CSRC address (tlep watch csrc offset)
829        ldq_p	r13, 0(r13)			// read CSRC
830
831        lda	r13, 0x40(r31)			// load Intim bit
832        Write_TLINTRSUMx(r13,r10,r14)		// clear the Intim bit
833
834        lda	r16, osfint_c_clk(r31)		// passive release
835        br	r31, pal_post_interrupt		// Build the stack frame
836
837
838        ALIGN_BRANCH
839tlep_ipint:
840        lda	r13, 0x20(r31)			// load IP Int bit
841        Write_TLINTRSUMx(r13,r10,r14)		// clear the IP Int bit
842
843        lda	r16, osfint_c_ip(r31)		// passive release
844        br	r31, pal_post_interrupt		// Build the stack frame
845
846
847        ALIGN_BRANCH
848tlep_uart0:
849        lda	r13, 0xffa(r31)			// get upper GBUS address bits
850        sll	r13, 28, r13			// shift up to top
851
852        ldl_p	r14, 0x80(r13)			// zero pointer register
853        lda	r14, 3(r31)			// index to RR3
854
855        stl_p	r14, 0x80(r13)			// write pointer register
856        mb
857
858        mb
859        ldl_p	r14, 0x80(r13)			// read RR3
860
861        srl	r14, 5, r10			// is it Channel A RX?
862        blbs	r10, uart0_rx
863
864        srl	r14, 4, r10			// is it Channel A TX?
865        blbs	r10, uart0_tx
866
867        srl	r14, 2, r10			// is it Channel B RX?
868        blbs	r10, uart1_rx
869
870        srl	r14, 1, r10			// is it Channel B TX?
871        blbs	r10, uart1_tx
872
873        lda	r8, 0(r31)			// passive release
874        br	r31, clear_duart0_int		// clear tlintrsum and post
875
876
877        ALIGN_BRANCH
878uart0_rx:
879        lda	r8, 0x680(r31)			// UART0 RX vector
880        br	r31, clear_duart0_int		// clear tlintrsum and post
881
882
883        ALIGN_BRANCH
884uart0_tx:
885        lda	r14, 0x28(r31)			// Reset TX Int Pending code
886        mb
887        stl_p	r14, 0x80(r13)			// write Channel A WR0
888        mb
889
890        lda	r8, 0x6c0(r31)			// UART0 TX vector
891        br	r31, clear_duart0_int		// clear tlintrsum and post
892
893
894        ALIGN_BRANCH
895uart1_rx:
896        lda	r8, 0x690(r31)			// UART1 RX vector
897        br	r31, clear_duart0_int		// clear tlintrsum and post
898
899
900        ALIGN_BRANCH
901uart1_tx:
902        lda	r14, 0x28(r31)			// Reset TX Int Pending code
903        stl_p	r14, 0(r13)			// write Channel B WR0
904
905        lda	r8, 0x6d0(r31)			// UART1 TX vector
906        br	r31, clear_duart0_int		// clear tlintrsum and post
907
908
909        ALIGN_BRANCH
910clear_duart0_int:
911        lda	r13, 1(r31)			// load duart0 bit
912        Write_TLINTRSUMx(r13,r10,r14)		// clear the duart0 bit
913
914        beq	r8, 1f
915        or	r8, r31, r13			// move vector to r13
916        br	r31, pal_post_dev_interrupt	// Build the stack frame
9171:	nop
918        nop
919        hw_rei
920//	lda	r16, osfint_c_passrel(r31)	// passive release
921//	br	r31, pal_post_interrupt		//
922
923
924        ALIGN_BRANCH
925tlep_ecc:
926        mfpr	r14, pt_whami			// get our node id
927        extbl	r14, 1, r14			// shift to bit 0
928
929        srl	r14, 1, r14			// shift off cpu number
930        Get_TLSB_Node_Address(r14,r10)		// compute our nodespace address
931
932        ldl_p	r13, 0x40(r10)	// read our TLBER WAS tlsb_tlber_offset
933        srl	r13, 17, r13			// shift down the CWDE/CRDE bits
934
935        and	r13, 3, r13			// mask the CWDE/CRDE bits
936        beq	r13, 1f
937
938        ornot	r31, r31, r12			// set flag
939        lda	r9, mchk_c_sys_ecc(r31)		// System Correctable error MCHK code
940        br	r31, sys_merge_sys_corr		// jump to CRD logout frame code
941
9421:	lda	r16, osfint_c_passrel(r31)	// passive release
943
944#endif // if TSUNAMI || BIG_TSUNAMI elif TLASER
945
946        ALIGN_BRANCH
947pal_post_dev_interrupt:
948        or	r13, r31, r17			// move vector to a1
949        or	r31, osfint_c_dev, r16		// a0 signals IO device interrupt
950
951pal_post_interrupt:
952        mfpr	r12, pt_entint
953
954        mtpr	r12, exc_addr
955
956        nop
957        nop
958
959        hw_rei_spe
960
961
962//
963// sys_passive_release
964//	Just pretend the interrupt never occurred.
965//
966
967EXPORT(sys_passive_release)
968        mtpr	r11, ev5__dtb_cm	// Restore Mbox current mode for ps
969        nop
970
971        mfpr	r31, pt0		// Pad write to dtb_cm
972        hw_rei
973
974//
975// sys_int_powerfail
976//	A powerfail interrupt has been detected.  The stack has been pushed.
977//	IPL and PS are updated as well.
978//
979//	I'm not sure what to do here, I'm treating it as an IO device interrupt
980//
981//
982
983        ALIGN_BLOCK
984sys_int_powerfail:
985        lda	r12, 0xffc4(r31)		// get GBUS_MISCR address bits
986        sll	r12, 24, r12			// shift to proper position
987        ldq_p	r12, 0(r12)			// read GBUS_MISCR
988        srl	r12, 5, r12			// isolate bit <5>
989        blbc	r12, 1f 			// if clear, no missed mchk
990
991                                                // Missed a CFAIL mchk
992        lda	r13, 0xffc7(r31)		// get GBUS$SERNUM address bits
993        sll	r13, 24, r13			// shift to proper position
994        lda	r14, 0x40(r31)			// get bit <6> mask
995        ldq_p	r12, 0(r13)			// read GBUS$SERNUM
996        or	r12, r14, r14			// set bit <6>
997        stq_p	r14, 0(r13)			// clear GBUS$SERNUM<6>
998        mb
999        mb
1000
10011:	br	r31, sys_int_mchk		// do a machine check
1002
1003        lda	r17, scb_v_pwrfail(r31)	// a1 to interrupt vector
1004        mfpr	r25, pt_entint
1005
1006        lda	r16, osfint_c_dev(r31)	// a0 to device code
1007        mtpr	r25, exc_addr
1008
1009        nop				// pad exc_addr write
1010        nop
1011
1012        hw_rei_spe
1013
1014//
1015// sys_halt_interrupt
1016//       A halt interrupt has been detected.  Pass control to the console.
1017//
1018//
1019//
1020        EXPORT(sys_halt_interrupt)
1021
1022        ldah	r13, 0x1800(r31)		// load Halt/^PHalt bits
1023        Write_TLINTRSUMx(r13,r10,r14)		// clear the ^PHalt bits
1024
1025        mtpr	r11, dtb_cm		// Restore Mbox current mode
1026        nop
1027        nop
1028        mtpr	r0, pt0
1029        lda     r0, hlt_c_hw_halt(r31)  // set halt code to hw halt
1030        br      r31, sys_enter_console  // enter the console
1031
1032
1033
1034//
1035// sys_int_mchk_or_crd
1036//
1037//	Current state:
1038//		Stack is pushed
1039//		ps, sp and gp are updated
1040//		r12
1041//		r13 - INTID (new EV5 IPL)
1042//		r14 - exc_addr
1043//		r25 - ISR
1044//		r16, r17, r18 - available
1045//
1046//
1047        ALIGN_BLOCK
1048sys_int_mchk_or_crd:
1049        srl	r25, isr_v_mck, r12
1050        blbs	r12, sys_int_mchk
1051        //
1052        // Not a Machine check interrupt, so must be an Internal CRD interrupt
1053        //
1054
1055        mb					//Clear out Cbox prior to reading IPRs
1056        srl 	r25, isr_v_crd, r13		//Check for CRD
1057        blbc	r13, pal_pal_bug_check_from_int	//If CRD not set, shouldn't be here!!!
1058
1059        lda	r9, 1(r31)
1060        sll 	r9, hwint_clr_v_crdc, r9	// get ack bit for crd
1061        mtpr	r9, ev5__hwint_clr		// ack the crd interrupt
1062
1063        or	r31, r31, r12			// clear flag
1064        lda	r9, mchk_c_ecc_c(r31)		// Correctable error MCHK code
1065
1066sys_merge_sys_corr:
1067        ldah	r14, 0xfff0(r31)
1068        mtpr   	r0, pt0				// save r0 for scratch
1069        zap	r14, 0xE0, r14			// Get Cbox IPR base
1070        mtpr   	r1, pt1				// save r0 for scratch
1071
1072        ldq_p	r0, ei_addr(r14)		// EI_ADDR IPR
1073        ldq_p	r10, fill_syn(r14)		// FILL_SYN IPR
1074        bis	r0, r10, r31			// Touch lds to make sure they complete before doing scrub
1075
1076        blbs	r12, 1f				// no scrubbing for IRQ0 case
1077// XXX bugnion	pvc_jsr	crd_scrub_mem, bsr=1
1078        bsr	r13, sys_crd_scrub_mem		// and go scrub
1079
1080                                                // ld/st pair in scrub routine will have finished due
1081                                                // to ibox stall of stx_c.  Don't need another mb.
1082        ldq_p	r8, ei_stat(r14)		// EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
1083        or	r8, r31, r12			// Must only be executed once in this flow, and must
1084        br	r31, 2f				// be after the scrub routine.
1085
10861:	ldq_p	r8, ei_stat(r14)		// EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
1087                                                // For IRQ0 CRD case only - meaningless data.
1088
10892:	mfpr	r13, pt_mces			// Get MCES
1090        srl	r12, ei_stat_v_ei_es, r14	// Isolate EI_STAT:EI_ES
1091        blbc	r14, 6f			// branch if 630
1092        srl	r13, mces_v_dsc, r14		// check if 620 reporting disabled
1093        blbc	r14, 5f				// branch if enabled
1094        or	r13, r31, r14			// don't set SCE if disabled
1095        br	r31, 8f			// continue
10965:	bis	r13, BIT(mces_v_sce), r14	// Set MCES<SCE> bit
1097        br	r31, 8f
1098
10996:     	srl	r13, mces_v_dpc, r14		// check if 630 reporting disabled
1100        blbc	r14, 7f			// branch if enabled
1101        or	r13, r31, r14			// don't set PCE if disabled
1102        br	r31, 8f			// continue
11037:	bis	r13, BIT(mces_v_pce), r14	// Set MCES<PCE> bit
1104
1105        // Setup SCB if dpc is not set
11068:	mtpr	r14, pt_mces			// Store updated MCES
1107        srl	r13, mces_v_sce, r1		// Get SCE
1108        srl	r13, mces_v_pce, r14		// Get PCE
1109        or	r1, r14, r1			// SCE OR PCE, since they share
1110                                                // the CRD logout frame
1111        // Get base of the logout area.
1112        GET_IMPURE(r14)				 // addr of per-cpu impure area
1113        GET_ADDR(r14,(pal_logout_area+mchk_crd_base),r14)
1114
1115        blbc	r1, sys_crd_write_logout_frame	// If pce/sce not set, build the frame
1116
1117        // Set the 2nd error flag in the logout area:
1118
1119        lda     r1, 3(r31)			// Set retry and 2nd error flags
1120        sll	r1, 30, r1			// Move to bits 31:30 of logout frame flag longword
1121        stl_p	r1, mchk_crd_flag+4(r14)	// store flag longword
1122        br 	sys_crd_ack
1123
1124sys_crd_write_logout_frame:
1125        // should only be here if neither the pce or sce bits are set
1126
1127        //
1128        // Write the mchk code to the logout area
1129        //
1130        stq_p	r9, mchk_crd_mchk_code(r14)
1131
1132
1133        //
1134        // Write the first 2 quadwords of the logout area:
1135        //
1136        lda     r1, 1(r31)		  	// Set retry flag
1137        sll	r1, 63, r9		  	// Move retry flag to bit 63
1138        lda	r1, mchk_crd_size(r9)	  	// Combine retry flag and frame size
1139        stq_p	r1, mchk_crd_flag(r14)	  	// store flag/frame size
1140
1141        //
1142        // Write error IPRs already fetched to the logout area
1143        //
1144        stq_p	r0, mchk_crd_ei_addr(r14)
1145        stq_p	r10, mchk_crd_fill_syn(r14)
1146        stq_p	r8, mchk_crd_ei_stat(r14)
1147        stq_p	r25, mchk_crd_isr(r14)
1148        //
1149        // Log system specific info here
1150        //
1151crd_storeTLEP_:
1152        lda	r1, 0xffc4(r31)			// Get GBUS$MISCR address
1153        sll	r1, 24, r1
1154        ldq_p	r1, 0(r1)			// Read GBUS$MISCR
1155        sll	r1, 16, r1			// shift up to proper field
1156        mfpr	r10, pt_whami			// get our node id
1157        extbl	r10, 1, r10			// shift to bit 0
1158        or	r1, r10, r1			// merge MISCR and WHAMI
1159        stl_p	r1, mchk_crd_whami(r14)		// write to crd logout area
1160        srl	r10, 1, r10			// shift off cpu number
1161
1162        Get_TLSB_Node_Address(r10,r0)		// compute our nodespace address
1163
1164        OSFcrd_TLEPstore_tlsb(tldev)
1165        OSFcrd_TLEPstore_tlsb_clr(tlber)
1166        OSFcrd_TLEPstore_tlsb_clr(tlesr0)
1167        OSFcrd_TLEPstore_tlsb_clr(tlesr1)
1168        OSFcrd_TLEPstore_tlsb_clr(tlesr2)
1169        OSFcrd_TLEPstore_tlsb_clr(tlesr3)
1170
1171sys_crd_ack:
1172        mfpr	r0, pt0					// restore r0
1173        mfpr	r1, pt1					// restore r1
1174
1175        srl	r12, ei_stat_v_ei_es, r12
1176        blbc	r12, 5f
1177        srl	r13, mces_v_dsc, r10			// logging enabled?
1178        br	r31, 6f
11795:	srl	r13, mces_v_dpc, r10			// logging enabled?
11806:	blbc	r10, sys_crd_post_interrupt		// logging enabled -- report it
1181
1182                                                        // logging not enabled
1183        // Get base of the logout area.
1184        GET_IMPURE(r13)				 // addr of per-cpu impure area
1185        GET_ADDR(r13,(pal_logout_area+mchk_crd_base),r13)
1186        ldl_p	r10, mchk_crd_rsvd(r13)			// bump counter
1187        addl	r10, 1, r10
1188        stl_p	r10, mchk_crd_rsvd(r13)
1189        mb
1190        br	r31, sys_crd_dismiss_interrupt		// just return
1191
1192        //
1193        // The stack is pushed.  Load up a0,a1,a2 and vector via entInt
1194        //
1195        //
1196
1197        ALIGN_BRANCH
1198sys_crd_post_interrupt:
1199        lda	r16, osfint_c_mchk(r31)	// flag as mchk/crd in a0
1200        lda	r17, scb_v_proc_corr_err(r31) // a1 <- interrupt vector
1201
1202        blbc	r12, 1f
1203        lda	r17, scb_v_sys_corr_err(r31) // a1 <- interrupt vector
1204
12051:	subq    r31, 1, r18            // get a -1
1206        mfpr	r25, pt_entInt
1207
1208        srl     r18, 42, r18           // shift off low bits of kseg addr
1209        mtpr	r25, exc_addr		// load interrupt vector
1210
1211        sll     r18, 42, r18           // shift back into position
1212        or    	r14, r18, r18           // EV4 algorithm - pass pointer to mchk frame as kseg address
1213
1214        hw_rei_spe			// done
1215
1216
1217        //
1218        // The stack is pushed.  Need to back out of it all.
1219        //
1220
1221sys_crd_dismiss_interrupt:
1222        br	r31, Call_Pal_Rti
1223
1224
1225// sys_crd_scrub_mem
1226//
1227//	r0 = addr of cache block
1228//
1229        ALIGN_BLOCK	// align for branch target
1230sys_crd_scrub_mem:
1231        // now find error in memory, and attempt to scrub that cache block
1232        // This routine just scrubs the failing octaword
1233        // Only need to "touch" one quadword per octaword to accomplish the scrub
1234        srl	r0, 39, r8		// get high bit of bad pa
1235        blbs	r8, 1f  		// don't attempt fixup on IO space addrs
1236        nop				// needed to align the ldq_pl to octaword boundary
1237        nop				//             "
1238
1239        ldq_p 	r8,  0(r0) 		// attempt to read the bad memory
1240                                        // location
1241                                        //    (Note bits 63:40,3:0 of ei_addr
1242                                        //     are set to 1, but as long as
1243                                        //     we are doing a phys ref, should
1244                                        //     be ok)
1245        nop				// Needed to keep the Ibox from swapping the ldq_p into E1
1246
1247        stq_p 	r8,  0(r0) 		// Store it back if it is still there.
1248                                        // If store fails, location already
1249                                        //  scrubbed by someone else
1250
1251        nop				// needed to align the ldq_p to octaword boundary
1252
1253        lda	r8, 0x20(r31)		// flip bit 5 to touch next hexaword
1254        xor	r8, r0, r0
1255        nop				// needed to align the ldq_p to octaword boundary
1256        nop				//             "
1257
1258        ldq_p 	r8,  0(r0) 		// attempt to read the bad memory
1259                                        // location
1260                                        //    (Note bits 63:40,3:0 of ei_addr
1261                                        //     are set to 1, but as long as
1262                                        //     we are doing a phys ref, should
1263                                        //     be ok)
1264        nop				// Needed to keep the Ibox from swapping the ldq_p into E1
1265
1266        stq_p 	r8,  0(r0) 		// Store it back if it is still there.
1267                                        // If store fails, location already
1268                                        //  scrubbed by someone else
1269
1270        lda	r8, 0x20(r31)		// restore r0 to original address
1271        xor	r8, r0, r0
1272
1273        //at this point, ei_stat could be locked due to a new corr error on the ld,
1274        //so read ei_stat to unlock AFTER this routine.
1275
1276// XXX bugnion	pvc$jsr	crd_scrub_mem, bsr=1, dest=1
12771:	ret	r31, (r13)		// and back we go
1278
1279
1280//
1281// sys_int_mchk - MCHK Interrupt code
1282//
1283// Machine check interrupt from the system.  Setup and join the
1284// regular machine check flow.
1285// On exit:
1286//       pt0     - saved r0
1287//       pt1     - saved r1
1288//       pt4     - saved r4
1289//       pt5     - saved r5
1290//       pt6     - saved r6
1291//       pt10    - saved exc_addr
1292//       pt_misc<47:32> - mchk code
1293//       pt_misc<31:16> - scb vector
1294//       r14     - base of Cbox IPRs in IO space
1295//       MCES<mchk> is set
1296//
1297        ALIGN_BLOCK
1298sys_int_mchk:
1299        lda	r14, mchk_c_sys_hrd_error(r31)
1300        mfpr	r12, exc_addr
1301
1302        addq	r14, 1, r14			// Flag as interrupt
1303        nop
1304
1305        sll	r14, 32, r14			// Move mchk code to position
1306        mtpr	r12, pt10			// Stash exc_addr
1307
1308        mfpr	r12, pt_misc			// Get MCES and scratch
1309        mtpr	r0, pt0				// Stash for scratch
1310
1311        zap	r12, 0x3c, r12			// Clear scratch
1312        blbs    r12, sys_double_machine_check   // MCHK halt if double machine check
1313
1314        or	r12, r14, r12			// Combine mchk code
1315        lda	r14, scb_v_sysmchk(r31)		// Get SCB vector
1316
1317        sll	r14, 16, r14			// Move SCBv to position
1318        or	r12, r14, r14			// Combine SCBv
1319
1320        bis	r14, BIT(mces_v_mchk), r14	// Set MCES<MCHK> bit
1321        mtpr	r14, pt_misc			// Save mchk code!scbv!whami!mces
1322
1323        ldah	r14, 0xfff0(r31)
1324        mtpr	r1, pt1				// Stash for scratch
1325
1326        zap	r14, 0xE0, r14			// Get Cbox IPR base
1327        mtpr	r4, pt4
1328
1329        mtpr	r5, pt5
1330
1331        mtpr	r6, pt6
1332        br	r31, sys_mchk_collect_iprs	// Join common machine check flow
1333
1334
1335//
1336// sys_int_perf_cnt - Performance counter interrupt code
1337//
1338//	A performance counter interrupt has been detected.  The stack
1339//	has been pushed. IPL and PS are updated as well.
1340//
1341//	on exit to interrupt entry point ENTINT::
1342//		a0 = osfint$c_perf
1343//		a1 = scb$v_perfmon (650)
1344//		a2 = 0 if performance counter 0 fired
1345//		a2 = 1 if performance counter 1 fired
1346//		a2 = 2 if performance counter 2 fired
1347//		     (if more than one counter overflowed, an interrupt will be
1348//			generated for each counter that overflows)
1349//
1350//
1351//
1352        ALIGN_BLOCK
1353sys_int_perf_cnt:			// Performance counter interrupt
1354        lda	r17, scb_v_perfmon(r31)	// a1 to interrupt vector
1355        mfpr	r25, pt_entint
1356
1357        lda	r16, osfint_c_perf(r31)	// a0 to perf counter code
1358        mtpr	r25, exc_addr
1359
1360        //isolate which perf ctr fired, load code in a2, and ack
1361        mfpr	r25, isr
1362        or	r31, r31, r18			// assume interrupt was pc0
1363
1364        srl	r25, isr_v_pc1, r25		// isolate
1365        cmovlbs	r25, 1, r18			// if pc1 set, load 1 into r14
1366
1367        srl	r25, 1, r25			// get pc2
1368        cmovlbs r25, 2, r18			// if pc2 set, load 2 into r14
1369
1370        lda	r25, 1(r31)			// get a one
1371        sll	r25, r18, r25
1372
1373        sll	r25, hwint_clr_v_pc0c, r25	// ack only the perf counter that generated the interrupt
1374        mtpr	r25, hwint_clr
1375
1376        hw_rei_spe
1377
1378
1379
1380//
1381//  sys_reset - System specific RESET code
1382//	On entry:
1383//       r1 = pal_base +8
1384//
1385//	Entry state on trap:
1386//       r0 = whami
1387//       r2 = base of scratch area
1388//       r3 = halt code
1389//	and the following 3 if init_cbox is enabled:
1390//       r5 = sc_ctl
1391//       r6 = bc_ctl
1392//       r7 = bc_cnfg
1393//
1394//	Entry state on switch:
1395//       r17 - new PC
1396//       r18 - new PCBB
1397//       r19 - new VPTB
1398//
1399
1400        ALIGN_BLOCK
1401        .globl sys_reset
1402sys_reset:
1403//	mtpr	r31, ic_flush_ctl	// do not flush the icache - done by hardware before SROM load
1404        mtpr	r31, itb_ia		// clear the ITB
1405        mtpr	r31, dtb_ia		// clear the DTB
1406
1407        lda	r1, -8(r1)		// point to start of code
1408        mtpr	r1, pal_base		// initialize PAL_BASE
1409
1410        // Interrupts
1411        mtpr	r31, astrr		// stop ASTs
1412        mtpr	r31, aster		// stop ASTs
1413        mtpr	r31, sirr		// clear software interrupts
1414
1415        mtpr	r0, pt1			// r0 is whami (unless we entered via swp)
1416
1417        ldah     r1,(BIT(icsr_v_sde-16)|BIT(icsr_v_fpe-16)|BIT(icsr_v_spe-16+1))(zero)
1418
1419        bis	r31, 1, r0
1420        sll	r0, icsr_v_crde, r0	// A 1 in iscr<corr_read_enable>
1421        or	r0, r1, r1		// Set the bit
1422
1423        mtpr	r1, icsr		// ICSR - Shadows enabled, Floating point enable,
1424                                        //	super page enabled, correct read per assembly option
1425
1426        // Mbox/Dcache init
1427        lda     r1,BIT(mcsr_v_sp1)(zero)
1428
1429        mtpr	r1, mcsr		// MCSR - Super page enabled
1430        lda	r1, BIT(dc_mode_v_dc_ena)(r31)
1431        ALIGN_BRANCH
1432//	mtpr	r1, dc_mode		// turn Dcache on
1433        nop
1434
1435        mfpr	r31, pt0		// No Mbox instr in 1,2,3,4
1436        mfpr	r31, pt0
1437        mfpr	r31, pt0
1438        mfpr	r31, pt0
1439        mtpr	r31, dc_flush		// flush Dcache
1440
1441        // build PS (IPL=7,CM=K,VMM=0,SW=0)
1442        lda	r11, 0x7(r31)		// Set shadow copy of PS - kern mode, IPL=7
1443        lda	r1, 0x1F(r31)
1444        mtpr	r1, ipl			// set internal <ipl>=1F
1445        mtpr	r31, ev5__ps			// set new ps<cm>=0, Ibox copy
1446        mtpr	r31, dtb_cm		// set new ps<cm>=0, Mbox copy
1447
1448        // Create the PALtemp pt_intmask
1449        //   MAP:
1450        //	OSF IPL		EV5 internal IPL(hex)	note
1451        //	0		0
1452        //	1		1
1453        //	2		2
1454        //	3		14			device
1455        //	4		15			device
1456        //	5		16			device
1457        //	6		1E			device,performance counter, powerfail
1458        //	7		1F
1459        //
1460
1461        ldah	r1, 0x1f1E(r31)		// Create upper lw of int_mask
1462        lda	r1, 0x1615(r1)
1463
1464        sll	r1, 32, r1
1465        ldah	r1, 0x1402(r1)		// Create lower lw of int_mask
1466
1467        lda	r1, 0x0100(r1)
1468        mtpr	r1, pt_intmask		// Stash in PALtemp
1469
1470        // Unlock a bunch of chip internal IPRs
1471        mtpr	r31, exc_sum		// clear out exeception summary and exc_mask
1472        mfpr	r31, va			// unlock va, mmstat
1473        lda     r8,(BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(zero)
1474
1475        mtpr	r8, icperr_stat			// Clear Icache parity error & timeout status
1476        lda	r8,(BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31)
1477
1478        mtpr	r8, dcperr_stat			// Clear Dcache parity error status
1479
1480        rc	r0			// clear intr_flag
1481        mtpr	r31, pt_trap
1482
1483        mfpr	r0, pt_misc
1484        srl	r0, pt_misc_v_switch, r1
1485        blbs	r1, sys_reset_switch	// see if we got here from swppal
1486
1487        // Rest of the "real" reset flow
1488        // ASN
1489        mtpr	r31, dtb_asn
1490        mtpr	r31, itb_asn
1491
1492        lda	r1, 0x67(r31)
1493        sll	r1, hwint_clr_v_pc0c, r1
1494        mtpr	r1, hwint_clr		// Clear hardware interrupt requests
1495
1496        lda	r1, BIT(mces_v_dpc)(r31) // 1 in disable processor correctable error
1497        mfpr	r0, pt1			// get whami
1498        insbl	r0, 1, r0		// isolate whami in correct pt_misc position
1499        or	r0, r1, r1		// combine whami and mces
1500        mtpr	r1, pt_misc		// store whami and mces, swap bit clear
1501
1502        zapnot	r3, 1, r0		// isolate halt code
1503        mtpr	r0, pt0			// save entry type
1504
1505        // Cycle counter
1506        or	r31, 1, r9		// get a one
1507        sll	r9, 32, r9		// shift to <32>
1508        mtpr	r31, cc			// clear Cycle Counter
1509        mtpr	r9, cc_ctl		// clear and enable the Cycle Counter
1510        mtpr	r31, pt_scc		// clear System Cycle Counter
1511
1512
1513        // Misc PALtemps
1514        mtpr	r31, maf_mode		// no mbox instructions for 3 cycles
1515        or	r31, 1, r1		// get bogus scbb value
1516        mtpr	r1, pt_scbb		// load scbb
1517        mtpr	r31, pt_prbr		// clear out prbr
1518#if defined(TSUNAMI) || defined(BIG_TSUNAMI)
1519        // yes, this is ugly, but you figure out a better
1520        // way to get the address of the kludge_initial_pcbb
1521        // in r1 with an uncooperative assembler --ali
1522        br     r1, kludge_getpcb_addr
1523        br     r31, kludge_initial_pcbb
1524kludge_getpcb_addr:
1525        ldq_p   r19, 0(r1)
1526        sll    r19, 44, r19
1527        srl    r19, 44, r19
1528        mulq   r19,4,r19
1529        addq   r19, r1, r1
1530        addq   r1,4,r1
1531#elif defined(TLASER)
1532        // or      zero,kludge_initial_pcbb,r1
1533        GET_ADDR(r1, (kludge_initial_pcbb-pal_base), r1)
1534#endif
1535        mtpr	r1, pt_pcbb		// load pcbb
1536        lda	r1, 2(r31)		// get a two
1537        sll	r1, 32, r1		// gen up upper bits
1538        mtpr	r1, mvptbr
1539        mtpr	r1, ivptbr
1540        mtpr	r31, pt_ptbr
1541        // Performance counters
1542        mtpr	r31, pmctr
1543
1544        // Clear pmctr_ctl in impure area
1545
1546
1547        ldah	r14, 0xfff0(r31)
1548        zap	r14, 0xE0, r14		// Get Cbox IPR base
1549        GET_IMPURE(r13)
1550        stq_p	r31, 0(r13)		// Clear lock_flag
1551
1552        mfpr	r0, pt0			// get entry type
1553        br	r31, sys_enter_console	// enter the cosole
1554
1555
1556        // swppal entry
1557        // r0 - pt_misc
1558        // r17 - new PC
1559        // r18 - new PCBB
1560        // r19 - new VPTB
1561sys_reset_switch:
1562        or	r31, 1, r9
1563        sll	r9, pt_misc_v_switch, r9
1564        bic	r0, r9, r0		// clear switch bit
1565        mtpr	r0, pt_misc
1566
1567        rpcc	r1			// get cyccounter
1568
1569        ldq_p	r22, osfpcb_q_fen(r18)	// get new fen/pme
1570        ldl_p	r23, osfpcb_l_cc(r18)	// get cycle counter
1571        ldl_p	r24, osfpcb_l_asn(r18)	// get new asn
1572
1573
1574        ldq_p	r25, osfpcb_q_Mmptr(r18)// get new mmptr
1575        sll	r25, page_offset_size_bits, r25 // convert pfn to pa
1576        mtpr	r25, pt_ptbr		// load the new mmptr
1577        mtpr	r18, pt_pcbb		// set new pcbb
1578
1579        bic	r17, 3, r17		// clean use pc
1580        mtpr	r17, exc_addr		// set new pc
1581        mtpr	r19, mvptbr
1582        mtpr	r19, ivptbr
1583
1584        ldq_p	r30, osfpcb_q_Usp(r18)	// get new usp
1585        mtpr	r30, pt_usp		// save usp
1586
1587        sll	r24, dtb_asn_v_asn, r8
1588        mtpr	r8, dtb_asn
1589        sll	r24, itb_asn_v_asn, r24
1590        mtpr	r24, itb_asn
1591
1592        mfpr	r25, icsr		// get current icsr
1593        lda	r24, 1(r31)
1594        sll	r24, icsr_v_fpe, r24	// 1 in icsr<fpe> position
1595        bic	r25, r24, r25		// clean out old fpe
1596        and	r22, 1, r22		// isolate new fen bit
1597        sll	r22, icsr_v_fpe, r22
1598        or	r22, r25, r25		// or in new fpe
1599        mtpr	r25, icsr		// update ibox ipr
1600
1601        subl	r23, r1, r1		// gen new cc offset
1602        insll	r1, 4, r1		// << 32
1603        mtpr	r1, cc			// set new offset
1604
1605        or	r31, r31, r0		// set success
1606        ldq_p	r30, osfpcb_q_Ksp(r18)	// get new ksp
1607        mfpr	r31, pt0		// stall
1608        hw_rei_stall
1609
1610//
1611//sys_machine_check - Machine check PAL
1612// 	A machine_check trap has occurred.  The Icache has been flushed.
1613//
1614//
1615
1616        ALIGN_BLOCK
1617EXPORT(sys_machine_check)
1618        // Need to fill up the refill buffer (32 instructions) and
1619        // then flush the Icache again.
1620        // Also, due to possible 2nd Cbox register file write for
1621        // uncorrectable errors, no register file read or write for 7 cycles.
1622
1623        nop
1624        mtpr	r0, pt0		// Stash for scratch -- OK if Cbox overwrites
1625                                //    r0 later
1626        nop
1627        nop
1628
1629        nop
1630        nop
1631
1632        nop
1633        nop
1634
1635        nop
1636        nop
1637                                // 10 instructions// 5 cycles
1638
1639        nop
1640        nop
1641
1642        nop
1643        nop
1644
1645                                                // Register file can now be written
1646        lda	r0, scb_v_procmchk(r31)		// SCB vector
1647        mfpr	r13, pt_mces			// Get MCES
1648        sll	r0, 16, r0			// Move SCBv to correct position
1649        bis	r13, BIT(mces_v_mchk), r14	// Set MCES<MCHK> bit
1650
1651
1652        zap	r14, 0x3C, r14			// Clear mchk_code word and SCBv word
1653        mtpr	r14, pt_mces
1654                                                // 20 instructions
1655
1656        nop
1657        or	r14, r0, r14			// Insert new SCB vector
1658        lda	r0, mchk_c_proc_hrd_error(r31)	// MCHK code
1659        mfpr	r12, exc_addr
1660
1661        sll	r0, 32, r0			// Move MCHK code to correct position
1662        mtpr	r4, pt4
1663        or	r14, r0, r14			// Insert new MCHK code
1664        mtpr	r14, pt_misc			// Store updated MCES, MCHK code, and SCBv
1665
1666        ldah	r14, 0xfff0(r31)
1667        mtpr	r1, pt1				// Stash for scratch - 30 instructions
1668
1669        zap	r14, 0xE0, r14			// Get Cbox IPR base
1670        mtpr	r12, pt10			// Stash exc_addr
1671
1672
1673
1674        mtpr	r31, ic_flush_ctl			// Second Icache flush, now it is really flushed.
1675        blbs	r13, sys_double_machine_check		// MCHK halt if double machine check
1676
1677        mtpr	r6, pt6
1678        mtpr	r5, pt5
1679
1680        // Look for the powerfail cases here....
1681        mfpr	r4, isr
1682        srl	r4, isr_v_pfl, r4
1683        blbc	r4, sys_mchk_collect_iprs	// skip if no powerfail interrupt pending
1684        lda	r4, 0xffc4(r31)			// get GBUS$MISCR address bits
1685        sll	r4, 24, r4			// shift to proper position
1686        ldq_p	r4, 0(r4)			// read GBUS$MISCR
1687        srl	r4, 5, r4			// isolate bit <5>
1688        blbc	r4, sys_mchk_collect_iprs	// skip if already cleared
1689                                                // No missed CFAIL mchk
1690        lda	r5, 0xffc7(r31)			// get GBUS$SERNUM address bits
1691        sll	r5, 24, r5			// shift to proper position
1692        lda	r6, 0x40(r31)			// get bit <6> mask
1693        ldq_p	r4, 0(r5)			// read GBUS$SERNUM
1694        or	r4, r6, r6			// set bit <6>
1695        stq_p	r6, 0(r5)			// clear GBUS$SERNUM<6>
1696        mb
1697        mb
1698
1699
1700        //
1701        // Start to collect the IPRs.  Common entry point for mchk flows.
1702        //
1703        // Current state:
1704        //	pt0	- saved r0
1705        //	pt1	- saved	r1
1706        //	pt4	- saved r4
1707        //	pt5	- saved r5
1708        //	pt6	- saved r6
1709        //	pt10	- saved exc_addr
1710        //	pt_misc<47:32> - mchk code
1711        //	pt_misc<31:16> - scb vector
1712        //	r14	- base of Cbox IPRs in IO space
1713        //	r0, r1, r4, r5, r6, r12, r13, r25 - available
1714        //	r8, r9, r10 - available as all loads are physical
1715        //	MCES<mchk> is set
1716        //
1717        //
1718
1719EXPORT(sys_mchk_collect_iprs)
1720        mb						// MB before reading Scache IPRs
1721        mfpr	r1, icperr_stat
1722
1723        mfpr	r8, dcperr_stat
1724        mtpr	r31, dc_flush				// Flush the Dcache
1725
1726        mfpr	r31, pt0				// Pad Mbox instructions from dc_flush
1727        mfpr	r31, pt0
1728        nop
1729        nop
1730
1731        ldq_p	r9, sc_addr(r14)			// SC_ADDR IPR
1732        bis	r9, r31, r31				// Touch ld to make sure it completes before
1733                                                        // read of SC_STAT
1734        ldq_p	r10, sc_stat(r14)			// SC_STAT, also unlocks SC_ADDR
1735
1736        ldq_p	r12, ei_addr(r14)			// EI_ADDR IPR
1737        ldq_p	r13, bc_tag_addr(r14)			// BC_TAG_ADDR IPR
1738        ldq_p	r0, fill_syn(r14)			// FILL_SYN IPR
1739        bis	r12, r13, r31				// Touch lds to make sure they complete before reading EI_STAT
1740        bis	r0, r0, r31				// Touch lds to make sure they complete before reading EI_STAT
1741        ldq_p	r25, ei_stat(r14)			// EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
1742        ldq_p	r31, ei_stat(r14)			// Read again to insure it is unlocked
1743
1744
1745
1746
1747        //
1748        // Look for nonretryable cases
1749        // In this segment:
1750        //	r5<0> = 1 means retryable
1751        //	r4, r6, and r14 are available for scratch
1752        //
1753        //
1754
1755
1756        bis	r31, r31, r5				// Clear local retryable flag
1757        srl	r25, ei_stat_v_bc_tperr, r25		// Move EI_STAT status bits to low bits
1758
1759        lda	r4, 1(r31)
1760        sll	r4, icperr_stat_v_tmr, r4
1761        and 	r1, r4, r4				// Timeout reset
1762        bne	r4, sys_cpu_mchk_not_retryable
1763
1764        and	r8, BIT(dcperr_stat_v_lock), r4		// DCache parity error locked
1765        bne	r4, sys_cpu_mchk_not_retryable
1766
1767        lda	r4, 1(r31)
1768        sll	r4, sc_stat_v_sc_scnd_err, r4
1769        and	r10, r4, r4				// 2nd Scache error occurred
1770        bne	r4, sys_cpu_mchk_not_retryable
1771
1772
1773        bis	r31, 0xa3, r4				// EI_STAT Bcache Tag Parity Error, Bcache Tag Control
1774                                                        // Parity Error, Interface Parity Error, 2nd Error
1775
1776        and	r25, r4, r4
1777        bne	r4, sys_cpu_mchk_not_retryable
1778
1779//	bis	r31, #<1@<ei_stat$v_unc_ecc_err-ei_stat$v_bc_tperr>>, r4
1780        bis	r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4
1781        and	r25, r4, r4				// Isolate the Uncorrectable Error Bit
1782//	bis	r31, #<1@<ei_stat$v_fil_ird-ei_stat$v_bc_tperr>>, r6
1783        bis	r31, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r6 // Isolate the Iread bit
1784        cmovne	r6, 0, r4				// r4 = 0 if IRD or if No Uncorrectable Error
1785        bne     r4, sys_cpu_mchk_not_retryable
1786
1787        lda	r4, 7(r31)
1788        and 	r10, r4, r4				// Isolate the Scache Tag Parity Error bits
1789        bne	r4, sys_cpu_mchk_not_retryable		// All Scache Tag PEs are not retryable
1790
1791
1792        lda	r4, 0x7f8(r31)
1793        and	r10, r4, r4				// Isolate the Scache Data Parity Error bits
1794        srl	r10, sc_stat_v_cbox_cmd, r6
1795        and	r6, 0x1f, r6				// Isolate Scache Command field
1796        subq	r6, 1, r6				// Scache Iread command = 1
1797        cmoveq	r6, 0, r4				// r4 = 0 if IRD or if No Parity Error
1798        bne     r4, sys_cpu_mchk_not_retryable
1799
1800        // Look for the system unretryable cases here....
1801
1802        mfpr	r4, isr					// mchk_interrupt pin asserted
1803        srl	r4, isr_v_mck, r4
1804        blbs	r4, sys_cpu_mchk_not_retryable
1805
1806
1807
1808        //
1809        // Look for retryable cases
1810        // In this segment:
1811        //	r5<0> = 1 means retryable
1812        //	r6 - holds the mchk code
1813        //	r4 and r14 are available for scratch
1814        //
1815        //
1816
1817
1818        // Within the chip, the retryable cases are Istream errors
1819        lda	r4, 3(r31)
1820        sll	r4, icperr_stat_v_dpe, r4
1821        and	r1, r4, r4
1822        cmovne	r4, 1, r5				// Retryable if just Icache parity error
1823
1824
1825        lda	r4, 0x7f8(r31)
1826        and	r10, r4, r4				// Isolate the Scache Data Parity Error bits
1827        srl	r10, sc_stat_v_cbox_cmd, r14
1828        and	r14, 0x1f, r14				// Isolate Scache Command field
1829        subq	r14, 1, r14				// Scache Iread command = 1
1830        cmovne	r4, 1, r4				// r4 = 1 if Scache data parity error bit set
1831        cmovne	r14, 0, r4				// r4 = 1 if Scache PE and Iread
1832        bis	r4, r5, r5				// Accumulate
1833
1834
1835        bis	r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4
1836        and	r25, r4, r4				// Isolate the Uncorrectable Error Bit
1837        and	r25, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r14 // Isolate the Iread bit
1838        cmovne	r4, 1, r4				// r4 = 1 if uncorr error
1839        cmoveq	r14, 0, r4				// r4 = 1 if uncorr and Iread
1840        bis	r4, r5, r5				// Accumulate
1841
1842        mfpr	r6, pt_misc
1843        extwl	r6, 4, r6				// Fetch mchk code
1844        bic	r6, 1, r6				// Clear flag from interrupt flow
1845        cmovne	r5, mchk_c_retryable_ird, r6		// Set mchk code
1846
1847
1848        //
1849        // Write the logout frame
1850        //
1851        // Current state:
1852        //	r0	- fill_syn
1853        //	r1	- icperr_stat
1854        //	r4	- available
1855        // 	r5<0>  	- retry flag
1856        //	r6     	- mchk code
1857        //	r8	- dcperr_stat
1858        //	r9	- sc_addr
1859        //	r10	- sc_stat
1860        //	r12	- ei_addr
1861        //	r13	- bc_tag_addr
1862        //	r14	- available
1863        //	r25	- ei_stat (shifted)
1864        //	pt0	- saved r0
1865        //	pt1	- saved	r1
1866        //	pt4	- saved r4
1867        //	pt5	- saved r5
1868        //	pt6	- saved r6
1869        //	pt10	- saved exc_addr
1870        //
1871        //
1872
1873sys_mchk_write_logout_frame:
1874        // Get base of the logout area.
1875        GET_IMPURE(r14)				 // addr of per-cpu impure area
1876        GET_ADDR(r14,pal_logout_area+mchk_mchk_base,r14)
1877
1878        // Write the first 2 quadwords of the logout area:
1879
1880        sll	r5, 63, r5				// Move retry flag to bit 63
1881        lda	r4, mchk_size(r5)			// Combine retry flag and frame size
1882        stq_p	r4, mchk_flag(r14)			// store flag/frame size
1883        lda	r4, mchk_sys_base(r31)			// sys offset
1884        sll	r4, 32, r4
1885        lda	r4, mchk_cpu_base(r4)			// cpu offset
1886        stq_p	r4, mchk_offsets(r14)			// store sys offset/cpu offset into logout frame
1887
1888        //
1889        // Write the mchk code to the logout area
1890        // Write error IPRs already fetched to the logout area
1891        // Restore some GPRs from PALtemps
1892        //
1893
1894        mfpr	r5, pt5
1895        stq_p	r6, mchk_mchk_code(r14)
1896        mfpr	r4, pt4
1897        stq_p	r1, mchk_ic_perr_stat(r14)
1898        mfpr	r6, pt6
1899        stq_p	r8, mchk_dc_perr_stat(r14)
1900        mfpr	r1, pt1
1901        stq_p	r9, mchk_sc_addr(r14)
1902        stq_p	r10, mchk_sc_stat(r14)
1903        stq_p	r12, mchk_ei_addr(r14)
1904        stq_p	r13, mchk_bc_tag_addr(r14)
1905        stq_p	r0,  mchk_fill_syn(r14)
1906        mfpr	r0, pt0
1907        sll	r25, ei_stat_v_bc_tperr, r25		// Move EI_STAT status bits back to expected position
1908        // retrieve lower 28 bits again from ei_stat and restore before storing to logout frame
1909        ldah    r13, 0xfff0(r31)
1910        zapnot  r13, 0x1f, r13
1911        ldq_p    r13, ei_stat(r13)
1912        sll     r13, 64-ei_stat_v_bc_tperr, r13
1913        srl     r13, 64-ei_stat_v_bc_tperr, r13
1914        or      r25, r13, r25
1915        stq_p	r25, mchk_ei_stat(r14)
1916
1917
1918
1919
1920        //
1921        // complete the CPU-specific part of the logout frame
1922        //
1923
1924        ldah	r13, 0xfff0(r31)
1925        zap	r13, 0xE0, r13			// Get Cbox IPR base
1926        ldq_p	r13, ld_lock(r13)		// Get ld_lock IPR
1927        stq_p	r13, mchk_ld_lock(r14)		// and stash it in the frame
1928
1929        // Unlock IPRs
1930        lda	r8, (BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31)
1931        mtpr	r8, dcperr_stat			// Clear Dcache parity error status
1932
1933        lda	r8, (BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(r31)
1934        mtpr	r8, icperr_stat			// Clear Icache parity error & timeout status
1935
19361:	ldq_p	r8, mchk_ic_perr_stat(r14)	// get ICPERR_STAT value
1937        GET_ADDR(r0,0x1800,r31)		// get ICPERR_STAT value
1938        and	r0, r8, r0			// compare
1939        beq	r0, 2f				// check next case if nothing set
1940        lda	r0, mchk_c_retryable_ird(r31)	// set new MCHK code
1941        br	r31, do_670			// setup new vector
1942
19432:	ldq_p	r8, mchk_dc_perr_stat(r14)	// get DCPERR_STAT value
1944        GET_ADDR(r0,0x3f,r31)			// get DCPERR_STAT value
1945        and	r0, r8, r0			// compare
1946        beq	r0, 3f				// check next case if nothing set
1947        lda	r0, mchk_c_dcperr(r31)		// set new MCHK code
1948        br	r31, do_670			// setup new vector
1949
19503:	ldq_p	r8, mchk_sc_stat(r14)		// get SC_STAT value
1951        GET_ADDR(r0,0x107ff,r31)		// get SC_STAT value
1952        and	r0, r8, r0			// compare
1953        beq	r0, 4f				// check next case if nothing set
1954        lda	r0, mchk_c_scperr(r31)		// set new MCHK code
1955        br	r31, do_670			// setup new vector
1956
19574:	ldq_p	r8, mchk_ei_stat(r14)		// get EI_STAT value
1958        GET_ADDR(r0,0x30000000,r31)		// get EI_STAT value
1959        and	r0, r8, r0			// compare
1960        beq	r0, 5f				// check next case if nothing set
1961        lda	r0, mchk_c_bcperr(r31)		// set new MCHK code
1962        br	r31, do_670			// setup new vector
1963
19645:	ldl_p	r8, mchk_tlber(r14)		// get TLBER value
1965        GET_ADDR(r0,0xfe01,r31)	        	// get high TLBER mask value
1966        sll	r0, 16, r0			// shift into proper position
1967        GET_ADDR(r1,0x03ff,r31)		        // get low TLBER mask value
1968        or	r0, r1, r0			// merge mask values
1969        and	r0, r8, r0			// compare
1970        beq	r0, 6f				// check next case if nothing set
1971        GET_ADDR(r0, 0xfff0, r31)		// set new MCHK code
1972        br	r31, do_660			// setup new vector
1973
19746:	ldl_p	r8, mchk_tlepaerr(r14)		// get TLEPAERR value
1975        GET_ADDR(r0,0xff7f,r31) 		// get TLEPAERR mask value
1976        and	r0, r8, r0			// compare
1977        beq	r0, 7f				// check next case if nothing set
1978        GET_ADDR(r0, 0xfffa, r31)		// set new MCHK code
1979        br	r31, do_660			// setup new vector
1980
19817:	ldl_p	r8, mchk_tlepderr(r14)		// get TLEPDERR value
1982        GET_ADDR(r0,0x7,r31)			// get TLEPDERR mask value
1983        and	r0, r8, r0			// compare
1984        beq	r0, 8f				// check next case if nothing set
1985        GET_ADDR(r0, 0xfffb, r31)		// set new MCHK code
1986        br	r31, do_660			// setup new vector
1987
19888:	ldl_p	r8, mchk_tlepmerr(r14)		// get TLEPMERR value
1989        GET_ADDR(r0,0x3f,r31)			// get TLEPMERR mask value
1990        and	r0, r8, r0			// compare
1991        beq	r0, 9f				// check next case if nothing set
1992        GET_ADDR(r0, 0xfffc, r31)		// set new MCHK code
1993        br	r31, do_660			// setup new vector
1994
19959:	ldq_p	r8, mchk_ei_stat(r14)		// get EI_STAT value
1996        GET_ADDR(r0,0xb,r31)			// get EI_STAT mask value
1997        sll	r0, 32, r0			// shift to upper lw
1998        and	r0, r8, r0			// compare
1999        beq	r0, 1f				// check next case if nothing set
2000        GET_ADDR(r0,0xfffd,r31) 		// set new MCHK code
2001        br	r31, do_660			// setup new vector
2002
20031:	ldl_p	r8, mchk_tlepaerr(r14)		// get TLEPAERR value
2004        GET_ADDR(r0,0x80,r31)			// get TLEPAERR mask value
2005        and	r0, r8, r0			// compare
2006        beq	r0, cont_logout_frame		// check next case if nothing set
2007        GET_ADDR(r0, 0xfffe, r31)		// set new MCHK code
2008        br	r31, do_660			// setup new vector
2009
2010do_670:	lda	r8, scb_v_procmchk(r31)		// SCB vector
2011        br	r31, do_6x0_cont
2012do_660:	lda	r8, scb_v_sysmchk(r31)		// SCB vector
2013do_6x0_cont:
2014        sll	r8, 16, r8			// shift to proper position
2015        mfpr	r1, pt_misc			// fetch current pt_misc
2016        GET_ADDR(r4,0xffff, r31)		// mask for vector field
2017        sll	r4, 16, r4			// shift to proper position
2018        bic	r1, r4, r1			// clear out old vector field
2019        or	r1, r8, r1			// merge in new vector
2020        mtpr	r1, pt_misc			// save new vector field
2021        stl_p	r0, mchk_mchk_code(r14)		// save new mchk code
2022
2023cont_logout_frame:
2024        // Restore some GPRs from PALtemps
2025        mfpr	r0, pt0
2026        mfpr	r1, pt1
2027        mfpr	r4, pt4
2028
2029        mfpr	r12, pt10			// fetch original PC
2030        blbs	r12, sys_machine_check_while_in_pal	// MCHK halt if machine check in pal
2031
2032//XXXbugnion        pvc_jsr armc, bsr=1
2033        bsr     r12, sys_arith_and_mchk     	// go check for and deal with arith trap
2034
2035        mtpr	r31, exc_sum			// Clear Exception Summary
2036
2037        mfpr	r25, pt10			// write exc_addr after arith_and_mchk to pickup new pc
2038        stq_p	r25, mchk_exc_addr(r14)
2039
2040        //
2041        // Set up the km trap
2042        //
2043
2044
2045sys_post_mchk_trap:
2046        mfpr	r25, pt_misc		// Check for flag from mchk interrupt
2047        extwl	r25, 4, r25
2048        blbs	r25, sys_mchk_stack_done // Stack from already pushed if from interrupt flow
2049
2050        bis	r14, r31, r12		// stash pointer to logout area
2051        mfpr	r14, pt10		// get exc_addr
2052
2053        sll	r11, 63-3, r25		// get mode to msb
2054        bge	r25, 3f
2055
2056        mtpr	r31, dtb_cm
2057        mtpr	r31, ev5__ps
2058
2059        mtpr	r30, pt_usp		// save user stack
2060        mfpr	r30, pt_ksp
2061
20623:
2063        lda	sp, 0-osfsf_c_size(sp)	// allocate stack space
2064        nop
2065
2066        stq	r18, osfsf_a2(sp) 	// a2
2067        stq	r11, osfsf_ps(sp)	// save ps
2068
2069        stq	r14, osfsf_pc(sp)	// save pc
2070        mfpr	r25, pt_entint		// get the VA of the interrupt routine
2071
2072        stq	r16, osfsf_a0(sp)	// a0
2073        lda	r16, osfint_c_mchk(r31)	// flag as mchk in a0
2074
2075        stq	r17, osfsf_a1(sp)	// a1
2076        mfpr	r17, pt_misc		// get vector
2077
2078        stq	r29, osfsf_gp(sp) 	// old gp
2079        mtpr	r25, exc_addr		//
2080
2081        or	r31, 7, r11		// get new ps (km, high ipl)
2082        subq	r31, 1, r18		// get a -1
2083
2084        extwl	r17, 2, r17		// a1 <- interrupt vector
2085        bis	r31, ipl_machine_check, r25
2086
2087        mtpr	r25, ipl		// Set internal ipl
2088        srl    	r18, 42, r18          	// shift off low bits of kseg addr
2089
2090        sll    	r18, 42, r18          	// shift back into position
2091        mfpr	r29, pt_kgp		// get the kern r29
2092
2093        or    	r12, r18, r18          	// EV4 algorithm - pass pointer to mchk frame as kseg address
2094        hw_rei_spe			// out to interrupt dispatch routine
2095
2096
2097        //
2098        // The stack is pushed.  Load up a0,a1,a2 and vector via entInt
2099        //
2100        //
2101        ALIGN_BRANCH
2102sys_mchk_stack_done:
2103        lda	r16, osfint_c_mchk(r31)	// flag as mchk/crd in a0
2104        lda	r17, scb_v_sysmchk(r31) // a1 <- interrupt vector
2105
2106        subq    r31, 1, r18            // get a -1
2107        mfpr	r25, pt_entInt
2108
2109        srl     r18, 42, r18           // shift off low bits of kseg addr
2110        mtpr	r25, exc_addr		// load interrupt vector
2111
2112        sll     r18, 42, r18           // shift back into position
2113        or    	r14, r18, r18           // EV4 algorithm - pass pointer to mchk frame as kseg address
2114
2115        hw_rei_spe			// done
2116
2117
2118        ALIGN_BRANCH
2119sys_cpu_mchk_not_retryable:
2120        mfpr	r6, pt_misc
2121        extwl	r6, 4, r6				// Fetch mchk code
2122        br	r31,  sys_mchk_write_logout_frame	//
2123
2124
2125
2126//
2127//sys_double_machine_check - a machine check was started, but MCES<MCHK> was
2128//	already set.  We will now double machine check halt.
2129//
2130//	pt0 - old R0
2131//
2132//
2133
2134EXPORT(sys_double_machine_check)
2135        lda	r0, hlt_c_dbl_mchk(r31)
2136        br	r31, sys_enter_console
2137
2138//
2139// sys_machine_check_while_in_pal - a machine check was started,
2140//	exc_addr points to a PAL PC.  We will now machine check halt.
2141//
2142//	pt0 - old R0
2143//
2144//
2145sys_machine_check_while_in_pal:
2146        stq_p	r12, mchk_exc_addr(r14)		// exc_addr has not yet been written
2147        lda	r0, hlt_c_mchk_from_pal(r31)
2148        br	r31, sys_enter_console
2149
2150
2151//ARITH and MCHK
2152//  Check for arithmetic errors and build trap frame,
2153//  but don't post the trap.
2154//  on entry:
2155//	pt10 - exc_addr
2156//	r12  - return address
2157//	r14  - logout frame pointer
2158//	r13 - available
2159//	r8,r9,r10 - available except across stq's
2160//	pt0,1,6 - available
2161//
2162//  on exit:
2163//	pt10 - new exc_addr
2164//	r17 = exc_mask
2165//	r16 = exc_sum
2166//	r14 - logout frame pointer
2167//
2168        ALIGN_BRANCH
2169sys_arith_and_mchk:
2170        mfpr	r13, ev5__exc_sum
2171        srl	r13, exc_sum_v_swc, r13
2172        bne	r13, handle_arith_and_mchk
2173
2174// XXX bugnion        pvc$jsr armc, bsr=1, dest=1
2175        ret     r31, (r12)              // return if no outstanding arithmetic error
2176
2177handle_arith_and_mchk:
2178        mtpr    r31, ev5__dtb_cm        // Set Mbox current mode to kernel
2179                                        //     no virt ref for next 2 cycles
2180        mtpr	r14, pt0
2181
2182        mtpr	r1, pt1			// get a scratch reg
2183        and     r11, osfps_m_mode, r1 // get mode bit
2184
2185        bis     r11, r31, r25           // save ps
2186        beq     r1, 1f                 // if zero we are in kern now
2187
2188        bis     r31, r31, r25           // set the new ps
2189        mtpr    r30, pt_usp             // save user stack
2190
2191        mfpr    r30, pt_ksp             // get kern stack
21921:
2193        mfpr    r14, exc_addr           // get pc into r14 in case stack writes fault
2194
2195        lda     sp, 0-osfsf_c_size(sp)  // allocate stack space
2196        mtpr    r31, ev5__ps            // Set Ibox current mode to kernel
2197
2198        mfpr    r1, pt_entArith
2199        stq     r14, osfsf_pc(sp)       // save pc
2200
2201        stq     r17, osfsf_a1(sp)
2202        mfpr    r17, ev5__exc_mask      // Get exception register mask IPR - no mtpr exc_sum in next cycle
2203
2204        stq     r29, osfsf_gp(sp)
2205        stq     r16, osfsf_a0(sp)       // save regs
2206
2207        bis	r13, r31, r16		// move exc_sum to r16
2208        stq     r18, osfsf_a2(sp)
2209
2210        stq     r11, osfsf_ps(sp)       // save ps
2211        mfpr    r29, pt_kgp             // get the kern gp
2212
2213        mfpr	r14, pt0		// restore logout frame pointer from pt0
2214        bis     r25, r31, r11           // set new ps
2215
2216        mtpr    r1, pt10		// Set new PC
2217        mfpr	r1, pt1
2218
2219// XXX bugnion        pvc$jsr armc, bsr=1, dest=1
2220        ret     r31, (r12)              // return if no outstanding arithmetic error
2221
2222
2223
2224// sys_enter_console - Common PALcode for ENTERING console
2225//
2226// Entry:
2227//	Entered when PAL wants to enter the console.
2228//	usually as the result of a HALT instruction or button,
2229//	or catastrophic error.
2230//
2231// Regs on entry...
2232//
2233//	R0 	= halt code
2234//	pt0	<- r0
2235//
2236// Function:
2237//
2238//	Save all readable machine state, and "call" the console
2239//
2240// Returns:
2241//
2242//
2243// Notes:
2244//
2245//	In these routines, once the save state routine has been executed,
2246//	the remainder of the registers become scratchable, as the only
2247//	"valid" copy of them is the "saved" copy.
2248//
2249//	Any registers or PTs that are modified before calling the save
2250//	routine will have there data lost. The code below will save all
2251//	state, but will loose pt 0,4,5.
2252//
2253//
2254
2255        ALIGN_BLOCK
2256EXPORT(sys_enter_console)
2257        mtpr	r1, pt4
2258        mtpr	r3, pt5
2259        subq	r31, 1, r1
2260        sll	r1, 42, r1
2261        ldah	r1, 1(r1)
2262
2263        /* taken from scrmax, seems like the obvious thing to do */
2264        mtpr	r1, exc_addr
2265        mfpr	r1, pt4
2266        mfpr	r3, pt5
2267        STALL
2268        STALL
2269        hw_rei_stall
2270
2271
2272//
2273// sys_exit_console - Common PALcode for ENTERING console
2274//
2275// Entry:
2276//	Entered when console wants to reenter PAL.
2277//	usually as the result of a CONTINUE.
2278//
2279//
2280// Regs' on entry...
2281//
2282//
2283// Function:
2284//
2285//	Restore all readable machine state, and return to user code.
2286//
2287//
2288//
2289//
2290        ALIGN_BLOCK
2291sys_exit_console:
2292
2293        GET_IMPURE(r1)
2294
2295        // clear lock and intr_flags prior to leaving console
2296        rc	r31			// clear intr_flag
2297        // lock flag cleared by restore_state
2298        // TB's have been flushed
2299
2300        ldq_p	r3, (cns_gpr+(8*3))(r1)		// restore r3
2301        ldq_p	r1, (cns_gpr+8)(r1)		// restore r1
2302        hw_rei_stall				// back to user
2303
2304
2305// kludge_initial_pcbb - PCB for Boot use only
2306
2307        ALIGN_128
2308.globl kludge_initial_pcbb
2309kludge_initial_pcbb:			// PCB is 128 bytes long
2310        nop
2311        nop
2312        nop
2313        nop
2314
2315        nop
2316        nop
2317        nop
2318        nop
2319
2320        nop
2321        nop
2322        nop
2323        nop
2324
2325        nop
2326        nop
2327        nop
2328        nop
2329
2330
2331// SET_SC_BC_CTL subroutine
2332//
2333// Subroutine to set the SC_CTL, BC_CONFIG, and BC_CTL registers and
2334// flush the Scache
2335// There must be no outstanding memory references -- istream or
2336// dstream -- when these registers are written.  EV5 prefetcher is
2337// difficult to turn off.  So, this routine needs to be exactly 32
2338// instructions long// the final jmp must be in the last octaword of a
2339// page (prefetcher doesn't go across page)
2340//
2341//
2342// Register expecations:
2343//	r0	base address of CBOX iprs
2344//      r5      value to set sc_ctl to (flush bit is added in)
2345//      r6      value to set bc_ctl to
2346//	r7	value to set bc_config to
2347//	r10	return address
2348// 	r19     old sc_ctl value
2349// 	r20	old value of bc_ctl
2350//	r21	old value of bc_config
2351//	r23	flush scache flag
2352// Register usage:
2353//      r17     sc_ctl with flush bit cleared
2354//	r22	loop address
2355//
2356//
2357set_sc_bc_ctl:
2358        ret	r31, (r10)		// return to where we came from
2359