title "MP primitives for MP+AT Systems" ;++ ; ;Copyright (c) 1991 Microsoft Corporation ;Copyright (c) 1992 Intel Corporation ;All rights reserved ; ;INTEL CORPORATION PROPRIETARY INFORMATION ; ;This software is supplied to Microsoft under the terms ;of a license agreement with Intel Corporation and may not be ;copied nor disclosed except in accordance with the terms ;of that agreement. ; ; ;Module Name: ; ; mpsproca.asm ; ;Abstract: ; ; PC+MP Start Next Processor assemble code ; ; This module along with mpspro.c implement the code to start ; processors on MP+AT Systems. ; ;Author: ; ; Ken Reneris (kenr) 12-Jan-1992 ; ;Revision History: ; ; Ron Mosgrove (Intel) - Modified to support PC+MP Systems ; ;-- .386p .xlist include i386\ixcmos.inc include hal386.inc include callconv.inc ; calling convention macros include i386\kimacro.inc include mac386.inc include apic.inc include ntapic.inc include i386\ixslpctx.inc .list ifndef NT_UP EXTRNP _HalpBuildTiledCR3,1 EXTRNP _HalpFreeTiledCR3,0 EXTRNP _HalpStartProcessor,2 endif EXTRNP _HalpAcquireCmosSpinLock EXTRNP _HalpReleaseCmosSpinLock EXTRNP _HalDisplayString,1 EXTRNP _HalpMarkProcessorStarted,2 EXTRNP _StartPx_BuildRealModeStart,1 EXTRNP _KeStallExecutionProcessor, 1 extrn _Halp1stPhysicalPageVaddr:DWORD extrn _HalpLowStub:DWORD extrn _HalpLowStubPhysicalAddress:DWORD extrn _HalpHiberInProgress:BYTE extrn _CurTiledCr3LowPart:DWORD ; ; Internal defines and structures ; WarmResetVector equ 467h ; warm reset vector in ROM data segment PAGELK SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING ;++ ; ; 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 or if the processor fails to ; start, 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. ; ; In order to use the Startup IPI the real mode startup code must be ; page aligned. The HalpLowStubPhysicalAddress has always been page ; aligned but because the PxParamBlock was placed first in this ; segment the real mode code has been something other than page aligned. ; This has been changed by making the first entry in the PxParamBlock ; a jump instruction to the real mode startup code. ; ; 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] LWarmResetVector equ [ebp - size PxParamBlock - 4] LStatusCode equ [ebp - size PxParamBlock - 8] LCmosValue equ [ebp - size PxParamBlock - 12] Prcb equ [ebp - size PxParamBlock - 16] cPublicProc _HalStartNextProcessor ,2 ifdef NT_UP xor eax, eax ; up build of hal, no processors to stdRET _HalStartNextProcessor ; start else push ebp ; save ebp mov ebp, esp ; Save Frame sub esp, size PxParamBlock + 16 ; Make room for local vars push esi ; Save required registers push edi push ebx pushfd xor eax, eax mov LStatusCode, eax mov PxFrame.SPx_flag, eax ; Initialize the MP Completion flag ; ; Copy Processor state into the stack based Parameter Block ; lea edi, PxFrame.SPx_PB ; Destination on stack mov esi, pProcessorState ; Input parameter address mov ecx, ProcessorStateLength ; Structure length rep movsb ; ; Build a CR3 for the starting processor. If returning ; from hibernation, then use setup tiled CR3 else ; create a new map ; mov al, _HalpHiberInProgress or al, al jz Hpsnp_Hiber mov eax, _CurTiledCr3LowPart jmp Hpsnp_TiledCr3_done Hpsnp_Hiber: stdCall _HalpBuildTiledCR3, Hpsnp_TiledCr3_done: ; ; Save the special registers ; mov PxFrame.SPx_TiledCR3, eax ; Newly contructed CR3 mov PxFrame.SPx_P0EBP, ebp ; Stack pointer lea eax, PxFrame stdCall _StartPx_BuildRealModeStart, ; ; Set the BIOS warm reset vector to our routine in Low Memory ; mov ebx, _Halp1stPhysicalPageVaddr add ebx, WarmResetVector cli mov eax, [ebx] ; Get current vector mov LWarmResetVector, eax ; Save it ; ; Actually build the vector (Seg:Offset) ; mov eax, _HalpLowStubPhysicalAddress shl eax, 12 ; seg:0 mov dword ptr [ebx], eax ; start Px at Seg:0 ; ; Tell BIOS to Jump Via The Vector we gave it ; By setting the Reset Code in CMOS ; stdCall _HalpAcquireCmosSpinLock mov al, 0fh CMOS_READ mov LCmosValue, eax mov eax, 0a0fh CMOS_WRITE stdCall _HalpReleaseCmosSpinLock ; ; Start the processor ; mov eax, pLoaderBlock ; lookup processor # we are mov eax, [eax].LpbPrcb ; starting mov Prcb, eax ; save this away for later movzx eax, byte ptr [eax].PbNumber stdCall _HalpStartProcessor < _HalpLowStubPhysicalAddress, eax > or eax, eax jnz short WaitTilPnOnline ; ; Zero Return Value means couldn't kick start the processor ; so there's no point in waiting for it. ; jmp NotWaitingOnProcessor WaitTilPnOnline: dec eax ; Local APIC ID mov ecx, Prcb mov [ecx].PbHalReserved.PrcbPCMPApicId, al ; ; We can't proceed until the started processor gives us the OK ; mov edi, 200 mov esi, _HalpLowStub WaitAbit: cmp [esi].SPx_flag, 0 ; wait for Px to get it's jne short ProcessorStarted ; info stdCall _KeStallExecutionProcessor, <2000> dec edi cmp edi, 0 jne short WaitAbit jmp short NotWaitingOnProcessor ProcessorStarted: mov LStatusCode, 1 ; Return TRUE mov ecx, Prcb ; save this away for later movzx ecx, byte ptr [ecx].PbNumber stdCall _HalpMarkProcessorStarted, NotWaitingOnProcessor: mov al, _HalpHiberInProgress or al, al jnz short Hpsnp_ResetVector stdCall _HalpFreeTiledCR3 ; free memory used for tiled CR3 Hpsnp_ResetVector: mov eax, LWarmResetVector mov [ebx], eax ; Restore reset vector stdCall _HalpAcquireCmosSpinLock mov eax, LCmosValue ; Restore the Cmos setting shl eax, 8 mov al, 0fh CMOS_WRITE stdCall _HalpReleaseCmosSpinLock mov eax, LStatusCode snp_exit: popfd pop ebx pop edi pop esi mov esp, ebp pop ebp stdRET _HalStartNextProcessor endif stdENDP _HalStartNextProcessor PAGELK ends ; end 32 bit code end