988 lines
25 KiB
NASM
988 lines
25 KiB
NASM
title "Multiprocessor Startup"
|
|
;++
|
|
;
|
|
;Copyright (c) 1992 NCR Corporation
|
|
;
|
|
;Module Name:
|
|
;
|
|
; ncrstart.asm
|
|
;
|
|
;Abstract:
|
|
;
|
|
; Provides the HAL support for starting processors.
|
|
;
|
|
;Author:
|
|
;
|
|
; Richard Barton (o-richb) 24-Jan-1992
|
|
;
|
|
;Revision History:
|
|
;
|
|
;--
|
|
.386p
|
|
.xlist
|
|
include hal386.inc
|
|
include callconv.inc ; calling convention macros
|
|
include i386\kimacro.inc
|
|
include i386\ix8259.inc
|
|
include i386\ncr.inc
|
|
|
|
|
|
extrn _DbgPrint:PROC
|
|
EXTRNP _HalpBuildTiledCR3,1
|
|
EXTRNP _HalpFreeTiledCR3,0
|
|
EXTRNP _HalEnableSystemInterrupt,3
|
|
EXTRNP _NCRFindIpiAddress,1
|
|
EXTRNP _NCRClearQicIpi,1
|
|
EXTRNP _HalQicStartupIpi,1
|
|
EXTRNP _NCRTranslateCMOSMask,1
|
|
EXTRNP _NCRTranslateToCMOSMask,1
|
|
EXTRNP _NCRAdjustDynamicClaims,0
|
|
if DBG
|
|
EXTRNP _NCRConsoleDebug,2
|
|
endif
|
|
extrn _NCRProcessorsToBringup:DWORD
|
|
extrn _NCRExistingProcessorMask:DWORD
|
|
extrn _NCRExistingDyadicProcessorMask:DWORD
|
|
extrn _NCRExistingQuadProcessorMask:DWORD
|
|
extrn _NCRExtendedProcessorMask:DWORD
|
|
extrn _NCRExtendedProcessor0Mask:DWORD
|
|
extrn _NCRExtendedProcessor1Mask:DWORD
|
|
extrn _NCRLogicalDyadicProcessorMask:DWORD
|
|
extrn _NCRLogicalQuadProcessorMask:DWORD
|
|
extrn _NCRActiveProcessorMask:DWORD
|
|
extrn _NCRActiveProcessorCount:DWORD
|
|
extrn _NCRMaxProcessorCount:DWORD
|
|
extrn _NCRLogicalNumberToPhysicalMask:DWORD
|
|
extrn _NCRSlotExtended0ToVIC:BYTE
|
|
extrn _NCRSlotExtended1ToVIC:BYTE
|
|
extrn _NonbootStartupVirtualPtr:DWORD
|
|
extrn _NonbootStartupPhysicalPtr:DWORD
|
|
extrn _PageZeroVirtualPtr:DWORD
|
|
extrn _HalpDefaultInterruptAffinity:DWORD
|
|
extrn _HalpActiveProcessors:DWORD
|
|
extrn _NCRProcessorIDR:DWORD
|
|
extern _DefaultNeverClaimIRQs:DWORD
|
|
extern _NCRNeverClaimIRQs:DWORD
|
|
|
|
EXTRNP _HalpInitializePICs,0
|
|
|
|
|
|
PxParamBlock struc
|
|
SPx_Mask dd ?
|
|
SPx_TiledCR3 dd ?
|
|
SPx_P0EBP dd ?
|
|
SPx_PB db processorstatelength dup (?)
|
|
PxParamBlock ends
|
|
|
|
page ,132
|
|
subttl "Initialize boot processor"
|
|
|
|
_TEXT SEGMENT PARA PUBLIC 'CODE'
|
|
ASSUME CS:FLAT, 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 KeRaise/LowerIrq's must be available once this function
|
|
; returns. (IPI's are only used once two or more processors are
|
|
; available)
|
|
;
|
|
; This routine makes some VIC accesses assuming that it's running on
|
|
; an NCR box. The real check won't happen until HalInitMP().
|
|
;
|
|
;Arguments:
|
|
;
|
|
; Number - Logical processor number of calling processor
|
|
;
|
|
;Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _HalInitializeProcessor ,1
|
|
|
|
;
|
|
; Initialize IDR in PCR to allow irq 2 only.
|
|
;
|
|
|
|
mov dword ptr PCR[PcIDR],0fffffffbh
|
|
mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
|
|
mov dword ptr PCR[PcHal.PcrMyClaimedIRQs], 0
|
|
mov dword ptr PCR[PcHal.PcrMyClaimedIRQsCount],0
|
|
|
|
|
|
;
|
|
; all processors execute this first section
|
|
;
|
|
; remember this processors logical number
|
|
;
|
|
|
|
mov ecx, 4[esp]
|
|
mov PCR[PcHal.PcrMyLogicalNumber], ecx
|
|
|
|
;
|
|
; Set IDR table to same value as PcIDR
|
|
;
|
|
mov _NCRProcessorIDR[ecx*4],0fffffffbh
|
|
|
|
|
|
;RMU
|
|
;if DBG
|
|
; push ebx
|
|
; push ecx
|
|
; push edx
|
|
; mov eax,1
|
|
; stdCall _NCRConsoleDebug, <eax,ecx>
|
|
; pop edx
|
|
; pop ecx
|
|
; pop ebx
|
|
;endif
|
|
;RMU
|
|
|
|
|
|
mov eax, 1
|
|
shl eax, cl
|
|
lock or _HalpActiveProcessors, eax
|
|
|
|
if 0
|
|
; begin - spinlock test code - kenr
|
|
push eax
|
|
push edx
|
|
|
|
mov eax, 1
|
|
shl eax, cl ; (eax) = pmask
|
|
shl eax, 16 ; mask into high word of dword
|
|
|
|
mov fs:PcHal.PcrCheckForBit, eax ; (pmask<<16)
|
|
|
|
or eax, 1 ; set low byte to 1
|
|
mov fs:PcHal.PcrSpinAcquireBits, eax ; (pmask<<16) | 1
|
|
|
|
not eax
|
|
and eax, 0ffff0000h
|
|
mov fs:PcHal.PcrSpinReleaseMask, eax ; ~(pmask<<16)
|
|
|
|
|
|
mov eax, ecx
|
|
inc eax ; handoff id
|
|
shl eax, 8
|
|
or eax, 1 ; (handoff << 8) | 1
|
|
mov fs:PcHal.PcrSpinId, eax
|
|
|
|
|
|
pop edx
|
|
pop eax
|
|
; end - spinlock test code
|
|
endif
|
|
|
|
|
|
;
|
|
; remember this processors physical mask
|
|
;
|
|
WHO_AM_I
|
|
jb IAmQuad
|
|
|
|
;
|
|
; Processor init code for Dyadic
|
|
;
|
|
|
|
lock or _NCRActiveProcessorMask, eax
|
|
lock inc _NCRActiveProcessorCount
|
|
|
|
mov edx, CPU_DYADIC
|
|
mov PCR[PcHal.PcrMyProcessorFlags],edx
|
|
;
|
|
; setup translation databases:
|
|
;
|
|
mov edx, 1
|
|
shl edx, cl ; edx contains logical mask
|
|
mov PCR[PcHal.PcrMyLogicalMask], edx
|
|
lock or _NCRLogicalDyadicProcessorMask, edx
|
|
lock or _HalpDefaultInterruptAffinity, edx
|
|
;
|
|
; Get the real hardware VIC mask so we can send CPIs
|
|
;
|
|
mov dx, VIC_BASE_ADDRESS+vic_ProcessorWhoAmIReg
|
|
xor eax,eax
|
|
in al,dx
|
|
mov _NCRLogicalNumberToPhysicalMask[ecx*4], eax
|
|
|
|
;
|
|
; make sure all processors can take interrupts (have this processor claim none)
|
|
;
|
|
VIC_WRITE ClaimRegLsb, 0
|
|
VIC_WRITE ClaimRegMsb, 0
|
|
|
|
or ecx, ecx
|
|
jz InitBoot
|
|
;
|
|
; nonboot processor only stuff
|
|
;
|
|
stdCall _HalpInitializePICs
|
|
|
|
;
|
|
; no need to send EOI for startup CPI since just initialized PICs above
|
|
;
|
|
|
|
;
|
|
; make sure each processor can get IPI
|
|
;
|
|
stdCall _HalEnableSystemInterrupt, <NCR_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI,IPI_LEVEL,0>
|
|
|
|
stdRET _HalInitializeProcessor
|
|
;
|
|
; boot processor only stuff
|
|
;
|
|
align dword
|
|
InitBoot:
|
|
;
|
|
; setup the cross-processor vector base
|
|
;
|
|
mov eax, NCR_CPI_VECTOR_BASE
|
|
VIC_WRITE CpiVectorBaseReg
|
|
;
|
|
; temporary fix for VIC errata - true spurious primary MC interrupts (where
|
|
; HW removes the request during INTA cycle) can result in a secondary MC based
|
|
; vector being supplied by the VIC (with the ISR bit actually set, but no
|
|
; real interrupt). Since currently no interrupts are routed through the
|
|
; secondary MC vector space, will simply set the secondary MC vector space
|
|
; equal to the primary vector space.
|
|
;
|
|
mov eax, NCR_SECONDARY_VECTOR_BASE
|
|
VIC_WRITE ExtMasterVectorBaseReg
|
|
mov eax, NCR_SECONDARY_VECTOR_BASE+8
|
|
VIC_WRITE ExtSlaveVectorBaseReg
|
|
|
|
stdRET _HalInitializeProcessor
|
|
;
|
|
; Processor init code for Quad processor
|
|
;
|
|
|
|
IAmQuad:
|
|
|
|
;
|
|
; save logical processor number to hardware mask
|
|
;
|
|
|
|
mov _NCRLogicalNumberToPhysicalMask[ecx*4], eax
|
|
|
|
;
|
|
; now lets see if we are extended or not
|
|
;
|
|
|
|
mov edx,eax ; save process mask
|
|
PROCESSOR_SLOT ; get the process slot for this CPU
|
|
shl eax,2h ; calculate shift to isolate mask to one board
|
|
push ecx ; save ecx (contains logical processor number)
|
|
mov ecx,eax
|
|
mov eax,edx ; now get processor mask
|
|
shr eax,cl ; now isolate processor on this board
|
|
mov ecx,eax ; save processor by board mask
|
|
|
|
push edx ; save edx with processor mask
|
|
QIC_READ ExtendedProcessorSelect ; get the extended processor mask
|
|
pop edx
|
|
|
|
test eax,ecx ; test for extended processor 0
|
|
jnz short ExtendedProcessor0
|
|
|
|
shr eax,4h ; isolate extended processor 1 mask
|
|
|
|
test eax,ecx ; test for extended processor 1
|
|
jnz short ExtendedProcessor
|
|
pop ecx
|
|
mov eax,edx
|
|
mov edx, CPU_QUAD
|
|
|
|
jmp short NotExtended;
|
|
|
|
ExtendedProcessor0:
|
|
|
|
;
|
|
; For Extended Processor 0 lets setup all other processors on the Quad Board
|
|
;
|
|
xor ecx,ecx
|
|
push edx ; save who am I mask
|
|
align dword
|
|
ExtendedLoop:
|
|
|
|
mov al,cl
|
|
or al,8
|
|
QIC_WRITE ProcessorId
|
|
|
|
mov al,0ffh
|
|
QIC_WRITE QicMask0
|
|
|
|
mov al,QIC_IRQ_ENABLE_MASK
|
|
QIC_WRITE QicMask1
|
|
|
|
xor al,al
|
|
QIC_WRITE ProcessorId
|
|
|
|
inc ecx
|
|
cmp ecx,4
|
|
jne short ExtendedLoop
|
|
|
|
;
|
|
; Qic setup
|
|
;
|
|
|
|
;
|
|
; Disable propagation of SBE and SINT to non-extened processors
|
|
;
|
|
QIC_READ Configuration
|
|
or al,7
|
|
QIC_WRITE Configuration
|
|
|
|
mov al, NCR_CPI_VECTOR_BASE
|
|
QIC_WRITE VicCpiVectorBaseReg
|
|
|
|
mov al, NCR_QIC_CPI_VECTOR_BASE
|
|
QIC_WRITE QuadCpiVectorBaseReg
|
|
|
|
mov al,0ffh
|
|
QIC_WRITE Clear1Reg
|
|
|
|
mov al,NCR_QIC_SPURIOUS_VECTOR
|
|
QIC_WRITE SpuriousVectorReg
|
|
|
|
pop edx ; restore the who am I mask
|
|
|
|
ExtendedProcessor:
|
|
pop ecx
|
|
mov eax,edx
|
|
mov edx, CPU_QUAD
|
|
or edx, CPU_EXTENDED
|
|
push eax
|
|
mov eax, 1
|
|
shl eax, cl
|
|
lock or _HalpDefaultInterruptAffinity, eax
|
|
pop eax
|
|
NotExtended:
|
|
mov PCR[PcHal.PcrMyProcessorFlags],edx
|
|
;
|
|
;
|
|
lock or _NCRActiveProcessorMask, eax
|
|
lock inc _NCRActiveProcessorCount
|
|
|
|
mov edx, 1
|
|
shl edx, cl ; edx contains logical mask
|
|
lock or _NCRLogicalQuadProcessorMask, edx
|
|
mov PCR[PcHal.PcrMyLogicalMask], edx
|
|
|
|
|
|
;
|
|
; make sure all processors can take interrupts (have this processor claim none)
|
|
;
|
|
VIC_WRITE ClaimRegLsb, 0
|
|
VIC_WRITE ClaimRegMsb, 0
|
|
|
|
or ecx, ecx
|
|
jz QuadInitBoot
|
|
|
|
stdCall _NCRFindIpiAddress, <ecx> ; lookup IPI address so we can send and clear IPI's
|
|
stdCall _NCRClearQicIpi, <2> ; clear the startup IPI
|
|
|
|
;
|
|
; nonboot processor only stuff
|
|
;
|
|
mov eax, PCR[PcHal.PcrMyProcessorFlags]
|
|
test eax,CPU_EXTENDED
|
|
jz short NoPic
|
|
|
|
stdCall _HalpInitializePICs
|
|
|
|
NoPic:
|
|
stdRET _HalInitializeProcessor
|
|
;
|
|
; boot processor only stuff
|
|
;
|
|
align dword
|
|
QuadInitBoot:
|
|
;
|
|
; setup the cross-processor vector base
|
|
;
|
|
mov eax, NCR_CPI_VECTOR_BASE
|
|
VIC_WRITE CpiVectorBaseReg
|
|
|
|
;
|
|
; temporary fix for VIC errata - true spurious primary MC interrupts (where
|
|
; HW removes the request during INTA cycle) can result in a secondary MC based
|
|
; vector being supplied by the VIC (with the ISR bit actually set, but no
|
|
; real interrupt). Since currently no interrupts are routed through the
|
|
; secondary MC vector space, will simply set the secondary MC vector space
|
|
; equal to the primary vector space.
|
|
;
|
|
|
|
mov eax, NCR_SECONDARY_VECTOR_BASE
|
|
VIC_WRITE ExtMasterVectorBaseReg
|
|
mov eax, NCR_SECONDARY_VECTOR_BASE+8
|
|
VIC_WRITE ExtSlaveVectorBaseReg
|
|
|
|
;
|
|
; Qic setup
|
|
;
|
|
|
|
mov al, NCR_CPI_VECTOR_BASE
|
|
QIC_WRITE VicCpiVectorBaseReg
|
|
|
|
mov al, NCR_QIC_CPI_VECTOR_BASE
|
|
QIC_WRITE QuadCpiVectorBaseReg
|
|
|
|
mov al,0ffh
|
|
QIC_WRITE Clear1Reg
|
|
|
|
stdRET _HalInitializeProcessor
|
|
stdENDP _HalInitializeProcessor
|
|
|
|
|
|
|
|
page ,132
|
|
subttl "Start non-boot processor"
|
|
|
|
|
|
;++
|
|
;
|
|
; BOOLEAN
|
|
; HalStartNextProcessor (
|
|
; IN PLOADER_BLOCK pLoaderBlock,
|
|
; IN PKPROCESSOR_STATE pProcessorState
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is called by the kernel durning kernel initialization
|
|
; to obtain more processors. It is called until no more processors
|
|
; are available.
|
|
;
|
|
; If another processor exists this function is to initialize it to
|
|
; the passed in processorstate structure, and return TRUE.
|
|
;
|
|
; If another processor does not exists, then a FALSE is returned.
|
|
;
|
|
; Also note that the loader block has been setup for the next processor.
|
|
; The new processor logical thread number can be obtained from it, if
|
|
; required.
|
|
;
|
|
;
|
|
; we need to consult with firmware tables to determine which processors
|
|
; are okay to start. note that we can not return false until there are
|
|
; no processors left. so we stay here until we either start another
|
|
; processor, there are no processors left to start, or all our attempts
|
|
; to start another processor fail.
|
|
;
|
|
; Arguments:
|
|
; pLoaderBlock, - Loader block which has been intialized for the
|
|
; next processor.
|
|
;
|
|
; pProcessorState - The processor state which is to be loaded into
|
|
; the next processor.
|
|
;
|
|
;
|
|
; Return Value:
|
|
;
|
|
; TRUE - ProcessorNumber was dispatched.
|
|
; FALSE - A processor was not dispatched. no other processors exists.
|
|
;
|
|
;--
|
|
|
|
pLoaderBlock equ dword ptr [ebp+8] ; zero based
|
|
pProcessorState equ dword ptr [ebp+12]
|
|
|
|
;
|
|
; Local variables
|
|
;
|
|
|
|
PxFrame equ [ebp - size PxParamBlock]
|
|
|
|
cPublicProc _HalStartNextProcessor ,2
|
|
;
|
|
; note that we can screen processors two ways: we can limit the number
|
|
; of processors to start or we can choose which physical processors we
|
|
; will start. this is mainly for debugging and benchmarking purposes.
|
|
;
|
|
; how many processors are we going to allow
|
|
;
|
|
mov ecx, _NCRActiveProcessorCount
|
|
cmp ecx, _NCRMaxProcessorCount
|
|
jae Done
|
|
;
|
|
; which processors are left
|
|
;
|
|
mov eax, _NCRExistingProcessorMask
|
|
xor eax, _NCRActiveProcessorMask
|
|
;
|
|
; which processors are we going to allow
|
|
;
|
|
and eax, _NCRProcessorsToBringup
|
|
jz Done
|
|
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
sub esp, size PxParamBlock
|
|
|
|
push esi
|
|
push edi
|
|
push ebx
|
|
|
|
push eax ; processors to choose from
|
|
|
|
mov esi, OFFSET FLAT:StartPx_RMStubE
|
|
mov ecx, esi
|
|
mov esi, OFFSET FLAT:StartPx_RMStub
|
|
sub ecx, esi
|
|
mov edi, _NonbootStartupVirtualPtr
|
|
add edi, size PxParamBlock
|
|
rep movsb ; Copy RMStub to low memory
|
|
|
|
lea edi, PxFrame.SPx_PB
|
|
mov esi, pProcessorState
|
|
mov ecx, processorstatelength ; Copy processorstate
|
|
rep movsb ; to PxFrame
|
|
|
|
stdCall _HalpBuildTiledCR3, <pProcessorState>
|
|
|
|
mov PxFrame.SPx_Mask, 0
|
|
mov PxFrame.SPx_TiledCR3, eax
|
|
mov PxFrame.SPx_P0EBP, ebp
|
|
|
|
mov ecx, size PxParamBlock ; copy param block
|
|
lea esi, PxFrame ; to low memory stub
|
|
mov edi, _NonbootStartupVirtualPtr
|
|
mov eax, edi
|
|
rep movsb
|
|
|
|
add eax, size PxParamBlock
|
|
mov ebx, OFFSET FLAT:StartPx_RMStub
|
|
sub eax, ebx ; (eax) = adjusted pointer
|
|
mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
|
|
mov [eax.SPrxFlatCS], bx ; patch realmode stub with
|
|
mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
|
|
|
|
;
|
|
; determine which one processor we are going to start. think i'll try
|
|
; alternating buses.
|
|
;
|
|
|
|
mov eax, dword ptr [esp] ; retrieve processors awaiting
|
|
bsf ecx, eax
|
|
|
|
;
|
|
; check to see if we are starting a dyadic or quad processor
|
|
;
|
|
mov eax,1
|
|
shl eax,cl
|
|
|
|
test eax,_NCRExistingQuadProcessorMask
|
|
jnz StartQuadProcessor
|
|
|
|
;
|
|
; Startup code for a Dyadic processor
|
|
;
|
|
mov ecx, eax ; now we only care about the startup mask
|
|
;
|
|
; fix the startee processors vector to allow it to receive the cpi
|
|
;
|
|
mov ebx, _PageZeroVirtualPtr
|
|
add ebx, NCR_STARTUP_VECTOR_VIC
|
|
|
|
cli
|
|
push dword ptr [ebx] ; Save current vector
|
|
|
|
mov eax, _NonbootStartupPhysicalPtr
|
|
shl eax, 12 ; seg:0
|
|
add eax, size PxParamBlock
|
|
mov dword ptr [ebx], eax ; start Px here
|
|
;
|
|
; enable the cpi for the startee processor (although unnecessary for 3360 -
|
|
; it's left enabled by BIOS)
|
|
;
|
|
push ebx
|
|
push ecx
|
|
stdCall _NCRTranslateToCMOSMask, <ecx>
|
|
bsf ecx, eax
|
|
mov al, cl
|
|
pop ecx
|
|
pop ebx
|
|
or al, ProcessorIdSelect
|
|
VIC_WRITE ProcessorIdReg ; assume startee's id
|
|
mov edx, ecx ; save processor number
|
|
mov eax, 1
|
|
mov ecx, NCR_STARTUP_CPI
|
|
shl eax, cl
|
|
not al
|
|
mov ecx, edx ; restore processor number
|
|
out PIC1_PORT1, al ; clear cpi's irq
|
|
VIC_WRITE ProcessorIdReg, 0 ; restore own id
|
|
|
|
mov eax,ecx ; get the startee mask
|
|
;
|
|
; interrupt the startee
|
|
;
|
|
push ebx
|
|
push ecx
|
|
stdCall _NCRTranslateToCMOSMask, <eax>
|
|
VIC_WRITE CpiLevel2Reg
|
|
pop ecx
|
|
pop ebx
|
|
|
|
mov eax,ecx ; get the startee mask
|
|
|
|
jmp StarteeWakeNow
|
|
;
|
|
; Startup code for a Quad Processor
|
|
;
|
|
|
|
StartQuadProcessor:
|
|
|
|
test eax,_NCRExtendedProcessor0Mask
|
|
jnz short StarteeExtended
|
|
|
|
mov ebx, _PageZeroVirtualPtr
|
|
add ebx, NCR_STARTUP_VECTOR_QIC
|
|
|
|
jmp short SkipVicSetup
|
|
StarteeExtended:
|
|
;
|
|
; fix the startee processors vector to allow it to receive the cpi
|
|
;
|
|
mov ebx, _PageZeroVirtualPtr
|
|
add ebx, NCR_STARTUP_VECTOR_VIC
|
|
|
|
SkipVicSetup:
|
|
|
|
cli
|
|
push dword ptr [ebx] ; Save current vector
|
|
|
|
mov eax, _NonbootStartupPhysicalPtr
|
|
shl eax, 12 ; seg:0
|
|
add eax, size PxParamBlock
|
|
mov dword ptr [ebx], eax ; start Px here
|
|
|
|
;
|
|
; generate startee processors mask
|
|
;
|
|
mov eax, 1
|
|
shl eax, cl ; mask of processor to start
|
|
|
|
test eax,_NCRExtendedProcessor0Mask
|
|
jz short StarteeNotExtended
|
|
|
|
;
|
|
; We are starting an Extended processor, we do this my using the VIC and not the QIC
|
|
;
|
|
|
|
;
|
|
; This is extended processor 0
|
|
;
|
|
|
|
PROCESSOR_SLOT
|
|
movzx eax, byte ptr _NCRSlotExtended0ToVIC[eax]
|
|
|
|
;
|
|
; enable the cpi for the startee processor (although unnecessary for 3360 -
|
|
; it's left enabled by BIOS)
|
|
;
|
|
push eax ; save the vic processor number
|
|
|
|
or al, ProcessorIdSelect
|
|
VIC_WRITE ProcessorIdReg ; assume startee's id
|
|
mov dl, cl ; save processor number
|
|
mov eax, 1
|
|
mov ecx, NCR_STARTUP_CPI
|
|
shl eax, cl
|
|
not al
|
|
mov cl, dl ; restore processor number
|
|
out PIC1_PORT1, al ; clear cpi's irq
|
|
VIC_WRITE ProcessorIdReg, 0 ; restore own id
|
|
|
|
pop eax
|
|
push ecx
|
|
mov ecx, eax
|
|
;
|
|
; generate startee processors mask
|
|
;
|
|
mov eax, 1
|
|
shl eax, cl ; mask of VIC processor to start
|
|
|
|
; interrupt the startee
|
|
|
|
VIC_WRITE CpiLevel2Reg
|
|
pop ecx
|
|
|
|
mov eax, 1
|
|
shl eax, cl ; mask of processor started
|
|
|
|
jmp short StarteeWakeNow
|
|
|
|
StarteeNotExtended:
|
|
|
|
push ecx
|
|
stdCall _HalQicStartupIpi, <ecx>
|
|
pop ecx
|
|
|
|
mov eax, 1
|
|
shl eax, cl ; mask of processor started
|
|
|
|
StarteeWakeNow:
|
|
|
|
;RMU
|
|
;if DBG
|
|
; push eax
|
|
; push ebx
|
|
; push ecx
|
|
; push edx
|
|
; mov edx,2
|
|
; stdCall _NCRConsoleDebug, <edx,eax>
|
|
; pop edx
|
|
; pop ecx
|
|
; pop ebx
|
|
; pop eax
|
|
;endif
|
|
;RMU
|
|
|
|
|
|
;
|
|
; wait for startee to say it's active. we should have a timeout on this
|
|
; loop. however, what if the startee went off in the weeds and corrupted
|
|
; something. if we timeout here we can't be sure what the other processor
|
|
; is doing.
|
|
;
|
|
align dword
|
|
@@: cmp eax, PxFrame.SPx_Mask
|
|
jne @b
|
|
|
|
|
|
;RMU
|
|
;if DBG
|
|
; push eax
|
|
; push ebx
|
|
; push ecx
|
|
; push edx
|
|
; mov edx,3
|
|
; stdCall _NCRConsoleDebug, <edx,eax>
|
|
; pop edx
|
|
; pop ecx
|
|
; pop ebx
|
|
; pop eax
|
|
;endif
|
|
;RMU
|
|
|
|
|
|
|
|
pop dword ptr [ebx] ; restore vector
|
|
add esp, 1*4 ; pop saved mask
|
|
|
|
sti
|
|
|
|
stdCall _HalpFreeTiledCR3 ; free memory used for tiled
|
|
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
mov esp, ebp
|
|
pop ebp
|
|
|
|
;
|
|
; tell 'em we started another one
|
|
;
|
|
mov eax, 1
|
|
stdRET _HalStartNextProcessor
|
|
|
|
|
|
;
|
|
; All processors are online so now lets start the claiming process
|
|
;
|
|
|
|
align dword
|
|
Done:
|
|
;
|
|
; now that all CPU's are online we need to calculate how many interrupts
|
|
; each CPU can claim
|
|
;
|
|
|
|
stdCall _NCRAdjustDynamicClaims
|
|
|
|
;
|
|
; setting the never claim mask to correct value will start the claim process
|
|
;
|
|
|
|
mov eax, _DefaultNeverClaimIRQs;
|
|
mov _NCRNeverClaimIRQs, eax
|
|
|
|
xor eax,eax
|
|
stdRET _HalStartNextProcessor
|
|
|
|
|
|
stdENDP _HalStartNextProcessor
|
|
|
|
|
|
_TEXT ENDS
|
|
|
|
|
|
;
|
|
; heavy-duty plagarism from systempro stuff follows:
|
|
;
|
|
|
|
|
|
_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; StartPx_RMStub
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; When a new processor is started, it starts in real-mode and is
|
|
; sent to a copy of this function which has been copied into low memory.
|
|
; (below 1m and accessable from real-mode).
|
|
;
|
|
; Once CR0 has been set, this function jmp's to a StartPx_PMStub
|
|
;
|
|
; Arguments:
|
|
; none
|
|
;
|
|
; Return Value:
|
|
; does not return, jumps to StartPx_PMStub
|
|
;
|
|
;--
|
|
|
|
cPublicProc StartPx_RMStub ,0
|
|
cli
|
|
|
|
db 066h ; load the GDT
|
|
lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
|
|
|
|
db 066h ; load the IDT
|
|
lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
|
|
|
|
mov eax, cs:[SPx_TiledCR3]
|
|
mov cr3, eax
|
|
|
|
mov ebp, dword ptr cs:[SPx_P0EBP]
|
|
mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
|
|
mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
|
|
mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
|
|
|
|
mov cr0, eax ; into prot mode
|
|
|
|
db 066h
|
|
db 0eah ; reload cs:eip
|
|
SPrxPMStub dd 0
|
|
SPrxFlatCS dw 0
|
|
|
|
StartPx_RMStubE equ $
|
|
stdENDP StartPx_RMStub
|
|
|
|
|
|
_TEXT16 ends ; End 16 bit code
|
|
|
|
_TEXT SEGMENT ; Start 32 bit code
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; StartPx_PMStub
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function completes the processor's state loading, and signals
|
|
; the requesting processor that the state has been loaded.
|
|
;
|
|
; Arguments:
|
|
; ebx - requested CR3 for this processors_state
|
|
; cx - requested ds for this processors_state
|
|
; ebp - EBP of P0
|
|
;
|
|
; Return Value: ; does not return - completes the loading of the processors_state
|
|
;
|
|
;--
|
|
align 16 ; to make sure we don't cross a page boundry
|
|
; before reloading CR3
|
|
|
|
cPublicProc _StartPx_PMStub ,0
|
|
|
|
; process is now in the load image copy of this function.
|
|
; (ie, it's not the low memory copy)
|
|
|
|
mov cr3, ebx ; get real CR3
|
|
mov ds, cx ; set real ds
|
|
|
|
lea esi, PxFrame.SPx_PB.PsSpecialRegisters
|
|
|
|
lldt word ptr ds:[esi].SrLdtr ; load ldtr
|
|
ltr word ptr ds:[esi].SrTr ; load tss
|
|
|
|
lea edi, PxFrame.SPx_PB.PsContextFrame
|
|
mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
|
|
mov fs, word ptr ds:[edi].CsSegFs
|
|
mov gs, word ptr ds:[edi].CsSegGs
|
|
mov ss, word ptr ds:[edi].CsSegSs
|
|
|
|
add esi, SrKernelDr0
|
|
.errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
|
|
.errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
|
|
.errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
|
|
.errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
|
|
.errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
|
|
lodsd
|
|
mov dr0, eax ; load dr0-dr7
|
|
lodsd
|
|
mov dr1, eax
|
|
lodsd
|
|
mov dr2, eax
|
|
lodsd
|
|
mov dr3, eax
|
|
lodsd
|
|
mov dr6, eax
|
|
lodsd
|
|
mov dr7, eax
|
|
|
|
mov esp, dword ptr ds:[edi].CsEsp
|
|
mov esi, dword ptr ds:[edi].CsEsi
|
|
mov ecx, dword ptr ds:[edi].CsEcx
|
|
|
|
push dword ptr ds:[edi].CsEflags
|
|
popfd ; load eflags
|
|
|
|
push dword ptr ds:[edi].CsEip ; make a copy of remaining
|
|
push dword ptr ds:[edi].CsEax ; registers which need
|
|
push dword ptr ds:[edi].CsEbx ; loaded
|
|
push dword ptr ds:[edi].CsEdx
|
|
push dword ptr ds:[edi].CsEdi
|
|
push dword ptr ds:[edi].CsEbp
|
|
|
|
; eax, ebx, edx are still free
|
|
|
|
WHO_AM_I
|
|
mov [PxFrame.SPx_Mask], eax
|
|
|
|
; Set remaining registers
|
|
pop ebp
|
|
pop edi
|
|
pop edx
|
|
pop ebx
|
|
pop eax
|
|
stdRET _StartPx_PMStub ; Set eip
|
|
|
|
stdENDP _StartPx_PMStub
|
|
|
|
_TEXT ends ; end 32 bit code
|
|
|
|
END
|