]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
UefiCpuPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
index 090e9fae07cd793d2266939aee0f2b11f75877f4..cea90f3d4deb56dcc4e1318aa966d259efc585d2 100644 (file)
@@ -1,12 +1,6 @@
 ;------------------------------------------------------------------------------ ;\r
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
-; This program and the accompanying materials\r
-; are licensed and made available under the terms and conditions of the BSD License\r
-; which accompanies this distribution.  The full text of the license may be found at\r
-; http://opensource.org/licenses/bsd-license.php.\r
-;\r
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+; Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
 ;\r
 ; Module Name:\r
 ;\r
@@ -52,16 +46,13 @@ BITS 16
     mov        si,  BufferStartLocation\r
     mov        ebx, [si]\r
 \r
-    mov        di,  ModeOffsetLocation\r
-    mov        eax, [di]\r
-    mov        di,  CodeSegmentLocation\r
-    mov        edx, [di]\r
-    mov        di,  ax\r
-    sub        di,  02h\r
-    mov        [di],dx                         ; Patch long mode CS\r
-    sub        di,  04h\r
-    add        eax, ebx\r
-    mov        [di],eax                        ; Patch address\r
+    mov        si,  DataSegmentLocation\r
+    mov        edx, [si]\r
+\r
+    ;\r
+    ; Get start address of 32-bit code in low memory (<1MB)\r
+    ;\r
+    mov        edi, ModeTransitionMemoryLocation\r
 \r
     mov        si, GdtrLocation\r
 o32 lgdt       [cs:si]\r
@@ -69,57 +60,91 @@ o32 lgdt       [cs:si]
     mov        si, IdtrLocation\r
 o32 lidt       [cs:si]\r
 \r
