diff options
Diffstat (limited to 'private/ntos/nthals/haloli/i386/oliproca.asm')
-rw-r--r-- | private/ntos/nthals/haloli/i386/oliproca.asm | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/private/ntos/nthals/haloli/i386/oliproca.asm b/private/ntos/nthals/haloli/i386/oliproca.asm new file mode 100644 index 000000000..6e72e8efe --- /dev/null +++ b/private/ntos/nthals/haloli/i386/oliproca.asm @@ -0,0 +1,478 @@ + title "MP primitives for Compaq SystemPro" +;++ +; +;Copyright (c) 1991 Microsoft Corporation +; +;Module Name: +; +; oliproca.asm +; +;Abstract: +; +; SystemPro Start Next Processor assemble code +; +; This module along with mpspro.c implement the code to start +; off the second processor on the Compaq SystemPro. +; +;Author: +; +; Ken Reneris (kenr) 12-Jan-1992 +; +; Bruno Sartirana (o-obruno) 3-Mar-92 +; Added support for the Olivetti LSX5030. +; +;Revision History: +; +;-- + + + +.386p + .xlist +include hal386.inc +include callconv.inc +include i386\kimacro.inc +include mac386.inc +;LSX5030 start +include i386\ix8259.inc +include i386\olimp.inc +;LSX5030 end + .list + + EXTRNP _HalpBuildTiledCR3,1 + EXTRNP _HalpFreeTiledCR3,0 + + extrn _MppIDT:DWORD + extrn _MpLowStub:DWORD + extrn _MpLowStubPhysicalAddress:DWORD + extrn ProcessorControlPort:WORD +;LSX5030 start + extrn _CpuLeft:DWORD + extrn _NextCpuToStart:DWORD + extrn DbgDelay:DWORD +;LSX5030 end + + +; +; Internal defines and structures +; + +PxParamBlock struc + SPx_flag dd ? + SPx_TiledCR3 dd ? + SPx_P0EBP dd ? + SPx_ControlPort dd ? + SPx_PB db processorstatelength dup (?) +PxParamBlock ends + + +_TEXT 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, 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. +; +; 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 + push ebp ; save ebp + mov ebp, esp ; + + sub esp, size PxParamBlock ; Make room for local vars + + DBG_DISPLAY 0f0h + + push esi + push edi + push ebx + + xor eax, eax + mov PxFrame.SPx_flag, eax + + cmp _CpuLeft, eax + je snp_exit ; exit FALSE + + mov esi, OFFSET FLAT:StartPx_RMStub + mov ecx, StartPx_RMStub_Len + mov edi, _MpLowStub ; Copy RMStub to low memory + add edi, size PxParamBlock + rep movsb + + lea edi, PxFrame.SPx_PB + mov esi, pProcessorState + mov ecx, processorstatelength ; Copy processorstate + rep movsb ; to PxFrame + + + stdCall _HalpBuildTiledCR3,<pProcessorState> + + mov PxFrame.SPx_TiledCR3, eax + mov PxFrame.SPx_P0EBP, ebp + + mov eax, pLoaderBlock ; lookup processor # we are + mov eax, [eax].LpbPrcb ; starting + movzx eax, byte ptr [eax].PbNumber + movzx edx, ProcessorControlPort[eax*2] ; Get processor's control port + mov PxFrame.SPx_ControlPort, edx ; Pass it along + + mov ecx, size PxParamBlock ; copy param block + lea esi, PxFrame ; to low memory stub + mov edi, _MpLowStub + 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 + + mov ebx, _MppIDT + add ebx, WarmResetVector + + cli + push dword ptr [ebx] ; Save current vector + + mov eax, _MpLowStubPhysicalAddress + shl eax, 12 ; seg:0 + add eax, size PxParamBlock + mov dword ptr [ebx], eax ; start Px here + +;LSX5030 start + mov eax, _NextCpuToStart + mov dx, word ptr ProcessorControlPort[eax*2] + in al, dx + or al, RESET ; assert RESET + out dx, al + and al, not RESET ; the 1-0 transition of PCR + ; reset bit resets the + ; processor + out dx, al ; reset processor +;LSX5030 end + +@@: + cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's + jz @b ; info + + pop dword ptr [ebx] ; restore WarmResetVector + + sti + + stdCall _HalpFreeTiledCR3 ; free memory used for tiled + ; CR3 + +;LSX5030 start + DBG_DISPLAY 0ffh + + dec _CpuLeft ; one less + inc _NextCpuToStart ; next CPU # to start +;LSX5030 end + + mov eax, 1 ; return TRUE + +snp_exit: + DBG_DISPLAY 0feh + pop ebx + pop edi + pop esi + mov esp, ebp + pop ebp + stdRET _HalStartNextProcessor + +_HalStartNextProcessor endp + + +_TEXT ends ; end 32 bit code + + +_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_RMStub_Len equ $ - StartPx_RMStub +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 + + public _StartPx_PMStub +_StartPx_PMStub proc + + ; 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 + +;LSX5030 start + mov eax, _NextCpuToStart + mov dx, word ptr ProcessorControlPort[eax*2] + in al, dx ; Get register + and al, not IPI_EN ; disable PINTs for now + out dx, al + ;and dx, Px_SLOT_MASK ; get processor slot (olibus) + ;or dx, LEV2_CACHE_REG ; calculate address of the 2nd + ; level cache policy register + ; for this processor + ;in al, dx ; Get register + ;and al, not LEV2_CACHE_ON ; turn cache off + ;or al, LEV2_CACHE_ON ; turn cache on + ;out dx, al + ;and dx, Px_SLOT_MASK ; get processor slot (olibus) + ;or dx, SLOT_CONFIG_REG_0 ; calculate address of + ; configuration register 0 for + ; this processor + ;in al, dx ; get register + ;and al, not INTERNAL_CACHE_ON ; turn internal cache off + ;or al, INTERNAL_CACHE_ON ; turn processor's internal + ; cache on + ;out dx, al + + ;DBG_DISPLAY 0b0h + +; sti + + inc [PxFrame.SPx_flag] ; Signal p0 that we are + ; done with its data + ;DBG_DISPLAY 0bfh + +;LSX5030 end + + ; Set remaining registers + pop ebp + pop edi + pop edx + pop ebx + pop eax + ret ; Set eip + +_StartPx_PMStub endp + +;LSX5030 start +;++ +; +; ULONG +; HalpGetNumberOfProcessors() +; +; Routine Description: +; +; This routine queries the CMOS to determine the number of processors +; that can be started. +; Also, it rearranges the ProcessorControlPort array to make it +; non-sparse. This means that, eventually, ProcessorControlPort[n] +; will contain the slot # of the processor n, where n=0,1,2,3. +; For example, if the machine has two processors, one in slot 0 and +; the other in slot 3, only the ProcessorControlPort array elements +; #0 and #1 will be meaningful. +; +; Arguments: +; +; None. +; +; Return Value: +; +; The number of available processors in register eax. +; +;-- + +cPublicProc _HalpGetNumberOfProcessors,0 + + + push ebx + push ecx + push edx + mov al, CMOS_GET_MP_STATUS + CMOS_READ + mov ch, al ; al[7-4] = CPU card present bits + ; al[3-0] = CPU diagnostics passed bits + shr al, 4 ; al[3-0] = CPU card present bits + mov cl, al ; ch[3-0] = CPU card diag passed bits + ; cl[3-0] = CPU card present bits + and cl, ch ; CPUs actually available (bit mapped) + + mov edx, 1 ; there's always the CPU0, so skip it + mov eax, 1 ; logical processor # +NextCPU: + bt ecx, edx + jnc IncLoopCounter + mov bx, word ptr ProcessorControlPort[edx*2] ; get address of + ; PCP #edx + mov word ptr ProcessorControlPort[eax*2], bx ; set PCP address + ; for processor #eax + inc eax +IncLoopCounter: + inc edx + cmp edx, MAX_NUMBER_PROCESSORS + jl NextCPU + + pop edx + pop ecx + pop ebx + + stdRET _HalpGetNumberOfProcessors + +stdENDP _HalpGetNumberOfProcessors + +;LSX5030 end + +_TEXT ends ; end 32 bit code + end |