windows-nt/Source/XPSP1/NT/base/hals/halx86/i386/ixswint.asm
2020-09-26 16:20:57 +08:00

328 lines
7.1 KiB
NASM

title "Software Interrupts"
;++
;
; Copyright (c) 1992 Microsoft Corporation
;
; Module Name:
;
; ixswint.asm
;
; Abstract:
;
; This module implements the software interrupt handlers
; for x86 machines
;
; Author:
;
; John Vert (jvert) 2-Jan-1992
;
; Environment:
;
; Kernel mode only.
;
; Revision History:
;
;--
.386p
.xlist
include hal386.inc
include callconv.inc ; calling convention macros
include i386\ix8259.inc
include i386\kimacro.inc
.list
EXTRNP _KiDeliverApc,3,IMPORT
EXTRNP _KiDispatchInterrupt,0,IMPORT
EXTRNP Kei386EoiHelper,0,IMPORT
EXTRNP _HalEndSystemInterrupt,2
extrn SWInterruptHandlerTable:dword
extrn SWInterruptLookUpTable:byte
ifdef IRQL_METRICS
extrn HalApcSoftwareIntCount:dword
extrn HalDpcSoftwareIntCount:dword
endif
_TEXT$02 SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
page ,132
subttl "Request Software Interrupt"
;++
;
; VOID
; HalRequestSoftwareInterrupt (
; IN KIRQL RequestIrql
; )
;
; Routine Description:
;
; This routine is used to request a software interrupt to the
; system. Also, this routine checks to see if any software
; interrupt should be generated.
; The following condition will cause software interrupt to
; be simulated:
; any software interrupt which has higher priority than
; current IRQL's is pending.
;
; NOTE: This routine simulates software interrupt as long as
; any pending SW interrupt level is higher than the current
; IRQL, even when interrupts are disabled.
;
; Arguments:
;
; (cl) = RequestIrql - Supplies the request IRQL value
;
; Return Value:
;
; None.
;
;--
cPublicFastCall HalRequestSoftwareInterrupt ,1
cPublicFpo 0, 1
mov eax,1
shl eax, cl ; convert to mask
pushfd ; save interrupt mode
cli ; disable interrupt
or PCR[PcIRR], eax ; set the request bit
mov cl, PCR[PcIrql] ; get current IRQL
mov eax, PCR[PcIRR] ; get SW interrupt request register
and eax, 3 ; mask off pending HW interrupts
xor edx, edx
mov dl, SWInterruptLookUpTable[eax] ; get the highest pending
; software interrupt level
cmp dl, cl ; Is highest SW int level > irql?
jbe short KsiExit ; No, jmp ksiexit
call SWInterruptHandlerTable[edx*4] ; yes, simulate interrupt
; to the appropriate handler
KsiExit:
popfd ; restore original interrupt mode
fstRET HalRequestSoftwareInterrupt
fstENDP HalRequestSoftwareInterrupt
page ,132
subttl "Request Software Interrupt"
;++
;
; VOID
; HalClearSoftwareInterrupt (
; IN KIRQL RequestIrql
; )
;
; Routine Description:
;
; This routine is used to clear a possible pending software interrupt.
; Support for this function is optional, and allows the kernel to
; reduce the number of spurious software interrupts it receives/
;
; Arguments:
;
; (cl) = RequestIrql - Supplies the request IRQL value
;
; Return Value:
;
; None.
;
;--
cPublicFastCall HalClearSoftwareInterrupt ,1
cPublicFpo 0, 0
mov eax,1
shl eax, cl ; convert to mask
not eax
and PCR[PcIRR], eax ; clear pending irr bit
fstRET HalClearSoftwareInterrupt
fstENDP HalClearSoftwareInterrupt
page ,132
subttl "Dispatch Interrupt"
;++
;
; VOID
; HalpDispatchInterrupt(
; VOID
; );
;
; Routine Description:
;
; This routine is the interrupt handler for a software interrupt generated
; at DISPATCH_LEVEL. Its function is to save the machine state, raise
; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC
; delivery routine.
;
; Arguments:
;
; None
; Interrupt is disabled
;
; Return Value:
;
; None.
;
;--
ENTER_DR_ASSIST hdpi_a, hdpi_t
align dword
public _HalpDispatchInterrupt
_HalpDispatchInterrupt proc
ifdef IRQL_METRICS
lock inc HalDpcSoftwareIntCount
endif
;
; Create IRET frame on stack
;
pop eax
pushfd
push cs
push eax
;
; Save machine state on trap frame
;
ENTER_INTERRUPT hdpi_a, hdpi_t
.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
public _HalpDispatchInterrupt2ndEntry
_HalpDispatchInterrupt2ndEntry:
; Save previous IRQL and set new priority level
push PCR[PcIrql] ; save previous IRQL
mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
and dword ptr PCR[PcIRR], not (1 shl DISPATCH_LEVEL) ; clear the pending bit in IRR
;
; Now it is safe to enable interrupt to allow higher priority interrupt
; to come in.
;
sti
;
; Go do Dispatch Interrupt processing
;
stdCall _KiDispatchInterrupt
;
; Do interrupt exit processing
;
SOFT_INTERRUPT_EXIT ; will do an iret
_HalpDispatchInterrupt endp
page ,132
subttl "APC Interrupt"
;++
;
; HalpApcInterrupt(
; VOID
; );
;
; Routine Description:
;
; This routine is entered as the result of a software interrupt generated
; at APC_LEVEL. Its function is to save the machine state, raise Irql to
; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine.
;
; Arguments:
;
; None
; Interrupt is Disabled
;
; Return Value:
;
; None.
;
;--
ENTER_DR_ASSIST hapc_a, hapc_t
align dword
public _HalpApcInterrupt
_HalpApcInterrupt proc
ifdef IRQL_METRICS
lock inc HalApcSoftwareIntCount
endif
;
; Create IRET frame on stack
;
pop eax
pushfd
push cs
push eax
;
; Save machine state in trap frame
;
ENTER_INTERRUPT hapc_a, hapc_t
.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
public _HalpApcInterrupt2ndEntry
_HalpApcInterrupt2ndEntry:
;
; Save previous IRQL and set new priority level
;
push PCR[PcIrql] ; save previous Irql
mov byte ptr PCR[PcIrql], APC_LEVEL ; set new Irql
and dword ptr PCR[PcIRR], not (1 shl APC_LEVEL) ; dismiss pending APC
;
; Now it is safe to enable interrupt to allow higher priority interrupt
; to come in.
;
sti
;
; call the APC delivery routine.
;
mov eax, [ebp]+TsSegCs ; get interrupted code's CS
and eax, MODE_MASK ; extract the mode
test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
jz short @f
or eax, MODE_MASK ; If v86 frame, then set user_mode
@@:
;
; call APC deliver routine
; Previous mode
; Null exception frame
; Trap frame
stdCall _KiDeliverApc, <eax, 0,ebp>
;
;
; Do interrupt exit processing
;
SOFT_INTERRUPT_EXIT ; will do an iret
_HalpApcInterrupt endp
_TEXT$02 ends
end