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