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