mirror of https://github.com/tongzx/nt5src
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.
111 lines
3.1 KiB
111 lines
3.1 KiB
// TITLE("Asynchronous Procedure Call (APC) Interrupt")
|
|
//++
|
|
//
|
|
// Copyright (c) 1990 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// apcint.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements the code necessary to field and process the
|
|
// Asynchronous Procedure Call (APC) interrupt.
|
|
//
|
|
// Author:
|
|
//
|
|
// David N. Cutler (davec) 3-Apr-1990
|
|
// Joe Notarangelo 15-Jul-1992 alpha version
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode only, IRQL APC_LEVEL.
|
|
//
|
|
// Revision History:
|
|
//
|
|
//--
|
|
|
|
#include "ksalpha.h"
|
|
|
|
SBTTL("Asynchronous Procedure Call Interrupt")
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine is entered as the result of a software interrupt generated
|
|
// at APC_LEVEL. Its function is to allocate an exception frame and call
|
|
// the kernel APC delivery routine to deliver kernel mode APCs and to check
|
|
// if a user mode APC should be delivered. If a user mode APC should be
|
|
// delivered, then the kernel APC delivery routine constructs a context
|
|
// frame on the user stack and alters the exception and trap frames so that
|
|
// control will be transfered to the user APC dispatcher on return from the
|
|
// interrupt.
|
|
//
|
|
// N.B. On entry to this routine only the volatile integer registers have
|
|
// been saved. The remainder of the machine state is saved if and only
|
|
// if the previous mode was user mode. It is assumed that none of the
|
|
// APC delivery code, nor any of the kernel mode APC routines themselves
|
|
// use any floating point instructions.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// s6/fp - Supplies a pointer to a trap frame.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
NESTED_ENTRY(KiApcInterrupt, ExceptionFrameLength, zero)
|
|
|
|
lda sp, -ExceptionFrameLength(sp) // allocate exception frame
|
|
stq ra, ExIntRa(sp) // save return address
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// Save the volatile floating state and determine the previous mode.
|
|
//
|
|
|
|
bsr ra, KiSaveVolatileFloatState // save volatile floats
|
|
ldl t0, TrPsr(fp) // get saved processor status
|
|
and t0, PSR_MODE_MASK, a0 // isolate previous mode
|
|
beq a0, 10f // if eq, kernel mode
|
|
|
|
//
|
|
// The previous mode was user.
|
|
//
|
|
// Save the nonvolatile machine state so a context record can be
|
|
// properly constructed to deliver an APC to user mode if required.
|
|
// It is also necessary to save the volatile floating state for
|
|
// suspend/resume operations.
|
|
//
|
|
|
|
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) //
|
|
bsr ra, KiSaveNonVolatileFloatState // save floating state
|
|
|
|
//
|
|
// Attempt to deliver an APC.
|
|
//
|
|
|
|
10: bis sp, zero, a1 // set address of exception frame
|
|
bis fp, zero, a2 // set address of trap frame
|
|
bsr ra, KiDeliverApc // call APC delivery routine
|
|
|
|
//
|
|
// Restore the volatile floating state and return from the interrupt.
|
|
//
|
|
|
|
bsr ra, KiRestoreVolatileFloatState // restore floating state
|
|
ldq ra, ExIntRa(sp) // restore return address
|
|
lda sp, ExceptionFrameLength(sp) // deallocate exception frame
|
|
ret zero, (ra) // return
|
|
|
|
.end KiApcInterrupt
|
|
|