422 lines
11 KiB
ArmAsm
422 lines
11 KiB
ArmAsm
|
// TITLE("Miscellaneous Kernel Functions")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1990 Microsoft Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// miscs.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This module implements machine dependent miscellaneous kernel functions.
|
|||
|
// Functions are provided to request a software interrupt, continue thread
|
|||
|
// execution, and perform last chance exception processing.
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// David N. Cutler (davec) 31-Mar-1990
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
// Thomas Van Baak (tvb) 29-Jul-1992
|
|||
|
//
|
|||
|
// Adapted for Alpha AXP.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include "ksalpha.h"
|
|||
|
|
|||
|
SBTTL("Request Software Interrupt")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// KiRequestSoftwareInterrupt (
|
|||
|
// KIRQL RequestIrql
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function requests a software interrupt at the specified IRQL
|
|||
|
// level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// RequestIrql (a0) - Supplies the requested IRQL value.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiRequestSoftwareInterrupt)
|
|||
|
|
|||
|
//
|
|||
|
// If an interrupt routine is active, do not request an interrupt from the
|
|||
|
// PAL. Indicate the interrupt has been requested in the PRCB. The interrupt
|
|||
|
// exit code will dispatch the software interrupt directly.
|
|||
|
//
|
|||
|
|
|||
|
GET_PROCESSOR_CONTROL_BLOCK_BASE // get current prcb address
|
|||
|
|
|||
|
LDP t0, PbInterruptTrapFrame(v0) // get interrupt trap frame
|
|||
|
beq t0, 10f // if eq, no interrupt active
|
|||
|
blbs a0, 10f // if lbs, APC interrupt requested
|
|||
|
stl a0, PbSoftwareInterrupts(v0) // set interrupt request bit in PRCB
|
|||
|
ret zero, (ra) //
|
|||
|
|
|||
|
//
|
|||
|
// Request software interrupt.
|
|||
|
//
|
|||
|
|
|||
|
10: REQUEST_SOFTWARE_INTERRUPT // request software interrupt
|
|||
|
|
|||
|
ret zero, (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 function 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 fp 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)
|
|||
|
|
|||
|
lda sp, -ExceptionFrameLength(sp) // allocate exception frame
|
|||
|
stq 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.
|
|||
|
//
|
|||
|
|
|||
|
stq s0, ExIntS0(sp) // save nonvolatile integer state
|
|||
|
stq s1, ExIntS1(sp) //
|
|||
|
stq s2, ExIntS2(sp) //
|
|||
|
stq s3, ExIntS3(sp) //
|
|||
|
stq s4, ExIntS4(sp) //
|
|||
|
stq s5, ExIntS5(sp) //
|
|||
|
|
|||
|
stt f2, ExFltF2(sp) // save nonvolatile floating state
|
|||
|
stt f3, ExFltF3(sp) //
|
|||
|
stt f4, ExFltF4(sp) //
|
|||
|
stt f5, ExFltF5(sp) //
|
|||
|
stt f6, ExFltF6(sp) //
|
|||
|
stt f7, ExFltF7(sp) //
|
|||
|
stt f8, ExFltF8(sp) //
|
|||
|
stt f9, ExFltF9(sp) //
|
|||
|
|
|||
|
//
|
|||
|
// Transfer information from the context frame to the exception and trap
|
|||
|
// frames.
|
|||
|
//
|
|||
|
|
|||
|
mov a1, s0 // preserve test alert argument in s0
|
|||
|
mov sp, a1 // set address of exception frame
|
|||
|
mov fp, a2 // set address of trap frame
|
|||
|
bsr ra, 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 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.
|
|||
|
//
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
LDP t3, TrTrapFrame(fp) // get old trap frame address
|
|||
|
ldl t2, TrPreviousMode(fp) // get old previous mode
|
|||
|
LoadByte(a0, ThPreviousMode(v0)) // get current previous mode
|
|||
|
STP t3, ThTrapFrame(v0) // restore old trap frame address
|
|||
|
StoreByte(t2, ThPreviousMode(v0)) // restore old previous mode
|
|||
|
beq s0, 10f // if eq, don't test for alert
|
|||
|
bsr ra, KeTestAlertThread // test alert for current thread
|
|||
|
|
|||
|
//
|
|||
|
// Exit the system via exception exit which will restore the nonvolatile
|
|||
|
// machine state.
|
|||
|
//
|
|||
|
|
|||
|
10: br zero, KiExceptionExit // finish in exception exit
|
|||
|
|
|||
|
//
|
|||
|
// Context record is misaligned or not accessible.
|
|||
|
//
|
|||
|
|
|||
|
20: ldq ra, ExIntRa(sp) // restore return address
|
|||
|
lda sp, ExceptionFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (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 fp 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)
|
|||
|
|
|||
|
lda sp, -ExceptionFrameLength(sp) // allocate exception frame
|
|||
|
stq ra, ExIntRa(sp) // save return address
|
|||
|
stq s0, ExIntS0(sp) // save S0 and S1 in the prologue
|
|||
|
stq s1, ExIntS1(sp) // so that Get/SetContext can find
|
|||
|
// the right ones.
|
|||
|
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.
|
|||
|
//
|
|||
|
|
|||
|
stq s2, ExIntS2(sp) //
|
|||
|
stq s3, ExIntS3(sp) //
|
|||
|
stq s4, ExIntS4(sp) //
|
|||
|
stq s5, ExIntS5(sp) //
|
|||
|
|
|||
|
stt f2, ExFltF2(sp) // save nonvolatile floating state
|
|||
|
stt f3, ExFltF3(sp) //
|
|||
|
stt f4, ExFltF4(sp) //
|
|||
|
stt f5, ExFltF5(sp) //
|
|||
|
stt f6, ExFltF6(sp) //
|
|||
|
stt f7, ExFltF7(sp) //
|
|||
|
stt f8, ExFltF8(sp) //
|
|||
|
stt f9, ExFltF9(sp) //
|
|||
|
|
|||
|
//
|
|||
|
// Call the raise exception kernel routine which will marshall the arguments
|
|||
|
// and then call the exception dispatcher.
|
|||
|
//
|
|||
|
// KiRaiseException requires five arguments: the first two are the same as
|
|||
|
// the first two of this function and the other three are set here.
|
|||
|
//
|
|||
|
|
|||
|
mov a2, a4 // set first chance argument
|
|||
|
mov sp, a2 // set address of exception frame
|
|||
|
mov fp, a3 // set address of trap frame
|
|||
|
bsr ra, 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.
|
|||
|
//
|
|||
|
|
|||
|
bis v0, zero, t0 // save return status
|
|||
|
LDP t1, TrTrapFrame(fp) // get old trap frame address
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
bne t0, 10f // if ne, dispatch not successful
|
|||
|
STP t1, ThTrapFrame(v0) // restore old trap frame address
|
|||
|
|
|||
|
//
|
|||
|
// Exit the system via exception exit which will restore the nonvolatile
|
|||
|
// machine state.
|
|||
|
//
|
|||
|
|
|||
|
br zero, KiExceptionExit // finish in exception exit
|
|||
|
|
|||
|
//
|
|||
|
// The context or exception record is misaligned or not accessible, or the
|
|||
|
// exception was not handled.
|
|||
|
//
|
|||
|
|
|||
|
10: ldq ra, ExIntRa(sp) // restore return address
|
|||
|
lda sp, ExceptionFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
.end NtRaiseException
|
|||
|
|
|||
|
SBTTL("Instruction Memory Barrier")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// KiImb (
|
|||
|
// VOID
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is called to flush the instruction cache on the
|
|||
|
// current processor.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiImb)
|
|||
|
|
|||
|
IMB // flush the icache via PALcode
|
|||
|
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
.end KiImb
|
|||
|
|
|||
|
SBTTL("Memory Barrier")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// KiImb (
|
|||
|
// VOID
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is called to issue a memory barrier on the current
|
|||
|
// processor.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiMb)
|
|||
|
|
|||
|
mb // memory barrier
|
|||
|
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
.end KiMb
|
|||
|
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// KiEnablePALAlignmentFixups(
|
|||
|
// VOID
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// Enable PAL fixups and PAL counting of alignment faults.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// None
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiEnablePALAlignmentFixups)
|
|||
|
|
|||
|
|
|||
|
ENABLE_ALIGNMENT_FIXUPS // enable alignment fixups
|
|||
|
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
.end KiEnablePALAlignmentFixups
|
|||
|
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// KiDisablePALAlignmentFixups(
|
|||
|
// VOID
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// Disable PAL fixups and force all alignment faults to
|
|||
|
// the kernel.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// None
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiDisablePALAlignmentFixups)
|
|||
|
|
|||
|
DISABLE_ALIGNMENT_FIXUPS // disable alignment fixups
|
|||
|
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
.end KiDisablePALAlignmentFixups
|
|||
|
|