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, ; 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, ; 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, ; 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