1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
;++
;
;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 i386\apic.inc
include i386\pcmp_nt.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 ; Vector == 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 CCHAR 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
; dismissed
;
; 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
|