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