mirror of https://github.com/lianthony/NT4.0
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.
317 lines
6.3 KiB
317 lines
6.3 KiB
title "Software Interrupts"
|
|
;++
|
|
;
|
|
; Copyright (c) 1992 Microsoft Corporation
|
|
; Copyright (c) 1992 Sequent Computer Systems, Inc.
|
|
;
|
|
; Module Name:
|
|
;
|
|
; w3swint.asm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; This module implements the software interrupt handlers for the
|
|
; APIC-based WinServer 3000 multiprocessor.
|
|
;
|
|
; Author:
|
|
;
|
|
; Phil Hochstetler ([email protected]) 3-30-93
|
|
;
|
|
; Environment:
|
|
;
|
|
; Kernel mode only.
|
|
;
|
|
; Revision History:
|
|
;
|
|
;--
|
|
|
|
.386p
|
|
.xlist
|
|
include hal386.inc
|
|
include callconv.inc ; calling convention macros
|
|
include i386\kimacro.inc
|
|
include i386\apic.inc
|
|
include i386\w3.inc
|
|
.list
|
|
|
|
EXTRNP _KeBugCheck,1
|
|
EXTRNP KfLowerIrql,1,IMPORT,FASTCALL
|
|
EXTRNP Kei386EoiHelper,0,IMPORT
|
|
EXTRNP _HalEndSystemInterrupt,2
|
|
EXTRNP _KiDeliverApc,3,IMPORT
|
|
EXTRNP _KiDispatchInterrupt,0,IMPORT
|
|
EXTRNP _HalBeginSystemInterrupt,3
|
|
|
|
extrn _HalpIRQLtoTPR:byte
|
|
extrn _HalpLocalUnitBase:dword
|
|
extrn _HalpIrql2IRRMask:dword
|
|
|
|
_TEXT 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 issue a software interrupt to the
|
|
; calling processor. Instead of using the hardware to do this,
|
|
; we have observed that emulation in software is *much* faster.
|
|
; This mostly because it takes 30 clocks or so to do a APIC access.
|
|
; The biggest win here is in avoiding having KeRaiseIrql/KeLowerIrql
|
|
; write to the APIC for 75% of the traffic (LOW_LEVEL to APC/DPC LEVEL).
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (cl) = RequestIrql - Supplies the request IRQL value
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
; equates for accessing argument
|
|
;
|
|
|
|
cPublicFastCall HalRequestSoftwareInterrupt ,1
|
|
cPublicFpo 0, 0
|
|
|
|
mov eax, 1
|
|
shl eax, cl ; create IRR bitmask
|
|
|
|
pushfd ; save interrupt mode
|
|
cli ; disable interrupt
|
|
|
|
or PCR[PcIRR], eax ; request SW interrupt
|
|
cmp PCR[PcHal.ProcIrql], cl ; take it now?
|
|
jb short @f
|
|
|
|
popfd ; restore interrupt mode
|
|
|
|
fstRET HalRequestSoftwareInterrupt ; no, just return
|
|
;
|
|
; Call KfLowerIrql(CurrentIrql) which handles unmasked software interrupts
|
|
;
|
|
@@:
|
|
mov cl, PCR[PcHal.ProcIrql]
|
|
|
|
popfd ; restore interrupt mode
|
|
|
|
fstCall KfLowerIrql ; (cl) = CurrentIrql
|
|
fstRET HalRequestSoftwareInterrupt
|
|
|
|
fstENDP HalRequestSoftwareInterrupt
|
|
|
|
page ,132
|
|
subttl "Clear 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
|
|
|
|
cPublicProc _HalpDispatchInterrupt ,0
|
|
|
|
;
|
|
; 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, set new priority level, and clear IRR bit
|
|
;
|
|
push dword ptr PCR[PcHal.ProcIrql]
|
|
mov byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL
|
|
and dword ptr PCR[PcIRR], NOT (1 SHL DISPATCH_LEVEL)
|
|
|
|
;
|
|
; 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
|
|
|
|
stdENDP _HalpDispatchInterrupt
|
|
|
|
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
|
|
|
|
cPublicProc _HalpApcInterrupt ,0
|
|
|
|
;
|
|
; Create IRET frame on stack
|
|
;
|
|
pop eax ; get caller PC
|
|
pushfd ; flags
|
|
push cs ; cs
|
|
push eax ; ip
|
|
|
|
;
|
|
; Save machine state on trap frame
|
|
;
|
|
|
|
ENTER_INTERRUPT hapc_a, hapc_t
|
|
.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
|
|
|
|
public HalpApcInterrupt2ndEntry
|
|
HalpApcInterrupt2ndEntry:
|
|
|
|
;
|
|
; Save previous IRQL, set new priority level, and clear IRR bit
|
|
;
|
|
push dword ptr PCR[PcHal.ProcIrql]
|
|
mov byte ptr PCR[PcHal.ProcIrql], APC_LEVEL
|
|
and dword ptr PCR[PcIRR], NOT (1 SHL APC_LEVEL)
|
|
|
|
;
|
|
; 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
|
|
|
|
stdENDP _HalpApcInterrupt
|
|
|
|
_TEXT ends
|
|
|
|
end
|