You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2894 lines
101 KiB
2894 lines
101 KiB
//++
|
|
//
|
|
// Module Name:
|
|
// trap.s
|
|
//
|
|
// Abstract:
|
|
// Low level interruption handlers
|
|
//
|
|
// Author:
|
|
// Bernard Lint 12-Jun-1995
|
|
//
|
|
// Environment:
|
|
// Kernel mode only
|
|
//
|
|
// Revision History:
|
|
//
|
|
//
|
|
// Open Design Issues:
|
|
//
|
|
// 1. Optimizations for more than 2-way parallelism when
|
|
// regsiters available.
|
|
//--
|
|
|
|
#include "ksia64.h"
|
|
|
|
.file "trap.s"
|
|
|
|
//
|
|
// Globals imported:
|
|
//
|
|
|
|
.global BdPcr
|
|
|
|
PublicFunction(BdSetMovlImmediate)
|
|
PublicFunction(BdInstallVectors)
|
|
PublicFunction(BdTrap)
|
|
PublicFunction(BdOtherBreakException)
|
|
PublicFunction(BdSingleStep)
|
|
PublicFunction(BdIvtStart)
|
|
PublicFunction(BdIvtEnd)
|
|
PublicFunction(memcpy)
|
|
|
|
//
|
|
// Register aliases used throughout the entire module
|
|
//
|
|
|
|
//
|
|
// Banked general registers
|
|
//
|
|
|
|
//
|
|
// Register aliases used throughout the entire module
|
|
//
|
|
|
|
//
|
|
// Banked general registers
|
|
//
|
|
|
|
//
|
|
// Register aliases used throughout the entire module
|
|
//
|
|
|
|
//
|
|
// Banked general registers
|
|
//
|
|
// h16-h23 can only be used when psr.ic=1.
|
|
//
|
|
// h24-h31 can only be used when psr.ic=0 (these are reserved for tlb
|
|
// and pal/machine check handlers when psr.ic=1).
|
|
//
|
|
|
|
//
|
|
// Shown below are aliases of bank 0 registers used in the low level handlers
|
|
// by macros ALLOCATE_TRAP_FRAME, SAVE_INTERRUPTION_RESOURCES, and
|
|
// NORMAL_KERNEL_EXIT. When the code in the macros are changes, these
|
|
// register aliases must be reviewed.
|
|
//
|
|
|
|
rHIPSR = h16
|
|
rHpT2 = h16
|
|
|
|
rHIIPA = h17
|
|
rHRSC = h17
|
|
rHDfhPFS = h17 // used to preserve pfs in BdDisabledFpRegisterVector
|
|
|
|
rHIIP = h18
|
|
rHFPSR = h18
|
|
|
|
rHOldPreds = h19
|
|
rHBrp = h19
|
|
rHCSD = h19
|
|
|
|
rHIFS = h20
|
|
rHPFS = h20
|
|
rHBSP = h20
|
|
|
|
rHISR = h21
|
|
rHUNAT = h21
|
|
rHpT3 = h21
|
|
|
|
rHSp = h22
|
|
rHDfhBrp = h22 // used to preserve brp in BdDisabledFpRegisterVector
|
|
rHpT4 = h22
|
|
|
|
rHpT1 = h23
|
|
|
|
rHIFA = h24
|
|
rTH3 = h24
|
|
|
|
rHHandler = h25
|
|
rTH1 = h26
|
|
rTH2 = h27
|
|
rHIIM = h28
|
|
rHEPCVa = h29
|
|
|
|
rHEPCVa2 = h30
|
|
rPanicCode = h30
|
|
|
|
//
|
|
// General registers used through out module
|
|
//
|
|
|
|
pApc = ps0 // User Apc Pending
|
|
pUser = ps1 // mode on entry was user
|
|
pKrnl = ps2 // mode on entry was kernel
|
|
pUstk = ps3
|
|
pKstk = ps4
|
|
pEM = ps5 // EM ISA on kernel entry
|
|
pIA = ps6 // X86 ISA on kernel entry
|
|
|
|
//
|
|
// Kernel registers used through out module
|
|
//
|
|
rkHandler = k6 // specific exception handler
|
|
|
|
|
|
|
|
|
|
//
|
|
// Macro definitions for this module only
|
|
//
|
|
|
|
//
|
|
// Define vector/exception entry/exit macros.
|
|
// N.B. All HANDLER_ENTRY functions go into .nsc section with
|
|
// BdNormalSystemCall being the first.
|
|
//
|
|
|
|
#define HANDLER_ENTRY(Name) \
|
|
.##global Name; \
|
|
.##proc Name; \
|
|
Name::
|
|
|
|
#define HANDLER_ENTRY_EX(Name, Handler) \
|
|
.##global Name; \
|
|
.##proc Name; \
|
|
.##type Handler, @function; \
|
|
.##personality Handler; \
|
|
Name::
|
|
|
|
#define VECTOR_ENTRY(Offset, Name, Extra0) \
|
|
.##org Offset; \
|
|
.##global Name; \
|
|
.##proc Name; \
|
|
Name::
|
|
|
|
#define VECTOR_EXIT(Name) \
|
|
.##endp Name
|
|
|
|
#define HANDLER_EXIT(Name) \
|
|
.##endp Name
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// IO_END_OF_INTERRUPT(rVector,rT1,rT2,pEOI)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// HalEOITable Entry corresponding to the vectorNo is tested.
|
|
// If the entry is nonzero, then vectorNo is stored to the location
|
|
// specified in the entry. If the entry is zero, return.
|
|
//
|
|
// Arguements:
|
|
//
|
|
//
|
|
// Notes:
|
|
//
|
|
// MS preprocessor requires /* */ style comments
|
|
//
|
|
//--
|
|
|
|
#define IO_END_OF_INTERRUPT(rVector,rT1,rT2,pEOI) ;\
|
|
add rT1 = @gprel(__imp_HalEOITable),gp ;\
|
|
;; ;\
|
|
ld8 rT1 = [rT1] ;\
|
|
;; ;\
|
|
shladd rT2 = rVector,3,rT1 ;\
|
|
;; ;\
|
|
ld8 rT1 = [rT2] ;\
|
|
;; ;\
|
|
cmp.ne pEOI = zero, rT1 ;\
|
|
;; ;\
|
|
(pEOI) st4.rel [rT1] = rVector
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// VECTOR_CALL_HANDLER(Handler, SpecificHandler)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common code for transfer to heavyweight handlers from
|
|
// interruption vectors. Put RSE in store intensive mode,
|
|
// cover current frame and call handler.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Handler: First level handler for this vector
|
|
// SpecificHandler: Specific handler to be called by the generic
|
|
// exception handler.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Notes:
|
|
// Uses just the kernel banked registers (h16-h31)
|
|
//
|
|
// MS preprocessor requires /* */ style comments
|
|
//--
|
|
|
|
|
|
#define VECTOR_CALL_HANDLER(Handler,SpecificHandler) ;\
|
|
mov rHIFA = cr##.##ifa ;\
|
|
movl rTH1 = BdPcr+PcSavedIFA ;\
|
|
;; ;\
|
|
;\
|
|
st8 [rTH1] = rHIFA ;\
|
|
movl rHHandler = SpecificHandler ;\
|
|
br##.##sptk Handler ;\
|
|
;;
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// ALLOCATE_TRAP_FRAME
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common code for allocating trap frame on kernel entry for heavyweight
|
|
// handler.
|
|
//
|
|
// On entry:
|
|
//
|
|
// On exit: sp -> trap frame; any instruction that depends on sp must be
|
|
// placed in the new instruction group. Interruption resources
|
|
// ipsr, iipa, iip, predicates, isr, sp, ifs are captured in
|
|
// seven of the banked registers h16-23. The last one is used
|
|
// by SAVE_INTERRUPTION_STATE as a pointer to save these resources
|
|
// in the trap frame.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Notes:
|
|
// Uses just the kernel banked registers (h16-h31)
|
|
//
|
|
// MS preprocessor requires /* */ style comments below
|
|
//--
|
|
|
|
#define ALLOCATE_TRAP_FRAME ;\
|
|
;\
|
|
pOverflow = pt2 ;\
|
|
;\
|
|
mov rHIPSR = cr##.##ipsr ;\
|
|
mov rHIIP = cr##.##iip ;\
|
|
cover /* cover and save IFS */;\
|
|
;; ;\
|
|
;\
|
|
mov rHIIPA = cr##.##iipa ;\
|
|
movl rTH2 = MM_EPC_VA ;\
|
|
;\
|
|
mov rTH3 = ar##.##bsp ;\
|
|
mov rHOldPreds = pr ;\
|
|
;; ;\
|
|
;\
|
|
mov rHIFS = cr##.##ifs ;\
|
|
add rHEPCVa = 0x30, rTH2 ;\
|
|
;\
|
|
mov rHISR = cr##.##isr ;\
|
|
movl rTH2 = BdPcr+PcInitialStack ;\
|
|
;\
|
|
tbit##.##z pEM, pIA = rHIPSR, PSR_IS /* set instr set */;\
|
|
extr##.##u rTH1 = rHIPSR, PSR_CPL, PSR_CPL_LEN /* get mode */;\
|
|
mov rHSp = sp ;\
|
|
;; ;\
|
|
;\
|
|
ssm (1 << PSR_IC) | (1 << PSR_DFH) | (1 << PSR_AC) ;\
|
|
cmp4##.##eq pKrnl, pUser = PL_KERNEL, rTH1 /* set mode pred */;\
|
|
cmp4##.##eq pKstk, pUstk = PL_KERNEL, rTH1 /* set stack pred */;\
|
|
;; ;\
|
|
;\
|
|
.pred.rel "mutex",pUstk,pKstk ;\
|
|
add sp = -TrapFrameLength, sp /* allocate TF */;\
|
|
;; ;\
|
|
add rHpT1 = TrStIPSR, sp ;\
|
|
;;
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// SAVE_INTERRUPTION_STATE(Label)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common code for saving interruption state on entry to a heavyweight
|
|
// handler.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Label: label for branching around BSP switch
|
|
//
|
|
// On entry:
|
|
//
|
|
// sp -> trap frame
|
|
//
|
|
// On exit:
|
|
//
|
|
// Static registers gp, teb, sp, fpsr spilled into the trap frame.
|
|
// Registers gp, teb, fpsr are set up for kernel mode execution.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Notes:
|
|
//
|
|
// Interruption resources already captured in bank 0 registers h16-h23.
|
|
// It's safe to take data TLB fault when saving them into the trap
|
|
// frame because kernel stack is always resident in memory. This macro
|
|
// is carefully constructed to save the bank registers' contents in
|
|
// the trap frame and reuse them to capture other register states as
|
|
// soon as they are available. Until we have a virtual register
|
|
// allocation scheme in place, the bank 0 register aliases defined at
|
|
// the beginning of the file must be updated when this macro is modified.
|
|
//
|
|
// MS preprocessor requires /* */ style comments below
|
|
//--
|
|
|
|
|
|
#define SAVE_INTERRUPTION_STATE(Label) ;\
|
|
;\
|
|
/* Save interruption resources in trap frame */ ;\
|
|
;\
|
|
;\
|
|
srlz##.##i /* I serialize required */;\
|
|
st8 [rHpT1] = rHIPSR, TrStISR-TrStIPSR /* save IPSR */;\
|
|
add rHpT2 = TrPreds, sp /* -> Preds */;\
|
|
;; ;\
|
|
;\
|
|
st8 [rHpT1] = rHISR, TrStIIP-TrStISR /* save ISR */;\
|
|
st8 [rHpT2] = rHOldPreds, TrBrRp-TrPreds ;\
|
|
;; ;\
|
|
;\
|
|
mov rHUNAT = ar##.##unat ;\
|
|
st8 [rHpT1] = rHIIP, TrStIFS-TrStIIP /* save IIP */;\
|
|
mov rHBrp = brp ;\
|
|
;; ;\
|
|
;\
|
|
mov rHFPSR = ar##.##fpsr ;\
|
|
st8 [rHpT1] = rHIFS, TrStIIPA-TrStIFS /* save IFS */;\
|
|
mov rHPFS = ar##.##pfs ;\
|
|
;; ;\
|
|
;\
|
|
st8 [rHpT1] = rHIIPA, TrStFPSR-TrStIIPA /* save IIPA */;\
|
|
st8 [rHpT2] = rHBrp, TrRsPFS-TrBrRp ;\
|
|
;; ;\
|
|
;\
|
|
mov rHRSC = ar##.##rsc ;\
|
|
st8 [rHpT2] = rHPFS /* save PFS */;\
|
|
add rHpT2 = TrApUNAT, sp ;\
|
|
;\
|
|
mov rHBSP = ar##.##bsp ;\
|
|
mov rHCSD = ar##.##csd ;\
|
|
;; ;\
|
|
;\
|
|
st8 [rHpT1] = rHFPSR, TrRsRSC-TrStFPSR /* save FPSR */;\
|
|
st8 [rHpT2] = rHUNAT, TrIntGp-TrApUNAT /* save UNAT */;\
|
|
;; ;\
|
|
;\
|
|
st8 [rHpT1] = rHRSC, TrRsBSP-TrRsRSC /* save RSC */;\
|
|
st8##.##spill [rHpT2] = gp, TrIntTeb-TrIntGp /* spill GP */;\
|
|
;; ;\
|
|
;\
|
|
st8##.##spill [rHpT2] = teb, TrIntSp-TrIntTeb /* spill TEB (r13) */;\
|
|
mov teb = kteb /* sanitize teb */;\
|
|
;; ;\
|
|
;\
|
|
st8 [rHpT1] = rHBSP /* save BSP */;\
|
|
movl rHpT1 = BdPcr + PcKernelGP ;\
|
|
;\
|
|
(pUstk) mov ar##.##rsc = RSC_KERNEL_DISABLED /* turn off RSE */;\
|
|
st8##.##spill [rHpT2] = rHSp, TrSegCSD-TrIntSp /* spill SP */;\
|
|
;; ;\
|
|
;\
|
|
st8 [rHpT2] = rHCSD /* save CSD */;\
|
|
(pKstk) br##.##dpnt Label /* br if on kernel stack */;\
|
|
;\
|
|
;\
|
|
/* */;\
|
|
/* Local register aliases for back store switch */;\
|
|
/* N.B. These must be below h24 since PSR.ic = 1 at this point */;\
|
|
/* h16-h23 are available */;\
|
|
/* */;\
|
|
;\
|
|
rpRNAT = h16 ;\
|
|
rpBSPStore= h17 ;\
|
|
rBSPStore = h18 ;\
|
|
rKBSPStore= h19 ;\
|
|
rRNAT = h20 ;\
|
|
rKrnlFPSR = h21 ;\
|
|
rEFLAG = h22 ;\
|
|
;\
|
|
/* */;\
|
|
/* If previous mode is user, switch to kernel backing store */;\
|
|
/* -- uses the "loadrs" approach. Note that we do not save the */;\
|
|
/* BSP/BSPSTORE in the trap frame if prvious mode was kernel */;\
|
|
/* */;\
|
|
;\
|
|
;\
|
|
mov rBSPStore = ar##.##bspstore /* get user bsp store point */;\
|
|
mov rRNAT = ar##.##rnat /* get RNAT */;\
|
|
add rpRNAT = TrRsRNAT, sp /* -> RNAT */;\
|
|
;; ;\
|
|
;\
|
|
ld8 rKBSPStore = [rHpT1] /* load kernel bstore */;\
|
|
movl rKrnlFPSR = FPSR_FOR_KERNEL /* initial fpsr value */;\
|
|
;; ;\
|
|
;\
|
|
mov ar##.##fpsr = rKrnlFPSR /* set fpsr */;\
|
|
add rpBSPStore = TrRsBSPSTORE, sp /* -> User BSPStore */;\
|
|
;; ;\
|
|
;\
|
|
st8 [rpRNAT] = rRNAT /* save user RNAT */;\
|
|
st8 [rpBSPStore] = rBSPStore /* save user BSP Store */;\
|
|
;; ;\
|
|
dep rKBSPStore = rBSPStore, rKBSPStore, 0, 9 ;\
|
|
/* adjust kernel BSPSTORE */;\
|
|
/* for NAT collection */;\
|
|
;\
|
|
;; ;\
|
|
;\
|
|
/* */;\
|
|
/* Now running on kernel backing store */;\
|
|
/* */;\
|
|
;\
|
|
Label: ;\
|
|
(pUstk) mov ar##.##bspstore = rKBSPStore /* switch to kernel BSP */;\
|
|
(pUstk) mov ar##.##rsc = RSC_KERNEL /* turn rse on, kernel mode */;\
|
|
bsw##.##1 /* switch back to user bank */;\
|
|
;; /* stop bit required */
|
|
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// RETURN_FROM_INTERRUPTION
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common handler code to restore trap frame and resume execution
|
|
// at the interruption address.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Label
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Note:
|
|
//
|
|
// On entry: interrrupts disabled, sp -> trap frame
|
|
// On exit:
|
|
// MS preprocessor requires /* */ style comments below
|
|
//--
|
|
|
|
#define RETURN_FROM_INTERRUPTION(Label) ;\
|
|
;\
|
|
.##regstk 0,3,2,0 /* must match the alloc instruction below */ ;\
|
|
;\
|
|
rBSP = loc0 ;\
|
|
rBSPStore = loc1 ;\
|
|
rRnat = loc2 ;\
|
|
;\
|
|
rpT1 = t1 ;\
|
|
rpT2 = t2 ;\
|
|
rpT3 = t3 ;\
|
|
rpT4 = t4 ;\
|
|
rThread = t6 ;\
|
|
rApcFlag = t7 ;\
|
|
rT1 = t8 ;\
|
|
rT2 = t9 ;\
|
|
;\
|
|
alloc rT1 = 0,4,2,0 ;\
|
|
movl rpT1 = BdPcr + PcCurrentThread /* ->PcCurrentThread */;\
|
|
;; ;\
|
|
;\
|
|
(pUstk) ld8 rThread = [rpT1] /* load thread ptr */;\
|
|
add rBSP = TrRsBSP, sp /* -> user BSP */;\
|
|
(pKstk) br##.##call##.##spnt brp = BdRestoreTrapFrame ;\
|
|
;; ;\
|
|
;\
|
|
add rBSPStore = TrRsBSPSTORE, sp /* -> user BSP Store */;\
|
|
add rRnat = TrRsRNAT, sp /* -> user RNAT */;\
|
|
(pKstk) br##.##spnt Label##ReturnToKernel ;\
|
|
;; ;\
|
|
;\
|
|
add rpT1 = ThApcState+AsUserApcPending, rThread ;\
|
|
;; ;\
|
|
ld1 rApcFlag = [rpT1], ThAlerted-ThApcState-AsUserApcPending ;\
|
|
;; ;\
|
|
st1.nta [rpT1] = zero ;\
|
|
cmp##.##ne pApc = zero, rApcFlag ;\
|
|
;; ;\
|
|
;\
|
|
PSET_IRQL (pApc, APC_LEVEL) ;\
|
|
(pApc) mov out1 = sp ;\
|
|
;; ;\
|
|
;\
|
|
(pApc) FAST_DISABLE_INTERRUPTS ;\
|
|
PSET_IRQL (pApc, zero) ;\
|
|
;\
|
|
ld8 rBSP = [rBSP] /* user BSP */;\
|
|
ld8 rBSPStore = [rBSPStore] /* user BSP Store */;\
|
|
ld8 rRnat = [rRnat] /* user RNAT */;\
|
|
br##.##call##.##sptk brp = BdRestoreDebugRegisters ;\
|
|
;; ;\
|
|
;\
|
|
invala ;\
|
|
br##.##call##.##sptk brp = BdRestoreTrapFrame ;\
|
|
;; ;\
|
|
;\
|
|
;\
|
|
Label##CriticalExitCode: ;\
|
|
;\
|
|
rHRscE = h17 ;\
|
|
rHRnat = h18 ;\
|
|
rHBSPStore = h19 ;\
|
|
rHRscD = h20 ;\
|
|
rHRscDelta = h24 ;\
|
|
;\
|
|
bsw##.##0 ;\
|
|
;; ;\
|
|
;\
|
|
mov rHRscE = ar##.##rsc /* save user RSC */;\
|
|
mov rHBSPStore = rBSPStore ;\
|
|
mov rHRscD = RSC_KERNEL_DISABLED ;\
|
|
;\
|
|
sub rHRscDelta = rBSP, rBSPStore /* delta = BSP - BSP Store */;\
|
|
;; ;\
|
|
mov rHRnat = rRnat ;\
|
|
dep rHRscD = rHRscDelta, rHRscD, 16, 14 /* set RSC.loadrs */;\
|
|
;; ;\
|
|
;\
|
|
alloc rTH1 = 0,0,0,0 ;\
|
|
mov ar##.##rsc = rHRscD /* RSE off */ ;\
|
|
;; ;\
|
|
loadrs /* pull in user regs */;\
|
|
/* up to tear point */ ;\
|
|
;; ;\
|
|
;\
|
|
mov ar##.##bspstore = rHBSPStore /* restore user BSP */ ;\
|
|
;; ;\
|
|
mov ar##.##rnat = rHRnat /* restore user RNAT */;\
|
|
;\
|
|
Label##ReturnToKernel: ;\
|
|
;\
|
|
(pUstk) mov ar.rsc = rHRscE /* restore user RSC */;\
|
|
bsw##.##0 ;\
|
|
;; ;\
|
|
;\
|
|
add rHpT2 = TrApUNAT, sp /* -> previous UNAT */;\
|
|
add rHpT1 = TrStFPSR, sp /* -> previous Preds */;\
|
|
;; ;\
|
|
;\
|
|
ld8 rHUNAT = [rHpT2],TrPreds-TrApUNAT ;\
|
|
ld8 rHFPSR = [rHpT1],TrRsPFS-TrStFPSR ;\
|
|
;; ;\
|
|
;\
|
|
ld8 rHOldPreds = [rHpT2], TrIntSp-TrPreds ;\
|
|
ld8 rHPFS = [rHpT1],TrStIIPA-TrRsPFS ;\
|
|
;; ;\
|
|
;\
|
|
ld8##.##fill rHSp = [rHpT2], TrBrRp-TrIntSp ;\
|
|
ld8 rHIIPA = [rHpT1], TrStIIP-TrStIIPA ;\
|
|
;; ;\
|
|
;\
|
|
mov ar##.##fpsr = rHFPSR /* restore FPSR */;\
|
|
ld8 rHIIP = [rHpT1], TrStIPSR-TrStIIP /* load IIP */;\
|
|
mov pr = rHOldPreds, -1 /* restore preds */;\
|
|
;\
|
|
mov ar##.##unat = rHUNAT /* restore UNAT */;\
|
|
ld8 rHBrp = [rHpT2], TrStIFS-TrBrRp ;\
|
|
mov ar##.##pfs = rHPFS /* restore PFS */;\
|
|
;; ;\
|
|
;\
|
|
ld8 rHIFS = [rHpT2] /* load IFS */;\
|
|
ld8 rHIPSR = [rHpT1] /* load IPSR */;\
|
|
;\
|
|
rsm 1 << PSR_IC /* reset ic bit */;\
|
|
;; ;\
|
|
srlz##.##d /* must serialize */;\
|
|
mov brp = rHBrp /* restore brp */;\
|
|
;\
|
|
/* */;\
|
|
/* Restore status registers */;\
|
|
/* */;\
|
|
;\
|
|
mov cr##.##ipsr = rHIPSR /* restore previous IPSR */;\
|
|
mov cr##.##iip = rHIIP /* restore previous IIP */;\
|
|
;\
|
|
mov cr##.##ifs = rHIFS /* restore previous IFS */;\
|
|
mov cr##.##iipa = rHIIPA /* restore previous IIPA */;\
|
|
;; ;\
|
|
;\
|
|
/* */;\
|
|
/* Resume at point of interruption (rfi must be at end of instruction group)*/;\
|
|
/* */;\
|
|
mov sp = rHSp /* restore sp */;\
|
|
mov h17 = r0 /* clear TB loop count */;\
|
|
rfi ;\
|
|
;;
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// USER_APC_CHECK
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common handler code for requesting
|
|
// pending APC if returning to user mode.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Note:
|
|
//
|
|
// On entry: interrrupts disabled, sp -> trap frame
|
|
// On exit:
|
|
// MS preprocessor requires /* */ style comments below
|
|
//--
|
|
|
|
|
|
#define USER_APC_CHECK ;\
|
|
;\
|
|
/* */;\
|
|
/* Check for pending APC's */;\
|
|
/* */;\
|
|
;\
|
|
movl t22=BdPcr + PcCurrentThread /* ->PcCurrentThread */;\
|
|
;; ;\
|
|
;\
|
|
LDPTR (t22,t22) ;\
|
|
;; ;\
|
|
add t22=ThApcState+AsUserApcPending, t22 /* -> pending flag */;\
|
|
;; ;\
|
|
;\
|
|
ld1 t8 = [t22], ThAlerted-ThApcState-AsUserApcPending ;\
|
|
;; ;\
|
|
st1 [t22] = zero ;\
|
|
cmp##.##ne pApc = zero, t8 /* pApc = 1 if pending */;\
|
|
;; ;\
|
|
;\
|
|
PSET_IRQL (pApc, APC_LEVEL) ;\
|
|
(pApc) mov out1 = sp ;\
|
|
;; ;\
|
|
(pApc) FAST_DISABLE_INTERRUPTS ;\
|
|
PSET_IRQL (pApc, zero)
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// BSTORE_SWITCH
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common handler code for switching to user backing store, if
|
|
// returning to user mode.
|
|
//
|
|
// On entry:
|
|
//
|
|
// sp: pointer to trap frame
|
|
//
|
|
// On exit:
|
|
//
|
|
// on user backing store, can't afford another alloc of any frame size
|
|
// other than zero. otherwise, the kernel may panic.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Note:
|
|
//
|
|
// MS preprocessor requires /* */ style comments below
|
|
//--
|
|
|
|
|
|
#define BSTORE_SWITCH ;\
|
|
/* */;\
|
|
/* Set sp to trap frame and switch to kernel banked registers */;\
|
|
/* */;\
|
|
rRscD = t11 ;\
|
|
rpT2 = t12 ;\
|
|
rRNAT = t13 ;\
|
|
rBSPStore = t14 ;\
|
|
rRscDelta = t15 ;\
|
|
rpT1 = t16 ;\
|
|
;\
|
|
;\
|
|
add rpT1 = TrRsRNAT, sp /* -> user RNAT */;\
|
|
add rpT2 = TrRsBSPSTORE, sp /* -> user BSP Store */;\
|
|
mov rRscD = RSC_KERNEL_DISABLED ;\
|
|
;; ;\
|
|
;\
|
|
/* */;\
|
|
/* Switch to user BSP -- put in load intensive mode to overlap RS restore */;\
|
|
/* with volatile state restore. */;\
|
|
/* */;\
|
|
;\
|
|
ld8 rRNAT = [rpT1], TrRsBSP-TrRsRNAT /* user RNAT */ ;\
|
|
ld8 rBSPStore = [rpT2] /* user BSP Store*/ ;\
|
|
;; ;\
|
|
;\
|
|
alloc t22 = 0,0,0,0 ;\
|
|
ld8 rRscDelta = [rpT1] /* user BSP */ ;\
|
|
;; ;\
|
|
sub rRscDelta = rRscDelta, rBSPStore /* delta = BSP - BSP Store */;\
|
|
;; ;\
|
|
;\
|
|
invala ;\
|
|
dep rRscD = rRscDelta, rRscD, 16, 14 /* set RSC.loadrs */;\
|
|
;; ;\
|
|
;\
|
|
mov ar##.##rsc = rRscD /* RSE off */ ;\
|
|
;; ;\
|
|
loadrs /* pull in user regs */;\
|
|
/* up to tear point */ ;\
|
|
;; ;\
|
|
;\
|
|
mov ar##.##bspstore = rBSPStore /* restore user BSP */ ;\
|
|
;; ;\
|
|
mov ar##.##rnat = rRNAT /* restore user RNAT */
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// NORMAL_KERNEL_EXIT
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Common handler code for restoring previous state and rfi.
|
|
//
|
|
// On entry:
|
|
//
|
|
// sp: pointer to trap frame
|
|
// ar.unat: contains Nat for previous sp (restored by ld8.fill)
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Note:
|
|
//
|
|
// Uses just the kernel banked registers (h16-h31)
|
|
//
|
|
// MS preprocessor requires /* */ style comments below
|
|
//--
|
|
|
|
#define NORMAL_KERNEL_EXIT ;\
|
|
;\
|
|
add rHpT2 = TrApUNAT, sp /* -> previous UNAT */;\
|
|
add rHpT1 = TrStFPSR, sp /* -> previous Preds */;\
|
|
;; ;\
|
|
;\
|
|
ld8 rHUNAT = [rHpT2],TrPreds-TrApUNAT ;\
|
|
ld8 rHFPSR = [rHpT1],TrRsPFS-TrStFPSR ;\
|
|
;; ;\
|
|
;\
|
|
ld8 rHOldPreds = [rHpT2], TrIntSp-TrPreds ;\
|
|
ld8 rHPFS = [rHpT1],TrStIIPA-TrRsPFS ;\
|
|
;; ;\
|
|
;\
|
|
ld8##.##fill rHSp = [rHpT2], TrBrRp-TrIntSp ;\
|
|
ld8 rHIIPA = [rHpT1], TrStIIP-TrStIIPA ;\
|
|
;; ;\
|
|
;\
|
|
mov ar##.##fpsr = rHFPSR /* restore FPSR */;\
|
|
ld8 rHIIP = [rHpT1], TrStIPSR-TrStIIP /* load IIP */;\
|
|
mov pr = rHOldPreds, -1 /* restore preds */;\
|
|
;\
|
|
mov ar##.##unat = rHUNAT /* restore UNAT */;\
|
|
ld8 rHBrp = [rHpT2], TrStIFS-TrBrRp ;\
|
|
mov ar##.##pfs = rHPFS /* restore PFS */;\
|
|
;; ;\
|
|
;\
|
|
ld8 rHIFS = [rHpT2] /* load IFS */;\
|
|
ld8 rHIPSR = [rHpT1] /* load IPSR */;\
|
|
;\
|
|
rsm 1 << PSR_IC /* reset ic bit */;\
|
|
;; ;\
|
|
srlz##.##d /* must serialize */;\
|
|
mov brp = rHBrp /* restore brp */;\
|
|
;\
|
|
/* */;\
|
|
/* Restore status registers */;\
|
|
/* */;\
|
|
;\
|
|
mov cr##.##ipsr = rHIPSR /* restore previous IPSR */;\
|
|
mov cr##.##iip = rHIIP /* restore previous IIP */;\
|
|
;\
|
|
mov cr##.##ifs = rHIFS /* restore previous IFS */;\
|
|
mov cr##.##iipa = rHIIPA /* restore previous IIPA */;\
|
|
;; ;\
|
|
;\
|
|
/* */;\
|
|
/* Resume at point of interruption (rfi must be at end of instruction group)*/;\
|
|
/* */;\
|
|
mov sp = rHSp /* restore sp */;\
|
|
mov h17 = r0 /* clear TB loop count */;\
|
|
rfi ;\
|
|
;;
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// GET_INTERRUPT_VECTOR(pGet, rVector)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Hook to get the vector for an interrupt. Currently just
|
|
// reads the Interrupt Vector Control Register.
|
|
//
|
|
// Agruments:
|
|
//
|
|
// pGet: Predicate: if true then get, else skip.
|
|
// rVector: Register for the vector number.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The vector number of the highest priority pending interrupt.
|
|
// Vectors number is an 8-bit value. All other bits 0.
|
|
//
|
|
//--
|
|
|
|
#define GET_INTERRUPT_VECTOR(pGet,rVector) \
|
|
srlz##.##d ;\
|
|
(pGet) mov rVector = cr##.##ivr
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// BdBreakVector
|
|
//
|
|
// Description:
|
|
//
|
|
// Interruption vector for break instruction.
|
|
//
|
|
// On entry:
|
|
//
|
|
// IIM contains break immediate value:
|
|
// -- BREAK_SYSCALL -> standard system call
|
|
// interrupts disabled
|
|
// r16-r31 switched to kernel bank
|
|
// r16-r31 all available since no TLB faults at this point
|
|
//
|
|
// Return value:
|
|
//
|
|
// if system call, sys call return value in v0.
|
|
//
|
|
// Process:
|
|
//--------------------------------------------------------------------
|
|
|
|
VECTOR_ENTRY(0x2C00, BdBreakVector, cr.iim)
|
|
|
|
mov b7 = h30 // restore the original value of b7
|
|
mov rHIIM = cr.iim // get break value
|
|
movl rTH1 = BdPcr+PcSavedIIM
|
|
;;
|
|
st8 [rTH1] = rHIIM
|
|
|
|
VECTOR_CALL_HANDLER(BdGenericExceptionHandler, BdOtherBreakException)
|
|
|
|
//
|
|
// Do not return from handler
|
|
//
|
|
|
|
VECTOR_EXIT(BdBreakVector)
|
|
|
|
//++
|
|
//
|
|
// BdTakenBranchVector
|
|
//
|
|
// Cause: A taken branch was successfully execcuted and the PSR.tb
|
|
// bit is 1. This trap is higher priority than single step trap.
|
|
//
|
|
// Parameters: cr.iip - address of bundle containing the instruction to
|
|
// be executed next.
|
|
//
|
|
// cr.ipsr - copy of PSR at the time of interruption.
|
|
//
|
|
// cr.iipa - address of bundle containing the last
|
|
// successfully executed instruction
|
|
//
|
|
// cr.isr - faulting status information. The ISR.code
|
|
// contains a bit vector for all traps which
|
|
// occurred in the trapping bundle.
|
|
//
|
|
//--
|
|
|
|
VECTOR_ENTRY(0x5f00, BdTakenBranchVector, cr.iipa)
|
|
|
|
mov rHIIP = cr.iip
|
|
movl rHEPCVa = MM_EPC_VA+0x20 // user system call entry point
|
|
|
|
mov rHIPSR = cr.ipsr
|
|
movl rHpT1 = BdPcr+PcInitialStack
|
|
;;
|
|
|
|
ld8 rHpT1 = [rHpT1]
|
|
mov rHOldPreds = pr
|
|
mov rPanicCode = UNEXPECTED_KERNEL_MODE_TRAP
|
|
;;
|
|
|
|
cmp.eq pt0 = rHEPCVa, rHIIP
|
|
extr.u rTH1 = rHIPSR, PSR_CPL, PSR_CPL_LEN
|
|
;;
|
|
|
|
cmp4.eq pKrnl, pUser = PL_KERNEL, rTH1
|
|
(pKrnl) br.spnt.few BdPanicHandler
|
|
;;
|
|
|
|
(pt0) ssm 1 << PSR_IC
|
|
(pt0) movl rTH1 = 1 << PSR_LP
|
|
;;
|
|
|
|
(pt0) or rHpT3 = rHIPSR, rTH1
|
|
movl rHHandler = BdSingleStep
|
|
|
|
(pt0) srlz.d
|
|
add rHpT1=-ThreadStateSaveAreaLength-TrapFrameLength+TrStIPSR,rHpT1
|
|
(pt0) br.spnt.few Ktbv10
|
|
|
|
mov pr = rHOldPreds, -2
|
|
br.sptk BdGenericExceptionHandler
|
|
;;
|
|
|
|
|
|
Ktbv10:
|
|
|
|
st8 [rHpT1] = rHpT3
|
|
movl rTH1 = 1 << PSR_SS | 1 << PSR_TB | 1 << PSR_DB
|
|
;;
|
|
|
|
rsm 1 << PSR_IC
|
|
mov pr = rHOldPreds, -2
|
|
andcm rHIPSR = rHIPSR, rTH1 // clear ss, tb, db bits
|
|
;;
|
|
|
|
srlz.d
|
|
mov cr.ipsr = rHIPSR
|
|
;;
|
|
rfi
|
|
;;
|
|
|
|
VECTOR_EXIT(BdTakenBranchVector)
|
|
|
|
//++
|
|
//
|
|
// BdSingleStepVector
|
|
//
|
|
// Cause: An instruction was successfully execcuted and the PSR.ss
|
|
// bit is 1.
|
|
//
|
|
// Parameters: cr.iip - address of bundle containing the instruction to
|
|
// be executed next.
|
|
//
|
|
// cr.ipsr - copy of PSR at the time of interruption.
|
|
//
|
|
// cr.iipa - address of bundle containing the last
|
|
// successfully executed instruction
|
|
//
|
|
// cr.isr - faulting status information. The ISR.code
|
|
// contains a bit vector for all traps which
|
|
// occurred in the trapping bundle.
|
|
//
|
|
//--
|
|
|
|
VECTOR_ENTRY(0x6000, BdSingleStepVector, cr.iipa)
|
|
|
|
mov rHIIP = cr.iip
|
|
movl rHEPCVa = MM_EPC_VA+0x20 // user system call entry point
|
|
|
|
mov rHIPSR = cr.ipsr
|
|
movl rHpT1 = BdPcr+PcInitialStack
|
|
;;
|
|
|
|
ld8 rHpT1 = [rHpT1]
|
|
mov rHOldPreds = pr
|
|
mov rPanicCode = UNEXPECTED_KERNEL_MODE_TRAP
|
|
;;
|
|
|
|
cmp.eq pt0 = rHEPCVa, rHIIP
|
|
extr.u rTH1 = rHIPSR, PSR_CPL, PSR_CPL_LEN
|
|
;;
|
|
|
|
cmp4.eq pKrnl, pUser = PL_KERNEL, rTH1
|
|
(pKrnl) br.spnt.few BdPanicHandler
|
|
;;
|
|
|
|
(pt0) ssm 1 << PSR_IC
|
|
(pt0) movl rTH1 = 1 << PSR_LP
|
|
;;
|
|
|
|
(pt0) or rHpT3 = rHIPSR, rTH1
|
|
movl rHHandler = BdSingleStep
|
|
|
|
(pt0) srlz.d
|
|
add rHpT1=-ThreadStateSaveAreaLength-TrapFrameLength+TrStIPSR,rHpT1
|
|
(pt0) br.spnt.few Kssv10
|
|
|
|
mov pr = rHOldPreds, -2
|
|
br.sptk BdGenericExceptionHandler
|
|
;;
|
|
|
|
|
|
Kssv10:
|
|
|
|
st8 [rHpT1] = rHpT3
|
|
movl rTH1 = 1 << PSR_SS | 1 << PSR_DB
|
|
;;
|
|
|
|
rsm 1 << PSR_IC
|
|
mov pr = rHOldPreds, -2
|
|
andcm rHIPSR = rHIPSR, rTH1 // clear ss, db bits
|
|
;;
|
|
|
|
srlz.d
|
|
mov cr.ipsr = rHIPSR
|
|
;;
|
|
rfi
|
|
;;
|
|
|
|
VECTOR_EXIT(BdSingleStepVector)
|
|
|
|
.text
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// BdGenericExceptionHandler
|
|
//
|
|
// Description:
|
|
//
|
|
// First level handler for heavyweight exceptions.
|
|
//
|
|
// On entry:
|
|
//
|
|
// ic off
|
|
// interrupts disabled
|
|
// current frame covered
|
|
//
|
|
// Process:
|
|
//
|
|
// Notes:
|
|
//
|
|
// PCR page mapped with TR
|
|
//--------------------------------------------------------------------
|
|
|
|
HANDLER_ENTRY(BdGenericExceptionHandler)
|
|
|
|
.prologue
|
|
.unwabi @nt, EXCEPTION_FRAME
|
|
|
|
ALLOCATE_TRAP_FRAME
|
|
|
|
//
|
|
// sp points to trap frame
|
|
//
|
|
// Save exception handler routine in kernel register
|
|
//
|
|
|
|
mov rkHandler = rHHandler
|
|
;;
|
|
|
|
//
|
|
// Save interruption state in trap frame and switch to user bank registers
|
|
// and switch to kernel backing store.
|
|
//
|
|
|
|
SAVE_INTERRUPTION_STATE(Kgeh_SaveTrapFrame)
|
|
|
|
//
|
|
// Now running with user banked registers and on kernel stack.
|
|
//
|
|
// Can now take TLB faults
|
|
//
|
|
// sp -> trap frame
|
|
//
|
|
|
|
br.call.sptk brp = BdSaveTrapFrame
|
|
;;
|
|
|
|
//
|
|
// setup debug registers if previous mode is user
|
|
//
|
|
|
|
(pUser) br.call.spnt brp = BdSetupDebugRegisters
|
|
|
|
//
|
|
// Register aliases
|
|
//
|
|
|
|
rpT1 = t0
|
|
rpT2 = t1
|
|
rpT3 = t2
|
|
rT1 = t3
|
|
rT2 = t4
|
|
rT3 = t5
|
|
rPreviousMode = t6 // previous mode
|
|
rT4 = t7
|
|
|
|
|
|
movl gp = _gp // make sure we are using loader's GP
|
|
mov rT1 = rkHandler // restore address of interruption routine
|
|
movl rpT1 = BdPcr+PcSavedIIM
|
|
;;
|
|
|
|
ld8 rT2 = [rpT1], PcSavedIFA-PcSavedIIM // load saved IIM
|
|
add rpT2 = TrEOFMarker, sp
|
|
add rpT3 = TrStIIM, sp
|
|
;;
|
|
|
|
ld8 rT4 = [rpT1] // load saved IFA
|
|
movl rT3 = KTRAP_FRAME_EOF | EXCEPTION_FRAME
|
|
;;
|
|
|
|
st8 [rpT2] = rT3, TrNewBSP-TrEOFMarker
|
|
st8 [rpT3] = rT2, TrStIFA-TrStIIM // save IIM in trap frame
|
|
mov bt0 = rT1 // set destination address
|
|
;;
|
|
|
|
st8 [rpT3] = rT4 // save IFA in trap frame
|
|
#if DBG
|
|
st8 [rpT2] = rT1 // save debug info in TrFrame
|
|
#endif // DBG
|
|
;;
|
|
|
|
PROLOGUE_END
|
|
|
|
.regstk 0, 1, 2, 0 // must be in sync with BdExceptionExit
|
|
alloc out1 = 0,1,2,0 // alloc 0 in, 1 locals, 2 outs
|
|
|
|
//
|
|
// Dispatch the exception via call to address in rkHandler
|
|
//
|
|
.pred.rel "mutex",pUser,pKrnl
|
|
add rpT1 = TrPreviousMode, sp // -> previous mode
|
|
(pUser) mov rPreviousMode = UserMode // set previous mode
|
|
(pKrnl) mov rPreviousMode = KernelMode
|
|
;;
|
|
|
|
st4 [rpT1] = rPreviousMode // **** TBD 1 byte -- save in trap frame
|
|
mov out0 = sp // trap frame pointer
|
|
br.call.sptk brp = bt0 // call handler(tf) (C code)
|
|
;;
|
|
|
|
.pred.rel "mutex",pUser,pKrnl
|
|
cmp.ne pt0, pt1 = v0, zero
|
|
(pUser) mov out1 = UserMode
|
|
(pKrnl) mov out1 = KernelMode
|
|
|
|
//
|
|
// does not return
|
|
//
|
|
|
|
mov out0 = sp
|
|
(pt1) br.cond.sptk BdAlternateExit
|
|
(pt0) br.call.spnt brp = BdExceptionDispatch
|
|
|
|
nop.m 0
|
|
nop.m 0
|
|
nop.i 0
|
|
;;
|
|
|
|
HANDLER_EXIT(BdGenericExceptionHandler)
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// BdPanicHandler
|
|
//
|
|
// Description:
|
|
//
|
|
// Handler for panic. Call the bug check routine. A place
|
|
// holder for now.
|
|
//
|
|
// On entry:
|
|
//
|
|
// running on kernel memory stack and kernel backing store
|
|
// sp: top of stack -- points to trap frame
|
|
// interrupts enabled
|
|
//
|
|
// IIP: address of bundle causing fault
|
|
//
|
|
// IPSR: copy of PSR at time of interruption
|
|
//
|
|
// Output:
|
|
//
|
|
// sp: top of stack -- points to trap frame
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
// Notes:
|
|
//
|
|
// If ISR code out of bounds, this code will inovke the panic handler
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
HANDLER_ENTRY(BdPanicHandler)
|
|
|
|
movl rTH1 = BdPcr+PcPanicStack
|
|
;;
|
|
|
|
ld8 sp = [rTH1]
|
|
movl rTH2 = BdPcr+PcSystemReserved
|
|
;;
|
|
|
|
st4 [rTH2] = rPanicCode
|
|
add sp = -TrapFrameLength, sp
|
|
;;
|
|
|
|
SAVE_INTERRUPTION_STATE(Kph_SaveTrapFrame)
|
|
|
|
rpRNAT = t16
|
|
rpBSPStore= t17
|
|
rBSPStore = t18
|
|
rKBSPStore= t19
|
|
rRNAT = t20
|
|
rKrnlFPSR = t21
|
|
|
|
mov ar.rsc = RSC_KERNEL_DISABLED
|
|
add rpRNAT = TrRsRNAT, sp
|
|
add rpBSPStore = TrRsBSPSTORE, sp
|
|
;;
|
|
|
|
mov rBSPStore = ar.bspstore
|
|
mov rRNAT = ar.rnat
|
|
;;
|
|
|
|
st8 [rpRNAT] = rRNAT
|
|
st8 [rpBSPStore] = rBSPStore
|
|
dep rKBSPStore = rBSPStore, sp, 0, 9
|
|
;;
|
|
|
|
mov ar.bspstore = rKBSPStore
|
|
mov ar.rsc = RSC_KERNEL
|
|
;;
|
|
|
|
alloc t22 = ar.pfs, 0, 0, 5, 0
|
|
movl out0 = BdPcr+PcSystemReserved
|
|
;;
|
|
|
|
ld4 out0 = [out0] // 1st argument: panic code
|
|
mov out1 = sp // 2nd argument: trap frame
|
|
//br.call.sptk.many brp = KeBugCheckEx
|
|
;;
|
|
|
|
HANDLER_EXIT(BdPanicHandler)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// VOID
|
|
// BdSaveTrapFrame(PKTRAP_FRAME)
|
|
//
|
|
// Description:
|
|
//
|
|
// Save volatile application state in trap frame.
|
|
// Note: sp, brp, UNAT, RSC, predicates, BSP, BSP Store,
|
|
// PFS, CSD, and FPSR saved elsewhere.
|
|
//
|
|
// Input:
|
|
//
|
|
// sp: points to trap frame
|
|
// ar.unat: contains the Nats of sp, gp, teb, which have already
|
|
// been spilled into the trap frame.
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdSaveTrapFrame)
|
|
|
|
.regstk 0, 3, 0, 0
|
|
|
|
//
|
|
// Local register aliases
|
|
//
|
|
|
|
rpTF1 = loc0
|
|
rpTF2 = loc1
|
|
rL1 = t0
|
|
rL2 = t1
|
|
rL3 = t2
|
|
rL4 = t3
|
|
rL5 = t4
|
|
|
|
|
|
//
|
|
// (ar.unat unchanged from point of save)
|
|
// Spill temporary (volatile) integer registers
|
|
//
|
|
|
|
alloc loc2 = 0,3,0,0 // don't destroy static register
|
|
add rpTF1 = TrIntT0, sp // -> t0 save area
|
|
add rpTF2 = TrIntT1, sp // -> t1 save area
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t0, TrIntT2-TrIntT0 // spill t0 - t22
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t1, TrIntT3-TrIntT1
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t2, TrIntT4-TrIntT2
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t3, TrIntT5-TrIntT3
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t4, TrIntT6-TrIntT4
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t5, TrIntT7-TrIntT5
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t6, TrIntT8-TrIntT6
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t7, TrIntT9-TrIntT7
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t8, TrIntT10-TrIntT8
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t9, TrIntT11-TrIntT9
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t10, TrIntT12-TrIntT10
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t11, TrIntT13-TrIntT11
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t12, TrIntT14-TrIntT12
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t13, TrIntT15-TrIntT13
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t14, TrIntT16-TrIntT14
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t15, TrIntT17-TrIntT15
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t16, TrIntT18-TrIntT16
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t17, TrIntT19-TrIntT17
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t18, TrIntT20-TrIntT18
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t19, TrIntT21-TrIntT19
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t20, TrIntT22-TrIntT20
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = t21, TrIntV0-TrIntT21
|
|
;;
|
|
.mem.offset 0,0
|
|
st8.spill [rpTF1] = t22, TrBrT0-TrIntT22
|
|
.mem.offset 8,0
|
|
st8.spill [rpTF2] = v0, TrIntNats-TrIntV0 // spill old V0
|
|
;;
|
|
|
|
//
|
|
// Now save the Nats interger regsisters saved so far (includes Nat for sp)
|
|
//
|
|
|
|
mov rL1 = ar.unat
|
|
mov rL2 = bt0
|
|
mov rL3 = bt1
|
|
;;
|
|
|
|
st8 [rpTF2] = rL1, TrBrT1-TrIntNats // save Nats of volatile regs
|
|
mov rL4 = ar.ccv
|
|
;;
|
|
|
|
//
|
|
// Save temporary (volatile) branch registers
|
|
//
|
|
|
|
st8 [rpTF1] = rL2, TrApCCV-TrBrT0 // save old bt0 - bt1
|
|
st8 [rpTF2] = rL3
|
|
;;
|
|
|
|
st8 [rpTF1] = rL4 // save ar.ccv
|
|
add rpTF1 = TrFltT0, sp // point to FltT0
|
|
add rpTF2 = TrFltT1, sp // point to FltT1
|
|
;;
|
|
|
|
//
|
|
// Spill temporary (volatile) floating point registers
|
|
//
|
|
|
|
stf.spill [rpTF1] = ft0, TrFltT2-TrFltT0 // spill float tmp 0 - 9
|
|
stf.spill [rpTF2] = ft1, TrFltT3-TrFltT1
|
|
;;
|
|
stf.spill [rpTF1] = ft2, TrFltT4-TrFltT2
|
|
stf.spill [rpTF2] = ft3, TrFltT5-TrFltT3
|
|
;;
|
|
stf.spill [rpTF1] = ft4, TrFltT6-TrFltT4
|
|
stf.spill [rpTF2] = ft5, TrFltT7-TrFltT5
|
|
;;
|
|
stf.spill [rpTF1] = ft6, TrFltT8-TrFltT6
|
|
stf.spill [rpTF2] = ft7, TrFltT9-TrFltT7
|
|
;;
|
|
stf.spill [rpTF1] = ft8
|
|
stf.spill [rpTF2] = ft9
|
|
;;
|
|
|
|
rum 1 << PSR_MFL // clear mfl bit
|
|
|
|
//
|
|
// TBD **** Debug/performance regs ** ?
|
|
// **** Performance regs not needed (either user or system wide)
|
|
// No performance regs switched on kernel entry
|
|
// **** Debug regs saved if in use
|
|
//
|
|
|
|
LEAF_RETURN
|
|
;;
|
|
LEAF_EXIT(BdSaveTrapFrame)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// VOID
|
|
// BdRestoreTrapFrame(PKTRAP_FRAME)
|
|
//
|
|
// Description:
|
|
//
|
|
// Restore volatile application state from trap frame. Restore CSD
|
|
// Note: sp, brp, RSC, UNAT, predicates, BSP, BSP Store, PFS,
|
|
// CSD and FPSR not restored here.
|
|
//
|
|
// Input:
|
|
//
|
|
// sp: points to trap frame
|
|
// RSE frame size is zero
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdRestoreTrapFrame)
|
|
|
|
LEAF_SETUP(0,2,0,0)
|
|
|
|
rpTF1 = loc0
|
|
rpTF2 = loc1
|
|
|
|
//
|
|
// **** TBD **** Restore debug/performance registers??
|
|
// **** Performance regs not needed (either user or system wide)
|
|
// No performance regs switched on kernel entry
|
|
// **** Debug regs saved if in use
|
|
//
|
|
|
|
//
|
|
// Restore RSC, CCV, CSD, and volatile branch, floating point, integer register
|
|
//
|
|
|
|
mov t21 = psr
|
|
add rpTF1 = TrRsRSC, sp
|
|
add rpTF2 = TrApCCV, sp
|
|
;;
|
|
|
|
ld8 t5 = [rpTF1], TrIntNats-TrRsRSC
|
|
ld8 t1 = [rpTF2], TrSegCSD-TrApCCV
|
|
;;
|
|
|
|
ld8 t0 = [rpTF1], TrBrT0-TrIntNats
|
|
ld8 t3 = [rpTF2], TrBrT1-TrSegCSD
|
|
;;
|
|
|
|
ld8 t2 = [rpTF1]
|
|
ld8 t4 = [rpTF2]
|
|
|
|
mov ar.rsc = t5
|
|
mov ar.ccv = t1
|
|
add rpTF1 = TrIntGp, sp
|
|
|
|
mov ar.unat = t0
|
|
mov ar.csd = t3
|
|
add rpTF2 = TrIntT0, sp
|
|
;;
|
|
|
|
ld8.fill gp = [rpTF1], TrIntT1-TrIntGp
|
|
ld8.fill t0 = [rpTF2], TrIntT2-TrIntT0
|
|
mov bt0 = t2
|
|
;;
|
|
|
|
ld8.fill t1 = [rpTF1], TrIntT3-TrIntT1
|
|
ld8.fill t2 = [rpTF2], TrIntT4-TrIntT2
|
|
mov bt1 = t4
|
|
;;
|
|
|
|
ld8.fill t3 = [rpTF1], TrIntT5-TrIntT3
|
|
ld8.fill t4 = [rpTF2], TrIntT6-TrIntT4
|
|
tbit.z pt1 = t21, PSR_MFL
|
|
;;
|
|
|
|
ld8.fill t5 = [rpTF1], TrIntT7-TrIntT5
|
|
ld8.fill t6 = [rpTF2], TrIntT8-TrIntT6
|
|
;;
|
|
|
|
ld8.fill t7 = [rpTF1], TrIntT9-TrIntT7
|
|
ld8.fill t8 = [rpTF2], TrIntT10-TrIntT8
|
|
;;
|
|
|
|
ld8.fill t9 = [rpTF1], TrIntT11-TrIntT9
|
|
ld8.fill t10 = [rpTF2], TrIntT12-TrIntT10
|
|
;;
|
|
|
|
ld8.fill t11 = [rpTF1], TrIntT13-TrIntT11
|
|
ld8.fill t12 = [rpTF2], TrIntT14-TrIntT12
|
|
;;
|
|
|
|
ld8.fill t13 = [rpTF1], TrIntT15-TrIntT13
|
|
ld8.fill t14 = [rpTF2], TrIntT16-TrIntT14
|
|
;;
|
|
|
|
ld8.fill t15 = [rpTF1], TrIntT17-TrIntT15
|
|
ld8.fill t16 = [rpTF2], TrIntT18-TrIntT16
|
|
;;
|
|
|
|
ld8.fill t17 = [rpTF1], TrIntT19-TrIntT17
|
|
ld8.fill t18 = [rpTF2], TrIntT20-TrIntT18
|
|
;;
|
|
|
|
ld8.fill t19 = [rpTF1], TrIntT21-TrIntT19
|
|
ld8.fill t20 = [rpTF2], TrIntT22-TrIntT20
|
|
;;
|
|
|
|
ld8.fill t21 = [rpTF1], TrIntTeb-TrIntT21
|
|
ld8.fill t22 = [rpTF2], TrIntV0-TrIntT22
|
|
;;
|
|
|
|
ld8.fill teb = [rpTF1], TrFltT1-TrIntTeb
|
|
ld8.fill v0 = [rpTF2], TrFltT0-TrIntV0
|
|
;;
|
|
|
|
ldf.fill ft0 = [rpTF2], TrFltT2-TrFltT0
|
|
ldf.fill ft1 = [rpTF1], TrFltT3-TrFltT1
|
|
;;
|
|
|
|
ldf.fill ft2 = [rpTF2], TrFltT4-TrFltT2
|
|
ldf.fill ft3 = [rpTF1], TrFltT5-TrFltT3
|
|
;;
|
|
|
|
ldf.fill ft4 = [rpTF2], TrFltT6-TrFltT4
|
|
ldf.fill ft5 = [rpTF1], TrFltT7-TrFltT5
|
|
;;
|
|
|
|
ldf.fill ft6 = [rpTF2], TrFltT8-TrFltT6
|
|
ldf.fill ft7 = [rpTF1], TrFltT9-TrFltT7
|
|
;;
|
|
|
|
ldf.fill ft8 = [rpTF2]
|
|
ldf.fill ft9 = [rpTF1]
|
|
br.ret.sptk.many brp
|
|
;;
|
|
|
|
LEAF_EXIT(BdRestoreTrapFrame)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// VOID
|
|
// BdSetupDebugRegisters
|
|
//
|
|
// Description:
|
|
//
|
|
// We maintain two debug register flags:
|
|
// 1. Thread DebugActive: Debug registers active for current thread
|
|
// 2. PCR KernelDebugActive: Debug registers active in kernel mode
|
|
// (setup by kernel debugger)
|
|
//
|
|
// On user -> kernel transitions there are four possibilities:
|
|
//
|
|
// Thread Kernel
|
|
// DebugActive DebugActive Action
|
|
//
|
|
// 1. 0 0 None
|
|
//
|
|
// 2. 1 0 None (kernel PSR.db = 0 by default)
|
|
//
|
|
// 3. 0 1 Set PSR.db = 1 for kernel
|
|
//
|
|
// 4. 1 1 Set PSR.db = 1 for kernel and
|
|
// load kernel debug registers
|
|
//
|
|
// Note we never save the user debug registers:
|
|
// the user cannot change the DRs so the values in the DR save area are
|
|
// always up-to-date (set by SetContext).
|
|
//
|
|
// Input:
|
|
//
|
|
// None (Previous mode is USER)
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdSetupDebugRegisters)
|
|
|
|
//
|
|
// *** TBD -- no support for kernel debug registers (KernelDebugActive = 0)
|
|
// All the calls to this function are removed and have to be reinstated
|
|
// when hardware debug support is implemented in the kernel debugger.
|
|
//
|
|
|
|
LEAF_RETURN
|
|
LEAF_EXIT(BdSetupDebugRegisters)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// VOID
|
|
// BdRestoreDebugRegisters
|
|
//
|
|
// Description:
|
|
//
|
|
// If debug active, restore user debug registers from DR save area in
|
|
// kernel stack.
|
|
//
|
|
// Input:
|
|
//
|
|
// None
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
// Note:
|
|
// We find the DR save are from the the StackBase not PCR->InitialStack,
|
|
// which can be changed in BdCallUserMode().
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdRestoreDebugRegisters)
|
|
|
|
//
|
|
// Local register aliases
|
|
//
|
|
|
|
rpSA0 = t0
|
|
rpSA1 = t1
|
|
rDebugActive = t2
|
|
rpT1 = t3
|
|
rPrcb = t4
|
|
rDr0 = t5
|
|
rDr1 = t6
|
|
rDrIndex0 = t7
|
|
rDrIndex1 = t8
|
|
rSaveLC = t9
|
|
rpCurrentThread = t10
|
|
rStackBase = t11
|
|
|
|
pNoRestore = pt0
|
|
|
|
//
|
|
// Restore debug registers, if debug active
|
|
//
|
|
|
|
movl rpT1 = BdPcr+PcCurrentThread
|
|
;;
|
|
mov rSaveLC = ar.lc // save
|
|
ld8 rpCurrentThread = [rpT1] // get Current thread pointer
|
|
;;
|
|
add rpT1 = ThDebugActive, rpCurrentThread
|
|
add rStackBase = ThStackBase, rpCurrentThread
|
|
;;
|
|
ld1 rDebugActive = [rpT1] // get thread debug active flag
|
|
;;
|
|
cmp.eq pNoRestore = zero, rDebugActive
|
|
(pNoRestore) br.sptk Krdr_Exit // skip if not active
|
|
;;
|
|
mov rDrIndex0 = 0
|
|
mov rDrIndex1 = 1
|
|
;;
|
|
add rpSA0 = -ThreadStateSaveAreaLength+TsDebugRegisters+DrDbI0,rStackBase
|
|
add rpSA1 = -ThreadStateSaveAreaLength+TsDebugRegisters+DrDbI1,rStackBase
|
|
mov ar.lc = 3 // 4 pair of ibr
|
|
;;
|
|
Krdr_ILoop:
|
|
ld8 rDr0 = [rpSA0], 16 // get ibr pair
|
|
ld8 rDr1 = [rpSA1], 16 // step by 16 = 1 pair of DRs
|
|
;;
|
|
.auto
|
|
mov ibr[rDrIndex0] = rDr0 // restore ibr pair
|
|
mov ibr[rDrIndex1] = rDr1
|
|
;;
|
|
add rDrIndex0 = 1, rDrIndex0 // next pair
|
|
add rDrIndex1 = 1, rDrIndex1
|
|
br.cloop.sptk Krdr_ILoop
|
|
;;
|
|
mov ar.lc = 3 // 4 pair of dbr
|
|
mov rDrIndex0 = 0
|
|
mov rDrIndex1 = 1
|
|
;;
|
|
Krdr_DLoop:
|
|
ld8 rDr0 = [rpSA0], 16 // get dbr pair
|
|
ld8 rDr1 = [rpSA1], 16 // step by 16 = 1 pair of DRs
|
|
;;
|
|
mov dbr[rDrIndex0] = rDr0 // restore dbr pair
|
|
mov dbr[rDrIndex1] = rDr1
|
|
;;
|
|
.default
|
|
add rDrIndex0 = 1, rDrIndex0 // next pair
|
|
add rDrIndex1 = 1, rDrIndex1
|
|
br.cloop.sptk Krdr_DLoop
|
|
;;
|
|
mov ar.lc = rSaveLC // restore
|
|
Krdr_Exit:
|
|
LEAF_RETURN
|
|
LEAF_EXIT(BdRestoreDebugRegisters)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// VOID
|
|
// BdSaveExceptionFrame(PKEXCEPTION_FRAME)
|
|
//
|
|
// Description:
|
|
//
|
|
// Save preserved context in exception frame.
|
|
//
|
|
// Input:
|
|
//
|
|
// a0: points to exception frame
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
// Note: t0 may contain the trap frame address; don't touch it.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdSaveExceptionFrame)
|
|
|
|
//
|
|
// Local register aliases
|
|
//
|
|
|
|
rpEF1 = t10
|
|
rpEF2 = t11
|
|
|
|
add rpEF1 = ExIntS0, a0 // -> ExIntS0
|
|
add rpEF2 = ExIntS1, a0 // -> ExIntS1
|
|
mov t3 = ar.ec
|
|
;;
|
|
|
|
.mem.offset 0,0
|
|
st8.spill [rpEF1] = s0, ExIntS2-ExIntS0
|
|
.mem.offset 8,0
|
|
st8.spill [rpEF2] = s1, ExIntS3-ExIntS1
|
|
mov t4 = ar.lc
|
|
;;
|
|
|
|
.mem.offset 0,0
|
|
st8.spill [rpEF1] = s2, ExApEC-ExIntS2
|
|
.mem.offset 8,0
|
|
st8.spill [rpEF2] = s3, ExApLC-ExIntS3
|
|
mov t5 = bs0
|
|
;;
|
|
|
|
st8 [rpEF1] = t3, ExBrS0-ExApEC
|
|
st8 [rpEF2] = t4, ExBrS1-ExApLC
|
|
mov t6 = bs1
|
|
;;
|
|
|
|
mov t2 = ar.unat // save user nat register for
|
|
mov t7 = bs2
|
|
mov t8 = bs3
|
|
|
|
st8 [rpEF1] = t5, ExBrS2-ExBrS0
|
|
st8 [rpEF2] = t6, ExBrS3-ExBrS1
|
|
mov t9 = bs4
|
|
;;
|
|
|
|
st8 [rpEF1] = t7, ExBrS4-ExBrS2
|
|
st8 [rpEF2] = t8, ExIntNats-ExBrS3
|
|
;;
|
|
|
|
st8 [rpEF1] = t9, ExFltS0-ExBrS4
|
|
st8 [rpEF2] = t2, ExFltS1-ExIntNats
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs0, ExFltS2-ExFltS0
|
|
stf.spill [rpEF2] = fs1, ExFltS3-ExFltS1
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs2, ExFltS4-ExFltS2
|
|
stf.spill [rpEF2] = fs3, ExFltS5-ExFltS3
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs4, ExFltS6-ExFltS4
|
|
stf.spill [rpEF2] = fs5, ExFltS7-ExFltS5
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs6, ExFltS8-ExFltS6
|
|
stf.spill [rpEF2] = fs7, ExFltS9-ExFltS7
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs8, ExFltS10-ExFltS8
|
|
stf.spill [rpEF2] = fs9, ExFltS11-ExFltS9
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs10, ExFltS12-ExFltS10
|
|
stf.spill [rpEF2] = fs11, ExFltS13-ExFltS11
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs12, ExFltS14-ExFltS12
|
|
stf.spill [rpEF2] = fs13, ExFltS15-ExFltS13
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs14, ExFltS16-ExFltS14
|
|
stf.spill [rpEF2] = fs15, ExFltS17-ExFltS15
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs16, ExFltS18-ExFltS16
|
|
stf.spill [rpEF2] = fs17, ExFltS19-ExFltS17
|
|
;;
|
|
|
|
stf.spill [rpEF1] = fs18
|
|
stf.spill [rpEF2] = fs19
|
|
LEAF_RETURN
|
|
;;
|
|
|
|
LEAF_EXIT(BdSaveExceptionFrame)
|
|
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// VOID
|
|
// BdRestoreExceptionFrame(PKEXCEPTION_FRAME)
|
|
//
|
|
// Description:
|
|
//
|
|
// Restores preserved context from the exception frame. Also
|
|
// restore volatile part of floating point context not restored with
|
|
// rest of volatile context.
|
|
//
|
|
// Input:
|
|
//
|
|
// a0: points to exception frame
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// none
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdRestoreExceptionFrame)
|
|
|
|
//
|
|
// Local register aliases
|
|
//
|
|
|
|
rpEF1 = t10
|
|
rpEF2 = t11
|
|
|
|
add rpEF1 = ExIntNats, a0
|
|
add rpEF2 = ExApEC, a0
|
|
;;
|
|
|
|
ld8 t2 = [rpEF1], ExBrS0-ExIntNats
|
|
ld8 t3 = [rpEF2], ExApLC-ExApEC
|
|
;;
|
|
|
|
ld8 t5 = [rpEF1], ExBrS1-ExBrS0
|
|
ld8 t4 = [rpEF2], ExBrS2-ExApLC
|
|
;;
|
|
|
|
mov ar.unat = t2
|
|
mov ar.ec = t3
|
|
;;
|
|
|
|
ld8 t6 = [rpEF1], ExBrS3-ExBrS1
|
|
ld8 t7 = [rpEF2], ExBrS4-ExBrS2
|
|
mov ar.lc = t4
|
|
;;
|
|
|
|
ld8 t8 = [rpEF1], ExIntS0-ExBrS3
|
|
ld8 t9 = [rpEF2], ExIntS1-ExBrS4
|
|
mov bs0 = t5
|
|
;;
|
|
|
|
ld8.fill s0 = [rpEF1], ExIntS2-ExIntS0
|
|
ld8.fill s1 = [rpEF2], ExIntS3-ExIntS1
|
|
mov bs1 = t6
|
|
;;
|
|
|
|
ld8.fill s2 = [rpEF1], ExFltS0-ExIntS2
|
|
ld8.fill s3 = [rpEF2], ExFltS1-ExIntS3
|
|
mov bs2 = t7
|
|
;;
|
|
|
|
ldf.fill fs0 = [rpEF1], ExFltS2-ExFltS0
|
|
ldf.fill fs1 = [rpEF2], ExFltS3-ExFltS1
|
|
mov bs3 = t8
|
|
;;
|
|
|
|
ldf.fill fs2 = [rpEF1], ExFltS4-ExFltS2
|
|
ldf.fill fs3 = [rpEF2], ExFltS5-ExFltS3
|
|
mov bs4 = t9
|
|
;;
|
|
|
|
ldf.fill fs4 = [rpEF1], ExFltS6-ExFltS4
|
|
ldf.fill fs5 = [rpEF2], ExFltS7-ExFltS5
|
|
;;
|
|
|
|
ldf.fill fs6 = [rpEF1], ExFltS8-ExFltS6
|
|
ldf.fill fs7 = [rpEF2], ExFltS9-ExFltS7
|
|
;;
|
|
|
|
ldf.fill fs8 = [rpEF1], ExFltS10-ExFltS8
|
|
ldf.fill fs9 = [rpEF2], ExFltS11-ExFltS9
|
|
;;
|
|
|
|
ldf.fill fs10 = [rpEF1], ExFltS12-ExFltS10
|
|
ldf.fill fs11 = [rpEF2], ExFltS13-ExFltS11
|
|
;;
|
|
|
|
ldf.fill fs12 = [rpEF1], ExFltS14-ExFltS12
|
|
ldf.fill fs13 = [rpEF2], ExFltS15-ExFltS13
|
|
;;
|
|
|
|
ldf.fill fs14 = [rpEF1], ExFltS16-ExFltS14
|
|
ldf.fill fs15 = [rpEF2], ExFltS17-ExFltS15
|
|
;;
|
|
|
|
ldf.fill fs16 = [rpEF1], ExFltS18-ExFltS16
|
|
ldf.fill fs17 = [rpEF2], ExFltS19-ExFltS17
|
|
;;
|
|
|
|
ldf.fill fs18 = [rpEF1]
|
|
ldf.fill fs19 = [rpEF2]
|
|
LEAF_RETURN
|
|
;;
|
|
LEAF_EXIT(BdRestoreExceptionFrame)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// BdSaveHigherFPVolatile(PKHIGHER_FP_SAVEAREA)
|
|
//
|
|
// Description:
|
|
//
|
|
// Save higher FP volatile context in higher FP save area
|
|
//
|
|
// Input:
|
|
//
|
|
// a0: pointer to higher FP save area
|
|
// brp: return address
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// None
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdSaveHigherFPVolatile)
|
|
|
|
//
|
|
// Local register aliases
|
|
//
|
|
|
|
rpSA1 = t0
|
|
rpSA2 = t1
|
|
|
|
//
|
|
// Spill higher floating point volatile registers f32-f127.
|
|
// Must add length of preserved area within FP save area to
|
|
// point to volatile save area.
|
|
//
|
|
|
|
//
|
|
// Clear DFH bit so the high floating point set may be saved by the kernel
|
|
// Disable interrupts so that save is atomic
|
|
//
|
|
|
|
rsm 1 << PSR_DFH
|
|
add rpSA1 = HiFltF32, a0 // -> HiFltF32
|
|
add rpSA2 = HiFltF33, a0 // -> HiFltF33
|
|
;;
|
|
|
|
srlz.d
|
|
|
|
stf.spill [rpSA1] = f32, HiFltF34-HiFltF32
|
|
stf.spill [rpSA2] = f33, HiFltF35-HiFltF33
|
|
;;
|
|
stf.spill [rpSA1] = f34, HiFltF36-HiFltF34
|
|
stf.spill [rpSA2] = f35, HiFltF37-HiFltF35
|
|
;;
|
|
stf.spill [rpSA1] = f36, HiFltF38-HiFltF36
|
|
stf.spill [rpSA2] = f37, HiFltF39-HiFltF37
|
|
;;
|
|
stf.spill [rpSA1] = f38, HiFltF40-HiFltF38
|
|
stf.spill [rpSA2] = f39, HiFltF41-HiFltF39
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f40, HiFltF42-HiFltF40
|
|
stf.spill [rpSA2] = f41, HiFltF43-HiFltF41
|
|
;;
|
|
stf.spill [rpSA1] = f42, HiFltF44-HiFltF42
|
|
stf.spill [rpSA2] = f43, HiFltF45-HiFltF43
|
|
;;
|
|
stf.spill [rpSA1] = f44, HiFltF46-HiFltF44
|
|
stf.spill [rpSA2] = f45, HiFltF47-HiFltF45
|
|
;;
|
|
stf.spill [rpSA1] = f46, HiFltF48-HiFltF46
|
|
stf.spill [rpSA2] = f47, HiFltF49-HiFltF47
|
|
;;
|
|
stf.spill [rpSA1] = f48, HiFltF50-HiFltF48
|
|
stf.spill [rpSA2] = f49, HiFltF51-HiFltF49
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f50, HiFltF52-HiFltF50
|
|
stf.spill [rpSA2] = f51, HiFltF53-HiFltF51
|
|
;;
|
|
stf.spill [rpSA1] = f52, HiFltF54-HiFltF52
|
|
stf.spill [rpSA2] = f53, HiFltF55-HiFltF53
|
|
;;
|
|
stf.spill [rpSA1] = f54, HiFltF56-HiFltF54
|
|
stf.spill [rpSA2] = f55, HiFltF57-HiFltF55
|
|
;;
|
|
stf.spill [rpSA1] = f56, HiFltF58-HiFltF56
|
|
stf.spill [rpSA2] = f57, HiFltF59-HiFltF57
|
|
;;
|
|
stf.spill [rpSA1] = f58, HiFltF60-HiFltF58
|
|
stf.spill [rpSA2] = f59, HiFltF61-HiFltF59
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f60, HiFltF62-HiFltF60
|
|
stf.spill [rpSA2] = f61, HiFltF63-HiFltF61
|
|
;;
|
|
stf.spill [rpSA1] = f62, HiFltF64-HiFltF62
|
|
stf.spill [rpSA2] = f63, HiFltF65-HiFltF63
|
|
;;
|
|
stf.spill [rpSA1] = f64, HiFltF66-HiFltF64
|
|
stf.spill [rpSA2] = f65, HiFltF67-HiFltF65
|
|
;;
|
|
stf.spill [rpSA1] = f66, HiFltF68-HiFltF66
|
|
stf.spill [rpSA2] = f67, HiFltF69-HiFltF67
|
|
;;
|
|
stf.spill [rpSA1] = f68, HiFltF70-HiFltF68
|
|
stf.spill [rpSA2] = f69, HiFltF71-HiFltF69
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f70, HiFltF72-HiFltF70
|
|
stf.spill [rpSA2] = f71, HiFltF73-HiFltF71
|
|
;;
|
|
stf.spill [rpSA1] = f72, HiFltF74-HiFltF72
|
|
stf.spill [rpSA2] = f73, HiFltF75-HiFltF73
|
|
;;
|
|
stf.spill [rpSA1] = f74, HiFltF76-HiFltF74
|
|
stf.spill [rpSA2] = f75, HiFltF77-HiFltF75
|
|
;;
|
|
stf.spill [rpSA1] = f76, HiFltF78-HiFltF76
|
|
stf.spill [rpSA2] = f77, HiFltF79-HiFltF77
|
|
;;
|
|
stf.spill [rpSA1] = f78, HiFltF80-HiFltF78
|
|
stf.spill [rpSA2] = f79, HiFltF81-HiFltF79
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f80, HiFltF82-HiFltF80
|
|
stf.spill [rpSA2] = f81, HiFltF83-HiFltF81
|
|
;;
|
|
stf.spill [rpSA1] = f82, HiFltF84-HiFltF82
|
|
stf.spill [rpSA2] = f83, HiFltF85-HiFltF83
|
|
;;
|
|
stf.spill [rpSA1] = f84, HiFltF86-HiFltF84
|
|
stf.spill [rpSA2] = f85, HiFltF87-HiFltF85
|
|
;;
|
|
stf.spill [rpSA1] = f86, HiFltF88-HiFltF86
|
|
stf.spill [rpSA2] = f87, HiFltF89-HiFltF87
|
|
;;
|
|
stf.spill [rpSA1] = f88, HiFltF90-HiFltF88
|
|
stf.spill [rpSA2] = f89, HiFltF91-HiFltF89
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f90, HiFltF92-HiFltF90
|
|
stf.spill [rpSA2] = f91, HiFltF93-HiFltF91
|
|
;;
|
|
stf.spill [rpSA1] = f92, HiFltF94-HiFltF92
|
|
stf.spill [rpSA2] = f93, HiFltF95-HiFltF93
|
|
;;
|
|
stf.spill [rpSA1] = f94, HiFltF96-HiFltF94
|
|
stf.spill [rpSA2] = f95, HiFltF97-HiFltF95
|
|
;;
|
|
stf.spill [rpSA1] = f96, HiFltF98-HiFltF96
|
|
stf.spill [rpSA2] = f97, HiFltF99-HiFltF97
|
|
;;
|
|
stf.spill [rpSA1] = f98, HiFltF100-HiFltF98
|
|
stf.spill [rpSA2] = f99, HiFltF101-HiFltF99
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f100, HiFltF102-HiFltF100
|
|
stf.spill [rpSA2] = f101, HiFltF103-HiFltF101
|
|
;;
|
|
stf.spill [rpSA1] = f102, HiFltF104-HiFltF102
|
|
stf.spill [rpSA2] = f103, HiFltF105-HiFltF103
|
|
;;
|
|
stf.spill [rpSA1] = f104, HiFltF106-HiFltF104
|
|
stf.spill [rpSA2] = f105, HiFltF107-HiFltF105
|
|
;;
|
|
stf.spill [rpSA1] = f106, HiFltF108-HiFltF106
|
|
stf.spill [rpSA2] = f107, HiFltF109-HiFltF107
|
|
;;
|
|
stf.spill [rpSA1] = f108, HiFltF110-HiFltF108
|
|
stf.spill [rpSA2] = f109, HiFltF111-HiFltF109
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f110, HiFltF112-HiFltF110
|
|
stf.spill [rpSA2] = f111, HiFltF113-HiFltF111
|
|
;;
|
|
stf.spill [rpSA1] = f112, HiFltF114-HiFltF112
|
|
stf.spill [rpSA2] = f113, HiFltF115-HiFltF113
|
|
;;
|
|
stf.spill [rpSA1] = f114, HiFltF116-HiFltF114
|
|
stf.spill [rpSA2] = f115, HiFltF117-HiFltF115
|
|
;;
|
|
stf.spill [rpSA1] = f116, HiFltF118-HiFltF116
|
|
stf.spill [rpSA2] = f117, HiFltF119-HiFltF117
|
|
;;
|
|
stf.spill [rpSA1] = f118, HiFltF120-HiFltF118
|
|
stf.spill [rpSA2] = f119, HiFltF121-HiFltF119
|
|
;;
|
|
|
|
stf.spill [rpSA1] = f120, HiFltF122-HiFltF120
|
|
stf.spill [rpSA2] = f121, HiFltF123-HiFltF121
|
|
;;
|
|
stf.spill [rpSA1] = f122, HiFltF124-HiFltF122
|
|
stf.spill [rpSA2] = f123, HiFltF125-HiFltF123
|
|
;;
|
|
stf.spill [rpSA1] = f124, HiFltF126-HiFltF124
|
|
stf.spill [rpSA2] = f125, HiFltF127-HiFltF125
|
|
;;
|
|
stf.spill [rpSA1] = f126
|
|
stf.spill [rpSA2] = f127
|
|
|
|
//
|
|
// Set DFH bit so the high floating point set may not be used by the kernel
|
|
// Must clear mfh after fp registers saved
|
|
//
|
|
|
|
rsm 1 << PSR_MFH
|
|
ssm 1 << PSR_DFH
|
|
;;
|
|
srlz.d
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(BdSaveHigherFPVolatile)
|
|
|
|
//++
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// BdRestoreHigherFPVolatile()
|
|
//
|
|
// Description:
|
|
//
|
|
// Restore higher FP volatile context from higher FP save area
|
|
//
|
|
// N.B. This function is carefully constructed to use only scratch
|
|
// registers rHpT1, rHpT3, and rTH2. This function may be
|
|
// called by C code and the disabled fp vector when user
|
|
// and kernel bank is used respectively.
|
|
// N.B. Caller must ensure higher fp enabled (psr.dfh=0)
|
|
// N.B. Caller must ensure no interrupt during restore
|
|
//
|
|
// Input:
|
|
//
|
|
// None.
|
|
//
|
|
// Output:
|
|
//
|
|
// None
|
|
//
|
|
// Return value:
|
|
//
|
|
// None
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LEAF_ENTRY(BdRestoreHigherFPVolatile)
|
|
|
|
//
|
|
// rHpT1 & rHpT3 are 2 registers that are available as
|
|
// scratch registers in this function.
|
|
//
|
|
|
|
srlz.d
|
|
movl rHpT1 = BdPcr+PcInitialStack
|
|
;;
|
|
|
|
ld8 rTH2 = [rHpT1]
|
|
;;
|
|
add rHpT1 = -ThreadStateSaveAreaLength+TsHigherFPVolatile+HiFltF32, rTH2
|
|
add rHpT3 = -ThreadStateSaveAreaLength+TsHigherFPVolatile+HiFltF33, rTH2
|
|
;;
|
|
|
|
ldf.fill f32 = [rHpT1], HiFltF34-HiFltF32
|
|
ldf.fill f33 = [rHpT3], HiFltF35-HiFltF33
|
|
;;
|
|
|
|
ldf.fill f34 = [rHpT1], HiFltF36-HiFltF34
|
|
ldf.fill f35 = [rHpT3], HiFltF37-HiFltF35
|
|
;;
|
|
ldf.fill f36 = [rHpT1], HiFltF38-HiFltF36
|
|
ldf.fill f37 = [rHpT3], HiFltF39-HiFltF37
|
|
;;
|
|
ldf.fill f38 = [rHpT1], HiFltF40-HiFltF38
|
|
ldf.fill f39 = [rHpT3], HiFltF41-HiFltF39
|
|
;;
|
|
|
|
ldf.fill f40 = [rHpT1], HiFltF42-HiFltF40
|
|
ldf.fill f41 = [rHpT3], HiFltF43-HiFltF41
|
|
;;
|
|
ldf.fill f42 = [rHpT1], HiFltF44-HiFltF42
|
|
ldf.fill f43 = [rHpT3], HiFltF45-HiFltF43
|
|
;;
|
|
ldf.fill f44 = [rHpT1], HiFltF46-HiFltF44
|
|
ldf.fill f45 = [rHpT3], HiFltF47-HiFltF45
|
|
;;
|
|
ldf.fill f46 = [rHpT1], HiFltF48-HiFltF46
|
|
ldf.fill f47 = [rHpT3], HiFltF49-HiFltF47
|
|
;;
|
|
ldf.fill f48 = [rHpT1], HiFltF50-HiFltF48
|
|
ldf.fill f49 = [rHpT3], HiFltF51-HiFltF49
|
|
;;
|
|
|
|
ldf.fill f50 = [rHpT1], HiFltF52-HiFltF50
|
|
ldf.fill f51 = [rHpT3], HiFltF53-HiFltF51
|
|
;;
|
|
ldf.fill f52 = [rHpT1], HiFltF54-HiFltF52
|
|
ldf.fill f53 = [rHpT3], HiFltF55-HiFltF53
|
|
;;
|
|
ldf.fill f54 = [rHpT1], HiFltF56-HiFltF54
|
|
ldf.fill f55 = [rHpT3], HiFltF57-HiFltF55
|
|
;;
|
|
ldf.fill f56 = [rHpT1], HiFltF58-HiFltF56
|
|
ldf.fill f57 = [rHpT3], HiFltF59-HiFltF57
|
|
;;
|
|
ldf.fill f58 = [rHpT1], HiFltF60-HiFltF58
|
|
ldf.fill f59 = [rHpT3], HiFltF61-HiFltF59
|
|
;;
|
|
|
|
ldf.fill f60 = [rHpT1], HiFltF62-HiFltF60
|
|
ldf.fill f61 = [rHpT3], HiFltF63-HiFltF61
|
|
;;
|
|
ldf.fill f62 = [rHpT1], HiFltF64-HiFltF62
|
|
ldf.fill f63 = [rHpT3], HiFltF65-HiFltF63
|
|
;;
|
|
ldf.fill f64 = [rHpT1], HiFltF66-HiFltF64
|
|
ldf.fill f65 = [rHpT3], HiFltF67-HiFltF65
|
|
;;
|
|
ldf.fill f66 = [rHpT1], HiFltF68-HiFltF66
|
|
ldf.fill f67 = [rHpT3], HiFltF69-HiFltF67
|
|
;;
|
|
ldf.fill f68 = [rHpT1], HiFltF70-HiFltF68
|
|
ldf.fill f69 = [rHpT3], HiFltF71-HiFltF69
|
|
;;
|
|
|
|
ldf.fill f70 = [rHpT1], HiFltF72-HiFltF70
|
|
ldf.fill f71 = [rHpT3], HiFltF73-HiFltF71
|
|
;;
|
|
ldf.fill f72 = [rHpT1], HiFltF74-HiFltF72
|
|
ldf.fill f73 = [rHpT3], HiFltF75-HiFltF73
|
|
;;
|
|
ldf.fill f74 = [rHpT1], HiFltF76-HiFltF74
|
|
ldf.fill f75 = [rHpT3], HiFltF77-HiFltF75
|
|
;;
|
|
ldf.fill f76 = [rHpT1], HiFltF78-HiFltF76
|
|
ldf.fill f77 = [rHpT3], HiFltF79-HiFltF77
|
|
;;
|
|
ldf.fill f78 = [rHpT1], HiFltF80-HiFltF78
|
|
ldf.fill f79 = [rHpT3], HiFltF81-HiFltF79
|
|
;;
|
|
|
|
ldf.fill f80 = [rHpT1], HiFltF82-HiFltF80
|
|
ldf.fill f81 = [rHpT3], HiFltF83-HiFltF81
|
|
;;
|
|
ldf.fill f82 = [rHpT1], HiFltF84-HiFltF82
|
|
ldf.fill f83 = [rHpT3], HiFltF85-HiFltF83
|
|
;;
|
|
ldf.fill f84 = [rHpT1], HiFltF86-HiFltF84
|
|
ldf.fill f85 = [rHpT3], HiFltF87-HiFltF85
|
|
;;
|
|
ldf.fill f86 = [rHpT1], HiFltF88-HiFltF86
|
|
ldf.fill f87 = [rHpT3], HiFltF89-HiFltF87
|
|
;;
|
|
ldf.fill f88 = [rHpT1], HiFltF90-HiFltF88
|
|
ldf.fill f89 = [rHpT3], HiFltF91-HiFltF89
|
|
;;
|
|
|
|
ldf.fill f90 = [rHpT1], HiFltF92-HiFltF90
|
|
ldf.fill f91 = [rHpT3], HiFltF93-HiFltF91
|
|
;;
|
|
ldf.fill f92 = [rHpT1], HiFltF94-HiFltF92
|
|
ldf.fill f93 = [rHpT3], HiFltF95-HiFltF93
|
|
;;
|
|
ldf.fill f94 = [rHpT1], HiFltF96-HiFltF94
|
|
ldf.fill f95 = [rHpT3], HiFltF97-HiFltF95
|
|
;;
|
|
ldf.fill f96 = [rHpT1], HiFltF98-HiFltF96
|
|
ldf.fill f97 = [rHpT3], HiFltF99-HiFltF97
|
|
;;
|
|
ldf.fill f98 = [rHpT1], HiFltF100-HiFltF98
|
|
ldf.fill f99 = [rHpT3], HiFltF101-HiFltF99
|
|
;;
|
|
|
|
ldf.fill f100 = [rHpT1], HiFltF102-HiFltF100
|
|
ldf.fill f101 = [rHpT3], HiFltF103-HiFltF101
|
|
;;
|
|
ldf.fill f102 = [rHpT1], HiFltF104-HiFltF102
|
|
ldf.fill f103 = [rHpT3], HiFltF105-HiFltF103
|
|
;;
|
|
ldf.fill f104 = [rHpT1], HiFltF106-HiFltF104
|
|
ldf.fill f105 = [rHpT3], HiFltF107-HiFltF105
|
|
;;
|
|
ldf.fill f106 = [rHpT1], HiFltF108-HiFltF106
|
|
ldf.fill f107 = [rHpT3], HiFltF109-HiFltF107
|
|
;;
|
|
ldf.fill f108 = [rHpT1], HiFltF110-HiFltF108
|
|
ldf.fill f109 = [rHpT3], HiFltF111-HiFltF109
|
|
;;
|
|
|
|
ldf.fill f110 = [rHpT1], HiFltF112-HiFltF110
|
|
ldf.fill f111 = [rHpT3], HiFltF113-HiFltF111
|
|
;;
|
|
ldf.fill f112 = [rHpT1], HiFltF114-HiFltF112
|
|
ldf.fill f113 = [rHpT3], HiFltF115-HiFltF113
|
|
;;
|
|
ldf.fill f114 = [rHpT1], HiFltF116-HiFltF114
|
|
ldf.fill f115 = [rHpT3], HiFltF117-HiFltF115
|
|
;;
|
|
ldf.fill f116 = [rHpT1], HiFltF118-HiFltF116
|
|
ldf.fill f117 = [rHpT3], HiFltF119-HiFltF117
|
|
;;
|
|
ldf.fill f118 = [rHpT1], HiFltF120-HiFltF118
|
|
ldf.fill f119 = [rHpT3], HiFltF121-HiFltF119
|
|
;;
|
|
|
|
ldf.fill f120 = [rHpT1], HiFltF122-HiFltF120
|
|
ldf.fill f121 = [rHpT3], HiFltF123-HiFltF121
|
|
;;
|
|
ldf.fill f122 = [rHpT1], HiFltF124-HiFltF122
|
|
ldf.fill f123 = [rHpT3], HiFltF125-HiFltF123
|
|
;;
|
|
ldf.fill f124 = [rHpT1], HiFltF126-HiFltF124
|
|
ldf.fill f125 = [rHpT3], HiFltF127-HiFltF125
|
|
;;
|
|
ldf.fill f126 = [rHpT1]
|
|
ldf.fill f127 = [rHpT3]
|
|
;;
|
|
|
|
rsm 1 << PSR_MFH // clear psr.mfh bit
|
|
br.ret.sptk brp
|
|
;;
|
|
|
|
LEAF_EXIT(BdRestoreHigherFPVolatile)
|
|
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine begins the common code for raising an exception.
|
|
// The routine saves the non-volatile state and dispatches to the
|
|
// next level exception dispatcher.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - pointer to trap frame
|
|
// a1 - previous mode
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
NESTED_ENTRY(BdExceptionDispatch)
|
|
|
|
//
|
|
// Build exception frame
|
|
//
|
|
|
|
.regstk 2, 3, 5, 0
|
|
.prologue 0xA, loc0
|
|
alloc t16 = ar.pfs, 2, 3, 5, 0
|
|
mov loc0 = sp
|
|
cmp4.eq pt0 = UserMode, a1 // previous mode is user?
|
|
|
|
mov loc1 = brp
|
|
add sp = -ExceptionFrameLength, sp
|
|
;;
|
|
|
|
.save ar.unat, loc2
|
|
mov loc2 = ar.unat
|
|
add t0 = ExFltS19+STACK_SCRATCH_AREA, sp
|
|
add t1 = ExFltS18+STACK_SCRATCH_AREA, sp
|
|
;;
|
|
|
|
.save.gf 0x0, 0xC0000
|
|
stf.spill [t0] = fs19, ExFltS17-ExFltS19
|
|
stf.spill [t1] = fs18, ExFltS16-ExFltS18
|
|
;;
|
|
|
|
.save.gf 0x0, 0x30000
|
|
stf.spill [t0] = fs17, ExFltS15-ExFltS17
|
|
stf.spill [t1] = fs16, ExFltS14-ExFltS16
|
|
mov t10 = bs4
|
|
;;
|
|
|
|
.save.gf 0x0, 0xC000
|
|
stf.spill [t0] = fs15, ExFltS13-ExFltS15
|
|
stf.spill [t1] = fs14, ExFltS12-ExFltS14
|
|
mov t11 = bs3
|
|
;;
|
|
|
|
.save.gf 0x0, 0x3000
|
|
stf.spill [t0] = fs13, ExFltS11-ExFltS13
|
|
stf.spill [t1] = fs12, ExFltS10-ExFltS12
|
|
mov t12 = bs2
|
|
;;
|
|
|
|
.save.gf 0x0, 0xC00
|
|
stf.spill [t0] = fs11, ExFltS9-ExFltS11
|
|
stf.spill [t1] = fs10, ExFltS8-ExFltS10
|
|
mov t13 = bs1
|
|
;;
|
|
|
|
.save.gf 0x0, 0x300
|
|
stf.spill [t0] = fs9, ExFltS7-ExFltS9
|
|
stf.spill [t1] = fs8, ExFltS6-ExFltS8
|
|
mov t14 = bs0
|
|
;;
|
|
|
|
.save.gf 0x0, 0xC0
|
|
stf.spill [t0] = fs7, ExFltS5-ExFltS7
|
|
stf.spill [t1] = fs6, ExFltS4-ExFltS6
|
|
mov t15 = ar.lc
|
|
;;
|
|
|
|
.save.gf 0x0, 0x30
|
|
stf.spill [t0] = fs5, ExFltS3-ExFltS5
|
|
stf.spill [t1] = fs4, ExFltS2-ExFltS4
|
|
;;
|
|
|
|
.save.f 0xC
|
|
stf.spill [t0] = fs3, ExFltS1-ExFltS3 // save fs3
|
|
stf.spill [t1] = fs2, ExFltS0-ExFltS2 // save fs2
|
|
;;
|
|
|
|
.save.f 0x3
|
|
stf.spill [t0] = fs1, ExBrS4-ExFltS1 // save fs1
|
|
stf.spill [t1] = fs0, ExBrS3-ExFltS0 // save fs0
|
|
;;
|
|
|
|
.save.b 0x18
|
|
st8 [t0] = t10, ExBrS2-ExBrS4 // save bs4
|
|
st8 [t1] = t11, ExBrS1-ExBrS3 // save bs3
|
|
;;
|
|
|
|
.save.b 0x6
|
|
st8 [t0] = t12, ExBrS0-ExBrS2 // save bs2
|
|
st8 [t1] = t13, ExIntS2-ExBrS1 // save bs1
|
|
;;
|
|
|
|
.save.b 0x1
|
|
st8 [t0] = t14, ExIntS3-ExBrS0 // save bs0
|
|
(pt0) add out0 = TrapFrameLength+TsHigherFPVolatile, a0
|
|
;;
|
|
|
|
.save.gf 0xC, 0x0
|
|
.mem.offset 0,0
|
|
st8.spill [t0] = s3, ExIntS1-ExIntS3 // save s3
|
|
.mem.offset 8,0
|
|
st8.spill [t1] = s2, ExIntS0-ExIntS2 // save s2
|
|
;;
|
|
|
|
.save.gf 0x3, 0x0
|
|
.mem.offset 0,0
|
|
st8.spill [t0] = s1, ExApLC-ExIntS1 // save s1
|
|
.mem.offset 8,0
|
|
st8.spill [t1] = s0, ExApEC-ExIntS0 // save s0
|
|
;;
|
|
|
|
.savepsp ar.pfs, ExceptionFrameLength-ExApEC-STACK_SCRATCH_AREA
|
|
st8 [t1] = t16, ExIntNats-ExApEC
|
|
mov t4 = ar.unat // captured Nats of s0-s3
|
|
;;
|
|
|
|
.savepsp ar.lc, ExceptionFrameLength-ExApLC-STACK_SCRATCH_AREA
|
|
st8 [t0] = t15
|
|
.savepsp @priunat, ExceptionFrameLength-ExIntNats-STACK_SCRATCH_AREA
|
|
st8 [t1] = t4 // save Nats of s0-s3
|
|
(pt0) br.call.sptk brp = BdSaveHigherFPVolatile
|
|
;;
|
|
|
|
|
|
PROLOGUE_END
|
|
|
|
add out0 = TrExceptionRecord, a0 // -> exception record
|
|
add out1 = STACK_SCRATCH_AREA, sp // -> exception frame
|
|
mov out2 = a0 // -> trap frame
|
|
|
|
br.call.sptk.many brp = BdTrap
|
|
|
|
add t1 = ExApEC+STACK_SCRATCH_AREA, sp
|
|
movl t0 = BdExceptionExit
|
|
;;
|
|
|
|
ld8 t1 = [t1]
|
|
mov brp = t0
|
|
;;
|
|
|
|
mov ar.unat = loc2
|
|
mov ar.pfs = t1
|
|
|
|
add s1 = STACK_SCRATCH_AREA, sp // s1 -> exception frame
|
|
mov s0 = a0 // s0 -> trap frame
|
|
br.ret.sptk brp
|
|
;;
|
|
|
|
ALTERNATE_ENTRY(BdExceptionExit)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine is called to exit from an exception.
|
|
//
|
|
// N.B. This transfer of control occurs from:
|
|
//
|
|
// 1. fall-through from above
|
|
// 2. exit from continue system service
|
|
// 3. exit from raise exception system service
|
|
// 4. exit into user mode from thread startup
|
|
//
|
|
// Arguments:
|
|
//
|
|
// loc0 - pointer to trap frame
|
|
// sp - pointer to high preserved float save area + STACK_SCRATCH_AREA
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Does not return.
|
|
//
|
|
//--
|
|
|
|
//
|
|
// upon entry of this block, s0 and s1 must be set to the address of
|
|
// the trap and the exception frames respectively.
|
|
//
|
|
// preserved state is restored here because they may have been modified
|
|
// by SetContext
|
|
//
|
|
|
|
|
|
LEAF_SETUP(0, 1, 2, 0) // must be in sync with
|
|
// BdGenericExceptionHandler
|
|
mov loc0 = s0 // -> trap frame
|
|
mov out0 = s1 // -> exception frame
|
|
;;
|
|
|
|
br.call.sptk brp = BdRestoreExceptionFrame
|
|
;;
|
|
|
|
mov sp = loc0 // deallocate exception
|
|
// frame by restoring sp
|
|
|
|
ALTERNATE_ENTRY(BdAlternateExit)
|
|
|
|
//
|
|
// sp -> trap frame addres
|
|
//
|
|
// Interrupts disabled from here to rfi
|
|
//
|
|
|
|
FAST_DISABLE_INTERRUPTS
|
|
;;
|
|
|
|
RETURN_FROM_INTERRUPTION(Ked)
|
|
|
|
NESTED_EXIT(BdExceptionDispatch)
|
|
|
|
|
|
|
|
NESTED_ENTRY(BdInstallVectors)
|
|
NESTED_SETUP (3,17,8,0)
|
|
|
|
IpValue:
|
|
mov loc4 = ip
|
|
movl loc5 = IpValue
|
|
;;
|
|
|
|
sub loc6 = loc4, loc5 // relocation = runtime add - link addr
|
|
mov loc8 = cr.iva
|
|
;;
|
|
|
|
//
|
|
// Set Break Instrution Vector
|
|
//
|
|
movl loc7 = 0x2C00
|
|
;;
|
|
|
|
add out0 = loc7, loc8 // out0 = address of IVT vector
|
|
movl out1 = BdBreakVector // out2 = address of exception handler
|
|
// (static value) to be plugged into IVT
|
|
mov out2 = loc6 // adjustment to go from static to runtime
|
|
br.call.dpnt.few brp = BdUpdateIvt // Fill in the address of routine into IVT
|
|
|
|
//
|
|
// Set Taken Branch Vector
|
|
//
|
|
movl loc7 = 0x5F00
|
|
;;
|
|
|
|
add out0 = loc7, loc8 // out0 = address of IVT vector
|
|
movl out1 = BdTakenBranchVector // out2 = address of exception handler
|
|
// (static value) to be plugged into IVT
|
|
mov out2 = loc6 // adjustment to go from static to runtime
|
|
br.call.dpnt.few brp = BdUpdateIvt // Fill in the address of routine into IVT
|
|
|
|
//
|
|
// Set Single Step Vector
|
|
//
|
|
movl loc7 = 0x6000
|
|
;;
|
|
|
|
add out0 = loc7, loc8 // out0 = address of IVT vector
|
|
movl out1 = BdSingleStepVector // out2 = address of exception handler
|
|
// (static value) to be plugged into IVT
|
|
mov out2 = loc6 // adjustment to go from static to runtime
|
|
br.call.dpnt.few brp = BdUpdateIvt // Fill in the address of routine into IVT
|
|
|
|
NESTED_RETURN
|
|
NESTED_EXIT(BdInstallVectors) // Return to caller using B0
|
|
|
|
|
|
//-------------------------------------------------
|
|
//
|
|
// BdUpdateIvt : Routine to fill in an entry into the IVT.
|
|
// This is a leaf routine.
|
|
//
|
|
// in0 = address of IVT vector
|
|
// in1 = address of exception handler (static value) to be plugged into IVT
|
|
// in2 = adjustment to go from static to runtime
|
|
//
|
|
//-------------------------------------------------
|
|
NESTED_ENTRY(BdUpdateIvt)
|
|
NESTED_SETUP (8,16,4,0)
|
|
|
|
mov out0 = in0
|
|
movl out1 = BdIvtStart
|
|
movl out2 = BdIvtEnd - BdIvtStart
|
|
;;
|
|
|
|
br.call.sptk brp = memcpy
|
|
;;
|
|
|
|
mov out0 = in0
|
|
mov out1 = in1
|
|
;;
|
|
br.call.sptk brp = BdSetMovlImmediate
|
|
|
|
NESTED_RETURN
|
|
NESTED_EXIT(BdUpdateIvt) // Return to caller using B0
|
|
|
|
|
|
BdIvtStart:
|
|
{
|
|
.mlx
|
|
nop.m 0
|
|
movl h31 = BdIvtStart
|
|
;;
|
|
}
|
|
{
|
|
.mii
|
|
nop.m 0
|
|
nop.i 0
|
|
mov h30 = b7
|
|
;;
|
|
}
|
|
{
|
|
.mii
|
|
nop.m 0
|
|
nop.i 0
|
|
mov b7 = h31
|
|
;;
|
|
}
|
|
{
|
|
.mib
|
|
nop.m 0
|
|
nop.i 0
|
|
(p0) br.sptk.few b7
|
|
;;
|
|
}
|
|
BdIvtEnd:
|
|
|
|
//
|
|
// All non-VECTOR_ENTRY functions must follow KiNormalSystemCall.
|
|
//
|
|
// N.B. KiNormalSystemCall must be the first function body in the .nsc
|
|
// section.
|
|
//
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// Routine:
|
|
//
|
|
// KiNormalSystemCall
|
|
//
|
|
// Description:
|
|
//
|
|
// Handler for normal (not fast) system calls
|
|
//
|
|
// On entry:
|
|
//
|
|
// ic off
|
|
// interrupts disabled
|
|
// v0: contains sys call #
|
|
// cover done by call
|
|
// r32-r39: sys call arguments
|
|
// CFM: sof = # args, ins = 0, outs = # args
|
|
//
|
|
// Return value:
|
|
//
|
|
// v0: system call return value
|
|
//
|
|
// Process:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
#if 0
|
|
.section .drectve, "MI", "progbits"
|
|
string " -section:.nsc,,align=0x4000"
|
|
|
|
.section .nsc = "ax", "progbits"
|
|
#endif
|
|
|
|
HANDLER_ENTRY_EX(KiNormalSystemCall, BdRestoreTrapFrame)
|
|
|
|
.prologue
|
|
.unwabi @nt, SYSCALL_FRAME
|
|
|
|
rThread = t1 // current thread
|
|
rIFS = t1
|
|
rIIP = t2
|
|
rPreds = t3
|
|
rIPSR = t4
|
|
rUNAT = t5
|
|
|
|
rSp = t6
|
|
|
|
rpT1 = t7
|
|
rpT2 = t8
|
|
rpT3 = t9
|
|
rpT4 = t10
|
|
rT0 = t11
|
|
rT1 = t12
|
|
rT2 = t13
|
|
rT3 = t14
|
|
rT4 = t15
|
|
|
|
rIntNats = t17
|
|
|
|
rpSd = t16 /* -> service descriptor entry */
|
|
rSdOffset = t17 /* service descriptor offset */
|
|
rArgTable = t18 /* pointer to argument table */
|
|
rArgNum = t20 /* number of arguments */
|
|
rArgBytes = t21
|
|
|
|
rpBSPStore = t16
|
|
rRscD = t16
|
|
rRNAT = t17
|
|
rRscE = t18
|
|
rKBSPStore = t18
|
|
rBSPStore = t19
|
|
rpBSP = t20
|
|
rRscDelta = t20
|
|
|
|
rBSP = t21
|
|
rPreviousMode = t22
|
|
|
|
pInvl = pt0 /* pInvl = not GUI service */
|
|
pVal = pt1
|
|
pGui = pt2 /* true if GUI call */
|
|
pNoGui = pt3 /* true if no GUI call */
|
|
pNatedArg = pt4 /* true if any input argument */
|
|
/* register is Nat'ed */
|
|
pNoCopy = pt5 /* no in-memory arguments to copy */
|
|
pCopy = pt6
|
|
|
|
|
|
mov rUNAT = ar.unat
|
|
tnat.nz pt0 = sp
|
|
mov rPreviousMode = KernelMode
|
|
|
|
mov rIPSR = psr
|
|
rsm 1 << PSR_I | 1 << PSR_MFH
|
|
br.sptk BdRestoreTrapFrame
|
|
|
|
HANDLER_EXIT(KiNormalSystemCall)
|