-    mov        si, EnableExecuteDisableLocation\r
-    cmp        byte [si], 0\r
-    jz         SkipEnableExecuteDisableBit\r
+    ;\r
+    ; Switch to protected mode\r
+    ;\r
+    mov        eax, cr0                    ; Get control register 0\r
+    or         eax, 000000003h             ; Set PE bit (bit #0) & MP\r
+    mov        cr0, eax\r
+\r
+    ; Switch to 32-bit code (>1MB)\r
+o32 jmp far    [cs:di]\r
+\r
+;\r
+; Following code must be copied to memory with type of EfiBootServicesCode.\r
+; This is required if NX is enabled for EfiBootServicesCode of memory.\r
+;\r
+BITS 32\r
+Flat32Start:                                   ; protected mode entry point\r
+    mov        ds, dx\r
+    mov        es, dx\r
+    mov        fs, dx\r
+    mov        gs, dx\r
+    mov        ss, dx\r
 \r
     ;\r
     ; Enable execute disable bit\r
     ;\r
+    mov        esi, EnableExecuteDisableLocation\r
+    cmp        byte [ebx + esi], 0\r
+    jz         SkipEnableExecuteDisableBit\r
+\r
     mov        ecx, 0c0000080h             ; EFER MSR number\r
     rdmsr                                  ; Read EFER\r
     bts        eax, 11                     ; Enable Execute Disable Bit\r
     wrmsr                                  ; Write EFER\r
 \r
 SkipEnableExecuteDisableBit:\r
-\r
-    mov        di,  DataSegmentLocation\r
-    mov        edi, [di]                   ; Save long mode DS in edi\r
-\r
-    mov        si, Cr3Location             ; Save CR3 in ecx\r
-    mov        ecx, [si]\r
-\r
-    xor        ax,  ax\r
-    mov        ds,  ax                     ; Clear data segment\r
-\r
-    mov        eax, cr0                    ; Get control register 0\r
-    or         eax, 000000003h             ; Set PE bit (bit #0) & MP\r
-    mov        cr0, eax\r
-\r
+    ;\r
+    ; Enable PAE\r
+    ;\r
     mov        eax, cr4\r
     bts        eax, 5\r
     mov        cr4, eax\r
 \r
+    ;\r
+    ; Load page table\r
+    ;\r
+    mov        esi, Cr3Location             ; Save CR3 in ecx\r
+    mov        ecx, [ebx + esi]\r
     mov        cr3, ecx                    ; Load CR3\r
 \r
+    ;\r
+    ; Enable long mode\r
+    ;\r
     mov        ecx, 0c0000080h             ; EFER MSR number\r
     rdmsr                                  ; Read EFER\r
     bts        eax, 8                      ; Set LME=1\r
     wrmsr                                  ; Write EFER\r
 \r
+    ;\r
+    ; Enable paging\r
+    ;\r
     mov        eax, cr0                    ; Read CR0\r
     bts        eax, 31                     ; Set PG=1\r
     mov        cr0, eax                    ; Write CR0\r
 \r
-    jmp        0:strict dword 0  ; far jump to long mode\r
+    ;\r
+    ; Far jump to 64-bit code\r
+    ;\r
+    mov        edi, ModeHighMemoryLocation\r
+    add        edi, ebx\r
+    jmp far    [edi]\r
+\r
 BITS 64\r
 LongModeStart:\r
-    mov        eax, edi\r
-    mov        ds,  ax\r
-    mov        es,  ax\r
-    mov        ss,  ax\r
-\r
     mov        esi, ebx\r
+    lea        edi, [esi + InitFlagLocation]\r
+    cmp        qword [edi], 1       ; ApInitConfig\r
+    jnz        GetApicId\r
+\r
+    ; Increment the number of APs executing here as early as possible\r
+    ; This is decremented in C code when AP is finished executing\r
+    mov        edi, esi\r
+    add        edi, NumApsExecutingLocation\r
+    lock inc   dword [edi]\r
+\r
+    ; AP init\r
     mov        edi, esi\r
     add        edi, LockLocation\r
     mov        rax, NotVacantFlag\r
@@ -129,26 +154,66 @@ TestLock:
     cmp        rax, NotVacantFlag\r
     jz         TestLock\r
 \r
-    mov        edi, esi\r
-    add        edi, NumApsExecutingLocation\r
-    inc        dword [edi]\r
-    mov        ebx, [edi]\r
+    lea        ecx, [esi + ApIndexLocation]\r
+    inc        dword [ecx]\r
+    mov        ebx, [ecx]\r
 \r
-ProgramStack:\r
+Releaselock:\r
+    mov        rax, VacantFlag\r
+    xchg       qword [edi], rax\r
+    ; program stack\r
     mov        edi, esi\r
     add        edi, StackSizeLocation\r
-    mov        rax, qword [edi]\r
+    mov        eax, dword [edi]\r
+    mov        ecx, ebx\r
+    inc        ecx\r
+    mul        ecx                               ; EAX = StackSize * (CpuNumber + 1)\r
     mov        edi, esi\r
     add        edi, StackStartAddressLocation\r
     add        rax, qword [edi]\r
     mov        rsp, rax\r
-    mov        qword [edi], rax\r
+    jmp        CProcedureInvoke\r
+\r
+GetApicId:\r
+    mov        eax, 0\r
+    cpuid\r
+    cmp        eax, 0bh\r
+    jb         NoX2Apic             ; CPUID level below CPUID_EXTENDED_TOPOLOGY\r
+\r
+    mov        eax, 0bh\r
+    xor        ecx, ecx\r
+    cpuid\r
+    test       ebx, 0ffffh\r
+    jz         NoX2Apic             ; CPUID.0BH:EBX[15:0] is zero\r
+\r
+    ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX\r
+    jmp        GetProcessorNumber\r
+\r
+NoX2Apic:\r
+    ; Processor is not x2APIC capable, so get 8-bit APIC ID\r
+    mov        eax, 1\r
+    cpuid\r
+    shr        ebx, 24\r
+    mov        edx, ebx\r
+\r
+GetProcessorNumber:\r
+    ;\r
+    ; Get processor number for this AP\r
+    ; Note that BSP may become an AP due to SwitchBsp()\r
+    ;\r
+    xor         ebx, ebx\r
+    lea         eax, [esi + CpuInfoLocation]\r
+    mov         edi, [eax]\r
 \r
-Releaselock:\r
-    mov        rax, VacantFlag\r
-    mov        edi, esi\r
-    add        edi, LockLocation\r
-    xchg       qword [edi], rax\r
+GetNextProcNumber:\r
+    cmp         dword [edi], edx                      ; APIC ID match?\r
+    jz          ProgramStack\r
+    add         edi, 20\r
+    inc         ebx\r
+    jmp         GetNextProcNumber\r
+\r
+ProgramStack:\r
+    mov         rsp, qword [edi + 12]\r
 \r
 CProcedureInvoke:\r
     push       rbp               ; Push BIST data at top of AP stack\r
@@ -156,12 +221,12 @@ CProcedureInvoke:
     push       rbp\r
     mov        rbp, rsp\r
 \r
-    mov        rax, ASM_PFX(InitializeFloatingPointUnits)\r
+    mov        rax, qword [esi + InitializeFloatingPointUnitsAddress]\r
     sub        rsp, 20h\r
     call       rax               ; Call assembly function to initialize FPU per UEFI spec\r
     add        rsp, 20h\r
 \r
-    mov        edx, ebx          ; edx is NumApsExecuting\r
+    mov        edx, ebx          ; edx is ApIndex\r
     mov        ecx, esi\r
     add        ecx, LockLocation ; rcx is address of exchange info data buffer\r
 \r
@@ -177,11 +242,15 @@ CProcedureInvoke:
 RendezvousFunnelProcEnd:\r
 \r
 ;-------------------------------------------------------------------------------------\r
-;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);\r
+;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);\r
 ;-------------------------------------------------------------------------------------\r
 global ASM_PFX(AsmRelocateApLoop)\r
 ASM_PFX(AsmRelocateApLoop):\r
 AsmRelocateApLoopStart:\r
