|
|
title "mpipia" ;++ ; ; Copyright (c) 1989-1995 Microsoft Corporation ; ; Module Name: ; ; mpipia.asm ; ; Abstract: ; ; This module implements the x86 specific fucntions required to ; support multiprocessor systems. ; ; Author: ; ; David N. Cutler (davec) 5-Feb-1995 ; ; Environment: ; ; Krnel mode only. ; ; Revision History: ; ;--
.586p .xlist include ks386.inc include mac386.inc include callconv.inc .list
EXTRNP HalRequestSoftwareInterrupt,1,IMPORT,FASTCALL EXTRNP HalRequestSoftwareInterrupt,1,IMPORT,FASTCALL EXTRNP _HalRequestIpi,1,IMPORT EXTRNP _KiFreezeTargetExecution, 2 ifdef DBGMP EXTRNP _KiPollDebugger endif extrn _KiProcessorBlock:DWORD
DELAYCOUNT equ 2000h
_DATA SEGMENT DWORD PUBLIC 'DATA'
public _KiSynchPacket _KiSynchPacket dd 0
_DATA ENDS
_TEXT SEGMENT DWORD PUBLIC 'CODE' ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++ ; ; BOOLEAN ; KiIpiServiceRoutine ( ; IN PKTRAP_FRAME TrapFrame, ; IN PKEXCEPTION_FRAME ExceptionFrame ; ) ; ; Routine Description: ; ; This routine is called at IPI level to process any outstanding ; interporcessor requests for the current processor. ; ; Arguments: ; ; TrapFrame - Supplies a pointer to a trap frame. ; ; ExceptionFrame - Not used. ; ; Return Value: ; ; A value of TRUE is returned, if one of more requests were service. ; Otherwise, FALSE is returned. ; ;--
cPublicProc _KiIpiServiceRoutine, 2
ifndef NT_UP
cPublicFpo 2, 3 push ebx ; save nonvolatile registers push esi ; push edi ;
mov esi, PCR[PcPrcb] ; get current processor block address
xor ebx, ebx ; set exchange value xor ecx, ecx ; mov eax, [esi].PbRequestSummary ; get current request summary mov edx, [esi].PbSignalDone ; get current request packet
isr05: ;
lock cmpxchg8b qword ptr PbRequestSummary[esi] ; capture and clear request data jnz short isr05 ; if nz, compare exchange failed mov ebx, eax ; save request summary mov edi, edx ; save request packet
; ; Check for freeze request or synchronous request. ;
test bl, IPI_FREEZE + IPI_SYNCH_REQUEST ; test for freeze or packet jnz short isr50 ; if nz, freeze or synch request
; ; For RequestSummary's other then IPI_FREEZE set return to TRUE ;
mov bh, 1 ; set return value
; ; Check for Packet ready. ; ; If a packet is ready, then get the address of the requested function ; and call the function passing the address of the packet address as a ; parameter. ;
isr10: test edi, edi ; test for request packet jz short isr20 ; if z set, no packet ready mov edx, edi ; clear low bit in packet address btr edx, 0 ; push [edx].PbCurrentPacket + 8 ; push parameters on stack push [edx].PbCurrentPacket + 4 ; push [edx].PbCurrentPacket + 0 ; push edi ; push source processor block address mov eax, [edx].PbWorkerRoutine ; get worker routine address mov edx, [esp + 16 + 4*4] ; get current trap frame address mov [esi].PbIpiFrame, edx ; save current trap frame address call eax ; call worker routine mov bh, 1 ; set return value
; ; Check for APC interrupt request. ;
isr20: test bl, IPI_APC ; check if APC interrupt requested jz short isr30 ; if z, APC interrupt not requested
mov ecx, APC_LEVEL ; request APC interrupt fstCall HalRequestSoftwareInterrupt ;
; ; Check for DPC interrupt request. ;
isr30: test bl, IPI_DPC ; check if DPC interrupt requested jz short isr40 ; if z, DPC interrupt not requested
mov ecx, DISPATCH_LEVEL ; request DPC interrupt fstCall HalRequestSoftwareInterrupt ;
isr40: mov al, bh ; return status pop edi ; restore nonvolatile registers pop esi ; pop ebx ;
stdRET _KiIpiServiceRoutine
; ; Freeze or synchronous request ;
isr50: test bl, IPI_FREEZE ; test if freeze request jz short isr60 ; if z, no freeze request
; ; Freeze request is requested ;
mov ecx, [esp] + 20 ; get exception frame address mov edx, [esp] + 16 ; get trap frame address stdCall _KiFreezeTargetExecution, <edx, ecx> ; freeze execution test bl, not IPI_FREEZE ; Any other IPI RequestSummary? setnz bh ; Set return code accordingly test bl, IPI_SYNCH_REQUEST ; test if synch request jz isr10 ; if z, no sync request
; ; Synchronous packet request. Pointer to requesting PRCB in KiSynchPacket. ;
isr60: mov eax, _KiSynchPacket ; get PRCB of requesting processor mov edx, eax ; clear low bit in packet address btr edx, 0 ; push [edx].PbCurrentPacket+8 ; push parameters on stack push [edx].PbCurrentPacket+4 ; push [edx].PbCurrentPacket+0 ; push eax ; push source processor block address mov eax, [edx].PbWorkerRoutine ; get worker routine address mov edx, [esp + 16 + 4*4] ; get current trap frame address mov [esi].PbIpiFrame, edx ; save current trap frame address call eax ; call worker routine mov bh, 1 ; set return value jmp isr10 ; join common code
else
xor eax, eax ; return FALSE
stdRET _KiIpiServiceRoutine
endif
stdENDP _KiIpiServiceRoutine
;++ ; ; VOID ; FASTCALL ; KiIpiSend ( ; IN KAFFINITY TargetProcessors, ; IN KIPI_REQUEST Request ; ) ; ; Routine Description: ; ; This function requests the specified operation on the targt set of ; processors. ; ; Arguments: ; ; TargetProcessors (ecx) - Supplies the set of processors on which the ; specified operation is to be executed. ; ; IpiRequest (edx) - Supplies the request operation code. ; ; Return Value: ; ; None. ; ;--
cPublicFastCall KiIpiSend, 2
ifndef NT_UP
cPublicFpo 0, 2 push esi ; save registers push edi ; mov esi, ecx ; save target processor set
shr ecx, 1 ; shift out first bit lea edi, _KiProcessorBlock ; get processor block array address jnc short is20 ; if nc, not in target set
is10: mov eax, [edi] ; get processor block address lock or [eax].PbRequestSummary, edx ; set request summary bit
is20: shr ecx, 1 ; shift out next bit lea edi, [edi+4] ; advance to next processor jc short is10 ; if target, go set summary bit jnz short is20 ; if more, check next
stdCall _HalRequestIpi, <esi> ; request IPI interrupts on targets
pop edi ; restore registers pop esi ; endif fstRet KiIpiSend
fstENDP KiIpiSend
;++ ; ; VOID ; KiIpiSendPacket ( ; IN KAFFINITY TargetProcessors, ; IN PKIPI_WORKER WorkerFunction, ; IN PVOID Parameter1, ; IN PVOID Parameter2, ; IN PVOID Parameter3 ; ) ; ; Routine Description: ; ; This routine executes the specified worker function on the specified ; set of processors. ; ; Arguments: ; ; TargetProcessors [esp + 4] - Supplies the set of processors on which the ; specfied operation is to be executed. ; ; WorkerFunction [esp + 8] - Supplies the address of the worker function. ; ; Parameter1 - Parameter3 [esp + 12] - Supplies worker function specific ; paramters. ; ; Return Value: ; ; None. ; ;--*/
cPublicProc _KiIpiSendPacket, 5
ifndef NT_UP
cPublicFpo 5, 2 push esi ; save registers push edi ;
; ; Store function address and parameters in the packet area of the PRCB on ; the current processor. ;
mov edx, PCR[PcPrcb] ; get current processor block address mov ecx, [esp] + 12 ; get target processor set mov eax, [esp] + 16 ; get worker function address mov edi, [esp] + 20 ; get worker function parameter 1 mov esi, [esp] + 24 ; get worker function parameter 2
mov [edx].PbTargetSet, ecx ; set target processor set mov [edx].PbWorkerRoutine, eax ; set worker function address
mov eax, [esp] + 28 ; get worker function parameter 3 mov [edx].PbCurrentPacket, edi ; set work function parameters mov [edx].PbCurrentPacket + 4, esi ; mov [edx].PbCurrentPacket + 8, eax ;
; ; Determine whether one and only one bit is set in the target set. ;
mov edi, ecx ; copy recipient target set lea esi, dword ptr [ecx-1] ; compute target set - 1 and edi, esi ; and target set with target set - 1 neg edi ; negate result (CF = 0 if zero) sbb edi, edi ; compute result as one if the inc edi ; target set has one bit set jnz short isp5 ; if nz, target set has one bit mov [edx].PbPacketBarrier, ecx ; set packet barrier isp5: add edx, edi ; set low order bit if appropriate
; ; Loop through the target processors and send the packet to the specified ; recipients. ;
shr ecx, 1 ; shift out first bit lea edi, _KiProcessorBlock ; get processor block array address jnc short isp30 ; if nc, not in target set isp10: mov esi, [edi] ; get processor block address isp20: mov eax, [esi].PbSignalDone ; check if packet being processed or eax, eax ; jne short isp20 ; if ne, packet being processed
lock cmpxchg [esi].PbSignalDone, edx ; compare and exchange
jnz short isp20 ; if nz, exchange failed
isp30: shr ecx, 1 ; shift out next bit lea edi, [edi+4] ; advance to next processor jc short isp10 ; if c, in target set jnz short isp30 ; if nz, more target processors
mov ecx, [esp] + 12 ; set target processor set stdCall _HalRequestIpi, <ecx> ; send IPI to targets
pop edi ; restore register pop esi ; endif
stdRet _KiIpiSendPacket
stdENDP _KiIpiSendPacket
;++ ; ; VOID ; FASTCALL ; KiIpiSignalPacketDone ( ; IN PKIPI_CONTEXT Signaldone ; ) ; ; Routine Description: ; ; This routine signals that a processor has completed a packet by ; clearing the calling processor's set member of the requesting ; processor's packet. ; ; Arguments: ; ; SignalDone (ecx) - Supplies a pointer to the processor block of the ; sending processor. ; ; N.B. The low order bit of signal done is set if the target set ; has one and only one bit set. ; ; Return Value: ; ; None. ; ;--
cPublicFastCall KiIpiSignalPacketDone, 1
ifndef NT_UP
btr ecx, 0 ; test and clear bit 0 jc short spd20 ; if c set, only one bit set mov edx, PCR[PcPrcb] ; get current processor block address mov eax, [edx].PbSetMember ; get processor bit lock xor [ecx].PbTargetSet, eax ; clear processor set member jnz short spd10 ; if nz, more targets to go xor eax, eax ; clear packet barrier mov [ecx].PbPacketBarrier, eax ;
spd10: fstRET KiIpiSignalPacketDone
; ; One and only one bit is set in the target set. Since this is the only ; processor that can clear any bits in the target set, the target set can ; be cleared with a simple write. ;
spd20: xor eax, eax ; clear target set mov [ecx].PbTargetSet, eax ;
endif
fstRET KiIpiSignalPacketDone
fstENDP KiIpiSignalPacketDone
;++ ; ; VOID ; FASTCALL ; KiIpiSignalPacketDoneAndStall ( ; IN PKIPI_CONTEXT Signaldone ; IN PULONG ReverseStall ; ) ; ; Routine Description: ; ; This routine signals that a processor has completed a packet by ; clearing the calling processor's set member of the requesting ; processor's packet, and then stalls of the reverse stall value ; ; Arguments: ; ; SignalDone (ecx) - Supplies a pointer to the processor block of the ; sending processor. ; ; N.B. The low order bit of signal done is set if the target set ; has one and only one bit set. ; ; ReverseStall (edx) - Supplies a pointer to the reverse stall barrier ; ; Return Value: ; ; None. ; ;--
cPublicFastCall KiIpiSignalPacketDoneAndStall, 2 cPublicFpo 0, 2
ifndef NT_UP
push ebx ; save register mov ebx, dword ptr [edx] ; get current value of barrier btr ecx, 0 ; test and clear bit 0 jc short sps10 ; if c set, only one bit set mov eax, PCR[PcPrcb] ; get processor block address mov eax, [eax].PbSetMember ; get processor bit lock xor [ecx].PbTargetSet, eax ; clear processor set member jnz short sps20 ; if nz, more targets to go xor eax, eax ; clear packet barrier mov [ecx].PbPacketBarrier, eax ; jmp short sps20 ;
; ; One and only one bit is set in the target set. Since this is the only ; processor that can clear any bits in the target set, the target set can ; be cleared with a simple write. ;
sps10: xor eax, eax ; clear target set mov [ecx].PbTargetSet, eax ;
; ; Wait for barrier value to change. ;
sps20: mov eax, DELAYCOUNT sps30: cmp ebx, dword ptr [edx] ; barrier set? jne short sps90 ; yes, all done
YIELD dec eax ; P54C pre C2 workaround jnz short sps30 ; if eax = 0, generate bus cycle
ifdef DBGMP stdCall _KiPollDebugger ; Check for debugger ^C endif
; ; There could be a freeze execution outstanding. Check and clear ; freeze flag. ;
.errnz IPI_FREEZE - 4 mov eax, PCR[PcPrcb] ; get processor block address lock btr [eax].PbRequestSummary, 2 ; Generate bus cycle jnc short sps20 ; Freeze pending?
cPublicFpo 0,4 push ecx ; save target processor block push edx ; save barrier address stdCall _KiFreezeTargetExecution, <[eax].PbIpiFrame, 0> ; pop edx ; restore barrier address pop ecx ; restore target procssor block jmp short sps20 ;
sps90: pop ebx ; restore register
endif fstRET KiIpiSignalPacketDoneAndStall
fstENDP KiIpiSignalPacketDoneAndStall
_TEXT ends end
|