572 lines
12 KiB
NASM
572 lines
12 KiB
NASM
title "Interprocessor Interrupt"
|
|
;++
|
|
;
|
|
;Copyright (c) 1991 Microsoft Corporation
|
|
;
|
|
;Module Name:
|
|
;
|
|
; oliipi.asm
|
|
;
|
|
;Abstract:
|
|
;
|
|
; SystemPro IPI code.
|
|
; Provides the HAL support for Interprocessor Interrupts for hte
|
|
; MP SystemPro implementation.
|
|
;
|
|
;Author:
|
|
;
|
|
; Ken Reneris (kenr) 13-Jan-1992
|
|
;
|
|
;Revision History:
|
|
;
|
|
; Bruno Sartirana (o-obruno) 3-Mar-92
|
|
; Added support for the Olivetti LSX5030.
|
|
;--
|
|
.386p
|
|
.xlist
|
|
|
|
;
|
|
; Include LSX5030 detection code
|
|
;
|
|
|
|
include i386\olidtect.asm
|
|
|
|
;
|
|
; Normal includes
|
|
;
|
|
|
|
include hal386.inc
|
|
include callconv.inc
|
|
include i386\kimacro.inc
|
|
include i386\ix8259.inc
|
|
;LSX5030 start
|
|
include i386\olimp.inc
|
|
EXTRNP _HalpInitializeProcessor,1
|
|
extrn _IdtIpiVector:DWORD
|
|
extrn KiI8259MaskTable:DWORD
|
|
;LSX5030 end
|
|
|
|
EXTRNP _KiCoprocessorError,0,IMPORT
|
|
EXTRNP Kei386EoiHelper,0,IMPORT
|
|
EXTRNP _HalBeginSystemInterrupt,3
|
|
EXTRNP _HalEndSystemInterrupt,2
|
|
EXTRNP _KiIpiServiceRoutine,2,IMPORT
|
|
EXTRNP _HalEnableSystemInterrupt,3
|
|
EXTRNP _HalpInitializePICs,0
|
|
EXTRNP _HalDisplayString,1
|
|
EXTRNP _HalEnableSystemInterrupt,3
|
|
EXTRNP _HalDisableSystemInterrupt,2
|
|
extrn _HalpActiveProcessors:DWORD
|
|
|
|
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
|
|
;LSX5030 start
|
|
|
|
;ifdef HALOLI_DBG
|
|
|
|
; for debug only
|
|
|
|
public DbgDelay
|
|
DbgDelay dd 20000000
|
|
|
|
;endif
|
|
|
|
; IPI IRQL decoding array
|
|
|
|
public PcrIpiIrql
|
|
PcrIpiIrql db 15
|
|
db 11
|
|
db 10
|
|
db 13
|
|
|
|
|
|
;LSX5030 end
|
|
|
|
;
|
|
; Processor Control Ports
|
|
;
|
|
|
|
public ProcessorControlPort, _HalpProcessorPCR, _HalpInitializedProcessors
|
|
ProcessorControlPort dw PCR_P0 ; P0 Processor Control Port
|
|
dw PCR_P1 ; P1 Processor Control Port
|
|
dw PCR_P2 ; P2 Processor Control Port
|
|
dw PCR_P3 ; P3 Processor Control Port
|
|
|
|
_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
|
|
|
|
_HalpInitializedProcessors dd 0
|
|
|
|
;
|
|
;InterruptVectorControl dw 0 ; P0 none for p0
|
|
;dw ICP_P1 ; P1 Processor Control Port
|
|
;dw ICP_P2 ; P2 Processor Control Port
|
|
;dw ICP_P3 ; P3 Processor Control Port
|
|
|
|
public _HalpFindFirstSetRight
|
|
_HalpFindFirstSetRight db 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
|
|
|
|
|
|
public _SystemType
|
|
_SystemType dd 0
|
|
|
|
;LSX5030 start
|
|
BadHalString db 'HAL: LSX5030 HAL.DLL cannot be run on non LSX5030', cr, lf
|
|
db ' Replace the hal.dll with the correct hal', cr, lf
|
|
db ' System is HALTING *********', 0
|
|
;LSX5030 end
|
|
|
|
_DATA ends
|
|
|
|
page ,132
|
|
subttl "Post InterProcessor Interrupt"
|
|
_TEXT SEGMENT DWORD PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalInitializeProcessor(
|
|
; ULONG Number
|
|
; );
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; Initialize hal pcr values for current processor (if any)
|
|
; (called shortly after processor reaches kernel, before
|
|
; HalInitSystem if P0)
|
|
;
|
|
; IPI's and KeReadir/LowerIrq's must be available once this function
|
|
; returns. (IPI's are only used once two or more processors are
|
|
; available)
|
|
;
|
|
; . Enable IPI interrupt (makes sense for P1, P2, ...).
|
|
; . Save Processor Number in PCR.
|
|
; . if (P0)
|
|
; . determine what kind of system is it,
|
|
; . if (NotSysProCompatible) Halt;
|
|
; . InitializePICs.
|
|
; . if (P1)
|
|
; . program VECTOR_PORT to accept IPI at IRQ13.
|
|
; . Save ProcesserControlPort (PCR) to PCRegion, per processor.
|
|
; . Enable PINTs on CPU.
|
|
;
|
|
;Arguments:
|
|
;
|
|
; eax: processor number - Logical processor number of calling processor
|
|
;
|
|
;Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
cPublicProc _HalInitializeProcessor,1
|
|
|
|
;LSX5030 start
|
|
|
|
;DBG_DISPLAY 0a0h
|
|
|
|
; Initialize PcIDR in PCR to enable slave IRQ
|
|
|
|
mov fs:PcIDR, 0fffffffbh
|
|
|
|
movzx eax, byte ptr [esp+4] ; get processor number
|
|
mov fs:PcHal.PcrNumber, al ; Save processor # in PCR
|
|
lock bts _HalpActiveProcessors, eax
|
|
lock inc _HalpInitializedProcessors
|
|
|
|
mov ecx, fs:PcSelfPcr ; Flat address of this PCR
|
|
mov _HalpProcessorPCR[eax*4], ecx ; Save it away
|
|
|
|
or eax, eax
|
|
jnz hip20_Any ; jump if not P0
|
|
|
|
|
|
; For P0 only, determine if this is an LSX5030 or not.
|
|
|
|
lea eax, _SystemType ; this just to honor the
|
|
; DetectOlivettiMp call interface
|
|
stdCall _DetectOlivettiMp,<eax>
|
|
;DBG_DISPLAY 0a1h
|
|
mov _SystemType, eax ; Remember system type
|
|
or eax, eax
|
|
jz _NotAnLSX5030 ; (SystemType == 0): Alien machine
|
|
|
|
; P0
|
|
|
|
; Initialized the stall scale factor to something other that 0,
|
|
; just in case KeStallExecutionProcessor was called before
|
|
; HalpInitializeStallExecution (when a DbgBreakPoint() is used
|
|
; before HalpInitializeStallExecution() is called.
|
|
;
|
|
|
|
mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
|
|
|
|
; load eax with the processor #
|
|
|
|
movzx eax, byte ptr fs:PcHal.PcrNumber ; get processor # from PCR
|
|
|
|
|
|
hip20_Any:
|
|
|
|
; Note: at this point eax must contain the processor number
|
|
|
|
mov dx, word ptr ProcessorControlPort[eax*2]
|
|
in al, dx ; get PCR status
|
|
and al, not PINT ; clear IPI pending bit
|
|
or al, IPI_EN ; enable IPI's
|
|
out dx, al ; store the new PCR status
|
|
|
|
mov fs:PcHal.PcrControlPort, dx ; Save port value
|
|
|
|
movzx eax, byte ptr [esp+4] ; get processor number
|
|
or eax, eax
|
|
jz hip30_Any ; jump if P0
|
|
|
|
; init PICs, interval timer, stall scale factor...
|
|
|
|
;DBG_DISPLAY 0a2h
|
|
|
|
stdCall _HalpInitializeProcessor,<eax>
|
|
|
|
;DBG_DISPLAY 0a3h
|
|
|
|
hip30_Any:
|
|
|
|
|
|
;LSX5030 end
|
|
|
|
stdRET _HalInitializeProcessor
|
|
|
|
;LSX5030 start
|
|
|
|
_NotAnLSX5030:
|
|
stdCall _HalDisplayString,<offset BadHalString>
|
|
hlt
|
|
|
|
;LSX5030 end
|
|
|
|
|
|
stdENDP _HalInitializeProcessor
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalRequestIpi(
|
|
; IN ULONG Mask
|
|
; );
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; Requests an interprocessor interrupt
|
|
;
|
|
;Arguments:
|
|
;
|
|
; Mask - Supplies a mask of the processors to be interrupted
|
|
;
|
|
;Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
cPublicProc _HalRequestIpi,1
|
|
|
|
movzx ecx, byte ptr [esp+4] ; (eax) = Processor bitmask
|
|
|
|
ifdef DBG
|
|
or ecx, ecx ; must ipi somebody
|
|
jz short ipibad
|
|
|
|
movzx eax, byte ptr fs:PcHal.PcrNumber
|
|
bt ecx, eax ; cannot ipi yourself
|
|
jc short ipibad
|
|
endif
|
|
|
|
@@:
|
|
movzx eax, _HalpFindFirstSetRight[ecx] ; lookup first processor to ipi
|
|
btr ecx, eax
|
|
mov dx, ProcessorControlPort[eax*2]
|
|
in al, dx ; (al) = original content of PCP
|
|
or al, PINT ; generate Ipi on target
|
|
out dx, al
|
|
or ecx, ecx ; ipi any other processors?
|
|
jnz @b ; yes, loop
|
|
|
|
stdRET _HalRequestIpi
|
|
|
|
ifdef DBG
|
|
ipibad: int 3
|
|
stdRET _HalRequestIpi
|
|
endif
|
|
|
|
stdENDP _HalRequestIpi
|
|
|
|
|
|
page ,132
|
|
subttl "LSX5030 Inter-Processor Interrupt Handler"
|
|
|
|
;LSX5030 start
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalpIpiHandler (
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is entered as the result of an interrupt generated by inter
|
|
; processor communication.
|
|
; The interrupt is dismissed.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
ENTER_DR_ASSIST Hixx_a, Hixx_t
|
|
|
|
cPublicProc _HalpIpiHandler,0
|
|
|
|
;
|
|
; Save machine state in trap frame
|
|
;
|
|
|
|
ENTER_INTERRUPT Hixx_a, Hixx_t ; (ebp) -> Trap frame
|
|
|
|
;
|
|
; Save previous IRQL
|
|
;
|
|
mov eax, _IdtIpiVector
|
|
push eax ; Vector
|
|
sub esp, 4 ; space for OldIrql
|
|
|
|
;DBG_DISPLAY 90h
|
|
|
|
; Dismiss interrupt.
|
|
;
|
|
mov dx, fs:PcHal.PcrControlPort
|
|
|
|
in al, dx
|
|
|
|
;
|
|
; Dismiss the interprocessor interrupt and call its handler
|
|
;
|
|
|
|
and al, not PINT
|
|
out dx, al ; clear PINT
|
|
|
|
|
|
;DBG_DISPLAY 91h
|
|
|
|
mov eax, _IdtIpiVector
|
|
|
|
; esp - stack location of OldIrql
|
|
; eax - vector
|
|
; IPI_LEVEL - Irql
|
|
|
|
stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,eax,esp>
|
|
|
|
;DBG_DISPLAY 92h
|
|
|
|
; Pass Null ExceptionFrame
|
|
; Pass TrapFrame to Ipi service rtn
|
|
stdCall _KiIpiServiceRoutine ,<ebp,0>
|
|
|
|
;
|
|
; Do interrupt exit processing
|
|
;
|
|
;DBG_DISPLAY 9fh
|
|
|
|
|
|
INTERRUPT_EXIT ; will return to caller
|
|
|
|
|
|
stdENDP _HalpIpiHandler
|
|
|
|
|
|
ifdef HALOLI_DBG
|
|
|
|
;++
|
|
;
|
|
; DbgDisplay (
|
|
; IN UCHAR DisplayCode
|
|
; )
|
|
;
|
|
; Description:
|
|
;
|
|
; This function writes 'DisplayCode' to the parallel port, where a LED
|
|
; display can be plugged in to show such a code.
|
|
; In order to allow the user to read the code on the LED display,
|
|
; after writing, a delay is introduced.
|
|
;
|
|
; Arguments:
|
|
; DisplayCode - Byte to write to the parallel port
|
|
;
|
|
; Return Value:
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
public _DbgDisplay
|
|
_DbgDisplay proc
|
|
|
|
|
|
push eax
|
|
push edx
|
|
|
|
; signal something on the parallel port
|
|
|
|
mov dx, 378h
|
|
mov eax, [esp+12]
|
|
out dx, al
|
|
|
|
mov eax, DbgDelay
|
|
|
|
@@:
|
|
dec eax
|
|
cmp eax, 0
|
|
jne @b
|
|
pop edx
|
|
pop eax
|
|
|
|
|
|
ret
|
|
_DbgDisplay endp
|
|
|
|
endif ; HALOLI_DBG
|
|
|
|
|
|
; ULONG
|
|
; HalpGetIpiIrqNumber (
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is entered during the phase 0 initialization of the
|
|
; first processor. It determines the IRQ # for IPI's.
|
|
; The IPI IRQ is stored in the PCR's by the LSX5030 configuration
|
|
; utility.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The IPI IRQ# in eax.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _HalpGetIpiIrqNumber,0
|
|
|
|
|
|
mov dx, word ptr ProcessorControlPort ; get 1st CPU slot #
|
|
in al, dx ; get PCR content
|
|
|
|
; determine which IRQ for IPI has been set by the user
|
|
|
|
shr eax, 2 ; bits 0,1 encode the IPI IRQ
|
|
and eax, 3 ; zero all the bits but 0,1
|
|
movzx ecx, byte ptr PcrIpiIrql[eax] ; decode the IRQ
|
|
push ecx
|
|
|
|
; edit the 8259 mask table to unmask IPI's from IPI_LEVEL-1 down
|
|
|
|
mov edx, 1
|
|
shl edx, cl
|
|
not edx ; mask with IPI IRQ# bit set to
|
|
; 0
|
|
; mov eax, IPI_LEVEL
|
|
; sub eax, ecx
|
|
lea eax, KiI8259MaskTable ; start from the beginning
|
|
; lea eax, KiI8259MaskTable[eax*4] ; start from
|
|
; IPI_LEVEL - IPI_IRQ#
|
|
mov ecx, IPI_LEVEL
|
|
|
|
NextEntry:
|
|
and [eax], edx
|
|
add eax, 4
|
|
dec ecx ; loop for IPI IRQ# times
|
|
jnz NextEntry
|
|
|
|
pop eax ; return IPI IRQ#
|
|
|
|
stdRET _HalpGetIpiIrqNumber
|
|
stdENDP _HalpGetIpiIrqNumber
|
|
|
|
|
|
page ,132
|
|
subttl "Irq13 Interrupt Handler"
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalpIrq13Handler (
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is entered as the result of an interrupt generated by
|
|
; coprocessor error,
|
|
; This routine will lower irql to its original level, and finally invoke
|
|
; coprocessor error handler. By doing this, the coprocessor
|
|
; error will be handled at Irql 0 as it should be.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
; Interrupt is dismissed
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
ENTER_DR_ASSIST Hi13_a, Hi13_t
|
|
|
|
cPublicProc _HalpIrq13Handler,0
|
|
|
|
|
|
;
|
|
; Save machine state in trap frame
|
|
;
|
|
|
|
ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
|
|
|
|
;
|
|
; Save previous IRQL
|
|
;
|
|
push 13 + PRIMARY_VECTOR_BASE ; Vector
|
|
sub esp, 4 ; space for OldIrql
|
|
;
|
|
; Dismiss interrupt.
|
|
|
|
; location for OldIrql
|
|
; Vector
|
|
; Irql
|
|
stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,13+PRIMARY_VECTOR_BASE,esp>
|
|
|
|
stdCall _KiCoprocessorError ; call CoprocessorError handler
|
|
|
|
;
|
|
; Do interrupt exit processing
|
|
;
|
|
|
|
INTERRUPT_EXIT ; will return to caller
|
|
|
|
|
|
stdENDP _HalpIrq13Handler
|
|
|
|
;LSX5030 end
|
|
|
|
_TEXT ENDS
|
|
END
|