+    cli                          ; Disable interrupt before switching to 32-bit mode\r
+    mov        rax, [rsp + 40]   ; CountTofinish\r
+    lock dec   dword [rax]       ; (*CountTofinish)--\r
+    mov        rsp, r9\r
     push       rcx\r
     push       rdx\r
 \r
@@ -214,19 +283,19 @@ PmEntry:
     jnz        HltLoop\r
     mov        ebx, edx           ; Save C-State to ebx\r
 MwaitLoop:\r
+    cli\r
     mov        eax, esp           ; Set Monitor Address\r
     xor        ecx, ecx           ; ecx = 0\r
     xor        edx, edx           ; edx = 0\r
     monitor\r
-    shl        ebx, 4\r
     mov        eax, ebx           ; Mwait Cx, Target C-State per eax[7:4]\r
+    shl        eax, 4\r
     mwait\r
     jmp        MwaitLoop\r
 HltLoop:\r
     cli\r
     hlt\r
     jmp        HltLoop\r
-    ret\r
 BITS 64\r
 AsmRelocateApLoopEnd:\r
 \r
@@ -235,13 +304,14 @@ AsmRelocateApLoopEnd:
 ;-------------------------------------------------------------------------------------\r
 global ASM_PFX(AsmGetAddressMap)\r
 ASM_PFX(AsmGetAddressMap):\r
-    mov        rax, ASM_PFX(RendezvousFunnelProc)\r
+    lea        rax, [ASM_PFX(RendezvousFunnelProc)]\r
     mov        qword [rcx], rax\r
     mov        qword [rcx +  8h], LongModeStart - RendezvousFunnelProcStart\r
     mov        qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
-    mov        rax, ASM_PFX(AsmRelocateApLoop)\r
+    lea        rax, [ASM_PFX(AsmRelocateApLoop)]\r
     mov        qword [rcx + 18h], rax\r
     mov        qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart\r
+    mov        qword [rcx + 28h], Flat32Start - RendezvousFunnelProcStart\r
     ret\r
 \r
 ;-------------------------------------------------------------------------------------\r