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.
1305 lines
30 KiB
1305 lines
30 KiB
//++
|
|
//
|
|
// Module Name:
|
|
//
|
|
// miscs.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements machine dependent miscellaneous kernel functions.
|
|
// Functions are provided to request a software interrupt, continue thread
|
|
// execution, flush TLBs and write buffers, and perform last chance
|
|
// exception processing.
|
|
//
|
|
// Author:
|
|
//
|
|
// William K. Cheung (wcheung) 3-Nov-1995
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode only.
|
|
//
|
|
// Revision History:
|
|
//
|
|
// 7-Jul-1997 bl Updated to EAS2.3
|
|
//
|
|
// 27-Feb-1996 wc Updated to EAS2.1
|
|
//
|
|
// 11-Jan-1996 wc Set up register sp to point to the exception frame
|
|
// on the stack before calling KiSaveExceptionFrame and
|
|
// branching directly to KiExceptionExit.
|
|
//
|
|
//--
|
|
|
|
#include "ksia64.h"
|
|
|
|
#define IPI_FREEZE_SHIFT 2
|
|
#if IPI_FREEZE != 1 << IPI_FREEZE_SHIFT
|
|
#error IPI_FREEZE_SHIFT incorrect!
|
|
#endif
|
|
|
|
//
|
|
// Global symbols
|
|
//
|
|
|
|
PublicFunction(KiContinue)
|
|
PublicFunction(KiSaveExceptionFrame)
|
|
PublicFunction(KeTestAlertThread)
|
|
PublicFunction(KiExceptionExit)
|
|
PublicFunction(KiRaiseException)
|
|
PublicFunction(KiLoadKernelDebugRegisters)
|
|
PublicFunction(KeIsExecutingDpc)
|
|
|
|
|
|
|
|
//
|
|
//++
|
|
//
|
|
// NTSTATUS
|
|
// NtContinue (
|
|
// IN PCONTEXT ContextRecord,
|
|
// IN BOOLEAN TestAlert
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine is called as a system service to continue execution after
|
|
// an exception has occurred. Its functions is to transfer information from
|
|
// the specified context record into the trap frame that was built when the
|
|
// system service was executed, and then exit the system as if an exception
|
|
// had occurred.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// ContextRecord (a0) - Supplies a pointer to a context record.
|
|
//
|
|
// TestAlert (a1) - Supplies a boolean value that specifies whether alert
|
|
// should be tested for the previous processor mode.
|
|
//
|
|
// N.B. Register t0 is assumed to contain the address of a trap frame.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Normally there is no return from this routine. However, if the specified
|
|
// context record is misaligned or is not accessible, then the appropriate
|
|
// status code is returned.
|
|
//
|
|
//--
|
|
|
|
NESTED_ENTRY(NtContinue)
|
|
|
|
NESTED_SETUP(2,4,3,0)
|
|
.fframe ExceptionFrameLength
|
|
add sp = -ExceptionFrameLength, sp
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// Transfer information from the context record to the exception and trap
|
|
// frames.
|
|
//
|
|
// N.B. Must zero the loadrs bit-field of Context->RsRSC
|
|
//
|
|
|
|
add t1 = TrStIPSR, t0 // -> TrapFrame->StIPSR
|
|
mov loc2 = t0
|
|
;;
|
|
|
|
ld8 loc3 = [t1] // load TrapFrame->StIPSR
|
|
mov out0 = a0 // context frame address
|
|
;;
|
|
|
|
add out1 = STACK_SCRATCH_AREA, sp // -> exception frame
|
|
mov out2 = t0 // trap frame address
|
|
br.call.sptk.many brp = KiContinue
|
|
;;
|
|
|
|
//
|
|
// If KiContinue() returns success, then exit via the exception exit code.
|
|
// Otherwise, return to the system service dispatcher.
|
|
//
|
|
// Check to determine if alert should be tested for the previous processor
|
|
// mode and restore the previous mode in the thread object.
|
|
//
|
|
// Application that invokes the NtContinue() system service must have
|
|
// flushed all stacked registers to the backing store. Sanitize the
|
|
// bspstore to be equal to bsp; otherwise, some stacked GRs will not be
|
|
// restored from the backing store.
|
|
//
|
|
|
|
add t0 = TrStIPSR, loc2
|
|
movl t7 = 1 << PSR_TB | 1 << PSR_DB | 1 << PSR_SS | 1 << PSR_PP
|
|
;;
|
|
|
|
ld8 t8 = [t0]
|
|
cmp.ne pt0 = zero, v0 // if ne, transfer failed.
|
|
;;
|
|
(pt0) dep t7 = 1, t7, PSR_LP, 1 // capture psr.lp if failed
|
|
;;
|
|
add t2 = TrTrapFrame, loc2
|
|
// andcm t8 = t8, t7 // Clear old values
|
|
and loc3 = t7, loc3 // capture psr.tb, db, ss, pp
|
|
;;
|
|
or t8 = loc3, t8
|
|
;;
|
|
|
|
st8 [t0] = t8
|
|
add t3 = TrRsRSC, loc2
|
|
(pt0) br.cond.spnt Nc10 // jump to Nc10 if pt0 is TRUE
|
|
;;
|
|
|
|
//
|
|
// Restore the nonvolatile machine state from the exception frame
|
|
// and exit the system via the exception exit code.
|
|
//
|
|
|
|
ld8 t5 = [t2] // get old trap frame address
|
|
movl t1 = KiPcr + PcCurrentThread // -> current thread
|
|
;;
|
|
|
|
ld8 t0 = [t3], TrPreviousMode-TrRsRSC // load TrapFrame->RsRSC
|
|
ld8 t4 = [t1] // get current thread address
|
|
cmp4.ne pt1 = zero, a1 // if ne, test for alert
|
|
;;
|
|
|
|
ld4 t6 = [t3], TrRsRSC-TrPreviousMode // get old previous mode
|
|
dep t0 = r0, t0, RSC_MBZ1, RSC_LOADRS_LEN // zero preload field
|
|
add t7 = ThPreviousMode, t4
|
|
;;
|
|
|
|
(pt1) ld1 out0 = [t7] // get current previous mode
|
|
st8 [t3] = t0 // save TrapFrame->RsRSC
|
|
add t8 = ThTrapFrame, t4
|
|
;;
|
|
|
|
st8 [t8] = t5 // restore old trap frame addr
|
|
st1 [t7] = t6 // restore old previous mode
|
|
(pt1) br.call.spnt.many brp = KeTestAlertThread
|
|
;;
|
|
|
|
//
|
|
// sp -> stack scratch area/FP save area/exception frame/trap frame
|
|
//
|
|
// Set up for branch to KiExceptionExit
|
|
//
|
|
// s0 = trap frame
|
|
// s1 = exception frame
|
|
//
|
|
// N.B. predicate register alias pUstk & pKstk must be the same as trap.s
|
|
// and they must be set up correctly upon entry into KiExceptionExit.
|
|
//
|
|
// N.B. The exception exit code will restore the exception frame & trap frame
|
|
// and then rfi to user code. pUstk is set to 1 while pKstk is set to 0.
|
|
//
|
|
|
|
pUstk = ps3
|
|
pKstk = ps4
|
|
|
|
//
|
|
// Interrupts must be disabled before calling KiExceptionExit
|
|
// because the unwind code cannot unwind from that point.
|
|
//
|
|
|
|
FAST_DISABLE_INTERRUPTS
|
|
cmp.eq pUstk, pKstk = zero, zero
|
|
add s1 = STACK_SCRATCH_AREA, sp
|
|
mov s0 = loc2
|
|
br KiExceptionExit
|
|
|
|
Nc10:
|
|
|
|
.restore
|
|
add sp = ExceptionFrameLength, sp
|
|
NESTED_RETURN
|
|
|
|
NESTED_EXIT(NtContinue)
|
|
|
|
//++
|
|
//
|
|
// NTSTATUS
|
|
// NtRaiseException (
|
|
// IN PEXCEPTION_RECORD ExceptionRecord,
|
|
// IN PCONTEXT ContextRecord,
|
|
// IN BOOLEAN FirstChance
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine is called as a system service to raise an exception.
|
|
// The exception can be raised as a first or second chance exception.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
|
|
//
|
|
// ContextRecord (a1) - Supplies a pointer to a context record.
|
|
//
|
|
// FirstChance (a2) - Supplies a boolean value that determines whether
|
|
// this is the first (TRUE) or second (FALSE) chance for dispatching
|
|
// the exception.
|
|
//
|
|
// N.B. Register t0 is assumed to contain the address of a trap frame.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Normally there is no return from this routine. However, if the specified
|
|
// context record or exception record is misaligned or is not accessible,
|
|
// then the appropriate status code is returned.
|
|
//
|
|
//--
|
|
|
|
NESTED_ENTRY(NtRaiseException)
|
|
|
|
NESTED_SETUP(3,3,5,0)
|
|
.fframe ExceptionFrameLength
|
|
add sp = -ExceptionFrameLength, sp
|
|
;;
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// Pop this trap frame off the thread list.
|
|
//
|
|
|
|
add t2 = TrTrapFrame, t0
|
|
movl t1 = KiPcr + PcCurrentThread
|
|
;;
|
|
|
|
ld8 t1 = [t1]; // Get current thread.
|
|
ld8 t2 = [t2]; // Load previous trap frame
|
|
;;
|
|
add t1 = ThTrapFrame, t1
|
|
|
|
|
|
//
|
|
// Save nonvolatile states.
|
|
//
|
|
|
|
add out0 = STACK_SCRATCH_AREA, sp
|
|
mov loc2 = t0 // save pointer to trap frame
|
|
;;
|
|
st8 [t1] = t2
|
|
br.call.sptk brp = KiSaveExceptionFrame
|
|
|
|
//
|
|
// Call the raise exception kernel routine wich will marshall the argments
|
|
// and then call the exception dispatcher.
|
|
//
|
|
|
|
add out2 = STACK_SCRATCH_AREA, sp // -> exception frame
|
|
mov out1 = a1
|
|
mov out0 = a0
|
|
|
|
add out4 = zero, a2
|
|
mov out3 = t0
|
|
br.call.sptk.many brp = KiRaiseException
|
|
|
|
//
|
|
// If the raise exception routine returns success, then exit via the exception
|
|
// exit code. Otherwise, return to the system service dispatcher.
|
|
//
|
|
// N.B. The exception exit code will restore the exception frame & trap frame
|
|
// and then rfi to user code.
|
|
//
|
|
// Set up for branch to KiExceptionExit
|
|
//
|
|
// s0 = trap frame
|
|
// s1 = exception frame
|
|
//
|
|
|
|
pUstk = ps3
|
|
pKstk = ps4
|
|
|
|
|
|
cmp4.ne p0, pt1 = zero, v0 // if ne, dispatch failed.
|
|
;;
|
|
|
|
//
|
|
// Interrupts must be disabled before calling KiExceptionExit
|
|
// because the unwind code cannot unwind from that point.
|
|
//
|
|
|
|
(pt1) FAST_DISABLE_INTERRUPTS
|
|
(pt1) mov s0 = loc2 // copy trap frame pointer
|
|
(pt1) add s1 = STACK_SCRATCH_AREA, sp
|
|
|
|
(pt1) cmp.eq pUstk, pKstk = zero, zero
|
|
(pt1) br.cond.sptk.many KiExceptionExit
|
|
|
|
.restore
|
|
add sp = ExceptionFrameLength, sp
|
|
NESTED_RETURN
|
|
|
|
NESTED_EXIT(NtRaiseException)
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KeFillLargeEntryTb (
|
|
// IN HARDWARE_PTE Pte[],
|
|
// IN PVOID Virtual,
|
|
// IN ULONG PageSize
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function fills a large translation buffer entry.
|
|
//
|
|
// N.B. It is assumed that the large entry is not in the TB and therefore
|
|
// the TB is not probed.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Pte (a0) - Supplies a pointer to the page table entries that are to be
|
|
// written into the TB.
|
|
//
|
|
// Virtual (a1) - Supplies the virtual address of the entry that is to
|
|
// be filled in the translation buffer.
|
|
//
|
|
// PageSize (a2) - Supplies the size of the large page table entry.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KeFillLargeEntryTb)
|
|
|
|
|
|
rPte = t0
|
|
rScnd = t1
|
|
ridtr = t2
|
|
rid = t3
|
|
rDtr = t4
|
|
|
|
rTb = t6
|
|
rTbPFN = t7
|
|
rpAttr = t8
|
|
rAttrOffset = t9
|
|
|
|
|
|
shr.u rScnd = a2, 6 // mask off page size fields
|
|
;;
|
|
shl rScnd = rScnd, 6 //
|
|
;;
|
|
and rScnd = a1, rScnd // examine the virtual address bit
|
|
;;
|
|
cmp.eq pt0, pt1 = r0, rScnd
|
|
shl ridtr = a2, PS_SHIFT
|
|
mov rDtr = DTR_VIDEO_INDEX
|
|
;;
|
|
|
|
rsm 1 << PSR_I // turn off interrupts
|
|
(pt0) add a0 = (1 << PTE_SHIFT), a0
|
|
;;
|
|
|
|
ld8 rPte = [a0] // load PTE
|
|
rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
|
|
;;
|
|
|
|
srlz.d // serialize
|
|
|
|
mov cr.itir = ridtr // idtr for insertion
|
|
mov cr.ifa = a1 // ifa for insertion
|
|
;;
|
|
|
|
itr.d dtr[rDtr] = rPte
|
|
ssm 1 << PSR_IC // set PSR.ic bit again
|
|
;;
|
|
|
|
srlz.i // I serialize
|
|
ssm 1 << PSR_I
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeFillLargeEntryTb) // return
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KeFillFixedEntryTb (
|
|
// IN HARDWARE_PTE Pte[],
|
|
// IN PVOID Virtual,
|
|
// IN ULONG PageSize,
|
|
// IN ULONG Index
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function fills a fixed translation buffer entry.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Pte (a0) - Supplies a pointer to the page table entries that are to be
|
|
// written into the TB.
|
|
//
|
|
// Virtual (a1) - Supplies the virtual address of the entry that is to
|
|
// be filled in the translation buffer.
|
|
//
|
|
// Index (a2) - Supplies the index where the TB entry is to be written.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KeFillFixedEntryTb)
|
|
|
|
|
|
rPte = t0
|
|
rScnd = t1
|
|
ridtr = t2
|
|
rid = t3
|
|
rIndex = t4
|
|
|
|
rTb = t6
|
|
rTbPFN = t7
|
|
rpAttr = t8
|
|
rAttrOffset = t9
|
|
|
|
|
|
rsm 1 << PSR_I // reset PSR.i
|
|
ld8 rPte = [a0] // load PTE
|
|
shl ridtr = a2, PS_SHIFT
|
|
;;
|
|
|
|
rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
|
|
tbit.z pt0, pt1 = a3, 31 // check the sign bit
|
|
// if 1 ITR, otherwise DTR
|
|
;;
|
|
srlz.d // serialize
|
|
and rIndex = 0xf, a3
|
|
;;
|
|
|
|
mov cr.itir = ridtr // idtr for insertion
|
|
mov cr.ifa = a1 // ifa for insertion
|
|
;;
|
|
|
|
(pt0) itr.d dtr[rIndex] = rPte // insert into DTR
|
|
(pt1) itr.i itr[rIndex] = rPte // insert into ITR
|
|
|
|
ssm 1 << PSR_IC // set PSR.ic bit again
|
|
;;
|
|
|
|
srlz.i // I serialize
|
|
|
|
#if DBG
|
|
|
|
mov t10 = PbProcessorState+KpsSpecialRegisters+KsTrD0
|
|
movl t13 = KiPcr + PcPrcb
|
|
;;
|
|
|
|
ld8 t13 = [t13]
|
|
mov t14 = PbProcessorState+KpsSpecialRegisters+KsTrI0
|
|
;;
|
|
|
|
add t10 = t10, t13
|
|
add t14 = t14, t13
|
|
;;
|
|
|
|
(pt0) shladd t15 = rIndex, 3, t10
|
|
(pt1) shladd t15 = rIndex, 3, t14
|
|
;;
|
|
|
|
(pt0) st8 [t15] = rPte
|
|
(pt1) st8 [t15] = rPte
|
|
;;
|
|
|
|
#endif
|
|
|
|
ssm 1 << PSR_I
|
|
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeFillFixedEntryTb)
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KeFillFixedLargeEntryTb (
|
|
// IN HARDWARE_PTE Pte[],
|
|
// IN PVOID Virtual,
|
|
// IN ULONG PageSize,
|
|
// IN ULONG Index
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function fills a fixed translation buffer entry with a large page
|
|
// size.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Pte (a0) - Supplies a pointer to the page table entries that are to be
|
|
// written into the TB.
|
|
//
|
|
// Virtual (a1) - Supplies the virtual address of the entry that is to
|
|
// be filled in the translation buffer.
|
|
//
|
|
// PageSize (a2) - Supplies the size of the large page table entry.
|
|
//
|
|
// Index (a3) - Supplies the index where the TB entry is to be written.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
// Yet to be implemented.
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KeFillFixedLargeEntryTb)
|
|
|
|
|
|
rPte = t0
|
|
rScnd = t1
|
|
ridtr = t2
|
|
rid = t3
|
|
rIndex = t4
|
|
|
|
rTb = t6
|
|
rTbPFN = t7
|
|
rpAttr = t8
|
|
rAttrOffset = t9
|
|
|
|
|
|
rsm 1 << PSR_I // reset PSR.i
|
|
ld8 rPte = [a0] // load PTE
|
|
shl ridtr = a2, PS_SHIFT
|
|
|
|
;;
|
|
|
|
rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
|
|
and rIndex = 0xf, a3 // set the DTR index
|
|
tbit.z pt0, pt1 = a3, 31 // check the sign bit
|
|
|
|
;;
|
|
|
|
srlz.d // serialize
|
|
|
|
mov cr.itir = ridtr // idtr for insertion
|
|
mov cr.ifa = a1 // ifa for insertion
|
|
;;
|
|
|
|
(pt0) itr.d dtr[rIndex] = rPte // insert into DTR
|
|
(pt1) itr.i itr[rIndex] = rPte // insert into ITR
|
|
|
|
ssm 1 << PSR_IC // set PSR.ic bit again
|
|
;;
|
|
|
|
srlz.i // I serialize
|
|
ssm 1 << PSR_I
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeFillFixedLargeEntryTb) // return
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KeFillInstEntryTb (
|
|
// IN HARDWARE_PTE Pte[],
|
|
// IN PVOID Virtual,
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function fills a large translation buffer entry.
|
|
//
|
|
// N.B. It is assumed that the large entry is not in the TB and therefore
|
|
// the TB is not probed.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Pte (a0) - Supplies a page table entry that is to be
|
|
// written into the Inst TB.
|
|
//
|
|
// Virtual (a1) - Supplies the virtual address of the entry that is to
|
|
// be filled in the translation buffer.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KeFillInstEntryTb)
|
|
|
|
riitr = t2
|
|
rid = t3
|
|
|
|
rsm 1 << PSR_I // reset PSR.i
|
|
;;
|
|
rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
|
|
mov riitr = PAGE_SIZE << PS_LEN
|
|
;;
|
|
|
|
srlz.d // serialize
|
|
mov cr.ifa = a1 // set va to install
|
|
mov cr.itir = riitr // iitr for insertion
|
|
;;
|
|
|
|
itc.i a0
|
|
;;
|
|
ssm 1 << PSR_IC // set PSR.ic bit again
|
|
;;
|
|
|
|
srlz.i // I serialize
|
|
ssm 1 << PSR_I
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeFillInstEntryTb) // return
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KeBreakinBreakpoint
|
|
// VOID
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function causes a BREAKIN breakpoint.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KeBreakinBreakpoint)
|
|
|
|
//
|
|
// Flush the RSE or the kernel debugger is unable to do a stack unwind
|
|
//
|
|
|
|
flushrs
|
|
;;
|
|
break.i BREAKPOINT_BREAKIN
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeBreakinBreakpoint)
|
|
|
|
|
|
#ifdef WX86
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KiIA32RegistersInit
|
|
// VOID
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function to Initialize per processor IA32 related registers
|
|
// These registers do not saved/restored on context switch time
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KiIA32RegistersInit)
|
|
|
|
mov t0 = TeGdtDescriptor
|
|
mov iA32iobase = 0
|
|
;;
|
|
mov iA32index = t0
|
|
|
|
LEAF_RETURN
|
|
LEAF_EXIT(KiIA32RegistersInit)
|
|
#endif // WX86
|
|
|
|
|
|
//++
|
|
//
|
|
// PKTHREAD
|
|
// KeGetCurrentThread (VOID)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Returns a pointer to the executing thread object.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KeGetCurrentThread)
|
|
|
|
movl v0 = KiPcr + PcCurrentThread // -> current thread
|
|
;;
|
|
|
|
ld8 v0 = [v0]
|
|
br.ret.sptk brp
|
|
|
|
LEAF_EXIT(KeGetCurrentThread)
|
|
|
|
//++
|
|
//
|
|
// BOOLEAN
|
|
// KeIsExecutingDpc (VOID)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Return a value which indicates if we are currently in a DPC.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KeIsExecutingDpc)
|
|
|
|
rsm 1 << PSR_I // disable interrupt
|
|
movl v0 = KiPcr + PcPrcb
|
|
;;
|
|
ld8 v0 = [v0]
|
|
;;
|
|
add v0 = PbDpcRoutineActive, v0
|
|
;;
|
|
ld8 t0 = [v0]
|
|
ssm 1 << PSR_I // enable interrupt
|
|
;;
|
|
cmp.eq pt1 = t0, zero
|
|
mov v0 = 1
|
|
;;
|
|
(pt1) mov v0 = 0
|
|
br.ret.sptk brp
|
|
|
|
LEAF_EXIT(KeIsExecutingDpc)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine saves the thread's current non-volatile NPX state,
|
|
// and sets a new initial floating point state for the caller.
|
|
//
|
|
// This is intended for use by kernel-mode code that needs to use
|
|
// the floating point registers. Must be paired with
|
|
// KeRestoreFloatingPointState
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - Supplies pointer to KFLOATING_SAVE structure
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KeSaveFloatingPointState)
|
|
|
|
mov v0 = zero
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeSaveFloatingPointState)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine restores the thread's current non-volatile NPX state,
|
|
// to the passed in state.
|
|
//
|
|
// This is intended for use by kernel-mode code that needs to use
|
|
// the floating point registers. Must be paired with
|
|
// KeSaveFloatingPointState
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - Supplies pointer to KFLOATING_SAVE structure
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KeRestoreFloatingPointState)
|
|
|
|
mov v0 = zero
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeRestoreFloatingPointState)
|
|
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine flush all the dirty registers to the backing store
|
|
// and invalidate them.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KiFlushRse)
|
|
|
|
flushrs
|
|
mov t1 = ar.rsc
|
|
mov t0 = RSC_KERNEL_DISABLED
|
|
;;
|
|
|
|
mov ar.rsc = t0
|
|
;;
|
|
loadrs
|
|
;;
|
|
mov ar.rsc = t1
|
|
;;
|
|
br.ret.sptk brp
|
|
|
|
LEAF_EXIT(KiFlushRse)
|
|
|
|
#if 0
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine invalidate all the physical stacked registers.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
LEAF_ENTRY(KiInvalidateStackedRegisters)
|
|
|
|
mov t1 = ar.rsc
|
|
mov t0 = RSC_KERNEL_DISABLED
|
|
;;
|
|
mov ar.rsc = t0
|
|
;;
|
|
loadrs
|
|
;;
|
|
mov ar.rsc = t1
|
|
;;
|
|
br.ret.sptk brp
|
|
|
|
LEAF_EXIT(KiInvalidateStackedRegisters)
|
|
#endif // 0
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KeSetLowPsrBit (
|
|
// UCHAR BitPosition,
|
|
// BOOLEAN Value
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine set one of the low psr bits to the specified value.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - bit position
|
|
// a1 - 1 or 0
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KeSetLowPsrBit)
|
|
|
|
mov t1 = psr
|
|
mov t2 = 1
|
|
cmp.ne pt1, pt0 = r0, a1
|
|
;;
|
|
|
|
shl t2 = t2, a0
|
|
;;
|
|
(pt1) or t3 = t1, t2
|
|
(pt0) andcm t3 = t1, t2
|
|
;;
|
|
|
|
mov psr.l = t3
|
|
;;
|
|
srlz.i
|
|
br.ret.sptk brp
|
|
|
|
LEAF_EXIT(KeSetLowPsrBit)
|
|
|
|
|
|
//++
|
|
//
|
|
// PVOID
|
|
// KiGetPhysicalAddress(
|
|
// PVOID Virtual
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine translates to physical address uing TPA instruction.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - virtual address to be translated to physical address.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// physical address
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KiGetPhysicalAddress)
|
|
|
|
tpa r8 = a0
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KiGetPhysicalAddress)
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KiSetRegionRegister(
|
|
// PVOID Region,
|
|
// ULONGLONG Contents
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine sets the value of a region register.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - Supplies the region register #
|
|
//
|
|
// a1 - Supplies the value to be stored in the specified region register
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
|
|
LEAF_ENTRY(KiSetRegionRegister)
|
|
|
|
mov rr[a0] = a1
|
|
;;
|
|
srlz.i
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KiSetRegionId)
|
|
|
|
|
|
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// KiSaveProcessorControlState(
|
|
// PKPROCESSOR_STATE ProcessorState
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine captures some of the special registers into the supplied
|
|
// ProcessorState.
|
|
//
|
|
// It is called indirectly by the debugger through KeFreezeTargetExecution.
|
|
// It is also called during bugcheck processing.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// a0 - Pointer to ProcessorState in Prcb.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(KiSaveProcessorControlState)
|
|
|
|
//
|
|
// save region registers
|
|
//
|
|
|
|
add t2 = KpsSpecialRegisters+KsRr0, a0
|
|
dep.z t0 = 0, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t1 = rr[t0]
|
|
dep.z t3 = 1, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t4 = rr[t3]
|
|
st8 [t2] = t1, KsRr1-KsRr0
|
|
dep.z t0 = 2, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t1 = rr[t0]
|
|
st8 [t2] = t4, KsRr2-KsRr1
|
|
dep.z t3 = 3, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t4 = rr[t3]
|
|
st8 [t2] = t1, KsRr3-KsRr2
|
|
dep.z t0 = 4, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t1 = rr[t0]
|
|
st8 [t2] = t4, KsRr4-KsRr3
|
|
dep.z t3 = 5, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
mov t4 = rr[t3]
|
|
st8 [t2] = t1, KsRr5-KsRr4
|
|
dep.z t0 = 6, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t1 = rr[t0]
|
|
st8 [t2] = t4, KsRr6-KsRr5
|
|
dep.z t3 = 7, RR_INDEX, RR_INDEX_LEN
|
|
;;
|
|
|
|
mov t4 = rr[t3]
|
|
st8 [t2] = t1, KsRr7-KsRr6
|
|
;;
|
|
|
|
st8 [t2] = t4
|
|
|
|
//
|
|
// save ITC, ITM, IVA, PTA and TPR
|
|
//
|
|
|
|
mov t0 = ar.itc
|
|
mov t1 = cr.itm
|
|
add t3 = KpsSpecialRegisters+KsApITC, a0
|
|
add t4 = KpsSpecialRegisters+KsApITM, a0
|
|
;;
|
|
|
|
mov t5 = cr.iva
|
|
mov t6 = cr.pta
|
|
st8 [t3] = t0, KsApIVA-KsApITC
|
|
st8 [t4] = t1, KsApPTA-KsApITM
|
|
;;
|
|
|
|
mov t0 = cr.tpr
|
|
mov t1 = ar.k0
|
|
st8 [t3] = t5, KsSaTPR-KsApIVA
|
|
st8 [t4] = t6, KsApKR0-KsApPTA
|
|
;;
|
|
|
|
mov t5 = ar.k1
|
|
mov t6 = ar.k2
|
|
st8 [t3] = t0, KsApKR1-KsSaTPR
|
|
st8 [t4] = t1, KsApKR2-KsApKR0
|
|
;;
|
|
|
|
mov t0 = ar.k3
|
|
mov t1 = ar.k4
|
|
st8 [t3] = t5, KsApKR3-KsApKR1
|
|
st8 [t4] = t6, KsApKR4-KsApKR2
|
|
;;
|
|
|
|
mov t5 = ar.k5
|
|
mov t6 = ar.k6
|
|
st8 [t3] = t0, KsApKR5-KsApKR3
|
|
st8 [t4] = t1, KsApKR6-KsApKR4
|
|
;;
|
|
|
|
mov t0 = ar.k7
|
|
mov t1 = cr.lid
|
|
st8 [t3] = t5, KsApKR7-KsApKR5
|
|
st8 [t4] = t6, KsSaLID-KsApKR6
|
|
;;
|
|
|
|
mov t5 = cr.irr0
|
|
mov t6 = cr.irr1
|
|
st8 [t3] = t0, KsSaIRR0-KsApKR7
|
|
st8 [t4] = t1, KsSaIRR1-KsSaLID
|
|
;;
|
|
|
|
mov t0 = cr.irr2
|
|
mov t1 = cr.irr3
|
|
st8 [t3] = t5, KsSaIRR2-KsSaIRR0
|
|
st8 [t4] = t6, KsSaIRR3-KsSaIRR1
|
|
;;
|
|
|
|
mov t5 = cr.itv
|
|
mov t6 = cr.pmv
|
|
st8 [t3] = t0, KsSaITV-KsSaIRR2
|
|
st8 [t4] = t1, KsSaPMV-KsSaIRR3
|
|
;;
|
|
|
|
mov t0 = cr.cmcv
|
|
mov t1 = cr.lrr0
|
|
st8 [t3] = t5, KsSaCMCV-KsSaITV
|
|
st8 [t4] = t6, KsSaLRR0-KsSaPMV
|
|
;;
|
|
|
|
mov t5 = cr.lrr1
|
|
mov t6 = cr.gpta
|
|
st8 [t3] = t0, KsSaLRR1-KsSaCMCV
|
|
st8 [t4] = t1, KsApGPTA-KsSaLRR0
|
|
|
|
|
|
|
|
mov t7 = 0
|
|
mov t8 = 1
|
|
;;
|
|
|
|
mov t0 = cpuid[t7]
|
|
mov t1 = cpuid[t8]
|
|
st8 [t3] = t5
|
|
st8 [t4] = t6
|
|
|
|
mov t9 = 2
|
|
mov t10 = 3
|
|
|
|
add t3 = KpsSpecialRegisters+KsApCPUID0, a0
|
|
add t4 = KpsSpecialRegisters+KsApCPUID1, a0
|
|
;;
|
|
|
|
mov t5 = cpuid[t9]
|
|
mov t6 = cpuid[t10]
|
|
st8 [t3] = t0, KsApCPUID2-KsApCPUID0
|
|
st8 [t4] = t1, KsApCPUID3-KsApCPUID1
|
|
|
|
mov t7 = 4
|
|
mov t8 = 652
|
|
;;
|
|
|
|
mov t0 = cpuid[t7]
|
|
st8 [t3] = t5, KsApCPUID4-KsApCPUID2
|
|
st8 [t4] = t6
|
|
;;
|
|
|
|
st8 [t3] = t0
|
|
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KiSaveProcessorControlState)
|
|
|
|
|
|
NESTED_ENTRY(KiRestoreProcessorControlState)
|
|
|
|
NESTED_SETUP(0,2,0,0)
|
|
;;
|
|
br.call.spnt brp = KiLoadKernelDebugRegisters
|
|
;;
|
|
NESTED_RETURN
|
|
|
|
NESTED_EXIT(KiRestoreProcessorControlState)
|
|
|
|
|
|
|
|
PublicFunction(KiSaveExceptionFrame)
|
|
PublicFunction(KiRestoreExceptionFrame)
|
|
PublicFunction(KiIpiProcessRequests)
|
|
PublicFunction(KiFreezeTargetExecution)
|
|
|
|
|
|
NESTED_ENTRY(KeIpiInterrupt)
|
|
NESTED_SETUP(1, 3, 1, 0)
|
|
PROLOGUE_END
|
|
;;
|
|
|
|
//
|
|
// Process all requests except freeze requests.
|
|
//
|
|
|
|
mov out0 = a0 // -> trap frame
|
|
mov loc2 = gp
|
|
br.call.sptk brp = KiIpiProcessRequests
|
|
;;
|
|
|
|
tbit.nz pt1 = v0, IPI_FREEZE_SHIFT
|
|
mov gp = loc2
|
|
mov out0 = a0 // -> trap frame
|
|
(pt1) br.call.dpnt brp = KiFreezeCurrentProcessor
|
|
;;
|
|
|
|
NESTED_RETURN
|
|
|
|
NESTED_EXIT(KeIpiInterrupt)
|
|
|
|
NESTED_ENTRY(KiFreezeCurrentProcessor)
|
|
NESTED_SETUP(1, 2, 2, 0)
|
|
.fframe ExceptionFrameLength
|
|
add sp = -ExceptionFrameLength, sp
|
|
;;
|
|
|
|
PROLOGUE_END
|
|
|
|
add out0 = STACK_SCRATCH_AREA, sp // -> exception frame
|
|
br.call.sptk brp = KiSaveExceptionFrame
|
|
;;
|
|
|
|
add out1 = STACK_SCRATCH_AREA, sp // -> exception frame
|
|
mov out0 = a0 // -> trap frame
|
|
br.call.sptk brp = KiFreezeTargetExecution
|
|
;;
|
|
|
|
add out0 = STACK_SCRATCH_AREA, sp // -> exception frame
|
|
br.call.sptk brp = KiRestoreExceptionFrame
|
|
;;
|
|
|
|
add sp = ExceptionFrameLength, sp
|
|
NESTED_RETURN
|
|
|
|
NESTED_EXIT(KiFreezeCurrentProcessor)
|
|
|
|
|
|
|
|
LEAF_ENTRY(KiReadMsr)
|
|
|
|
mov v0 = msr[a0]
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KiReadMsr)
|
|
|
|
LEAF_ENTRY(KiWriteMsr)
|
|
|
|
mov msr[a0] = a1
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KiWriteMsr)
|
|
|
|
LEAF_ENTRY(KeYieldProcessor)
|
|
|
|
YIELD
|
|
LEAF_RETURN
|
|
|
|
LEAF_EXIT(KeYieldProcessor)
|