Leaked source code of windows server 2003
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.

1019 lines
28 KiB

  1. title "Interprocessor Interrupt"
  2. ;++
  3. ;
  4. ;Copyright (c) 1991 Microsoft Corporation
  5. ;Copyright (c) 1992 Intel Corporation
  6. ;All rights reserved
  7. ;
  8. ;INTEL CORPORATION PROPRIETARY INFORMATION
  9. ;
  10. ;This software is supplied to Microsoft under the terms
  11. ;of a license agreement with Intel Corporation and may not be
  12. ;copied nor disclosed except in accordance with the terms
  13. ;of that agreement.
  14. ;
  15. ;
  16. ;Module Name:
  17. ;
  18. ; mpipi.asm
  19. ;
  20. ;Abstract:
  21. ;
  22. ; PC+MP IPI code.
  23. ; Provides the HAL support for Interprocessor Interrupts and Processor
  24. ; initialization for PC+MP Systems
  25. ;
  26. ;Author:
  27. ;
  28. ; Ken Reneris (kenr) 13-Jan-1992
  29. ;
  30. ;Revision History:
  31. ;
  32. ; Ron Mosgrove (Intel) Aug 1993
  33. ; Modified for PC+MP Systems
  34. ;--
  35. .486p
  36. .xlist
  37. ;
  38. ; Normal includes
  39. ;
  40. include hal386.inc
  41. include i386\kimacro.inc
  42. include mac386.inc
  43. include apic.inc
  44. include callconv.inc ; calling convention macros
  45. include ntapic.inc
  46. EXTRNP Kei386EoiHelper,0,IMPORT
  47. EXTRNP _HalpMarkProcessorStarted,2
  48. EXTRNP _HalBeginSystemInterrupt,3
  49. EXTRNP _HalEndSystemInterrupt,2
  50. EXTRNP _KiIpiServiceRoutine,2,IMPORT
  51. EXTRNP _HalDisplayString,1
  52. EXTRNP HalpAcquireHighLevelLock,1,,FASTCALL
  53. EXTRNP HalpReleaseHighLevelLock,2,,FASTCALL
  54. EXTRNP HalpSendIpi,2,,FASTCALL
  55. ifdef ACPI_HAL
  56. EXTRNP _DetectAcpiMP,2
  57. else
  58. EXTRNP _DetectMPS,1
  59. endif
  60. EXTRNP _HalpRegisterKdSupportFunctions,1
  61. EXTRNP _HalpInitializeLocalUnit,0
  62. EXTRNP _HalpResetThisProcessor,0
  63. if DBG OR DEBUGGING
  64. EXTRNP _DbgBreakPoint,0,IMPORT
  65. endif
  66. extrn _HalpDefaultInterruptAffinity:DWORD
  67. extrn _HalpActiveProcessors:DWORD
  68. extrn _HalpGlobal8259Mask:WORD
  69. extrn _HalpStaticIntAffinity:BYTE
  70. extrn _HalpPICINTToVector:BYTE
  71. extrn _rgzBadHal:BYTE
  72. extrn _HalpMaxProcsPerCluster:BYTE
  73. extrn _HalpIntDestMap:BYTE
  74. I386_80387_BUSY_PORT equ 0f0h
  75. SEND_IPI macro IpiCommand
  76. mov ecx, eax
  77. mov edx, IpiCommand
  78. fstCall halpSendIpi
  79. endm
  80. _DATA SEGMENT DWORD PUBLIC 'DATA'
  81. ALIGN dword
  82. public _HalpProcessorPCR
  83. _HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
  84. ;
  85. ; The following symbols are used by the Local Apic Error handler.
  86. ;
  87. LogApicErrors equ 1
  88. if LogApicErrors
  89. public _HalpLocalApicErrorLock
  90. public _HalpLocalApicErrorCount
  91. public _HalpApicErrorLog
  92. APIC_ERROR_LOG_SIZE equ 128 ; Must be 2^n see usage below
  93. ALIGN dword
  94. _HalpApicErrorLog dw APIC_ERROR_LOG_SIZE dup(0)
  95. _HalpLocalApicErrorLock dd 0
  96. _HalpLocalApicErrorCount dd 0
  97. ;
  98. ; Bit:
  99. ;
  100. ; 0 - Send checksum error
  101. ; 1 - Recieve checksum error
  102. ; 2 - Send accept error
  103. ; 3 - Receive accept error
  104. ; 4 - reserved
  105. ; 5 - Send illegal vector
  106. ; 6 - Receive illegal vector
  107. ; 7 - illegal register address
  108. ; 8-31 - reserved
  109. ;
  110. endif ; LogApicErrors
  111. public HalpBroadcastLock, HalpBroadcastTargets
  112. public HalpBroadcastFunction, HalpBroadcastContext
  113. HalpBroadcastLock dd 0
  114. HalpBroadcastFunction dd 0
  115. HalpBroadcastContext dd 0
  116. HalpBroadcastTargets dd 0
  117. _DATA ends
  118. _TEXT SEGMENT DWORD PUBLIC 'DATA'
  119. ALIGN dword
  120. ;
  121. ; The _PicExtintIntiHandlers and the _PicNopIntiHandlers tables are
  122. ; used by the enable and disable system interrupt routines to determine
  123. ; the EXTINT interrupt handler to install.
  124. ;
  125. public _PicExtintIntiHandlers
  126. _PicExtintIntiHandlers label dword
  127. dd PicInterruptHandlerInti0 ; Inti 0 - PIC 1
  128. dd PicInterruptHandlerInti1 ; Inti 1 - PIC 1
  129. dd PicInterruptHandlerInti2 ; Inti 2 - PIC 1
  130. dd PicInterruptHandlerInti3 ; Inti 3 - PIC 1
  131. dd PicInterruptHandlerInti4 ; Inti 4 - PIC 1
  132. dd PicInterruptHandlerInti5 ; Inti 5 - PIC 1
  133. dd PicInterruptHandlerInti6 ; Inti 6 - PIC 1
  134. dd PicInterruptHandlerInti7 ; Inti 7 - PIC 1
  135. dd PicInterruptHandlerInti8 ; Inti 8 - PIC 2
  136. dd PicInterruptHandlerInti9 ; Inti 9 - PIC 2
  137. dd PicInterruptHandlerIntiA ; Inti 10 - PIC 2
  138. dd PicInterruptHandlerIntiB ; Inti 11 - PIC 2
  139. dd PicInterruptHandlerIntiC ; Inti 12 - PIC 2
  140. dd PicInterruptHandlerIntiD ; Inti 13 - PIC 2
  141. dd PicInterruptHandlerIntiE ; Inti 14 - PIC 2
  142. dd PicInterruptHandlerIntiF ; Inti 15 - PIC 2
  143. public _PicNopIntiHandlers
  144. _PicNopIntiHandlers label dword
  145. dd PicNopHandlerInti0 ; Inti 0 - PIC 1
  146. dd PicNopHandlerInti1 ; Inti 1 - PIC 1
  147. dd PicNopHandlerInti2 ; Inti 2 - PIC 1
  148. dd PicNopHandlerInti3 ; Inti 3 - PIC 1
  149. dd PicNopHandlerInti4 ; Inti 4 - PIC 1
  150. dd PicNopHandlerInti5 ; Inti 5 - PIC 1
  151. dd PicNopHandlerInti6 ; Inti 6 - PIC 1
  152. dd PicNopHandlerInti7 ; Inti 7 - PIC 1
  153. dd CommonPic2NopHandler ; Inti 8 - PIC 2
  154. dd CommonPic2NopHandler ; Inti 9 - PIC 2
  155. dd CommonPic2NopHandler ; Inti 10 - PIC 2
  156. dd CommonPic2NopHandler ; Inti 11 - PIC 2
  157. dd CommonPic2NopHandler ; Inti 12 - PIC 2
  158. dd PicNopHandlerIntiD ; Inti 13 - PIC 2
  159. dd CommonPic2NopHandler ; Inti 14 - PIC 2
  160. dd CommonPic2NopHandler ; Inti 15 - PIC 2
  161. _TEXT ends
  162. page ,132
  163. subttl "Post InterProcessor Interrupt"
  164. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  165. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  166. ;++
  167. ;
  168. ; VOID
  169. ; HalInitializeProcessor(
  170. ; ULONG Number
  171. ; PVOID LoaderBlock
  172. ; );
  173. ;
  174. ;Routine Description:
  175. ;
  176. ; Initialize hal pcr values for current processor (if any)
  177. ; (called shortly after processor reaches kernel, before
  178. ; HalInitSystem if P0)
  179. ;
  180. ; IPI's and KeReadir/LowerIrq's must be available once this function
  181. ; returns. (IPI's are only used once two or more processors are
  182. ; available)
  183. ;
  184. ; . Enable IPI interrupt (makes sense for P1, P2, ...).
  185. ; . Save Processor Number in PCR.
  186. ; . if (P0)
  187. ; . determine if the system is a PC+MP,
  188. ; . if not a PC+MP System Halt;
  189. ; . Enable IPI's on CPU.
  190. ;
  191. ;Arguments:
  192. ;
  193. ; Number - Logical processor number of calling processor
  194. ;
  195. ;Return Value:
  196. ;
  197. ; None.
  198. ;
  199. ;--
  200. cPublicProc _HalInitializeProcessor ,2
  201. mov PCR[PcIDR], 0FFFFFFFFH ; mark all INTs as disabled
  202. movzx eax, byte ptr [esp+4]
  203. mov PCR[PcHal.PcrNumber], al ; Save processor # in PCR
  204. mov ecx, PCR[PcSelfPcr] ; Flat address of this PCR
  205. mov _HalpProcessorPCR[eax*4], ecx ; Save it away
  206. mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
  207. ;
  208. ; set bit in affinity mask for this active processor
  209. ;
  210. lock bts _HalpActiveProcessors, eax
  211. ;
  212. ; set interrupt affinity to either be most-significant processor or
  213. ; a set of all processors
  214. ;
  215. mov edx, eax
  216. mov eax, _HalpDefaultInterruptAffinity
  217. hip10: cmp _HalpStaticIntAffinity, 1 ; Signle or all?
  218. sbb ecx, ecx ; set mask 0 or -1
  219. and ecx, eax ; include existing set or not
  220. bts ecx, edx ; include self
  221. cmp ecx, eax ; new mask a better choice?
  222. jc short hip20 ; no, done
  223. lock cmpxchg _HalpDefaultInterruptAffinity, ecx ; set new mask
  224. jnz short hip10 ; if it didn't take, do it again
  225. hip20:
  226. ;
  227. ; Most of the following code is only needed on P0
  228. ;
  229. or edx, edx
  230. jnz PnInitCode ; Not P0 skip a lot
  231. ; Run on P0 only
  232. ;
  233. ; Determine if the system we are on is an PC+MP
  234. ;
  235. ; DetectMPS has a parameter we don't currently use. It's a boolean
  236. ; which is set to TRUE if the system we're on is a MP system. Remember,
  237. ; we could have a UP PC+MP system.
  238. ;
  239. ; The DetectMPS routine also allocates Virtual Addresses for all of
  240. ; the APIC's in the system (it needs to access the devices anyway so ...)
  241. ;
  242. sub esp, 4
  243. ifdef ACPI_HAL
  244. mov eax, esp
  245. stdCall _DetectAcpiMP <eax, [esp + 12]> ; Are we running on an ACPI MP
  246. else
  247. stdCall _DetectMPS <esp> ; Are we running on an PC+MP
  248. endif
  249. add esp,4
  250. cmp eax, 0 ; Yes (nonZero) or
  251. je NotPcMp ; No (Zero)
  252. ; stdCall _HalDisplayString, <offset HalSignonString>
  253. ;
  254. ; This next call has nothing to do with processor init.
  255. ; But this is the only function in the HAL that gets
  256. ; called before KdInit.
  257. ;
  258. stdCall _HalpRegisterKdSupportFunctions <[esp + 8]>
  259. mov ax, 0FFFFH ; mask all PIC interrupts
  260. mov _HalpGlobal8259Mask, ax ; save the mask
  261. SET_8259_MASK
  262. ;
  263. ; Other P0 initialization would go here
  264. ;
  265. jmp CommonInitCode
  266. PnInitCode:
  267. ;
  268. ; Pn initialization goes here
  269. ;
  270. mov ecx, PCR[PcPrcb] ; get PRCB
  271. movzx eax, byte ptr [ecx].PbHalReserved.PrcbPCMPApicID ; get APIC id
  272. movzx ecx, byte ptr [ecx].PbNumber ; get processor number
  273. stdCall _HalpMarkProcessorStarted, <eax, ecx>
  274. CommonInitCode:
  275. stdCall _HalInitApicInterruptHandlers
  276. ;
  277. ; initialize the APIC local unit for this Processor
  278. ;
  279. stdCall _HalpInitializeLocalUnit
  280. stdRET _HalInitializeProcessor
  281. NotPcMp:
  282. stdCall _HalDisplayString, <offset _rgzBadHal>
  283. hlt
  284. stdENDP _HalInitializeProcessor
  285. D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
  286. ;++
  287. ;
  288. ; VOID
  289. ; HalInitApicInterruptHandlers(
  290. ; );
  291. ;
  292. ;Routine Description:
  293. ;
  294. ; This routine installs the interrupt vector in the IDT for the APIC
  295. ; spurious interrupt.
  296. ;
  297. ;Arguments:
  298. ;
  299. ; None.
  300. ;
  301. ;Return Value:
  302. ;
  303. ; None.
  304. ;
  305. ;--
  306. cPublicProc _HalInitApicInterruptHandlers ,0
  307. enter 8,0 ; setup ebp, reserve 8 bytes of stack
  308. sidt fword ptr [ebp-8] ; get IDT address
  309. mov edx, [ebp-6] ; (edx)->IDT
  310. mov ecx, PIC1_SPURIOUS_VECTOR ; Spurious Vector
  311. mov eax, offset FLAT:PicSpuriousService37
  312. mov word ptr [edx+8*ecx], ax ; Lower half of handler addr
  313. mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector
  314. mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate
  315. shr eax, 16 ; (ax)=higher half of handler addr
  316. mov word ptr [edx+8*ecx+6], ax
  317. mov ecx, APIC_SPURIOUS_VECTOR ; Apic Spurious Vector
  318. mov eax, offset FLAT:_HalpApicSpuriousService
  319. mov word ptr [edx+8*ecx], ax ; Lower half of handler addr
  320. mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector
  321. mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate
  322. shr eax, 16 ; (ax)=higher half of handler addr
  323. mov word ptr [edx+8*ecx+6], ax
  324. leave
  325. stdRET _HalInitApicInterruptHandlers
  326. stdENDP _HalInitApicInterruptHandlers
  327. cPublicProc PicSpuriousService37 ,0
  328. iretd
  329. stdENDP PicSpuriousService37
  330. ;++
  331. ;
  332. ; VOID
  333. ; HalpApicRebootService(
  334. ; );
  335. ;
  336. ;Routine Description:
  337. ;
  338. ; This is the ISR that handles Reboot events
  339. ;
  340. ;--
  341. ENTER_DR_ASSIST HReboot_a, HReboot_t
  342. cPublicProc _HalpApicRebootService ,0
  343. ENTER_INTERRUPT_FORCE_STATE HReboot_a, HReboot_t ; (ebp) -> Trap frame
  344. mov eax, APIC_REBOOT_VECTOR
  345. mov ecx, dword ptr APIC[LU_TPR] ; get the old TPR
  346. push ecx ; save it
  347. mov dword ptr APIC[LU_TPR], eax ; set the TPR
  348. APICFIX edx
  349. ;
  350. ; EOI the local APIC, warm reset does not reset the 82489 APIC
  351. ; so if we don't EOI here we'll never see an interrupt after
  352. ; the reboot.
  353. ;
  354. mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
  355. stdCall _HalpResetThisProcessor
  356. ;
  357. ; We should never get here, but just in case someone is stepping
  358. ; through this
  359. ;
  360. pop eax
  361. mov dword ptr APIC[LU_TPR], eax ; reset the TPR
  362. APICFIX edx
  363. ;
  364. ; Do interrupt exit processing without EOI
  365. ;
  366. SPURIOUS_INTERRUPT_EXIT
  367. stdENDP _HalpApicRebootService
  368. ;++
  369. ;
  370. ; VOID
  371. ; HalpGenericCallService(
  372. ; );
  373. ;
  374. ; Routine Description:
  375. ; This is the ISR that handles the GenericCall interrupt
  376. ;
  377. ;--
  378. ENTER_DR_ASSIST HGeneric_a, HGeneric_t
  379. cPublicProc _HalpBroadcastCallService ,0
  380. ENTER_INTERRUPT HGeneric_a, HGeneric_t ; (ebp) -> Trap frame
  381. ;
  382. ; (esp) - base of trap frame
  383. ;
  384. ; dismiss interrupt and raise Irql
  385. ;
  386. push APIC_GENERIC_VECTOR
  387. sub esp, 4 ; allocate space to save OldIrql
  388. stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL-1,APIC_GENERIC_VECTOR,esp>
  389. call _HalpPollForBroadcast
  390. INTERRUPT_EXIT ; lower irql to old value, iret
  391. stdENDP _HalpBroadcastCallService
  392. ;++
  393. ;
  394. ; VOID
  395. ; HalpGenericCall(
  396. ; IN VOID (*WorkerFunction)(VOID),
  397. ; IN ULONG Context,
  398. ; IN KAFFINITY TargetProcessors
  399. ; );
  400. ;
  401. ; Routine Description:
  402. ; Causes the WorkerFunction to be called on the specified target
  403. ; processors. The WorkerFunction is called at CLOCK2_LEVEL-1
  404. ; (Must be below IPI_LEVEL in order to prevent system deadlocks).
  405. ;
  406. ; Enviroment:
  407. ; Must be called with interrupts enabled.
  408. ; Must be called with IRQL = CLOCK2_LEVEL-1
  409. ;--
  410. cPublicProc _HalpGenericCall,3
  411. cPublicFpo 3, 0
  412. GENERIC_IPI equ (DELIVER_FIXED OR LOGICAL_DESTINATION OR ICR_USE_DEST_FIELD OR APIC_GENERIC_VECTOR)
  413. @@: call _HalpPollForBroadcast
  414. test HalpBroadcastLock, 1 ; Is broadcast busy?
  415. jnz short @b ; Yes, wait
  416. lock bts HalpBroadcastLock, 0 ; Try to get lock
  417. jc short @b ; didn't get it, loop
  418. hgc30: mov ecx, [esp+4]
  419. mov edx, [esp+8]
  420. mov eax, [esp+12]
  421. mov HalpBroadcastFunction, ecx
  422. mov HalpBroadcastContext, edx
  423. mov HalpBroadcastTargets, eax
  424. or eax, eax ; (eax) = Targets
  425. jz gc90
  426. SEND_IPI GENERIC_IPI
  427. ;
  428. ; Wait for all processors to call broadcast function
  429. ;
  430. @@: call _HalpPollForBroadcast
  431. cmp HalpBroadcastTargets, 0
  432. jnz short @b
  433. gc90: mov HalpBroadcastLock, 0 ; Release BroadcastLock
  434. stdRET _HalpGenericCall
  435. stdENDP _HalpGenericCall
  436. ;++
  437. ;
  438. ; VOID
  439. ; _HalpPollForBroadcast (
  440. ; VOID
  441. ; );
  442. ;
  443. ; Routine Description:
  444. ;
  445. ; IRQL = CLOCK2_LEVEL-1
  446. ;--
  447. cPublicProc _HalpPollForBroadcast, 0
  448. cPublicFpo 0, 0
  449. mov eax, PCR[PcSetMember]
  450. test HalpBroadcastTargets, eax
  451. jz short pb90
  452. mov ecx, HalpBroadcastFunction ; Pickup broadcast function
  453. push HalpBroadcastContext
  454. not eax ; Remove our bit from destionations
  455. lock and HalpBroadcastTargets, eax
  456. call ecx
  457. pb90: stdRET _HalpPollForBroadcast
  458. stdENDP _HalpPollForBroadcast
  459. ;++
  460. ;
  461. ; ULONG
  462. ; FASTCALL
  463. ; HalpWaitForPending (
  464. ; ULONG Count (ecx)
  465. ; PULONG LuICR (edx)
  466. ; );
  467. ;
  468. ; Routine Description:
  469. ;
  470. ; Waits for DELIVERY_PENDING to clear and returns remaining iteration count
  471. ;--
  472. cPublicFastCall HalpWaitForPending, 2
  473. cPublicFpo 0, 0
  474. wfp10: test dword ptr [edx], DELIVERY_PENDING
  475. jz short wfp20
  476. dec ecx
  477. jnz short wfp10
  478. wfp20: mov eax, ecx
  479. fstRet HalpWaitForPending
  480. fstENDP HalpWaitForPending
  481. ;++
  482. ;
  483. ; VOID
  484. ; HalpLocalApicErrorService(
  485. ; );
  486. ;
  487. ;Routine Description:
  488. ;
  489. ; This routine fields Local APIC error Events
  490. ;
  491. ;--
  492. ENTER_DR_ASSIST HApicErr_a, HApicErr_t
  493. cPublicProc _HalpLocalApicErrorService ,0
  494. ;
  495. ; Save machine state in trap frame
  496. ;
  497. ENTER_INTERRUPT HApicErr_a, HApicErr_t ; (ebp) -> Trap frame
  498. if LogApicErrors
  499. lea ecx, _HalpLocalApicErrorLock
  500. fstCall HalpAcquireHighLevelLock
  501. push eax
  502. mov eax, _HalpLocalApicErrorCount
  503. inc _HalpLocalApicErrorCount
  504. lea ecx, _HalpApicErrorLog
  505. and eax, APIC_ERROR_LOG_SIZE-1
  506. shl eax, 1
  507. add ecx, eax
  508. endif ; LogApicErrors
  509. mov dword ptr APIC[LU_EOI], 0 ; local unit EOI
  510. APICFIX eax
  511. ;
  512. ; The Apic EDS (Rev 4.0) says you have to write before you read
  513. ; this doesn't work. The write clears the status bits.
  514. ; But P6 works as according to the EDS!
  515. ;
  516. mov eax, PCR[PcPrcb]
  517. cmp byte ptr [eax].PbCpuType, 6
  518. jc short lae10
  519. mov dword ptr APIC[LU_ERROR_STATUS], 0
  520. lae10:
  521. mov eax, dword ptr APIC[LU_ERROR_STATUS] ; read error status
  522. ; Find out what kind of error it is and update the appropriate count.
  523. if LogApicErrors
  524. ; out 80h, al
  525. mov byte ptr [ecx], al
  526. inc ecx
  527. mov al, byte ptr PCR[PcHal.PcrNumber]
  528. mov byte ptr [ecx], al
  529. lea ecx, _HalpLocalApicErrorLock
  530. pop edx
  531. fstCall HalpReleaseHighLevelLock
  532. endif ; LogApicErrors
  533. SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
  534. stdENDP _HalpLocalApicErrorService
  535. page ,132
  536. subttl "PC+MP IPI Interrupt Handler"
  537. ;++
  538. ;
  539. ; VOID
  540. ; HalpIpiHandler (
  541. ; );
  542. ;
  543. ; Routine Description:
  544. ;
  545. ; This routine is entered as the result of an interrupt generated by inter
  546. ; processor communication.
  547. ;
  548. ; Arguments:
  549. ;
  550. ; None.
  551. ;
  552. ; Return Value:
  553. ;
  554. ; None.
  555. ;
  556. ;--
  557. ENTER_DR_ASSIST Hipi_a, Hipi_t
  558. cPublicProc _HalpIpiHandler ,0
  559. ;
  560. ; Save machine state in trap frame
  561. ;
  562. ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
  563. ;
  564. ; Save previous IRQL
  565. ;
  566. push APIC_IPI_VECTOR ; Vector
  567. sub esp, 4 ; space for OldIrql
  568. ;
  569. ; We now dismiss the interprocessor interrupt and call its handler
  570. ;
  571. stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,APIC_IPI_VECTOR,esp>
  572. stdCall _KiIpiServiceRoutine, <ebp,0>
  573. ;
  574. ; Do interrupt exit processing
  575. ;
  576. INTERRUPT_EXIT ; will return to caller
  577. stdENDP _HalpIpiHandler
  578. ;++
  579. ;
  580. ; VOID
  581. ; HalpApicSpuriousService(
  582. ; );
  583. ;
  584. ;Routine Description:
  585. ;
  586. ; A place for spurious interrupts to end up.
  587. ;
  588. ;--
  589. cPublicProc _HalpApicSpuriousService,0
  590. iretd
  591. stdENDP _HalpApicSpuriousService
  592. ;++
  593. ;
  594. ; VOID
  595. ; _PicInterruptHandlerIntiXX(
  596. ; );
  597. ;
  598. ;Routine Description:
  599. ;
  600. ; These handlers receive interrupts from the PIC and reissues them via
  601. ; a vector at the proper priority level. This is used to provide a symetric
  602. ; interrupt distribution on a non symetric system.
  603. ;
  604. ; The PIC interrupts will normally only be received (in the PC+MP Hal) via an
  605. ; interrupt input from on either the IO Unit or the Local unit which has been
  606. ; programed as EXTINT. EXTINT interrupts are received outside of the APIC
  607. ; priority structure (the PIC provides the vector). We use the APIC ICR to
  608. ; generate interrupts to the proper handler at the proper priority.
  609. ;
  610. ; The EXTINT interrupts are directed to a single processor, currently P0.
  611. ; There is no good reason why they can't be directed to another processor.
  612. ;
  613. ; Since one processor must absorb the overhead of redistributing PIC interrupts
  614. ; the interrupt handling on a system using EXTINT interrupts is not symetric.
  615. ;
  616. ;--
  617. ENTER_DR_ASSIST Hcpic_a, Hcpic_t
  618. cPublicProc PicHandler ,0
  619. PicInterruptHandlerInti0:
  620. push 0
  621. jmp short CommonPicHandler
  622. PicInterruptHandlerInti1:
  623. push 1
  624. jmp short CommonPicHandler
  625. PicInterruptHandlerInti2:
  626. push 2
  627. jmp short CommonPicHandler
  628. PicInterruptHandlerInti3:
  629. push 3
  630. jmp short CommonPicHandler
  631. PicInterruptHandlerInti4:
  632. push 4
  633. jmp short CommonPicHandler
  634. PicInterruptHandlerInti5:
  635. push 5
  636. jmp short CommonPicHandler
  637. PicInterruptHandlerInti6:
  638. push 6
  639. jmp short CommonPicHandler
  640. PicInterruptHandlerInti7:
  641. ;
  642. ; Check to see if this is a spurious interrupt
  643. ;
  644. push eax
  645. mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
  646. out PIC1_PORT0, al
  647. IODelay ; delay
  648. in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
  649. test al, 10000000B ; Is In-Service register set?
  650. pop eax
  651. jz short pic7_spurious ;
  652. push 7
  653. jmp short CommonPicHandler
  654. picf_spurious:
  655. mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi
  656. out PIC1_PORT0, al
  657. pop eax
  658. pic7_spurious:
  659. iretd ; ignore PIC
  660. PicInterruptHandlerInti8:
  661. push 8
  662. jmp short CommonPicHandler
  663. PicInterruptHandlerInti9:
  664. push 9
  665. jmp short CommonPicHandler
  666. PicInterruptHandlerIntiA:
  667. push 10
  668. jmp short CommonPicHandler
  669. PicInterruptHandlerIntiB:
  670. push 11
  671. jmp short CommonPicHandler
  672. PicInterruptHandlerIntiC:
  673. push 12
  674. jmp short CommonPicHandler
  675. PicInterruptHandlerIntiD:
  676. push 13
  677. push eax
  678. xor eax, eax
  679. out I386_80387_BUSY_PORT, al
  680. pop eax
  681. jmp short CommonPicHandler
  682. PicInterruptHandlerIntiE:
  683. push 14
  684. jmp short CommonPicHandler
  685. PicInterruptHandlerIntiF:
  686. push eax
  687. mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
  688. out PIC2_PORT0, al
  689. IODelay ; delay
  690. in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
  691. test al, 10000000B ; Is In-Service register set?
  692. jz short picf_spurious ; Go eoi PIC1 & Ignore PIC2
  693. pop eax
  694. push 15
  695. jmp short CommonPicHandler
  696. CommonPicHandler:
  697. ENTER_INTERRUPT Hcpic_a, Hcpic_t,PassDwordParm ; (ebp) -> Trap frame
  698. ;
  699. ; Need to determine if we have a level interrupt and if so don't EOI it
  700. ; It should be EOI'd by end system interrupt
  701. ;
  702. cmp bl, 8 ; Pic or Slave Pic
  703. jae short cph20
  704. mov al, bl
  705. or al, OCW2_SPECIFIC_EOI ; specific eoi
  706. out PIC1_PORT0, al ; dismiss the interrupt
  707. jmp short cph30
  708. cph20:
  709. mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
  710. out PIC2_PORT0, al
  711. mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi
  712. out PIC1_PORT0, al ; send irq2 specific eoi to master
  713. cph30:
  714. mov al, _HalpPICINTToVector[ebx] ; Get vector for PIC interrupt
  715. or al, al ; Is vector known?
  716. jz short cph90 ; No, don't dispatch it
  717. ;
  718. ; Now gain exclusive access to the ICR
  719. ;
  720. STALL_WHILE_APIC_BUSY
  721. cmp bl, 8
  722. je short HandleClockInti
  723. ;
  724. ; Write the IPI Command to the Memory Mapped Register
  725. ;
  726. mov dword ptr APIC[LU_INT_CMD_HIGH], DESTINATION_ALL_CPUS
  727. APICFIX edx
  728. mov dword ptr APIC[LU_INT_CMD_LOW], eax
  729. jmp short cph90
  730. HandleClockInti:
  731. ;
  732. ; Write the IPI Command to the Memory Mapped Register
  733. ;
  734. mov dword ptr APIC[LU_INT_CMD_LOW], (DELIVER_FIXED OR ICR_SELF OR APIC_CLOCK_VECTOR)
  735. cph90: APICFIX edx
  736. SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
  737. stdENDP PicHandler
  738. ;++
  739. ;
  740. ; VOID
  741. ; _PicXXNopHandler(
  742. ; );
  743. ;
  744. ;Routine Description:
  745. ;
  746. ; These handlers are designed to be installed on a system to field any PIC
  747. ; interrupts when there are not supposed to be any delivered.
  748. ;
  749. ; In the Debug case this routine increments an error count EOI's the PIC and
  750. ; returns. Normally the increment is not performed.
  751. ;--
  752. cPublicProc PicNopHandler ,0
  753. PicNopHandlerInti0:
  754. push eax ; Save Scratch Registers
  755. mov al, 0
  756. jmp short CommonPic1NopHandler
  757. PicNopHandlerInti1:
  758. push eax ; Save Scratch Registers
  759. mov al, 1
  760. jmp short CommonPic1NopHandler
  761. PicNopHandlerInti2:
  762. push eax ; Save Scratch Registers
  763. mov al, 2
  764. jmp short CommonPic1NopHandler
  765. PicNopHandlerInti3:
  766. push eax ; Save Scratch Registers
  767. mov al, 3
  768. jmp short CommonPic1NopHandler
  769. PicNopHandlerInti4:
  770. push eax ; Save Scratch Registers
  771. mov al, 4
  772. jmp short CommonPic1NopHandler
  773. PicNopHandlerInti5:
  774. push eax ; Save Scratch Registers
  775. mov al, 5
  776. jmp short CommonPic1NopHandler
  777. PicNopHandlerInti6:
  778. push eax ; Save Scratch Registers
  779. mov al, 6
  780. jmp short CommonPic1NopHandler
  781. PicNopHandlerInti7:
  782. push eax ; Save Scratch Registers
  783. mov al, 7
  784. CommonPic1NopHandler:
  785. ;
  786. ; Need to determine if we have a level interrupt and if so don't EOI it
  787. ; It should be EOI'd by end system interrupt
  788. ;
  789. or al, OCW2_SPECIFIC_EOI ; specific eoi
  790. out PIC1_PORT0, al ; dismiss the interrupt
  791. pop eax ; Restore Scratch registers
  792. iretd
  793. PicNopHandlerIntiD:
  794. push eax
  795. xor eax, eax
  796. out I386_80387_BUSY_PORT, al
  797. pop eax
  798. CommonPic2NopHandler:
  799. push eax
  800. ;
  801. ; Need to determine if we have a level interrupt and if so don't EOI it
  802. ; It should be EOI'd by end system interrupt
  803. ;
  804. mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
  805. out PIC2_PORT0, al
  806. mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi
  807. out PIC1_PORT0, al ; send irq2 specific eoi to master
  808. pop eax
  809. iretd
  810. stdENDP PicNopHandler
  811. _TEXT ENDS
  812. END