summaryrefslogtreecommitdiff
path: root/system/alpha/palcode/platform_tlaser.S
diff options
context:
space:
mode:
Diffstat (limited to 'system/alpha/palcode/platform_tlaser.S')
-rw-r--r--system/alpha/palcode/platform_tlaser.S2821
1 files changed, 2821 insertions, 0 deletions
diff --git a/system/alpha/palcode/platform_tlaser.S b/system/alpha/palcode/platform_tlaser.S
new file mode 100644
index 000000000..a807d065c
--- /dev/null
+++ b/system/alpha/palcode/platform_tlaser.S
@@ -0,0 +1,2821 @@
+// build_fixed_image: not sure what means
+// real_mm to be replaced during rewrite
+// remove_save_state remove_restore_state can be remooved to save space ??
+
+
+#define egore 0
+#define acore 0
+#define beh_model 0
+#define ev5_p2 1
+#define ev5_p1 0
+#define ldvpte_bug_fix 1
+#define spe_fix 0
+#define osf_chm_fix 0
+#define build_fixed_image 0
+#define enable_p4_fixups 0
+#define osf_svmin 1
+#define enable_physical_console 0
+#define fill_err_hack 0
+#define icflush_on_tbix 0
+#define max_cpuid 1
+#define perfmon_debug 0
+#define rax_mode 0
+
+#define hw_rei_spe hw_rei
+
+#include "ev5_defs.h"
+#include "ev5_impure.h"
+#include "ev5_alpha_defs.h"
+#include "ev5_paldef.h"
+#include "ev5_osfalpha_defs.h"
+#include "fromHudsonMacros.h"
+#include "fromHudsonOsf.h"
+#include "dc21164FromGasSources.h"
+#include "cserve.h"
+#include "tlaserreg.h"
+//#include "simos.h"
+
+
+#define ldlp ldl_p
+#define ldqp ldq_p
+
+#define stlp stl_p
+#define stqp stq_p
+#define stqpc stqp
+
+#ifdef SIMOS
+#define ldqpl ldq_p
+#define sdqpl sdq_p
+#else
+<--bomb>
+#endif
+
+#define pt_entInt pt_entint
+#define pt_entArith pt_entarith
+#define mchk_size ((mchk_cpu_base + 7 + 8) &0xfff8)
+#define mchk_flag CNS_Q_FLAG
+#define mchk_sys_base 56
+#define mchk_cpu_base (CNS_Q_LD_LOCK + 8)
+#define mchk_offsets CNS_Q_EXC_ADDR
+#define mchk_mchk_code 8
+#define mchk_ic_perr_stat CNS_Q_ICPERR_STAT
+#define mchk_dc_perr_stat CNS_Q_DCPERR_STAT
+#define mchk_sc_addr CNS_Q_SC_ADDR
+#define mchk_sc_stat CNS_Q_SC_STAT
+#define mchk_ei_addr CNS_Q_EI_ADDR
+#define mchk_bc_tag_addr CNS_Q_BC_TAG_ADDR
+#define mchk_fill_syn CNS_Q_FILL_SYN
+#define mchk_ei_stat CNS_Q_EI_STAT
+#define mchk_exc_addr CNS_Q_EXC_ADDR
+#define mchk_ld_lock CNS_Q_LD_LOCK
+#define osfpcb_q_Ksp pcb_q_ksp
+#define pal_impure_common_size ((0x200 + 7) & 0xfff8)
+
+#define ALIGN_BLOCK \
+ .align 5
+
+#define ALIGN_BRANCH \
+ .align 3
+
+#define EXPORT(_x) \
+ .align 5; \
+ .globl _x; \
+_x:
+
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+// XXX the following is 'made up'
+// XXX bugnion
+
+// XXX bugnion not sure how to align 'quad'
+#define ALIGN_QUAD \
+ .align 3
+
+#define ALIGN_128 \
+ .align 7
+
+
+#define GET_IMPURE(_r) mfpr _r,pt_impure
+#define GET_ADDR(_r1,_off,_r2) lda _r1,_off(_r2)
+
+
+#define BIT(_x) (1<<(_x))
+
+
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+// XXX back to original code
+
+// .sbttl "System specific code - beh model version"
+
+//
+// Entry points
+// SYS$CFLUSH - Cache flush
+// SYS$CSERVE - Console service
+// SYS$WRIPIR - interprocessor interrupts
+// SYS$HALT_INTERRUPT - Halt interrupt
+// SYS$PASSIVE_RELEASE - Interrupt, passive release
+// SYS$INTERRUPT - Interrupt
+// SYS$RESET - Reset
+// SYS$ENTER_CONSOLE
+
+//
+// Macro to read TLINTRSUMx
+//
+// Based on the CPU_NUMBER, read either the TLINTRSUM0 or TLINTRSUM1 register
+//
+// Assumed register usage:
+// rsum TLINTRSUMx contents
+// raddr node space address
+// scratch scratch register
+
+
+// .macro Read_TLINTRSUMx rsum, raddr, scratch, ?label1, ?label2
+//
+// nop
+// mfpr 'scratch', pt_whami // Get our whami (VID)
+//
+// extbl 'scratch', #1, 'scratch' // shift down to bit 0
+// lda 'raddr', ^xff88(r31) // Get base node space address bits
+//
+// sll 'raddr', #24, 'raddr' // Shift up to proper position
+// srl 'scratch', #1, 'rsum' // Shift off the cpu number
+//
+// sll 'rsum', #22, 'rsum' // Get our node offset
+// addq 'raddr', 'rsum', 'raddr' // Get our base node space address
+//
+// blbs 'scratch', label1
+// lda 'raddr', <tlep$tlintrsum0_offset>('raddr')
+//
+// br r31, label2
+//label1: lda 'raddr', <tlep$tlintrsum1_offset>('raddr')
+//
+//label2: ldlp 'rsum', 0('raddr') // read the right tlintrsum reg
+//.endm
+
+#define Read_TLINTRSUMx(_rsum,_raddr,_scratch) \
+ nop; \
+ mfpr _scratch,pt_whami; \
+ extbl _scratch,1,_scratch; \
+ lda _raddr,0xff88(zero); \
+ sll _raddr,24,_raddr; \
+ srl _scratch,1,_rsum; \
+ sll _rsum,22,_rsum; \
+ addq _raddr,_rsum,_raddr; \
+ blbs _scratch,1f; \
+ lda _raddr,0x1180(_raddr); \
+ br r31,2f; \
+1: \
+ lda _raddr,0x11c0(_raddr); \
+2: ldlp _rsum,0(_raddr)
+
+
+
+//
+// Macro to write TLINTRSUMx
+//
+// Based on the CPU_NUMBER, write either the TLINTRSUM0 or TLINTRSUM1 register
+//
+// Assumed register usage:
+// rsum TLINTRSUMx write data
+// raddr node space address
+// scratch scratch register
+
+// .macro Write_TLINTRSUMx rsum, raddr, whami, ?label1, ?label2
+//
+// nop
+// mfpr 'whami', pt_whami // Get our whami (VID)
+//
+// extbl 'whami', #1, 'whami' // shift down to bit 0
+// lda 'raddr', ^xff88(r31) // Get base node space address bits
+//
+// sll 'raddr', #24, 'raddr' // Shift up to proper position
+// blbs 'whami', label1
+//
+// lda 'raddr', <tlep$tlintrsum0_offset>('raddr')
+// br r31, label2
+//
+// label1: lda 'raddr', <tlep$tlintrsum1_offset>('raddr')
+// label2: srl 'whami', #1, 'whami' // Shift off the cpu number
+//
+// sll 'whami', #22, 'whami' // Get our node offset
+// addq 'raddr', 'whami', 'raddr' // Get our base node space address
+//
+// mb
+// stqp 'rsum', 0('raddr') // write the right tlintrsum reg
+// mb
+// ldqp 'rsum', 0('raddr') // dummy read to tlintrsum
+// bis 'rsum', 'rsum', 'rsum' // needed to complete the ldqp above -jpo
+// .endm
+
+
+#define Write_TLINTRSUMx(_rsum,_raddr,_whami) \
+ nop; \
+ mfpr _whami,pt_whami; \
+ extbl _whami,1,_whami; \
+ lda _raddr,0xff88(zero); \
+ sll _raddr,24,_raddr; \
+ blbs _whami,1f; \
+ lda _raddr,0x1180(_raddr);\
+ br zero,2f; \
+1: lda _raddr,0x11c0(_raddr);\
+2: srl _whami,1,_whami; \
+ addq _raddr,_whami,_raddr; \
+ mb; \
+ stqp _rsum,0(_raddr); \
+ ldqp _rsum,0(_raddr); \
+ bis _rsum,_rsum,_rsum
+
+
+//
+// Macro to determine highest priority TIOP Node ID from interrupt pending mask
+//
+// Assumed register usage:
+// rmask - TLINTRSUMx contents, shifted to isolate IOx bits
+// rid - TLSB Node ID of highest TIOP
+
+//.macro Intr_Find_TIOP rmask, rid, ?l1, ?l2, ?l3, ?l4, ?l5, ?l6
+// srl 'rmask', #4, 'rid' // check IOP8
+// blbc 'rid', l1 // not IOP8
+//
+// lda 'rid', 8(r31) // IOP8
+// br r31, l6
+//
+// l1: srl 'rmask', #3, 'rid' // check IOP7
+// blbc 'rid', l2 // not IOP7
+//
+// lda 'rid', 7(r31) // IOP7
+// br r31, l6
+//
+// l2: srl 'rmask', #2, 'rid' // check IOP6
+// blbc 'rid', l3 // not IOP6
+//
+// lda 'rid', 6(r31) // IOP6
+// br r31, l6
+//
+// l3: srl 'rmask', #1, 'rid' // check IOP5
+// blbc 'rid', l4 // not IOP5
+//
+// lda 'rid', 5(r31) // IOP5
+// br r31, l6
+//
+// l4: srl 'rmask', #0, 'rid' // check IOP4
+// blbc 'rid', l5 // not IOP4
+//
+// lda r14, 4(r31) // IOP4
+// br r31, l6
+//
+// l5: lda r14, 0(r31) // passive release
+// l6:
+// .endm
+
+
+#define Intr_Find_TIOP(_rmask,_rid) \
+ srl _rmask,3,_rid; \
+ blbc _rid,1f; \
+ lda _rid,8(zero); \
+ br zero,6f; \
+1: srl _rmask,3,_rid; \
+ blbc _rid, 2f; \
+ lda _rid, 7(r31); \
+ br r31, 6f; \
+2: srl _rmask, 2, _rid; \
+ blbc _rid, 3f; \
+ lda _rid, 6(r31); \
+ br r31, 6f; \
+3: srl _rmask, 1, _rid; \
+ blbc _rid, 4f; \
+ lda _rid, 5(r31); \
+ br r31, 6f; \
+4: srl _rmask, 0, _rid; \
+ blbc _rid, 5f; \
+ lda r14, 4(r31); \
+ br r31, 6f; \
+5: lda r14, 0(r31); \
+6:
+
+
+
+
+//
+// Macro to calculate base node space address for given node id
+//
+// Assumed register usage:
+// rid - TLSB node id
+// raddr - base node space address
+
+//.macro Get_TLSB_Node_Address rid, raddr
+// sll 'rid', #22, 'rid' // Get offset of IOP node
+// lda 'raddr', ^xff88(r31) // Get base node space address bits
+//
+// sll 'raddr', #24, 'raddr' // Shift up to proper position
+// addq 'raddr', 'rid', 'raddr' // Get TIOP node space address
+// .iif ne turbo_pcia_intr_fix, srl 'rid', #22, 'rid' // Restore IOP node id
+//.endm
+
+
+#define turbo_pcia_intr_fix 0
+
+
+#if turbo_pcia_intr_fix != 0
+#define Get_TLSB_Node_Address(_rid,_raddr) \
+ sll _rid,22,_rid; \
+ lda _raddr,0xff88(zero); \
+ sll _raddr,24,_raddr; \
+ addq _raddr,_rid,_raddr; \
+ srl _rid,22,_rid
+#else
+#define Get_TLSB_Node_Address(_rid,_raddr) \
+ sll _rid,22,_rid; \
+ lda _raddr,0xff88(zero); \
+ sll _raddr,24,_raddr; \
+ addq _raddr,_rid,_raddr
+#endif
+
+
+
+
+
+// .macro mchk$TLEPstore rlog, rs, rs1, nodebase, tlepreg, clr, tlsb, crd
+// .iif eq tlsb, lda 'rs1',<tlep$'tlepreg'_offset>(r31)
+// .iif ne tlsb, lda 'rs1',<tlsb$'tlepreg'_offset>(r31)
+// or 'rs1', 'nodebase', 'rs1'
+// ldlp 'rs', 0('rs1')
+// .iif eq crd, stlp 'rs', mchk$'tlepreg'('rlog') // store in frame
+// .iif ne crd, stlp 'rs', mchk$crd_'tlepreg'('rlog') // store in frame
+// .iif ne clr, stlp 'rs',0('rs1') // optional write to clear
+// .endm
+
+
+// .macro OSFmchk$TLEPstore tlepreg, clr=0, tlsb=0
+// mchk$TLEPstore r14, r8, r4, r13, <tlepreg>, <clr>, <tlsb>, crd=0
+// .endm
+
+#define CONCAT(_a,_b) _a ## _b
+
+#define OSFmchk_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \
+ lda _rs1,CONCAT(tlep_,_tlepreg)(zero); \
+ or _rs1,_nodebase,_rs1; \
+ ldlp _rs1,0(_rs1); \
+ stlp _rs,CONCAT(mchk_,_tlepreg)(_rlog)
+
+
+#define OSFmchk_TLEPstore(_tlepreg) OSFmchk_TLEPstore_1(r14,r8,r4,r13,_tlepreg)
+
+
+// .macro OSFcrd$TLEPstore tlepreg, clr=0, tlsb=0
+// mchk$TLEPstore r14, r10, r1, r0, <tlepreg>, <clr>, <tlsb>, crd=1
+// .endm
+
+#define OSFcrd_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \
+ lda _rs1,CONCAT(tlep_,_tlepreg)(zero); \
+ or _rs1,_nodebase,_rs1; \
+ ldlp _rs1,0(_rs1); \
+ stlp _rs,CONCAT(mchk_crd_,_tlepreg)(_rlog)
+
+#define OSFcrd_TLEPstore_tlsb_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \
+ lda _rs1,CONCAT(tlsb_,_tlepreg)(zero); \
+ or _rs1,_nodebase,_rs1; \
+ ldlp _rs1,0(_rs1); \
+ stlp _rs,CONCAT(mchk_crd_,_tlepreg)(_rlog)
+
+#define OSFcrd_TLEPstore_tlsb_clr_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \
+ lda _rs1,CONCAT(tlsb_,_tlepreg)(zero); \
+ or _rs1,_nodebase,_rs1; \
+ ldlp _rs1,0(_rs1); \
+ stlp _rs,CONCAT(mchk_crd_,_tlepreg)(_rlog); \
+ stlp _rs,0(_rs1)
+
+
+#define OSFcrd_TLEPstore(_tlepreg) OSFcrd_TLEPstore_1(r14,r8,r4,r13,_tlepreg)
+#define OSFcrd_TLEPstore_tlsb(_tlepreg) OSFcrd_TLEPstore_tlsb_1(r14,r8,r4,r13,_tlepreg)
+#define OSFcrd_TLEPstore_tlsb_clr(_tlepreg) OSFcrd_TLEPstore_tlsb_clr_1(r14,r8,r4,r13,_tlepreg)
+
+
+
+
+// .macro save_pcia_intr irq
+// and r13, #^xf, r25 // isolate low 4 bits
+// addq r14, #4, r14 // format the TIOP Node id field
+// sll r14, #4, r14 // shift the TIOP Node id
+// or r14, r25, r10 // merge Node id/hose/HPC
+// mfpr r14, pt14 // get saved value
+// extbl r14, #'irq', r25 // confirm none outstanding
+// bne r25, sys$machine_check_while_in_pal
+// insbl r10, #'irq', r10 // align new info
+// or r14, r10, r14 // merge info
+// mtpr r14, pt14 // save it
+// bic r13, #^xf, r13 // clear low 4 bits of vector
+// .endm
+
+#define save_pcia_intr(_irq) \
+ and r13, 0xf, r25; \
+ addq r14, 4, r14; \
+ sll r14, 4, r14; \
+ or r14, r25, r10; \
+ mfpr r14, pt14; \
+ extbl r14, _irq, r25; \
+ bne r25, sys_machine_check_while_in_pal; \
+ insbl r10, _irq, r10; \
+ or r14, r10, r14; \
+ mtpr r14, pt14; \
+ bic r13, 0xf, r13
+
+
+
+ ALIGN_BLOCK
+
+// .sbttl "wripir - PALcode for wripir instruction"
+//orig SYS$WRIPIR: // R16 has the processor number.
+
+EXPORT(sys_wripir)
+
+//++
+// Convert the processor number to a CPU mask
+//--
+
+ and r16,0xf, r14 // mask the top stuff (16 CPUs supported)
+ bis r31,0x1,r16 // get a one
+ sll r16,r14,r14 // shift the bit to the right place
+
+//++
+// Build the Broadcast Space base address
+//--
+ lda r13,0xff8e(r31) // Load the upper address bits
+ sll r13,24,r13 // shift them to the top
+
+//++
+// Send out the IP Intr
+//--
+ stqp r14, 0x40(r13) // Write to TLIPINTR reg WAS TLSB_TLIPINTR_OFFSET
+ wmb // Push out the store
+
+ hw_rei
+
+
+ ALIGN_BLOCK
+// .sbttl "CFLUSH- PALcode for CFLUSH instruction"
+//+
+// SYS$CFLUSH
+// Entry:
+//
+// R16 - contains the PFN of the page to be flushed
+//
+// Function:
+// Flush all Dstream caches of 1 entire page
+//
+//-
+
+EXPORT(sys_cflush)
+
+// #convert pfn to addr, and clean off <63:20>
+// #sll r16, <page_offset_size_bits>+<63-20>>, r12
+ sll r16, page_offset_size_bits+(63-20),r12
+
+// #ldah r13,<<1@22>+32768>@-16(r31)// + xxx<31:16>
+// # stolen from srcmax code. XXX bugnion
+ lda r13, 0x10(r31) // assume 16Mbytes of cache
+ sll r13, 20, r13 // convert to bytes
+
+
+ srl r12, 63-20, r12 // shift back to normal position
+ xor r12, r13, r12 // xor addr<18>
+
+ or r31, 8192/(32*8), r13 // get count of loads
+ nop
+
+cflush_loop:
+ subq r13, 1, r13 // decr counter
+ mfpr r25, ev5__intid // Fetch level of interruptor
+
+ ldqp r31, 32*0(r12) // do a load
+ ldqp r31, 32*1(r12) // do next load
+
+ ldqp r31, 32*2(r12) // do next load
+ ldqp r31, 32*3(r12) // do next load
+
+ ldqp r31, 32*4(r12) // do next load
+ ldqp r31, 32*5(r12) // do next load
+
+ ldqp r31, 32*6(r12) // do next load
+ ldqp r31, 32*7(r12) // do next load
+
+ mfpr r14, ev5__ipl // Fetch current level
+ lda r12, (32*8)(r12) // skip to next cache block addr
+
+ cmple r25, r14, r25 // R25 = 1 if intid .less than or eql ipl
+ beq r25, 1f // if any int's pending, re-queue CFLUSH -- need to check for hlt interrupt???
+
+ bne r13, cflush_loop // loop till done
+ hw_rei // back to user
+
+ ALIGN_BRANCH
+1: // Here if interrupted
+ mfpr r12, exc_addr
+ subq r12, 4, r12 // Backup PC to point to CFLUSH
+
+ mtpr r12, exc_addr
+ nop
+
+ mfpr r31, pt0 // Pad exc_addr write
+ hw_rei
+
+
+ ALIGN_BLOCK
+// .sbttl "CSERVE- PALcode for CSERVE instruction"
+//+
+// SYS$CSERVE
+//
+// Function:
+// Various functions for private use of console software
+//
+// option selector in r0
+// arguments in r16....
+//
+//
+// r0 = 0 unknown
+//
+// r0 = 1 ldqp
+// r0 = 2 stqp
+// args, are as for normal STQP/LDQP in VMS PAL
+//
+// r0 = 3 dump_tb's
+// r16 = detination PA to dump tb's to.
+//
+// r0<0> = 1, success
+// r0<0> = 0, failure, or option not supported
+// r0<63:1> = (generally 0, but may be function dependent)
+// r0 - load data on ldqp
+//
+//-
+EXPORT(sys_cserve)
+
+#ifdef SIMOS
+ /* taken from scrmax */
+ cmpeq r18, CSERVE_K_RD_IMPURE, r0
+ bne r0, Sys_Cserve_Rd_Impure
+
+ cmpeq r18, CSERVE_K_JTOPAL, r0
+ bne r0, Sys_Cserve_Jtopal
+ call_pal 0
+
+ or r31, r31, r0
+ hw_rei // and back we go
+
+Sys_Cserve_Rd_Impure:
+ mfpr r0, pt_impure // Get base of impure scratch area.
+ hw_rei
+
+ ALIGN_BRANCH
+
+Sys_Cserve_Jtopal:
+ bic a0, 3, t8 // Clear out low 2 bits of address
+ bis t8, 1, t8 // Or in PAL mode bit
+ mtpr t8,exc_addr
+ hw_rei
+
+
+#else /* SIMOS */
+
+ cmpeq r16, cserve_ldlp, r12 // check for ldqp
+ bne r12, 1f // br if
+
+ cmpeq r16, cserve_stlp, r12 // check for stqp
+ bne r12, 2f // br if
+
+ cmpeq r16, cserve_callback, r12 // check for callback entry
+ bne r12, csrv_callback // br if
+
+ cmpeq r16, cserve_identify, r12 // check for callback entry
+ bne r12, csrv_identify // br if
+
+ or r31, r31, r0 // set failure
+ nop // pad palshadow write
+
+ hw_rei // and back we go
+#endif /* SIMOS */
+
+// ldqp
+ ALIGN_QUAD
+1:
+ ldqp r0,0(r17) // get the data
+ nop // pad palshadow write
+
+ hw_rei // and back we go
+
+
+// stqp
+ ALIGN_QUAD
+2:
+ stqp r18, 0(r17) // store the data
+#ifdef SIMOS
+ lda r0,17(r31) // bogus
+#else
+ lda r0, CSERVE_SUCCESS(r31) // set success
+#endif
+ hw_rei // and back we go
+
+
+ ALIGN_QUAD
+csrv_callback:
+ ldq r16, 0(r17) // restore r16
+ ldq r17, 8(r17) // restore r17
+ lda r0, hlt_c_callback(r31)
+ br r31, sys_enter_console
+
+
+csrv_identify:
+ mfpr r0, pal_base
+ ldqp r0, 8(r0)
+ hw_rei
+
+
+// dump tb's
+ ALIGN_QUAD
+0:
+ // DTB PTEs - 64 entries
+ addq r31, 64, r0 // initialize loop counter
+ nop
+
+1: mfpr r12, ev5__dtb_pte_temp // read out next pte to temp
+ mfpr r12, ev5__dtb_pte // read out next pte to reg file
+
+ subq r0, 1, r0 // decrement loop counter
+ nop // Pad - no Mbox instr in cycle after mfpr
+
+ stqp r12, 0(r16) // store out PTE
+ addq r16, 8 ,r16 // increment pointer
+
+ bne r0, 1b
+
+ ALIGN_BRANCH
+ // ITB PTEs - 48 entries
+ addq r31, 48, r0 // initialize loop counter
+ nop
+
+2: mfpr r12, ev5__itb_pte_temp // read out next pte to temp
+ mfpr r12, ev5__itb_pte // read out next pte to reg file
+
+ subq r0, 1, r0 // decrement loop counter
+ nop //
+
+ stqp r12, 0(r16) // store out PTE
+ addq r16, 8 ,r16 // increment pointer
+
+ bne r0, 2b
+ or r31, 1, r0 // set success
+
+ hw_rei // and back we go
+
+
+// .sbttl "SYS$INTERRUPT - Interrupt processing code"
+
+//+
+// SYS$INTERRUPT
+//
+// Current state:
+// Stack is pushed
+// ps, sp and gp are updated
+// r12, r14 - available
+// r13 - INTID (new EV5 IPL)
+// r25 - ISR
+// r16, r17, r18 - available
+//
+//-
+
+
+EXPORT(sys_interrupt)
+ cmpeq r13, 31, r12
+ bne r12, sys_int_mchk_or_crd // Check for level 31 interrupt (machine check or crd)
+
+ cmpeq r13, 30, r12
+ bne r12, sys_int_powerfail // Check for level 30 interrupt (powerfail)
+
+ cmpeq r13, 29, r12
+ bne r12, sys_int_perf_cnt // Check for level 29 interrupt (performance counters)
+
+ cmpeq r13, 23, r12
+ bne r12, sys_int_23 // Check for level 23 interrupt
+
+ cmpeq r13, 22, r12
+ bne r12, sys_int_22 // Check for level 22 interrupt (might be
+ // interprocessor or timer interrupt)
+
+ cmpeq r13, 21, r12
+ bne r12, sys_int_21 // Check for level 21 interrupt
+
+ cmpeq r13, 20, r12
+ bne r12, sys_int_20 // Check for level 20 interrupt (might be corrected
+ // system error interrupt)
+
+ mfpr r14, exc_addr // ooops, something is wrong
+ br r31, pal_pal_bug_check_from_int
+
+
+
+
+//+
+//sys$int_2*
+// Routines to handle device interrupts at IPL 23-20.
+// System specific method to ack/clear the interrupt, detect passive release,
+// detect interprocessor (22), interval clock (22), corrected
+// system error (20)
+//
+// Current state:
+// Stack is pushed
+// ps, sp and gp are updated
+// r12, r14 - available
+// r13 - INTID (new EV5 IPL)
+// r25 - ISR
+//
+// On exit:
+// Interrupt has been ack'd/cleared
+// a0/r16 - signals IO device interrupt
+// a1/r17 - contains interrupt vector
+// exit to ent_int address
+//
+//-
+ ALIGN_BRANCH
+sys_int_23:
+ Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx
+ srl r13, 22, r13 // shift down to examine IPL17
+
+ Intr_Find_TIOP(r13,r14)
+ beq r14, 1f
+
+ Get_TLSB_Node_Address(r14,r10)
+ lda r10, 0xac0(r10) // Get base TLILID address
+
+ ldlp r13, 0(r10) // Read the TLILID register
+ bne r13, pal_post_dev_interrupt
+
+1: lda r16, osfint_c_passrel(r31) // passive release
+ br r31, pal_post_interrupt //
+
+
+ ALIGN_BRANCH
+sys_int_22:
+ Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx
+ srl r13, 6, r14 // check the Intim bit
+
+ blbs r14, tlep_intim // go service Intim
+ srl r13, 5, r14 // check the IP Int bit
+
+ blbs r14, tlep_ipint // go service IP Int
+ srl r13, 17, r13 // shift down to examine IPL16
+
+ Intr_Find_TIOP(r13,r14)
+ beq r14, 1f
+
+ Get_TLSB_Node_Address(r14,r10)
+ lda r10, 0xa80(r10) // Get base TLILID address
+
+ ldlp r13, 0(r10) // Read the TLILID register
+#if turbo_pcia_intr_fix == 0
+// .if eq turbo_pcia_intr_fix
+ bne r13, pal_post_dev_interrupt
+//orig .iff
+ beq r13, 1f
+
+ and r13, 0x3, r10 // check for PCIA bits
+ beq r10, pal_post_dev_interrupt // done if nothing set
+ save_pcia_intr(2)
+ br r31, pal_post_dev_interrupt //
+// .endc
+#endif /* turbo_pcia_intr_fix == 0 */
+
+1: lda r16, osfint_c_passrel(r31) // passive release
+ br r31, pal_post_interrupt //
+
+
+ ALIGN_BRANCH
+sys_int_21:
+ Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx
+ srl r13, 12, r13 // shift down to examine IPL15
+
+ Intr_Find_TIOP(r13,r14)
+ beq r14, 1f
+
+ Get_TLSB_Node_Address(r14,r10)
+ lda r10, 0xa40(r10) // Get base TLILID address
+
+ ldlp r13, 0(r10) // Read the TLILID register
+#if turbo_pcia_intr_fix == 0
+//orig .if eq turbo_pcia_intr_fix
+ bne r13, pal_post_dev_interrupt
+//orig .iff
+ beq r13, 1f
+
+ and r13, 0x3, r10 // check for PCIA bits
+ beq r10, pal_post_dev_interrupt // done if nothing set
+ save_pcia_intr(1)
+ br r31, pal_post_dev_interrupt //
+// orig .endc
+#endif /* turbo_pcia_intr_fix == 0 */
+
+1: lda r16, osfint_c_passrel(r31) // passive release
+ br r31, pal_post_interrupt //
+
+
+ ALIGN_BRANCH
+sys_int_20:
+ lda r13, 1(r31) // Duart0 bit
+ Write_TLINTRSUMx(r13,r10,r14) // clear the duart0 bit
+
+ Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx
+ blbs r13, tlep_uart0 // go service UART int
+
+ srl r13, 7, r13 // shift down to examine IPL14
+ Intr_Find_TIOP(r13,r14)
+
+ beq r14, tlep_ecc // Branch if not IPL14
+ Get_TLSB_Node_Address(r14,r10)
+
+ lda r10, tlsb_tlilid0_offset(r10) // Get base TLILID address
+ ldlp r13, 0(r10) // Read the TLILID register
+
+#if turbo_pcia_intr_fix == 0
+// orig .if eq turbo_pcia_intr_fix
+ bne r13, pal_post_dev_interrupt
+// orig .iff
+ beq r13, 1f
+
+ and r13, 0x3, r10 // check for PCIA bits
+ beq r10, pal_post_dev_interrupt // done if nothing set
+ save_pcia_intr(0)
+ br r31, pal_post_dev_interrupt //
+// orig .endc
+#endif
+1: lda r16, osfint_c_passrel(r31) // passive release
+ br r31, pal_post_interrupt //
+
+
+ ALIGN_BRANCH
+tlep_intim:
+ lda r13, 0xffb(r31) // get upper GBUS address bits
+ sll r13, 28, r13 // shift up to top
+
+ lda r13, (tlep_watch_csrc_offset)(r13) // full CSRC address
+ ldqp r13, 0(r13) // read CSRC
+
+ lda r13, 0x40(r31) // load Intim bit
+ Write_TLINTRSUMx(r13,r10,r14) // clear the Intim bit
+
+ lda r16, osfint_c_clk(r31) // passive release
+ br r31, pal_post_interrupt // Build the stack frame
+
+
+ ALIGN_BRANCH
+tlep_ipint:
+ lda r13, 0x20(r31) // load IP Int bit
+ Write_TLINTRSUMx(r13,r10,r14) // clear the IP Int bit
+
+ lda r16, osfint_c_ip(r31) // passive release
+ br r31, pal_post_interrupt // Build the stack frame
+
+
+ ALIGN_BRANCH
+tlep_uart0:
+ lda r13, 0xffa(r31) // get upper GBUS address bits
+ sll r13, 28, r13 // shift up to top
+
+ ldlp r14, 0x80(r13) // zero pointer register
+ lda r14, 3(r31) // index to RR3
+
+ stlp r14, 0x80(r13) // write pointer register
+ mb
+
+ mb
+ ldlp r14, 0x80(r13) // read RR3
+
+ srl r14, 5, r10 // is it Channel A RX?
+ blbs r10, uart0_rx
+
+ srl r14, 4, r10 // is it Channel A TX?
+ blbs r10, uart0_tx
+
+ srl r14, 2, r10 // is it Channel B RX?
+ blbs r10, uart1_rx
+
+ srl r14, 1, r10 // is it Channel B TX?
+ blbs r10, uart1_tx
+
+ lda r8, 0(r31) // passive release
+ br r31, clear_duart0_int // clear tlintrsum and post
+
+
+ ALIGN_BRANCH
+uart0_rx:
+ lda r8, 0x680(r31) // UART0 RX vector
+ br r31, clear_duart0_int // clear tlintrsum and post
+
+
+ ALIGN_BRANCH
+uart0_tx:
+ lda r14, 0x28(r31) // Reset TX Int Pending code
+ mb
+ stlp r14, 0x80(r13) // write Channel A WR0
+ mb
+
+ lda r8, 0x6c0(r31) // UART0 TX vector
+ br r31, clear_duart0_int // clear tlintrsum and post
+
+
+ ALIGN_BRANCH
+uart1_rx:
+ lda r8, 0x690(r31) // UART1 RX vector
+ br r31, clear_duart0_int // clear tlintrsum and post
+
+
+ ALIGN_BRANCH
+uart1_tx:
+ lda r14, 0x28(r31) // Reset TX Int Pending code
+ stlp r14, 0(r13) // write Channel B WR0
+
+ lda r8, 0x6d0(r31) // UART1 TX vector
+ br r31, clear_duart0_int // clear tlintrsum and post
+
+
+ ALIGN_BRANCH
+clear_duart0_int:
+ lda r13, 1(r31) // load duart0 bit
+ Write_TLINTRSUMx(r13,r10,r14) // clear the duart0 bit
+
+ beq r8, 1f
+ or r8, r31, r13 // move vector to r13
+ br r31, pal_post_dev_interrupt // Build the stack frame
+1: nop
+ nop
+ hw_rei
+// lda r16, osfint_c_passrel(r31) // passive release
+// br r31, pal_post_interrupt //
+
+
+ ALIGN_BRANCH
+tlep_ecc:
+ mfpr r14, pt_whami // get our node id
+ extbl r14, 1, r14 // shift to bit 0
+
+ srl r14, 1, r14 // shift off cpu number
+ Get_TLSB_Node_Address(r14,r10) // compute our nodespace address
+
+ ldlp r13, 0x40(r10) // read our TLBER WAS tlsb_tlber_offset
+ srl r13, 17, r13 // shift down the CWDE/CRDE bits
+
+ and r13, 3, r13 // mask the CWDE/CRDE bits
+ beq r13, 1f
+
+ ornot r31, r31, r12 // set flag
+ lda r9, mchk_c_sys_ecc(r31) // System Correctable error MCHK code
+ br r31, sys_merge_sys_corr // jump to CRD logout frame code
+
+1: lda r16, osfint_c_passrel(r31) // passive release
+
+
+ ALIGN_BRANCH
+
+pal_post_dev_interrupt:
+ or r13, r31, r17 // move vector to a1
+ or r31, osfint_c_dev, r16 // a0 signals IO device interrupt
+
+pal_post_interrupt:
+ mfpr r12, pt_entint
+
+ mtpr r12, exc_addr
+
+ nop
+ nop
+
+ hw_rei_spe
+
+
+
+//+
+// sys_passive_release
+// Just pretend the interrupt never occurred.
+//-
+
+EXPORT(sys_passive_release)
+ mtpr r11, ev5__dtb_cm // Restore Mbox current mode for ps
+ nop
+
+ mfpr r31, pt0 // Pad write to dtb_cm
+ hw_rei
+
+//+
+//sys_int_powerfail
+// A powerfail interrupt has been detected. The stack has been pushed.
+// IPL and PS are updated as well.
+//
+// I'm not sure what to do here, I'm treating it as an IO device interrupt
+//
+//-
+
+ ALIGN_BLOCK
+sys_int_powerfail:
+ lda r12, 0xffc4(r31) // get GBUS_MISCR address bits
+ sll r12, 24, r12 // shift to proper position
+ ldqp r12, 0(r12) // read GBUS_MISCR
+ srl r12, 5, r12 // isolate bit <5>
+ blbc r12, 1f // if clear, no missed mchk
+
+ // Missed a CFAIL mchk
+ lda r13, 0xffc7(r31) // get GBUS$SERNUM address bits
+ sll r13, 24, r13 // shift to proper position
+ lda r14, 0x40(r31) // get bit <6> mask
+ ldqp r12, 0(r13) // read GBUS$SERNUM
+ or r12, r14, r14 // set bit <6>
+ stqp r14, 0(r13) // clear GBUS$SERNUM<6>
+ mb
+ mb
+
+1: br r31, sys_int_mchk // do a machine check
+
+ lda r17, scb_v_pwrfail(r31) // a1 to interrupt vector
+ mfpr r25, pt_entint
+
+ lda r16, osfint_c_dev(r31) // a0 to device code
+ mtpr r25, exc_addr
+
+ nop // pad exc_addr write
+ nop
+
+ hw_rei_spe
+
+//+
+// sys$halt_interrupt
+// A halt interrupt has been detected. Pass control to the console.
+//
+//
+//-
+ EXPORT(sys_halt_interrupt)
+
+ ldah r13, 0x1800(r31) // load Halt/^PHalt bits
+ Write_TLINTRSUMx(r13,r10,r14) // clear the ^PHalt bits
+
+ mtpr r11, dtb_cm // Restore Mbox current mode
+ nop
+ nop
+ mtpr r0, pt0
+#ifndef SIMOS
+ pvc_jsr updpcb, bsr=1
+ bsr r0, pal_update_pcb // update the pcb
+#endif
+ lda r0, hlt_c_hw_halt(r31) // set halt code to hw halt
+ br r31, sys_enter_console // enter the console
+
+
+
+//+
+// sys$int_mchk_or_crd
+//
+// Current state:
+// Stack is pushed
+// ps, sp and gp are updated
+// r12
+// r13 - INTID (new EV5 IPL)
+// r14 - exc_addr
+// r25 - ISR
+// r16, r17, r18 - available
+//
+//-
+ ALIGN_BLOCK
+
+sys_int_mchk_or_crd:
+ srl r25, isr_v_mck, r12
+ blbs r12, sys_int_mchk
+ //+
+ // Not a Machine check interrupt, so must be an Internal CRD interrupt
+ //-
+
+ mb //Clear out Cbox prior to reading IPRs
+ srl r25, isr_v_crd, r13 //Check for CRD
+ blbc r13, pal_pal_bug_check_from_int //If CRD not set, shouldn't be here!!!
+
+ lda r9, 1(r31)
+ sll r9, hwint_clr_v_crdc, r9 // get ack bit for crd
+ mtpr r9, ev5__hwint_clr // ack the crd interrupt
+
+ or r31, r31, r12 // clear flag
+ lda r9, mchk_c_ecc_c(r31) // Correctable error MCHK code
+
+sys_merge_sys_corr:
+ ldah r14, 0xfff0(r31)
+ mtpr r0, pt0 // save r0 for scratch
+ zap r14, 0xE0, r14 // Get Cbox IPR base
+ mtpr r1, pt1 // save r0 for scratch
+
+ ldqp r0, ei_addr(r14) // EI_ADDR IPR
+ ldqp r10, fill_syn(r14) // FILL_SYN IPR
+ bis r0, r10, r31 // Touch lds to make sure they complete before doing scrub
+
+ blbs r12, 1f // no scrubbing for IRQ0 case
+// XXX bugnion pvc_jsr crd_scrub_mem, bsr=1
+ bsr r13, sys_crd_scrub_mem // and go scrub
+
+ // ld/st pair in scrub routine will have finished due
+ // to ibox stall of stx_c. Don't need another mb.
+ ldqp r8, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
+ or r8, r31, r12 // Must only be executed once in this flow, and must
+ br r31, 2f // be after the scrub routine.
+
+1: ldqp r8, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
+ // For IRQ0 CRD case only - meaningless data.
+
+2: mfpr r13, pt_mces // Get MCES
+ srl r12, ei_stat_v_ei_es, r14 // Isolate EI_STAT:EI_ES
+ blbc r14, 6f // branch if 630
+ srl r13, mces_v_dsc, r14 // check if 620 reporting disabled
+ blbc r14, 5f // branch if enabled
+ or r13, r31, r14 // don't set SCE if disabled
+ br r31, 8f // continue
+5: bis r13, BIT(mces_v_sce), r14 // Set MCES<SCE> bit
+ br r31, 8f
+
+6: srl r13, mces_v_dpc, r14 // check if 630 reporting disabled
+ blbc r14, 7f // branch if enabled
+ or r13, r31, r14 // don't set PCE if disabled
+ br r31, 8f // continue
+7: bis r13, BIT(mces_v_pce), r14 // Set MCES<PCE> bit
+
+ // Setup SCB if dpc is not set
+8: mtpr r14, pt_mces // Store updated MCES
+ srl r13, mces_v_sce, r1 // Get SCE
+ srl r13, mces_v_pce, r14 // Get PCE
+ or r1, r14, r1 // SCE OR PCE, since they share
+ // the CRD logout frame
+ // Get base of the logout area.
+ GET_IMPURE(r14) // addr of per-cpu impure area
+ GET_ADDR(r14,(pal_logout_area+mchk_crd_base),r14)
+
+ blbc r1, sys_crd_write_logout_frame // If pce/sce not set, build the frame
+
+ // Set the 2nd error flag in the logout area:
+
+ lda r1, 3(r31) // Set retry and 2nd error flags
+ sll r1, 30, r1 // Move to bits 31:30 of logout frame flag longword
+ stlp r1, mchk_crd_flag+4(r14) // store flag longword
+ br sys_crd_ack
+
+sys_crd_write_logout_frame:
+ // should only be here if neither the pce or sce bits are set
+
+ //+
+ // Write the mchk code to the logout area
+ //-
+ stqp r9, mchk_crd_mchk_code(r14)
+
+
+ //+
+ // Write the first 2 quadwords of the logout area:
+ //-
+ lda r1, 1(r31) // Set retry flag
+ sll r1, 63, r9 // Move retry flag to bit 63
+ lda r1, mchk_crd_size(r9) // Combine retry flag and frame size
+ stqp r1, mchk_crd_flag(r14) // store flag/frame size
+
+#ifndef SIMOS
+ /* needed? bugnion */
+ lda r1, mchk_crd_sys_base(r31) // sys offset
+ sll r1, 32, r1
+ lda r1, mchk_crd_cpu_base(r1) // cpu offset
+ stqp r1, mchk_crd_offsets(r14) // store sys offset/cpu offset into logout frame
+
+#endif
+ //+
+ // Write error IPRs already fetched to the logout area
+ //-
+ stqp r0, mchk_crd_ei_addr(r14)
+ stqp r10, mchk_crd_fill_syn(r14)
+ stqp r8, mchk_crd_ei_stat(r14)
+ stqp r25, mchk_crd_isr(r14)
+ //+
+ // Log system specific info here
+ //-
+crd_storeTLEP_:
+ lda r1, 0xffc4(r31) // Get GBUS$MISCR address
+ sll r1, 24, r1
+ ldqp r1, 0(r1) // Read GBUS$MISCR
+ sll r1, 16, r1 // shift up to proper field
+ mfpr r10, pt_whami // get our node id
+ extbl r10, 1, r10 // shift to bit 0
+ or r1, r10, r1 // merge MISCR and WHAMI
+ stlp r1, mchk_crd_whami(r14) // write to crd logout area
+ srl r10, 1, r10 // shift off cpu number
+
+ Get_TLSB_Node_Address(r10,r0) // compute our nodespace address
+
+ OSFcrd_TLEPstore_tlsb(tldev)
+ OSFcrd_TLEPstore_tlsb_clr(tlber)
+ OSFcrd_TLEPstore_tlsb_clr(tlesr0)
+ OSFcrd_TLEPstore_tlsb_clr(tlesr1)
+ OSFcrd_TLEPstore_tlsb_clr(tlesr2)
+ OSFcrd_TLEPstore_tlsb_clr(tlesr3)
+
+sys_crd_ack:
+ mfpr r0, pt0 // restore r0
+ mfpr r1, pt1 // restore r1
+
+ srl r12, ei_stat_v_ei_es, r12
+ blbc r12, 5f
+ srl r13, mces_v_dsc, r10 // logging enabled?
+ br r31, 6f
+5: srl r13, mces_v_dpc, r10 // logging enabled?
+6: blbc r10, sys_crd_post_interrupt // logging enabled -- report it
+
+ // logging not enabled --
+ // Get base of the logout area.
+ GET_IMPURE(r13) // addr of per-cpu impure area
+ GET_ADDR(r13,(pal_logout_area+mchk_crd_base),r13)
+ ldlp r10, mchk_crd_rsvd(r13) // bump counter
+ addl r10, 1, r10
+ stlp r10, mchk_crd_rsvd(r13)
+ mb
+ br r31, sys_crd_dismiss_interrupt // just return
+
+ //+
+ // The stack is pushed. Load up a0,a1,a2 and vector via entInt
+ //
+ //-
+
+ ALIGN_BRANCH
+sys_crd_post_interrupt:
+ lda r16, osfint_c_mchk(r31) // flag as mchk/crd in a0
+ lda r17, scb_v_proc_corr_err(r31) // a1 <- interrupt vector
+
+ blbc r12, 1f
+ lda r17, scb_v_sys_corr_err(r31) // a1 <- interrupt vector
+
+1: subq r31, 1, r18 // get a -1
+ mfpr r25, pt_entInt
+
+ srl r18, 42, r18 // shift off low bits of kseg addr
+ mtpr r25, exc_addr // load interrupt vector
+
+ sll r18, 42, r18 // shift back into position
+ or r14, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address
+
+ hw_rei_spe // done
+
+
+ //+
+ // The stack is pushed. Need to back out of it all.
+ //-
+
+sys_crd_dismiss_interrupt:
+ br r31, Call_Pal_Rti
+
+
+// .sbttl sys_crd_scrub_mem
+
+ //+
+ //
+ // sys_crd_scrub_mem
+ // called
+ // jsr r13, sys$crd_scrub_mem
+ // r0 = addr of cache block
+ //
+ //-
+
+
+
+ ALIGN_BLOCK // align for branch target
+sys_crd_scrub_mem:
+ // now find error in memory, and attempt to scrub that cache block
+ // This routine just scrubs the failing octaword
+ // Only need to "touch" one quadword per octaword to accomplish the scrub
+ srl r0, 39, r8 // get high bit of bad pa
+ blbs r8, 1f // don't attempt fixup on IO space addrs
+ nop // needed to align the ldqpl to octaword boundary
+ nop // "
+
+ ldqpl r8, 0(r0) // attempt to read the bad memory
+ // location
+ // (Note bits 63:40,3:0 of ei_addr
+ // are set to 1, but as long as
+ // we are doing a phys ref, should
+ // be ok)
+ nop // Needed to keep the Ibox from swapping the ldqpl into E1
+
+ stqpc r8, 0(r0) // Store it back if it is still there.
+ // If store fails, location already
+ // scrubbed by someone else
+
+ nop // needed to align the ldqpl to octaword boundary
+
+ lda r8, 0x20(r31) // flip bit 5 to touch next hexaword
+ xor r8, r0, r0
+ nop // needed to align the ldqpl to octaword boundary
+ nop // "
+
+ ldqpl r8, 0(r0) // attempt to read the bad memory
+ // location
+ // (Note bits 63:40,3:0 of ei_addr
+ // are set to 1, but as long as
+ // we are doing a phys ref, should
+ // be ok)
+ nop // Needed to keep the Ibox from swapping the ldqpl into E1
+
+ stqpc r8, 0(r0) // Store it back if it is still there.
+ // If store fails, location already
+ // scrubbed by someone else
+
+ lda r8, 0x20(r31) // restore r0 to original address
+ xor r8, r0, r0
+
+ //at this point, ei_stat could be locked due to a new corr error on the ld,
+ //so read ei_stat to unlock AFTER this routine.
+
+// XXX bugnion pvc$jsr crd_scrub_mem, bsr=1, dest=1
+1: ret r31, (r13) // and back we go
+
+
+// .sbttl "SYS$INT_MCHK - MCHK Interrupt code"
+//+
+// Machine check interrupt from the system. Setup and join the
+// regular machine check flow.
+// On exit:
+// pt0 - saved r0
+// pt1 - saved r1
+// pt4 - saved r4
+// pt5 - saved r5
+// pt6 - saved r6
+// pt10 - saved exc_addr
+// pt_misc<47:32> - mchk code
+// pt_misc<31:16> - scb vector
+// r14 - base of Cbox IPRs in IO space
+// MCES<mchk> is set
+//-
+ ALIGN_BLOCK
+sys_int_mchk:
+ lda r14, mchk_c_sys_hrd_error(r31)
+ mfpr r12, exc_addr
+
+ addq r14, 1, r14 // Flag as interrupt
+ nop
+
+ sll r14, 32, r14 // Move mchk code to position
+ mtpr r12, pt10 // Stash exc_addr
+
+ mfpr r12, pt_misc // Get MCES and scratch
+ mtpr r0, pt0 // Stash for scratch
+
+ zap r12, 0x3c, r12 // Clear scratch
+ blbs r12, sys_double_machine_check // MCHK halt if double machine check
+
+ or r12, r14, r12 // Combine mchk code
+ lda r14, scb_v_sysmchk(r31) // Get SCB vector
+
+ sll r14, 16, r14 // Move SCBv to position
+ or r12, r14, r14 // Combine SCBv
+
+ bis r14, BIT(mces_v_mchk), r14 // Set MCES<MCHK> bit
+ mtpr r14, pt_misc // Save mchk code!scbv!whami!mces
+
+ ldah r14, 0xfff0(r31)
+ mtpr r1, pt1 // Stash for scratch
+
+ zap r14, 0xE0, r14 // Get Cbox IPR base
+ mtpr r4, pt4
+
+ mtpr r5, pt5
+
+#if beh_model
+// .if ne beh_model
+ ldah r25, 0xC000(r31) // Get base of demon space
+ lda r25, 0x340(r25) // Add interrupt demon offset
+
+ ldqp r13, 0(r25) // Read the control register
+ nop
+
+ and r13, 0x10, r8 // For debug, check that the interrupt is expected
+ beq r8, interrupt_not_expected
+
+ bic r13, 0x10, r13
+ stqp r13, 0(r25) // Ack and clear the interrupt
+// XXX bugnion pvc$violate 379 // stqp can't trap except replay. mt ipr only problem if mf same ipr in same shadow
+ .endc
+#endif
+
+ mtpr r6, pt6
+ br r31, sys_mchk_collect_iprs // Join common machine check flow
+
+
+// .sbttl "SYS$INT_PERF_CNT - Performance counter interrupt code"
+//+
+//sys$int_perf_cnt
+//
+// A performance counter interrupt has been detected. The stack has been pushed.
+// IPL and PS are updated as well.
+//
+// on exit to interrupt entry point ENTINT::
+// a0 = osfint$c_perf
+// a1 = scb$v_perfmon (650)
+// a2 = 0 if performance counter 0 fired
+// a2 = 1 if performance counter 1 fired
+// a2 = 2 if performance counter 2 fired
+// (if more than one counter overflowed, an interrupt will be
+// generated for each counter that overflows)
+//
+//
+//-
+ ALIGN_BLOCK
+sys_int_perf_cnt: // Performance counter interrupt
+ lda r17, scb_v_perfmon(r31) // a1 to interrupt vector
+ mfpr r25, pt_entint
+
+ lda r16, osfint_c_perf(r31) // a0 to perf counter code
+ mtpr r25, exc_addr
+
+ //isolate which perf ctr fired, load code in a2, and ack
+ mfpr r25, isr
+ or r31, r31, r18 // assume interrupt was pc0
+
+ srl r25, isr_v_pc1, r25 // isolate
+ cmovlbs r25, 1, r18 // if pc1 set, load 1 into r14
+
+ srl r25, 1, r25 // get pc2
+ cmovlbs r25, 2, r18 // if pc2 set, load 2 into r14
+
+ lda r25, 1(r31) // get a one
+ sll r25, r18, r25
+
+ sll r25, hwint_clr_v_pc0c, r25 // ack only the perf counter that generated the interrupt
+ mtpr r25, hwint_clr
+
+ hw_rei_spe
+
+
+
+ ALIGN_BLOCK
+// .sbttl "System specific RESET code"
+//+
+// RESET code
+// On entry:
+// r1 = pal_base +8
+//
+// Entry state on trap:
+// r0 = whami
+// r2 = base of scratch area
+// r3 = halt code
+// and the following 3 if init_cbox is enabled:
+// r5 = sc_ctl
+// r6 = bc_ctl
+// r7 = bc_cnfg
+//
+// Entry state on switch:
+// r17 - new PC
+// r18 - new PCBB
+// r19 - new VPTB
+//
+//-
+
+#if rax_mode==0
+ .globl sys_reset
+sys_reset:
+// mtpr r31, ic_flush_ctl // do not flush the icache - done by hardware before SROM load
+ mtpr r31, itb_ia // clear the ITB
+ mtpr r31, dtb_ia // clear the DTB
+
+ lda r1, -8(r1) // point to start of code
+ mtpr r1, pal_base // initialize PAL_BASE
+
+ // Interrupts
+ mtpr r31, astrr // stop ASTs
+ mtpr r31, aster // stop ASTs
+ mtpr r31, sirr // clear software interrupts
+
+ mtpr r0, pt1 // r0 is whami (unless we entered via swp)
+
+//orig ldah r1, <<1@<icsr$v_sde-16>> ! <1@<icsr$v_fpe-16>> ! <2@<icsr$v_spe-16>>>(r31)
+ ldah r1,(BIT(icsr_v_sde-16)|BIT(icsr_v_fpe-16)|BIT(icsr_v_spe-16+1))(zero)
+
+#if disable_crd == 0
+// .if eq disable_crd
+ bis r31, 1, r0
+ sll r0, icsr_v_crde, r0 // A 1 in iscr<corr_read_enable>
+ or r0, r1, r1 // Set the bit
+#endif
+
+ mtpr r1, icsr // ICSR - Shadows enabled, Floating point enable,
+ // super page enabled, correct read per assembly option
+
+ // Mbox/Dcache init
+//orig lda r1, <1@<mcsr$v_sp1>>(r31)
+ lda r1,BIT(mcsr_v_sp1)(zero)
+
+ mtpr r1, mcsr // MCSR - Super page enabled
+ lda r1, BIT(dc_mode_v_dc_ena)(r31)
+ ALIGN_BRANCH
+// mtpr r1, dc_mode // turn Dcache on
+ nop
+
+ mfpr r31, pt0 // No Mbox instr in 1,2,3,4
+ mfpr r31, pt0
+ mfpr r31, pt0
+ mfpr r31, pt0
+ mtpr r31, dc_flush // flush Dcache
+
+ // build PS (IPL=7,CM=K,VMM=0,SW=0)
+ lda r11, 0x7(r31) // Set shadow copy of PS - kern mode, IPL=7
+ lda r1, 0x1F(r31)
+ mtpr r1, ipl // set internal <ipl>=1F
+ mtpr r31, ev5__ps // set new ps<cm>=0, Ibox copy
+ mtpr r31, dtb_cm // set new ps<cm>=0, Mbox copy
+
+ // Create the PALtemp pt_intmask -
+ // MAP:
+ // OSF IPL EV5 internal IPL(hex) note
+ // 0 0
+ // 1 1
+ // 2 2
+ // 3 14 device
+ // 4 15 device
+ // 5 16 device
+ // 6 1E device,performance counter, powerfail
+ // 7 1F
+ //
+
+ ldah r1, 0x1f1E(r31) // Create upper lw of int_mask
+ lda r1, 0x1615(r1)
+
+ sll r1, 32, r1
+ ldah r1, 0x1402(r1) // Create lower lw of int_mask
+
+ lda r1, 0x0100(r1)
+ mtpr r1, pt_intmask // Stash in PALtemp
+
+ // Unlock a bunch of chip internal IPRs
+ mtpr r31, exc_sum // clear out exeception summary and exc_mask
+ mfpr r31, va // unlock va, mmstat
+//rig lda r8, <<1@icperr_stat$v_dpe> ! <1@icperr_stat$v_tpe> ! <1@icperr_stat$v_tmr>>(r31)
+ lda r8,(BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(zero)
+
+ mtpr r8, icperr_stat // Clear Icache parity error & timeout status
+//orig lda r8, <<1@dcperr_stat$v_lock> ! <1@dcperr_stat$v_seo>>(r31)
+ lda r8,(BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31)
+
+ mtpr r8, dcperr_stat // Clear Dcache parity error status
+
+ rc r0 // clear intr_flag
+ mtpr r31, pt_trap
+
+ mfpr r0, pt_misc
+ srl r0, pt_misc_v_switch, r1
+ blbs r1, sys_reset_switch // see if we got here from swppal
+
+ // Rest of the "real" reset flow
+ // ASN
+ mtpr r31, dtb_asn
+ mtpr r31, itb_asn
+
+ lda r1, 0x67(r31)
+ sll r1, hwint_clr_v_pc0c, r1
+ mtpr r1, hwint_clr // Clear hardware interrupt requests
+
+ lda r1, BIT(mces_v_dpc)(r31) // 1 in disable processor correctable error
+ mfpr r0, pt1 // get whami
+ insbl r0, 1, r0 // isolate whami in correct pt_misc position
+ or r0, r1, r1 // combine whami and mces
+ mtpr r1, pt_misc // store whami and mces, swap bit clear
+
+ zapnot r3, 1, r0 // isolate halt code
+ mtpr r0, pt0 // save entry type
+
+ // Cycle counter
+ or r31, 1, r9 // get a one
+ sll r9, 32, r9 // shift to <32>
+ mtpr r31, cc // clear Cycle Counter
+ mtpr r9, cc_ctl // clear and enable the Cycle Counter
+ mtpr r31, pt_scc // clear System Cycle Counter
+
+
+ // Misc PALtemps
+ mtpr r31, maf_mode // no mbox instructions for 3 cycles
+ or r31, 1, r1 // get bogus scbb value
+ mtpr r1, pt_scbb // load scbb
+ mtpr r31, pt_prbr // clear out prbr
+#ifdef SIMOS
+// or zero,kludge_initial_pcbb,r1
+ GET_ADDR(r1, (kludge_initial_pcbb-pal_base), r1)
+#else
+ mfpr r1, pal_base
+//orig sget_addr r1, (kludge_initial_pcbb-pal$base), r1, verify=0// get address for temp pcbb
+ GET_ADDR(r1, (kludge_initial_pcbb-pal_base), r1)
+#endif
+ mtpr r1, pt_pcbb // load pcbb
+ lda r1, 2(r31) // get a two
+ sll r1, 32, r1 // gen up upper bits
+ mtpr r1, mvptbr
+ mtpr r1, ivptbr
+ mtpr r31, pt_ptbr
+ // Performance counters
+ mtpr r31, pmctr
+
+#if init_cbox != 0
+// .if ne init_cbox
+ // Only init the Scache and the Bcache if there have been no previous
+ // cacheable dstream loads or stores.
+ //
+ // Inputs:
+ // r5 - sc_ctl
+ // r6 - bc_ctl
+ // r7 - bc_cnfg
+
+ ldah r0, 0xfff0(r31)
+ zap r0, 0xE0, r0 // Get Cbox IPR base
+ ldqp r19, ev5__sc_ctl(r0) // read current sc_ctl
+temp = <<<1@bc_ctl$v_ei_dis_err> + <1@bc_ctl$v_ei_ecc_or_parity> + <1@bc_ctl$v_corr_fill_dat>>@-1>
+ lda r20, temp(r31) // create default bc_ctl (bc disabled, errors disabled, ecc mode)
+ sll r20, 1, r20
+temp = 0x017441 // default bc_config
+ get_addr r21, temp, r31 // create default bc_config
+ lda r23, <1@sc_ctl_v_sc_flush>(r31) //set flag to invalidate scache in set_sc_bc_ctl
+
+// XXX bugnion pvc$jsr scbcctl, bsr=1
+ bsr r10, set_sc_bc_ctl
+ update_bc_ctl_shadow r6, r23 // update bc_ctl shadow using r6 as input// r23 gets adjusted impure pointer
+ store_reg1 bc_config, r7, r23, ipr=1 // update bc_config shadow in impure area
+// .endc
+#endif
+ // Clear pmctr_ctl in impure area
+
+#ifndef SIMOS
+ // can't assemble ???
+ update_pmctr_ctl r31, r1 // clear pmctr_ctl // r1 trashed
+#endif
+
+ ldah r14, 0xfff0(r31)
+ zap r14, 0xE0, r14 // Get Cbox IPR base
+#ifndef SIMOS
+ ldqp r31, sc_stat(r14) // Clear sc_stat and sc_addr
+ ldqp r31, ei_stat(r14)
+ ldqp r31, ei_stat(r14) // Clear ei_stat, ei_addr, bc_tag_addr, fill_syn
+#endif
+ GET_IMPURE(r13)
+ stqpc r31, 0(r13) // Clear lock_flag
+
+ mfpr r0, pt0 // get entry type
+ br r31, sys_enter_console // enter the cosole
+
+#endif /* rax_mode == 0 */
+
+
+
+
+//.if ne rax_mode
+#if rax_mode != 0
+
+ // For RAX:
+ // r0 - icsr at first, then used for cbox ipr base offset
+ // r2 - mcsr
+ // r3 - dc_mode
+ // r4 - maf_mode
+ // r5 - sc_ctl
+ // r6 - bc_ctl
+ // r7 - bc_cnfg
+ .globl sys_reset
+sys_reset:
+ mtpr r31, ev5__dtb_cm // set mbox mode to kernel
+ mtpr r31, ev5__ps // set Ibox mode to kernel - E1
+
+ mtpr r0, ev5__icsr // Load ICSR - E1
+
+ mtpr r2, ev5__mcsr
+ mfpr r8, pal_base
+
+ ldah r0, 0xfff0(r31)
+ zap r0, 0xE0, r0 // Get Cbox IPR base
+
+ mtpr r31, ev5__itb_asn // clear asn - E1
+ ldqp r19, ev5__sc_ctl(r0) // read current sc_ctl
+
+temp = <<<1@bc_ctl$v_ei_dis_err> + <1@bc_ctl$v_ei_ecc_or_parity> + <1@bc_ctl$v_corr_fill_dat>>@-1>
+ lda r20, temp(r31) // create default bc_ctl (bc disabled, errors disabled, ecc mode)
+ sll r20, 1, r20
+
+temp = 0x017441 // default bc_config
+ get_addr r21, temp, r31 // create default bc_config
+ lda r23, <1@sc_ctl_v_sc_flush>(r31) //set flag to invalidate scache in set_sc_bc_ctl
+
+// XXX bugnion pvc$jsr scbcctl, bsr=1
+ bsr r10, set_sc_bc_ctl
+ update_bc_ctl_shadow r6, r2 // initialize bc_ctl shadow// adjusted impure pointer in r2
+ store_reg1 pmctr_ctl, r31, r2, ipr=1 // clear pmctr_ctl
+ store_reg1 bc_config, r7, r2, ipr=1 // initialize bc_config shadow
+
+ mtpr r3, ev5__dc_mode // write dc_mode
+ mtpr r31, ev5__dc_flush // flush dcache
+
+ mtpr r31, ev5__exc_sum // clear exc_sum - E1
+ mtpr r31, ev5__exc_mask // clear exc_mask - E1
+
+ ldah r2, 4(r31) // For EXC_ADDR
+ mtpr r2, ev5__exc_addr // EXC_ADDR to 40000 (hex)
+
+ mtpr r31, ev5__sirr // Clear SW interrupts (for ISP)
+ mtpr r4, ev5__maf_mode // write maf_mode
+
+ mtpr r31, ev5__alt_mode // set alt_mode to kernel
+ mtpr r31, ev5__itb_ia // clear ITB - E1
+
+ lda r1, 0x1F(r31) // For IPL
+ mtpr r1, ev5__ipl // IPL to 1F
+
+ mtpr r31, ev5__hwint_clr // clear hardware interrupts
+ mtpr r31, ev5__aster // disable AST interrupts
+
+ mtpr r31, ev5__astrr // clear AST requests
+ mtpr r31, ev5__dtb_ia // clear dtb
+
+ nop
+ mtpr r31, pt_trap
+
+ srl r2, page_offset_size_bits, r9 // Start to make PTE for address 40000
+ sll r9, 32, r9
+
+ lda r9, 0x7F01(r9) // Make PTE, V set, all RE set, all but UWE set
+ nop
+
+ mtpr r9, dtb_pte // ACORE hack, load TB with 1-1 translation for address 40000
+ mtpr r2, itb_tag // ACORE hack, load TB with 1-1 translation for address 40000
+
+ mtpr r2, dtb_tag
+ mtpr r9, itb_pte
+
+ and r31, r31, r0 // clear deposited registers, note: r2 already overwritten
+ and r31, r31, r3
+
+ and r31, r31, r4
+ and r31, r31, r5
+
+ and r31, r31, r6
+ and r31, r31, r7
+
+ hw_rei //May need to be a rei_stall since
+ //we write to TB's above
+ //However, it currently works ok. (JH)
+
+
+// .endc
+#endif /*rax_mode != 0 */
+
+
+ // swppal entry
+ // r0 - pt_misc
+ // r17 - new PC
+ // r18 - new PCBB
+ // r19 - new VPTB
+sys_reset_switch:
+ or r31, 1, r9
+ sll r9, pt_misc_v_switch, r9
+ bic r0, r9, r0 // clear switch bit
+ mtpr r0, pt_misc
+
+ rpcc r1 // get cyccounter
+
+ ldqp r22, osfpcb_q_fen(r18) // get new fen/pme
+ ldlp r23, osfpcb_l_cc(r18) // get cycle counter
+ ldlp r24, osfpcb_l_asn(r18) // get new asn
+
+
+ ldqp r25, osfpcb_q_Mmptr(r18)// get new mmptr
+ sll r25, page_offset_size_bits, r25 // convert pfn to pa
+ mtpr r25, pt_ptbr // load the new mmptr
+ mtpr r18, pt_pcbb // set new pcbb
+
+ bic r17, 3, r17 // clean use pc
+ mtpr r17, exc_addr // set new pc
+ mtpr r19, mvptbr
+ mtpr r19, ivptbr
+
+ ldqp r30, osfpcb_q_Usp(r18) // get new usp
+ mtpr r30, pt_usp // save usp
+
+ sll r24, dtb_asn_v_asn, r8
+ mtpr r8, dtb_asn
+ sll r24, itb_asn_v_asn, r24
+ mtpr r24, itb_asn
+
+ mfpr r25, icsr // get current icsr
+ lda r24, 1(r31)
+ sll r24, icsr_v_fpe, r24 // 1 in icsr<fpe> position
+ bic r25, r24, r25 // clean out old fpe
+ and r22, 1, r22 // isolate new fen bit
+ sll r22, icsr_v_fpe, r22
+ or r22, r25, r25 // or in new fpe
+ mtpr r25, icsr // update ibox ipr
+
+ subl r23, r1, r1 // gen new cc offset
+ insll r1, 4, r1 // << 32
+ mtpr r1, cc // set new offset
+
+ or r31, r31, r0 // set success
+ ldqp r30, osfpcb_q_Ksp(r18) // get new ksp
+ mfpr r31, pt0 // stall
+ hw_rei_stall
+
+// .sbttl "SYS_MACHINE_CHECK - Machine check PAL"
+ ALIGN_BLOCK
+//+
+//sys$machine_check
+// A machine_check trap has occurred. The Icache has been flushed.
+//
+//-
+
+EXPORT(sys_machine_check)
+ // Need to fill up the refill buffer (32 instructions) and
+ // then flush the Icache again.
+ // Also, due to possible 2nd Cbox register file write for
+ // uncorrectable errors, no register file read or write for 7 cycles.
+
+ nop
+ mtpr r0, pt0 // Stash for scratch -- OK if Cbox overwrites r0 later
+
+ nop
+ nop
+
+ nop
+ nop
+
+ nop
+ nop
+
+ nop
+ nop
+ // 10 instructions// 5 cycles
+
+ nop
+ nop
+
+ nop
+ nop
+
+ // Register file can now be written
+ lda r0, scb_v_procmchk(r31) // SCB vector
+ mfpr r13, pt_mces // Get MCES
+ sll r0, 16, r0 // Move SCBv to correct position
+// bis r13, #<1@mces$v_mchk>, r14 // Set MCES<MCHK> bit
+ bis r13, BIT(mces_v_mchk), r14 // Set MCES<MCHK> bit
+
+
+ zap r14, 0x3C, r14 // Clear mchk_code word and SCBv word
+ mtpr r14, pt_mces
+ // 20 instructions
+
+ nop
+ or r14, r0, r14 // Insert new SCB vector
+ lda r0, mchk_c_proc_hrd_error(r31) // MCHK code
+ mfpr r12, exc_addr
+
+ sll r0, 32, r0 // Move MCHK code to correct position
+ mtpr r4, pt4
+ or r14, r0, r14 // Insert new MCHK code
+ mtpr r14, pt_misc // Store updated MCES, MCHK code, and SCBv
+
+ ldah r14, 0xfff0(r31)
+ mtpr r1, pt1 // Stash for scratch - 30 instructions
+
+ zap r14, 0xE0, r14 // Get Cbox IPR base
+ mtpr r12, pt10 // Stash exc_addr
+
+
+
+ mtpr r31, ic_flush_ctl // Second Icache flush, now it is really flushed.
+ blbs r13, sys_double_machine_check // MCHK halt if double machine check
+
+ mtpr r6, pt6
+ mtpr r5, pt5
+
+ // Look for the powerfail cases here....
+ mfpr r4, isr
+ srl r4, isr_v_pfl, r4
+ blbc r4, sys_mchk_collect_iprs // skip if no powerfail interrupt pending
+ lda r4, 0xffc4(r31) // get GBUS$MISCR address bits
+ sll r4, 24, r4 // shift to proper position
+ ldqp r4, 0(r4) // read GBUS$MISCR
+ srl r4, 5, r4 // isolate bit <5>
+ blbc r4, sys_mchk_collect_iprs // skip if already cleared
+ // No missed CFAIL mchk
+ lda r5, 0xffc7(r31) // get GBUS$SERNUM address bits
+ sll r5, 24, r5 // shift to proper position
+ lda r6, 0x40(r31) // get bit <6> mask
+ ldqp r4, 0(r5) // read GBUS$SERNUM
+ or r4, r6, r6 // set bit <6>
+ stqp r6, 0(r5) // clear GBUS$SERNUM<6>
+ mb
+ mb
+
+
+ //+
+ // Start to collect the IPRs. Common entry point for mchk flows.
+ //
+ // Current state:
+ // pt0 - saved r0
+ // pt1 - saved r1
+ // pt4 - saved r4
+ // pt5 - saved r5
+ // pt6 - saved r6
+ // pt10 - saved exc_addr
+ // pt_misc<47:32> - mchk code
+ // pt_misc<31:16> - scb vector
+ // r14 - base of Cbox IPRs in IO space
+ // r0, r1, r4, r5, r6, r12, r13, r25 - available
+ // r8, r9, r10 - available as all loads are physical
+ // MCES<mchk> is set
+ //
+ //-
+
+EXPORT(sys_mchk_collect_iprs)
+ mb // MB before reading Scache IPRs
+ mfpr r1, icperr_stat
+
+ mfpr r8, dcperr_stat
+ mtpr r31, dc_flush // Flush the Dcache
+
+ mfpr r31, pt0 // Pad Mbox instructions from dc_flush
+ mfpr r31, pt0
+ nop
+ nop
+
+ ldqp r9, sc_addr(r14) // SC_ADDR IPR
+ bis r9, r31, r31 // Touch ld to make sure it completes before
+ // read of SC_STAT
+ ldqp r10, sc_stat(r14) // SC_STAT, also unlocks SC_ADDR
+
+ ldqp r12, ei_addr(r14) // EI_ADDR IPR
+ ldqp r13, bc_tag_addr(r14) // BC_TAG_ADDR IPR
+ ldqp r0, fill_syn(r14) // FILL_SYN IPR
+ bis r12, r13, r31 // Touch lds to make sure they complete before reading EI_STAT
+ bis r0, r0, r31 // Touch lds to make sure they complete before reading EI_STAT
+ ldqp r25, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
+ ldqp r31, ei_stat(r14) // Read again to insure it is unlocked
+
+
+
+
+ //+
+ // Look for nonretryable cases
+ // In this segment:
+ // r5<0> = 1 means retryable
+ // r4, r6, and r14 are available for scratch
+ //
+ //-
+
+
+ bis r31, r31, r5 // Clear local retryable flag
+ srl r25, ei_stat_v_bc_tperr, r25 // Move EI_STAT status bits to low bits
+
+ lda r4, 1(r31)
+ sll r4, icperr_stat_v_tmr, r4
+ and r1, r4, r4 // Timeout reset
+ bne r4, sys_cpu_mchk_not_retryable
+
+ and r8, BIT(dcperr_stat_v_lock), r4 // DCache parity error locked
+ bne r4, sys_cpu_mchk_not_retryable
+
+ lda r4, 1(r31)
+ sll r4, sc_stat_v_sc_scnd_err, r4
+ and r10, r4, r4 // 2nd Scache error occurred
+ bne r4, sys_cpu_mchk_not_retryable
+
+
+ bis r31, 0xa3, r4 // EI_STAT Bcache Tag Parity Error, Bcache Tag Control
+ // Parity Error, Interface Parity Error, 2nd Error
+
+ and r25, r4, r4
+ bne r4, sys_cpu_mchk_not_retryable
+
+// bis r31, #<1@<ei_stat$v_unc_ecc_err-ei_stat$v_bc_tperr>>, r4
+ bis r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4
+ and r25, r4, r4 // Isolate the Uncorrectable Error Bit
+// bis r31, #<1@<ei_stat$v_fil_ird-ei_stat$v_bc_tperr>>, r6
+ bis r31, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r6 // Isolate the Iread bit
+ cmovne r6, 0, r4 // r4 = 0 if IRD or if No Uncorrectable Error
+ bne r4, sys_cpu_mchk_not_retryable
+
+ lda r4, 7(r31)
+ and r10, r4, r4 // Isolate the Scache Tag Parity Error bits
+ bne r4, sys_cpu_mchk_not_retryable // All Scache Tag PEs are not retryable
+
+
+ lda r4, 0x7f8(r31)
+ and r10, r4, r4 // Isolate the Scache Data Parity Error bits
+ srl r10, sc_stat_v_cbox_cmd, r6
+ and r6, 0x1f, r6 // Isolate Scache Command field
+ subq r6, 1, r6 // Scache Iread command = 1
+ cmoveq r6, 0, r4 // r4 = 0 if IRD or if No Parity Error
+ bne r4, sys_cpu_mchk_not_retryable
+
+ // Look for the system unretryable cases here....
+
+ mfpr r4, isr // mchk_interrupt pin asserted
+ srl r4, isr_v_mck, r4
+ blbs r4, sys_cpu_mchk_not_retryable
+
+
+
+ //+
+ // Look for retryable cases
+ // In this segment:
+ // r5<0> = 1 means retryable
+ // r6 - holds the mchk code
+ // r4 and r14 are available for scratch
+ //
+ //-
+
+
+ // Within the chip, the retryable cases are Istream errors
+ lda r4, 3(r31)
+ sll r4, icperr_stat_v_dpe, r4
+ and r1, r4, r4
+ cmovne r4, 1, r5 // Retryable if just Icache parity error
+
+
+ lda r4, 0x7f8(r31)
+ and r10, r4, r4 // Isolate the Scache Data Parity Error bits
+ srl r10, sc_stat_v_cbox_cmd, r14
+ and r14, 0x1f, r14 // Isolate Scache Command field
+ subq r14, 1, r14 // Scache Iread command = 1
+ cmovne r4, 1, r4 // r4 = 1 if Scache data parity error bit set
+ cmovne r14, 0, r4 // r4 = 1 if Scache PE and Iread
+ bis r4, r5, r5 // Accumulate
+
+
+ bis r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4
+ and r25, r4, r4 // Isolate the Uncorrectable Error Bit
+ and r25, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r14 // Isolate the Iread bit
+ cmovne r4, 1, r4 // r4 = 1 if uncorr error
+ cmoveq r14, 0, r4 // r4 = 1 if uncorr and Iread
+ bis r4, r5, r5 // Accumulate
+
+ mfpr r6, pt_misc
+ extwl r6, 4, r6 // Fetch mchk code
+ bic r6, 1, r6 // Clear flag from interrupt flow
+ cmovne r5, mchk_c_retryable_ird, r6 // Set mchk code
+
+
+
+ // In the system, the retryable cases are ...
+ // (code here handles beh model read NXM)
+
+#if beh_model != 0
+// .if ne beh_model
+ ldah r4, 0xC000(r31) // Get base of demon space
+ lda r4, 0x550(r4) // Add NXM demon flag offset
+
+ ldqp r4, 0(r4) // Read the demon register
+ lda r14, mchk_c_read_nxm(r31)
+ cmovlbs r4, r14, r6 // Set mchk code if read NXM
+ cmovlbs r4, 1, r4
+ bis r4, r5, r5 // Accumulate retry bit
+#endif
+
+
+ //+
+ // Write the logout frame
+ //
+ // Current state:
+ // r0 - fill_syn
+ // r1 - icperr_stat
+ // r4 - available
+ // r5<0> - retry flag
+ // r6 - mchk code
+ // r8 - dcperr_stat
+ // r9 - sc_addr
+ // r10 - sc_stat
+ // r12 - ei_addr
+ // r13 - bc_tag_addr
+ // r14 - available
+ // r25 - ei_stat (shifted)
+ // pt0 - saved r0
+ // pt1 - saved r1
+ // pt4 - saved r4
+ // pt5 - saved r5
+ // pt6 - saved r6
+ // pt10 - saved exc_addr
+ //
+ //-
+
+sys_mchk_write_logout_frame:
+ // Get base of the logout area.
+ GET_IMPURE(r14) // addr of per-cpu impure area
+ GET_ADDR(r14,pal_logout_area+mchk_mchk_base,r14)
+
+ // Write the first 2 quadwords of the logout area:
+
+ sll r5, 63, r5 // Move retry flag to bit 63
+ lda r4, mchk_size(r5) // Combine retry flag and frame size
+ stqp r4, mchk_flag(r14) // store flag/frame size
+ lda r4, mchk_sys_base(r31) // sys offset
+ sll r4, 32, r4
+ lda r4, mchk_cpu_base(r4) // cpu offset
+ stqp r4, mchk_offsets(r14) // store sys offset/cpu offset into logout frame
+
+ //+
+ // Write the mchk code to the logout area
+ // Write error IPRs already fetched to the logout area
+ // Restore some GPRs from PALtemps
+ //-
+
+ mfpr r5, pt5
+ stqp r6, mchk_mchk_code(r14)
+ mfpr r4, pt4
+ stqp r1, mchk_ic_perr_stat(r14)
+ mfpr r6, pt6
+ stqp r8, mchk_dc_perr_stat(r14)
+ mfpr r1, pt1
+ stqp r9, mchk_sc_addr(r14)
+ stqp r10, mchk_sc_stat(r14)
+ stqp r12, mchk_ei_addr(r14)
+ stqp r13, mchk_bc_tag_addr(r14)
+ stqp r0, mchk_fill_syn(r14)
+ mfpr r0, pt0
+ sll r25, ei_stat_v_bc_tperr, r25 // Move EI_STAT status bits back to expected position
+ // retrieve lower 28 bits again from ei_stat and restore before storing to logout frame
+ ldah r13, 0xfff0(r31)
+ zapnot r13, 0x1f, r13
+ ldqp r13, ei_stat(r13)
+ sll r13, 64-ei_stat_v_bc_tperr, r13
+ srl r13, 64-ei_stat_v_bc_tperr, r13
+ or r25, r13, r25
+ stqp r25, mchk_ei_stat(r14)
+
+
+
+
+ //+
+ // complete the CPU-specific part of the logout frame
+ //-
+
+#ifndef SIMOS
+ // cant' assemble.Where is the macro ?
+ mchk_logout mm_stat
+ mchk_logout va // Unlocks VA and MM_STAT
+ mchk_logout isr
+ mchk_logout icsr
+ mchk_logout pal_base
+ mchk_logout exc_mask
+ mchk_logout exc_sum
+#endif
+
+ ldah r13, 0xfff0(r31)
+ zap r13, 0xE0, r13 // Get Cbox IPR base
+ ldqp r13, ld_lock(r13) // Get ld_lock IPR
+ stqp r13, mchk_ld_lock(r14) // and stash it in the frame
+
+ //+
+ // complete the PAL-specific part of the logout frame
+ //-
+#ifdef vms
+ t = 0
+ .repeat 24
+ pt_mchk_logout \t
+ t = t + 1
+ .endr
+#endif
+#ifndef SIMOS
+ //can't assemble ?
+ pt_mchk_logout 0
+ pt_mchk_logout 1
+ pt_mchk_logout 2
+ pt_mchk_logout 3
+ pt_mchk_logout 4
+ pt_mchk_logout 5
+ pt_mchk_logout 6
+ pt_mchk_logout 7
+ pt_mchk_logout 8
+ pt_mchk_logout 9
+ pt_mchk_logout 10
+ pt_mchk_logout 11
+ pt_mchk_logout 12
+ pt_mchk_logout 13
+ pt_mchk_logout 14
+ pt_mchk_logout 15
+ pt_mchk_logout 16
+ pt_mchk_logout 17
+ pt_mchk_logout 18
+ pt_mchk_logout 19
+ pt_mchk_logout 20
+ pt_mchk_logout 21
+ pt_mchk_logout 22
+ pt_mchk_logout 23
+#endif
+
+
+ //+
+ // Log system specific info here
+ //-
+
+#if alpha_fw != 0
+// .if ne alpha_fw
+storeTLEP_:
+ lda r13, 0xffc4(r31) // Get GBUS$MISCR address
+ sll r13, 24, r13
+ ldqp r13, 0(r13) // Read GBUS$MISCR
+ sll r13, 16, r13 // shift up to proper field
+ mfpr r8, pt_whami // get our node id
+ extbl r8, 1, r8 // shift to bit 0
+ or r13, r8, r13 // merge MISCR and WHAMI
+ stlp r13, mchk$gbus(r14) // write to logout area
+ srl r8, 1, r8 // shift off cpu number
+
+ Get_TLSB_Node_Address r8,r13 // compute our nodespace address
+
+ OSFmchk_TLEPstore tldev, tlsb=1
+ OSFmchk_TLEPstore tlber, tlsb=1, clr=1
+ OSFmchk_TLEPstore tlcnr, tlsb=1
+ OSFmchk_TLEPstore tlvid, tlsb=1
+ OSFmchk_TLEPstore tlesr0, tlsb=1, clr=1
+ OSFmchk_TLEPstore tlesr1, tlsb=1, clr=1
+ OSFmchk_TLEPstore tlesr2, tlsb=1, clr=1
+ OSFmchk_TLEPstore tlesr3, tlsb=1, clr=1
+ OSFmchk_TLEPstore tlmodconfig
+ OSFmchk_TLEPstore tlepaerr, clr=1
+ OSFmchk_TLEPstore tlepderr, clr=1
+ OSFmchk_TLEPstore tlepmerr, clr=1
+ OSFmchk_TLEPstore tlintrmask0
+ OSFmchk_TLEPstore tlintrmask1
+ OSFmchk_TLEPstore tlintrsum0
+ OSFmchk_TLEPstore tlintrsum1
+ OSFmchk_TLEPstore tlep_vmg
+// .endc
+#endif /*alpha_fw != 0 */
+ // Unlock IPRs
+ lda r8, (BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31)
+ mtpr r8, dcperr_stat // Clear Dcache parity error status
+
+ lda r8, (BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(r31)
+ mtpr r8, icperr_stat // Clear Icache parity error & timeout status
+
+1: ldqp r8, mchk_ic_perr_stat(r14) // get ICPERR_STAT value
+ GET_ADDR(r0,0x1800,r31) // get ICPERR_STAT value
+ and r0, r8, r0 // compare
+ beq r0, 2f // check next case if nothing set
+ lda r0, mchk_c_retryable_ird(r31) // set new MCHK code
+ br r31, do_670 // setup new vector
+
+2: ldqp r8, mchk_dc_perr_stat(r14) // get DCPERR_STAT value
+ GET_ADDR(r0,0x3f,r31) // get DCPERR_STAT value
+ and r0, r8, r0 // compare
+ beq r0, 3f // check next case if nothing set
+ lda r0, mchk_c_dcperr(r31) // set new MCHK code
+ br r31, do_670 // setup new vector
+
+3: ldqp r8, mchk_sc_stat(r14) // get SC_STAT value
+ GET_ADDR(r0,0x107ff,r31) // get SC_STAT value
+ and r0, r8, r0 // compare
+ beq r0, 4f // check next case if nothing set
+ lda r0, mchk_c_scperr(r31) // set new MCHK code
+ br r31, do_670 // setup new vector
+
+4: ldqp r8, mchk_ei_stat(r14) // get EI_STAT value
+ GET_ADDR(r0,0x30000000,r31) // get EI_STAT value
+ and r0, r8, r0 // compare
+ beq r0, 5f // check next case if nothing set
+ lda r0, mchk_c_bcperr(r31) // set new MCHK code
+ br r31, do_670 // setup new vector
+
+5: ldlp r8, mchk_tlber(r14) // get TLBER value
+ GET_ADDR(r0,0xfe01,r31) // get high TLBER mask value
+ sll r0, 16, r0 // shift into proper position
+ GET_ADDR(r1,0x03ff,r31) // get low TLBER mask value
+ or r0, r1, r0 // merge mask values
+ and r0, r8, r0 // compare
+ beq r0, 6f // check next case if nothing set
+ GET_ADDR(r0, 0xfff0, r31) // set new MCHK code
+ br r31, do_660 // setup new vector
+
+6: ldlp r8, mchk_tlepaerr(r14) // get TLEPAERR value
+ GET_ADDR(r0,0xff7f,r31) // get TLEPAERR mask value
+ and r0, r8, r0 // compare
+ beq r0, 7f // check next case if nothing set
+ GET_ADDR(r0, 0xfffa, r31) // set new MCHK code
+ br r31, do_660 // setup new vector
+
+7: ldlp r8, mchk_tlepderr(r14) // get TLEPDERR value
+ GET_ADDR(r0,0x7,r31) // get TLEPDERR mask value
+ and r0, r8, r0 // compare
+ beq r0, 8f // check next case if nothing set
+ GET_ADDR(r0, 0xfffb, r31) // set new MCHK code
+ br r31, do_660 // setup new vector
+
+8: ldlp r8, mchk_tlepmerr(r14) // get TLEPMERR value
+ GET_ADDR(r0,0x3f,r31) // get TLEPMERR mask value
+ and r0, r8, r0 // compare
+ beq r0, 9f // check next case if nothing set
+ GET_ADDR(r0, 0xfffc, r31) // set new MCHK code
+ br r31, do_660 // setup new vector
+
+9: ldqp r8, mchk_ei_stat(r14) // get EI_STAT value
+ GET_ADDR(r0,0xb,r31) // get EI_STAT mask value
+ sll r0, 32, r0 // shift to upper lw
+ and r0, r8, r0 // compare
+ beq r0, 1f // check next case if nothing set
+ GET_ADDR(r0,0xfffd,r31) // set new MCHK code
+ br r31, do_660 // setup new vector
+
+1: ldlp r8, mchk_tlepaerr(r14) // get TLEPAERR value
+ GET_ADDR(r0,0x80,r31) // get TLEPAERR mask value
+ and r0, r8, r0 // compare
+ beq r0, cont_logout_frame // check next case if nothing set
+ GET_ADDR(r0, 0xfffe, r31) // set new MCHK code
+ br r31, do_660 // setup new vector
+
+do_670: lda r8, scb_v_procmchk(r31) // SCB vector
+ br r31, do_6x0_cont
+do_660: lda r8, scb_v_sysmchk(r31) // SCB vector
+do_6x0_cont:
+ sll r8, 16, r8 // shift to proper position
+ mfpr r1, pt_misc // fetch current pt_misc
+ GET_ADDR(r4,0xffff, r31) // mask for vector field
+ sll r4, 16, r4 // shift to proper position
+ bic r1, r4, r1 // clear out old vector field
+ or r1, r8, r1 // merge in new vector
+ mtpr r1, pt_misc // save new vector field
+ stlp r0, mchk_mchk_code(r14) // save new mchk code
+
+cont_logout_frame:
+ // Restore some GPRs from PALtemps
+ mfpr r0, pt0
+ mfpr r1, pt1
+ mfpr r4, pt4
+
+ mfpr r12, pt10 // fetch original PC
+ blbs r12, sys_machine_check_while_in_pal // MCHK halt if machine check in pal
+
+//XXXbugnion pvc_jsr armc, bsr=1
+ bsr r12, sys_arith_and_mchk // go check for and deal with arith trap
+
+ mtpr r31, exc_sum // Clear Exception Summary
+
+ mfpr r25, pt10 // write exc_addr after arith_and_mchk to pickup new pc
+ stqp r25, mchk_exc_addr(r14)
+
+ //+
+ // Set up the km trap
+ //-
+
+
+sys_post_mchk_trap:
+ mfpr r25, pt_misc // Check for flag from mchk interrupt
+ extwl r25, 4, r25
+ blbs r25, sys_mchk_stack_done // Stack from already pushed if from interrupt flow
+
+ bis r14, r31, r12 // stash pointer to logout area
+ mfpr r14, pt10 // get exc_addr
+
+ sll r11, 63-3, r25 // get mode to msb
+ bge r25, 3f
+
+ mtpr r31, dtb_cm
+ mtpr r31, ev5__ps
+
+ mtpr r30, pt_usp // save user stack
+ mfpr r30, pt_ksp
+
+3:
+ lda sp, 0-osfsf_c_size(sp) // allocate stack space
+ nop
+
+ stq r18, osfsf_a2(sp) // a2
+ stq r11, osfsf_ps(sp) // save ps
+
+ stq r14, osfsf_pc(sp) // save pc
+ mfpr r25, pt_entint // get the VA of the interrupt routine
+
+ stq r16, osfsf_a0(sp) // a0
+ lda r16, osfint_c_mchk(r31) // flag as mchk in a0
+
+ stq r17, osfsf_a1(sp) // a1
+ mfpr r17, pt_misc // get vector
+
+ stq r29, osfsf_gp(sp) // old gp
+ mtpr r25, exc_addr //
+
+ or r31, 7, r11 // get new ps (km, high ipl)
+ subq r31, 1, r18 // get a -1
+
+ extwl r17, 2, r17 // a1 <- interrupt vector
+ bis r31, ipl_machine_check, r25
+
+ mtpr r25, ipl // Set internal ipl
+ srl r18, 42, r18 // shift off low bits of kseg addr
+
+ sll r18, 42, r18 // shift back into position
+ mfpr r29, pt_kgp // get the kern r29
+
+ or r12, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address
+ hw_rei_spe // out to interrupt dispatch routine
+
+
+ //+
+ // The stack is pushed. Load up a0,a1,a2 and vector via entInt
+ //
+ //-
+ ALIGN_BRANCH
+sys_mchk_stack_done:
+ lda r16, osfint_c_mchk(r31) // flag as mchk/crd in a0
+ lda r17, scb_v_sysmchk(r31) // a1 <- interrupt vector
+
+ subq r31, 1, r18 // get a -1
+ mfpr r25, pt_entInt
+
+ srl r18, 42, r18 // shift off low bits of kseg addr
+ mtpr r25, exc_addr // load interrupt vector
+
+ sll r18, 42, r18 // shift back into position
+ or r14, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address
+
+ hw_rei_spe // done
+
+
+ ALIGN_BRANCH
+sys_cpu_mchk_not_retryable:
+ mfpr r6, pt_misc
+ extwl r6, 4, r6 // Fetch mchk code
+ br r31, sys_mchk_write_logout_frame //
+
+
+
+//+
+//sys$double_machine_check - a machine check was started, but MCES<MCHK> was
+// already set. We will now double machine check halt.
+//
+// pt0 - old R0
+//
+//+
+
+EXPORT(sys_double_machine_check)
+#ifndef SIMOS
+ pvc$jsr updpcb, bsr=1
+ bsr r0, pal_update_pcb // update the pcb
+#endif
+ lda r0, hlt_c_dbl_mchk(r31)
+ br r31, sys_enter_console
+
+//+
+//sys$machine_check_while_in_pal - a machine check was started, exc_addr points to
+// a PAL PC. We will now machine check halt.
+//
+// pt0 - old R0
+//
+//+
+sys_machine_check_while_in_pal:
+ stqp r12, mchk_exc_addr(r14) // exc_addr has not yet been written
+
+#ifndef SIMOS
+ pvc$jsr updpcb, bsr=1
+ bsr r0, pal_update_pcb // update the pcb
+#endif
+ lda r0, hlt_c_mchk_from_pal(r31)
+ br r31, sys_enter_console
+
+
+//ARITH and MCHK
+// Check for arithmetic errors and build trap frame,
+// but don't post the trap.
+// on entry:
+// pt10 - exc_addr
+// r12 - return address
+// r14 - logout frame pointer
+// r13 - available
+// r8,r9,r10 - available except across stq's
+// pt0,1,6 - available
+//
+// on exit:
+// pt10 - new exc_addr
+// r17 = exc_mask
+// r16 = exc_sum
+// r14 - logout frame pointer
+//
+ ALIGN_BRANCH
+sys_arith_and_mchk:
+ mfpr r13, ev5__exc_sum
+ srl r13, exc_sum_v_swc, r13
+ bne r13, handle_arith_and_mchk
+
+// XXX bugnion pvc$jsr armc, bsr=1, dest=1
+ ret r31, (r12) // return if no outstanding arithmetic error
+
+handle_arith_and_mchk:
+ mtpr r31, ev5__dtb_cm // Set Mbox current mode to kernel -
+ // no virt ref for next 2 cycles
+ mtpr r14, pt0
+
+ mtpr r1, pt1 // get a scratch reg
+ and r11, osfps_m_mode, r1 // get mode bit
+
+ bis r11, r31, r25 // save ps
+ beq r1, 1f // if zero we are in kern now
+
+ bis r31, r31, r25 // set the new ps
+ mtpr r30, pt_usp // save user stack
+
+ mfpr r30, pt_ksp // get kern stack
+1:
+ mfpr r14, exc_addr // get pc into r14 in case stack writes fault
+
+ lda sp, 0-osfsf_c_size(sp) // allocate stack space
+ mtpr r31, ev5__ps // Set Ibox current mode to kernel
+
+ mfpr r1, pt_entArith
+ stq r14, osfsf_pc(sp) // save pc
+
+ stq r17, osfsf_a1(sp)
+ mfpr r17, ev5__exc_mask // Get exception register mask IPR - no mtpr exc_sum in next cycle
+
+ stq r29, osfsf_gp(sp)
+ stq r16, osfsf_a0(sp) // save regs
+
+ bis r13, r31, r16 // move exc_sum to r16
+ stq r18, osfsf_a2(sp)
+
+ stq r11, osfsf_ps(sp) // save ps
+ mfpr r29, pt_kgp // get the kern gp
+
+ mfpr r14, pt0 // restore logout frame pointer from pt0
+ bis r25, r31, r11 // set new ps
+
+ mtpr r1, pt10 // Set new PC
+ mfpr r1, pt1
+
+// XXX bugnion pvc$jsr armc, bsr=1, dest=1
+ ret r31, (r12) // return if no outstanding arithmetic error
+
+
+
+// .sbttl "SYS$ENTER_CONSOLE - Common PALcode for ENTERING console"
+
+ ALIGN_BLOCK
+
+// SYS$enter_console
+//
+// Entry:
+// Entered when PAL wants to enter the console.
+// usually as the result of a HALT instruction or button,
+// or catastrophic error.
+//
+// Regs on entry...
+//
+// R0 = halt code
+// pt0 <- r0
+//
+// Function:
+//
+// Save all readable machine state, and "call" the console
+//
+// Returns:
+//
+//
+// Notes:
+//
+// In these routines, once the save state routine has been executed,
+// the remainder of the registers become scratchable, as the only
+// "valid" copy of them is the "saved" copy.
+//
+// Any registers or PTs that are modified before calling the save
+// routine will have there data lost. The code below will save all
+// state, but will loose pt 0,4,5.
+//
+//-
+
+EXPORT(sys_enter_console)
+ mtpr r1, pt4
+ mtpr r3, pt5
+#ifdef SIMOS
+ subq r31, 1, r1
+ sll r1, 42, r1
+ ldah r1, 1(r1)
+#else /* SIMOS */
+ lda r3, pal_enter_console_ptr(r31) //find stored vector
+ ldqp r1, 0(r3)
+#endif /* SIMOS */
+
+#ifdef SIMOS
+ /* taken from scrmax, seems like the obvious thing to do */
+ mtpr r1, exc_addr
+ mfpr r1, pt4
+ mfpr r3, pt5
+ STALL
+ STALL
+ hw_rei_stall
+#else
+ pvc$violate 1007
+ jmp r31, (r1) // off to common routine
+#endif
+
+
+// .sbttl "SYS$EXIT_CONSOLE - Common PALcode for ENTERING console"
+//+
+// sys$exit_console
+//
+// Entry:
+// Entered when console wants to reenter PAL.
+// usually as the result of a CONTINUE.
+//
+//
+// Regs' on entry...
+//
+//
+// Function:
+//
+// Restore all readable machine state, and return to user code.
+//
+//
+//
+//-
+ ALIGN_BLOCK
+sys_exit_console:
+ //Disable physical mode:
+#if enable_physical_console != 0
+// .if ne enable_physical_console
+ mfpr r25, pt_ptbr
+ bic r25, 1, r25 // clear physical console flag
+ mtpr r25, pt_ptbr
+#endif
+
+ GET_IMPURE(r1)
+
+ // clear lock and intr_flags prior to leaving console
+ rc r31 // clear intr_flag
+ // lock flag cleared by restore_state
+#ifndef SIMOS
+ pvc$jsr rststa, bsr=1
+ bsr r3, pal_restore_state // go restore all state
+ // note, R1 and R3 are NOT restored
+ // by restore_state.
+#endif
+ // TB's have been flushed
+
+ ldqp r3, (cns_gpr+(8*3))(r1) // restore r3
+ ldqp r1, (cns_gpr+8)(r1) // restore r1
+ hw_rei_stall // back to user
+
+#if turbo_pcia_intr_fix != 0
+// .if ne turbo_pcia_intr_fix
+check_pcia_intr:
+ mfpr r14, pt14 // fetch saved PCIA interrupt info
+ beq r14, check_done // don't bother checking if no info
+ mfpr r13, ipl // check the current IPL
+ bic r13, 3, r25 // isolate ipl<5:2>
+ cmpeq r25, 0x14, r25 // is it an I/O interrupt?
+ beq r25, check_done // no, return
+ and r13, 3, r25 // get I/O interrupt index
+ extbl r14, r25, r13 // extract info for this interrupt
+ beq r13, check_done // if no info, return
+
+ // This is an RTI from a PCIA interrupt
+ lda r12, 1(r31) // get initial bit mask
+ sll r12, r25, r25 // shift to select interrupt index
+ zap r14, r25, r14 // clear out info from this interrupt
+ mtpr r14, pt14 // and save it
+
+ and r13, 3, r25 // isolate HPC field
+ subq r25, 1, r25 // subtract 1 to get HPC number
+ srl r13, 2, r13 // generate base register address
+ sll r13, 6, r13 // get slot/hose address bits
+ lda r13, 0x38(r13) // insert other high bits
+ sll r13, 28, r13 // shift high bits into position
+
+ // Read the IPROGx register
+ sll r25, 21, r14 // HPC address bit position
+ or r13, r14, r14 // add in upper bits
+ lda r14, 0x400(r14) // add in lower bits
+ ldqp r14, 0(r14) // read IPROG
+ srl r14, 4, r12 // check the In Progress bit
+ blbc r12, 1f // skip if none in progress
+ and r14, 0xf, r14 // isolate interrupt source
+ lda r12, 1(r31) // make initial mask
+ sll r12, r14, r14 // shift to make new intr source mask
+ br r31, 2f
+ // Write the SMPLIRQx register
+1: or r31, r31, r14 // default interrupt source mask
+2: GET_ADDR(r12, 0xffff, r31) // default SMPLIRQx data
+ bic r12, r14, r12 // clear any interrupts in progres
+//orig lda r14, <0xbffc@-2>(r31) // get register address bits
+ lda r14,(0xbffc>>2)(r31)
+
+ sll r14, 10, r14 // shift into position
+ or r14, r13, r14 // add in upper bits
+ sll r25, 8, r25 // shift HPC number into position
+ or r14, r25, r14 // add in lower bits
+ stqp r12, 0(r14) // write SMPLIRQx register
+ mb
+ ldqp r12, 0(r14) // read it back
+ bis r12, r12, r12 // touch register to insure completion
+
+check_done: // do these now and return
+ lda r25, osfsf_c_size(sp) // get updated sp
+ bis r25, r31, r14 // touch r14,r25 to stall mf exc_addr
+ br r31, pcia_check_return
+#endif
+
+
+// .sbttl KLUDGE_INITIAL_PCBB - PCB for Boot use only
+
+ ALIGN_128
+
+kludge_initial_pcbb: // PCB is 128 bytes long
+// .repeat 16
+// .quad 0
+// .endr
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+// .sbttl "SET_SC_BC_CTL subroutine"
+//
+// Subroutine to set the SC_CTL, BC_CONFIG, and BC_CTL registers and flush the Scache
+// There must be no outstanding memory references -- istream or dstream -- when
+// these registers are written. EV5 prefetcher is difficult to turn off. So,
+// this routine needs to be exactly 32 instructions long// the final jmp must
+// be in the last octaword of a page (prefetcher doesn't go across page)
+//
+//
+// Register expecations:
+// r0 base address of CBOX iprs
+// r5 value to set sc_ctl to (flush bit is added in)
+// r6 value to set bc_ctl to
+// r7 value to set bc_config to
+// r10 return address
+// r19 old sc_ctl value
+// r20 old value of bc_ctl
+// r21 old value of bc_config
+// r23 flush scache flag
+// Register usage:
+// r17 sc_ctl with flush bit cleared
+// r22 loop address
+//
+//
+#ifndef SIMOS
+ align_page <32*4> // puts start of routine at next page boundary minus 32 longwords.
+#endif
+
+set_sc_bc_ctl:
+
+#ifndef SIMOS
+ br r22, sc_ctl_loop //this branch must be in the same 4 instruction block as it's dest
+sc_ctl_loop:
+// XXX bugnion pvc$jsr scloop, dest=1
+ mb
+ mb
+
+ bis r5, r23, r5 //r5 <- same sc_ctl with flush bit set (if flag set in r23)
+
+ stqp r19, ev5__sc_ctl(r0) // write sc_ctl
+ stqp r20, ev5__bc_ctl(r0) // write bc_ctl
+ bis r31, r6, r20 // update r20 with new bc_ctl for 2nd time through loop
+ stqp r21, bc_config(r0) // write bc_config register
+ bis r31, r7, r21 // update r21 with new bc_config for 2nd time through loop
+
+ bic r19, BIT(sc_ctl_v_sc_flush), r17 //r17 <- same sc_ctl without flush bit set
+ //NOTE: only works because flush bit is in lower 16 bits
+
+ wmb // don't merge with other writes
+ stqp r17, ev5__sc_ctl(r0) // write sc_ctl without flush bit
+ ldqp r17, ev5__sc_ctl(r0) // read sc_ctl
+ bis r17, r17, r17 // stall until the data comes back
+ bis r31, r5, r19 // update r19 with new sc_ctl for 2nd time through loop
+
+ // fill with requisite number of nops (unops ok) to make exactly 32 instructions in loop
+ t = 0
+ .repeat 15
+ unop
+ t = t + 1
+ .endr
+ $opdef mnemonic= myjmp, -
+ format= <custom=iregister, iregister, branch_offset>, -
+ encoding= <26:31=0x1A, 21:25=%OP1,16:20=%OP2,14:15=0x00,0:13=%op3>
+
+// XXXbugnion pvc$jsr scloop
+ myjmp r22,r22,sc_ctl_loop // first time, jump to sc_ctl_loop (hint will cause prefetcher to go to loop instead
+ // of straight) // r22 gets sc_ctl_done
+ // 2nd time, code continues at sc_ctl_done (I hope)
+sc_ctl_done:
+// XXX bugnion pvc$jsr scloop, dest=1
+// XXX bugnion pvc$jsr scbcctl
+#endif /*SIMOS*/
+ ret r31, (r10) // return to where we came from
+
+
+.end
+
+
+
+