290 lines
9.0 KiB
ArmAsm
290 lines
9.0 KiB
ArmAsm
|
// TITLE("Miscellaneous Kernel Functions")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1990 Microsoft Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// misc.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This module implements machine dependent miscellaneous kernel functions.
|
|||
|
// Functions are provided to request a software interrupt, continue thread
|
|||
|
// execution, flush the write buffer, and perform last chance exception
|
|||
|
// processing.
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// David N. Cutler (davec) 31-Mar-1990
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include "ksmips.h"
|
|||
|
|
|||
|
SBTTL("Request Software Interrupt")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// KiRequestSoftwareInterrupt (
|
|||
|
// ULONG RequestIrql
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function requests a software interrupt at the specified IRQL
|
|||
|
// level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// RequestIrql (a0) - Supplies the request IRQL value.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiRequestSoftwareInterrupt)
|
|||
|
|
|||
|
li t0,1 << (CAUSE_INTPEND - 1) // get partial request mask value
|
|||
|
|
|||
|
DISABLE_INTERRUPTS(t1) // disable interrupts
|
|||
|
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
mfc0 t2,cause // get exception cause register
|
|||
|
sll t0,t0,a0 // shift request mask into position
|
|||
|
or t2,t2,t0 // merge interrupt request mask
|
|||
|
mtc0 t2,cause // set exception cause register
|
|||
|
.set at
|
|||
|
.set reorder
|
|||
|
|
|||
|
ENABLE_INTERRUPTS(t1) // enable interrupts
|
|||
|
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end KiRequestSoftwareInterrupt
|
|||
|
|
|||
|
SBTTL("Continue Execution System Service")
|
|||
|
//++
|
|||
|
//
|
|||
|
// 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 s8 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, ExceptionFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,ExceptionFrameLength // allocate exception frame
|
|||
|
sw ra,ExIntRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Save the nonvolatile machine state so that it can be restored by exception
|
|||
|
// exit if it is not overwritten by the specified context record.
|
|||
|
//
|
|||
|
|
|||
|
sd s0,TrXIntS0(s8) // save integer registers s0 - s7
|
|||
|
sd s1,TrXIntS1(s8) //
|
|||
|
sd s2,TrXIntS2(s8) //
|
|||
|
sd s3,TrXIntS3(s8) //
|
|||
|
sd s4,TrXIntS4(s8) //
|
|||
|
sd s5,TrXIntS5(s8) //
|
|||
|
sd s6,TrXIntS6(s8) //
|
|||
|
sd s7,TrXIntS7(s8) //
|
|||
|
li t0,TRUE // set saved s-registers flag
|
|||
|
sb t0,TrSavedFlag(s8) //
|
|||
|
|
|||
|
sdc1 f20,ExFltF20(sp) // save floating registers f20 - f31
|
|||
|
sdc1 f22,ExFltF22(sp) //
|
|||
|
sdc1 f24,ExFltF24(sp) //
|
|||
|
sdc1 f26,ExFltF26(sp) //
|
|||
|
sdc1 f28,ExFltF28(sp) //
|
|||
|
sdc1 f30,ExFltF30(sp) //
|
|||
|
|
|||
|
//
|
|||
|
// Transfer information from the context frame to the exception and trap
|
|||
|
// frames.
|
|||
|
//
|
|||
|
|
|||
|
sb a1,ExceptionFrameLength + 4(sp) // save test alert argument
|
|||
|
move a1,sp // set address of exception frame
|
|||
|
move a2,s8 // set address of trap frame
|
|||
|
jal KiContinue // transfer context to kernel frames
|
|||
|
|
|||
|
//
|
|||
|
// If the kernel continuation routine returns success, then exit via the
|
|||
|
// exception exit code. Otherwise return to the system service dispatcher.
|
|||
|
//
|
|||
|
|
|||
|
bne zero,v0,20f // if ne, transfer failed
|
|||
|
|
|||
|
//
|
|||
|
// Check to determine if alert should be tested for the previous processor
|
|||
|
// mode and restore the previous mode in the thread object.
|
|||
|
//
|
|||
|
|
|||
|
lw t0,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
lbu t1,ExceptionFrameLength + 4(sp) // get test alert argument
|
|||
|
lw t2,TrTrapFrame(s8) // get old trap frame address
|
|||
|
lbu t3,TrPreviousMode(s8) // get old previous mode
|
|||
|
lbu a0,ThPreviousMode(t0) // get current previous mode
|
|||
|
sw t2,ThTrapFrame(t0) // restore old trap frame address
|
|||
|
sb t3,ThPreviousMode(t0) // restore old previous mode
|
|||
|
beq zero,t1,10f // if eq, don't test for alert
|
|||
|
jal KeTestAlertThread // test alert for current thread
|
|||
|
|
|||
|
//
|
|||
|
// Exit the system via exception exit which will restore the nonvolatile
|
|||
|
// machine state.
|
|||
|
//
|
|||
|
|
|||
|
10: j KiExceptionExit // finish in exception exit
|
|||
|
|
|||
|
//
|
|||
|
// Context record is misaligned or not accessible.
|
|||
|
//
|
|||
|
|
|||
|
20: lw ra,ExIntRa(sp) // restore return address
|
|||
|
addu sp,sp,ExceptionFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end NtContinue
|
|||
|
|
|||
|
SBTTL("Raise Exception System Service")
|
|||
|
//++
|
|||
|
//
|
|||
|
// 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 s8 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, ExceptionFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,ExceptionFrameLength // allocate exception frame
|
|||
|
sw ra,ExIntRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Save the nonvolatile machine state so that it can be restored by exception
|
|||
|
// exit if it is not overwritten by the specified context record.
|
|||
|
//
|
|||
|
|
|||
|
sd s0,TrXIntS0(s8) // save integer registers s0 - s7
|
|||
|
sd s1,TrXIntS1(s8) //
|
|||
|
sd s2,TrXIntS2(s8) //
|
|||
|
sd s3,TrXIntS3(s8) //
|
|||
|
sd s4,TrXIntS4(s8) //
|
|||
|
sd s5,TrXIntS5(s8) //
|
|||
|
sd s6,TrXIntS6(s8) //
|
|||
|
sd s7,TrXIntS7(s8) //
|
|||
|
li t0,TRUE // set saved s-registers flag
|
|||
|
sb t0,TrSavedFlag(s8) //
|
|||
|
|
|||
|
sdc1 f20,ExFltF20(sp) // save floating registers f20 - f31
|
|||
|
sdc1 f22,ExFltF22(sp) //
|
|||
|
sdc1 f24,ExFltF24(sp) //
|
|||
|
sdc1 f26,ExFltF26(sp) //
|
|||
|
sdc1 f28,ExFltF28(sp) //
|
|||
|
sdc1 f30,ExFltF30(sp) //
|
|||
|
|
|||
|
//
|
|||
|
// Call the raise exception kernel routine which will marshall the arguments
|
|||
|
// and then call the exception dispatcher.
|
|||
|
//
|
|||
|
|
|||
|
sw a2,ExArgs + 16(sp) // set first chance argument
|
|||
|
move a2,sp // set address of exception frame
|
|||
|
move a3,s8 // set address of trap frame
|
|||
|
jal KiRaiseException // call raise exception routine
|
|||
|
|
|||
|
//
|
|||
|
// If the raise exception routine returns success, then exit via the exception
|
|||
|
// exit code. Otherwise return to the system service dispatcher.
|
|||
|
//
|
|||
|
|
|||
|
lw t0,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
lw t1,TrTrapFrame(s8) // get old trap frame address
|
|||
|
bne zero,v0,10f // if ne, dispatch not successful
|
|||
|
sw t1,ThTrapFrame(t0) // restore old trap frame address
|
|||
|
|
|||
|
//
|
|||
|
// Exit the system via exception exit which will restore the nonvolatile
|
|||
|
// machine state.
|
|||
|
//
|
|||
|
|
|||
|
j KiExceptionExit // finish in exception exit
|
|||
|
|
|||
|
//
|
|||
|
// The context or exception record is misaligned or not accessible, or the
|
|||
|
// exception was not handled.
|
|||
|
//
|
|||
|
|
|||
|
10: lw ra,ExIntRa(sp) // restore return address
|
|||
|
addu sp,sp,ExceptionFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end NtRaiseException
|