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

245 lines
6.1 KiB
NASM

;++
;
;Copyright (c) 1991 Microsoft Corporation
;Copyright (c) 1992 Intel Corporation
;All rights reserved
;
;INTEL CORPORATION PROPRIETARY INFORMATION
;
;This software is supplied to Microsoft under the terms
;of a license agreement with Intel Corporation and may not be
;copied nor disclosed except in accordance with the terms
;of that agreement.
;
;
;Module Name:
;
; mpsysint.asm
;
;Abstract:
;
; This module implements the HAL routines to begin/end
; system interrupts for a PC+MP implementation
;
;Author:
;
; John Vert (jvert) 22-Jul-1991
;
;Environment:
;
; Kernel Mode
;
;Revision History:
;
; Ron Mosgrove (Intel) Aug 1993
; Modified for PC+MP Systems
;
;--
.386p
.xlist
include hal386.inc
include callconv.inc ; calling convention macros
include i386\kimacro.inc
include mac386.inc
include apic.inc
include ntapic.inc
.list
EXTRNP _KeBugCheck,1,IMPORT
EXTRNP _KiDispatchInterrupt,0,IMPORT
extrn _HalpVectorToIRQL:byte
extrn _HalpIRQLtoTPR:byte
_TEXT SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
page ,132
subttl "End System Interrupt"
;++
;
; VOID
; HalpEndSystemInterrupt
; IN KIRQL NewIrql,
; IN ULONG Vector
; )
;
; Routine Description:
;
; This routine is used to lower IRQL to the specified value.
; The IRQL and PIRQL will be updated accordingly. 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:
;
; NewIrql - the new irql to be set.
;
; Vector - Vector number of the interrupt
;
; Note that esp+12 is the beginning of interrupt/trap frame and upon
; entering to this routine the interrupts are off.
;
; Return Value:
;
; None.
;
;--
HeiNewIrql equ [esp + 4]
HeiVector equ [esp + 8]
cPublicProc _HalEndSystemInterrupt ,2
cPublicFpo 2, 0
xor ecx,ecx
mov cl, byte ptr HeiNewIrql ; get new IRQL
mov cl, _HalpIRQLtoTPR[ecx] ; get corresponding TPR value
mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
APICFIX edx
cmp cl, DPC_VECTOR ; Is new irql < DPC?
jc short es10 ; Yes, go check for pending DPC
es05: mov dword ptr APIC[LU_TPR], ecx ; Set new Priority
;
; We have to ensure that the requested priority is set before
; we return. The caller is counting on it.
;
mov edx, dword ptr APIC[LU_TPR]
CHECKTPR ecx, edx
stdRET _HalEndSystemInterrupt
es10: cmp PCR[PcHal.DpcPending], 0 ; Is a DPC pending?
mov PCR[PcHal.ShortDpc], 0 ; Clear short dpc flag
jz short es05 ; No, eoi
mov dword ptr APIC[LU_TPR], DPC_VECTOR ; lower to DPC level
APICFIX edx
push ebx ; Save EBX (used by KiDispatchInterrupt)
push ecx ; Save OldIrql
cPublicFpo 2, 2
sti
es20: mov PCR[PcHal.DpcPending], 0 ; Clear pending flag
stdCall _KiDispatchInterrupt ; Dispatch interrupt
cli
pop ecx
pop ebx
jmp short es05
stdENDP _HalEndSystemInterrupt
;++
;
;BOOLEAN
;HalBeginSystemInterrupt(
; IN KIRQL Irql
; IN ULONG Vector,
; OUT PKIRQL OldIrql
; )
;
;Routine Description:
;
; This routine raises the IRQL to the level of the specified
; interrupt vector. It is called by the hardware interrupt
; handler before any other interrupt service routine code is
; executed. The CPU interrupt flag is set on exit.
;
; On APIC-based systems we do not need to check for spurious
; interrupts since they now have their own vector. We also
; no longer need to check whether or not the incoming priority
; is higher than the current priority that is guaranteed by
; the priority mechanism of the APIC.
;
; SO
;
; All BeginSystemInterrupt needs to do is set the APIC TPR
; appropriate for the IRQL, and return TRUE. Note that to
; use the APIC ISR priority we are not going issue EOI until
; EndSystemInterrupt is called.
;
; Arguments:
;
; Irql - Supplies the IRQL to raise to
;
; Vector - Supplies the vector of the interrupt to be
; handled
;
; OldIrql- Location to return OldIrql
;
; Return Value:
;
; TRUE - Interrupt successfully dismissed and Irql raised.
; This routine can not fail.
;
;--
align dword
HbsiIrql equ byte ptr [esp+4]
HbsiVector equ byte ptr [esp+8]
HbsiOldIrql equ dword ptr [esp+12]
cPublicProc _HalBeginSystemInterrupt ,3
cPublicFpo 3, 0
xor eax, eax
mov al, HbsiIrql ; (eax) = New Vector
mov al, _HalpIRQLtoTPR[eax] ; get corresponding TPR value
;
; Read the TPR for the Priority (Vector) in use,
; and convert it to an IRQL
;
mov ecx, dword ptr APIC[LU_TPR] ; Get the Priority
mov dword ptr APIC[LU_TPR], eax
APICFIX edx
mov eax, HbsiOldIrql ; return the current IRQL as OldIrql
shr ecx, 4
mov cl, byte ptr _HalpVectorToIRQL[ecx]
mov byte ptr [eax], cl
mov eax, 1 ; return TRUE
sti
;
; If OldIrql < DISPATCH_LEVEL and new irql >= DISPATCH_LEVEL (which
; is assumed), then set
;
cmp cl, DISPATCH_LEVEL
jnc short bs10
if DBG
cmp PCR[PcHal.ShortDpc], 0
je short @f
int 3
@@:
endif
mov PCR[PcHal.ShortDpc], DISPATCH_LEVEL
bs10:
stdRET _HalBeginSystemInterrupt
stdENDP _HalBeginSystemInterrupt
_TEXT ENDS
END