Home | History | Annotate | Download | only in Ia32
      1 ;------------------------------------------------------------------------------ ;
      2 ; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
      3 ; This program and the accompanying materials
      4 ; are licensed and made available under the terms and conditions of the BSD License
      5 ; which accompanies this distribution.  The full text of the license may be found at
      6 ; http://opensource.org/licenses/bsd-license.php.
      7 ;
      8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
      9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     10 ;
     11 ; Module Name:
     12 ;
     13 ;   MpFuncs.nasm
     14 ;
     15 ; Abstract:
     16 ;
     17 ;   This is the assembly code for MP support
     18 ;
     19 ;-------------------------------------------------------------------------------
     20 
     21 %include "MpEqu.inc"
     22 extern ASM_PFX(InitializeFloatingPointUnits)
     23 
     24 SECTION .text
     25 
     26 ;-------------------------------------------------------------------------------------
     27 ;RendezvousFunnelProc  procedure follows. All APs execute their procedure. This
     28 ;procedure serializes all the AP processors through an Init sequence. It must be
     29 ;noted that APs arrive here very raw...ie: real mode, no stack.
     30 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
     31 ;IS IN MACHINE CODE.
     32 ;-------------------------------------------------------------------------------------
     33 global ASM_PFX(RendezvousFunnelProc)
     34 ASM_PFX(RendezvousFunnelProc):
     35 RendezvousFunnelProcStart:
     36 ; At this point CS = 0x(vv00) and ip= 0x0.
     37 BITS 16
     38     mov        ebp, eax                        ; save BIST information
     39 
     40     mov        ax, cs
     41     mov        ds, ax
     42     mov        es, ax
     43     mov        ss, ax
     44     xor        ax, ax
     45     mov        fs, ax
     46     mov        gs, ax
     47 
     48     mov        si,  BufferStartLocation
     49     mov        ebx, [si]
     50 
     51     mov        si,  ModeOffsetLocation
     52     mov        eax, [si]
     53     mov        si,  CodeSegmentLocation
     54     mov        edx, [si]
     55     mov        di,  ax
     56     sub        di,  02h
     57     mov        [di], dx
     58     sub        di,  04h
     59     add        eax, ebx
     60     mov        [di],eax
     61 
     62     mov        si,  DataSegmentLocation
     63     mov        edx, [si]
     64 
     65     mov        si, GdtrLocation
     66 o32 lgdt       [cs:si]
     67 
     68     mov        si, IdtrLocation
     69 o32 lidt       [cs:si]
     70 
     71     xor        ax,  ax
     72     mov        ds,  ax
     73 
     74     mov        eax, cr0                        ; Get control register 0
     75     or         eax, 000000003h                 ; Set PE bit (bit #0) & MP
     76     mov        cr0, eax
     77 
     78     jmp        0:strict dword 0                ; far jump to protected mode
     79 BITS 32
     80 Flat32Start:                                   ; protected mode entry point
     81     mov        ds, dx
     82     mov        es, dx
     83     mov        fs, dx
     84     mov        gs, dx
     85     mov        ss, dx
     86 
     87     mov        esi, ebx
     88 
     89     mov         edi, esi
     90     add         edi, EnableExecuteDisableLocation
     91     cmp         byte [edi], 0
     92     jz          SkipEnableExecuteDisable
     93 
     94     ;
     95     ; Enable IA32 PAE execute disable
     96     ;
     97 
     98     mov         ecx, 0xc0000080
     99     rdmsr
    100     bts         eax, 11
    101     wrmsr
    102 
    103     mov         edi, esi
    104     add         edi, Cr3Location
    105     mov         eax, dword [edi]
    106     mov         cr3, eax
    107 
    108     mov         eax, cr4
    109     bts         eax, 5
    110     mov         cr4, eax
    111 
    112     mov         eax, cr0
    113     bts         eax, 31
    114     mov         cr0, eax
    115 
    116 SkipEnableExecuteDisable:
    117     mov        edi, esi
    118     add        edi, InitFlagLocation
    119     cmp        dword [edi], 1       ; 1 == ApInitConfig
    120     jnz        GetApicId
    121 
    122     ; AP init
    123     mov        edi, esi
    124     add        edi, LockLocation
    125     mov        eax, NotVacantFlag
    126 
    127 TestLock:
    128     xchg       [edi], eax
    129     cmp        eax, NotVacantFlag
    130     jz         TestLock
    131 
    132     mov        ecx, esi
    133     add        ecx, NumApsExecutingLocation
    134     inc        dword [ecx]
    135     mov        ebx, [ecx]
    136 
    137 Releaselock:
    138     mov        eax, VacantFlag
    139     xchg       [edi], eax
    140 
    141     mov        edi, esi
    142     add        edi, StackSizeLocation
    143     mov        eax, [edi]
    144     mov        ecx, ebx
    145     inc        ecx
    146     mul        ecx                               ; EAX = StackSize * (CpuNumber + 1)
    147     mov        edi, esi
    148     add        edi, StackStartAddressLocation
    149     add        eax, [edi]
    150     mov        esp, eax
    151     jmp        CProcedureInvoke
    152 
    153 GetApicId:
    154     mov        eax, 0
    155     cpuid
    156     cmp        eax, 0bh
    157     jb         NoX2Apic             ; CPUID level below CPUID_EXTENDED_TOPOLOGY
    158 
    159     mov        eax, 0bh
    160     xor        ecx, ecx
    161     cpuid
    162     test       ebx, 0ffffh
    163     jz         NoX2Apic             ; CPUID.0BH:EBX[15:0] is zero
    164 
    165     ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
    166     jmp        GetProcessorNumber
    167 
    168 NoX2Apic:
    169     ; Processor is not x2APIC capable, so get 8-bit APIC ID
    170     mov        eax, 1
    171     cpuid
    172     shr        ebx, 24
    173     mov        edx, ebx
    174 
    175 GetProcessorNumber:
    176     ;
    177     ; Get processor number for this AP
    178     ; Note that BSP may become an AP due to SwitchBsp()
    179     ;
    180     xor         ebx, ebx
    181     lea         eax, [esi + CpuInfoLocation]
    182     mov         edi, [eax]
    183 
    184 GetNextProcNumber:
    185     cmp         [edi], edx                       ; APIC ID match?
    186     jz          ProgramStack
    187     add         edi, 20
    188     inc         ebx
    189     jmp         GetNextProcNumber    
    190 
    191 ProgramStack:
    192     mov         esp, [edi + 12]
    193    
    194 CProcedureInvoke:
    195     push       ebp               ; push BIST data at top of AP stack
    196     xor        ebp, ebp          ; clear ebp for call stack trace
    197     push       ebp
    198     mov        ebp, esp
    199 
    200     mov        eax, ASM_PFX(InitializeFloatingPointUnits)
    201     call       eax               ; Call assembly function to initialize FPU per UEFI spec
    202 
    203     push       ebx               ; Push NumApsExecuting
    204     mov        eax, esi
    205     add        eax, LockLocation
    206     push       eax               ; push address of exchange info data buffer
    207 
    208     mov        edi, esi
    209     add        edi, ApProcedureLocation
    210     mov        eax, [edi]
    211 
    212     call       eax               ; Invoke C function
    213 
    214     jmp        $                 ; Never reach here
    215 RendezvousFunnelProcEnd:
    216 
    217 ;-------------------------------------------------------------------------------------
    218 ;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
    219 ;-------------------------------------------------------------------------------------
    220 global ASM_PFX(AsmRelocateApLoop)
    221 ASM_PFX(AsmRelocateApLoop):
    222 AsmRelocateApLoopStart:
    223     mov        eax, esp
    224     mov        esp, [eax + 16]     ; TopOfApStack
    225     push       dword [eax]         ; push return address for stack trace
    226     push       ebp
    227     mov        ebp, esp
    228     mov        ebx, [eax + 8]      ; ApTargetCState
    229     mov        ecx, [eax + 4]      ; MwaitSupport
    230     mov        eax, [eax + 20]     ; CountTofinish
    231     lock dec   dword [eax]         ; (*CountTofinish)--
    232     cmp        cl,  1              ; Check mwait-monitor support
    233     jnz        HltLoop
    234 MwaitLoop:
    235     mov        eax, esp
    236     xor        ecx, ecx
    237     xor        edx, edx
    238     monitor
    239     mov        eax, ebx            ; Mwait Cx, Target C-State per eax[7:4]
    240     shl        eax, 4
    241     mwait
    242     jmp        MwaitLoop
    243 HltLoop:
    244     cli
    245     hlt
    246     jmp        HltLoop
    247 AsmRelocateApLoopEnd:
    248 
    249 ;-------------------------------------------------------------------------------------
    250 ;  AsmGetAddressMap (&AddressMap);
    251 ;-------------------------------------------------------------------------------------
    252 global ASM_PFX(AsmGetAddressMap)
    253 ASM_PFX(AsmGetAddressMap):
    254     pushad
    255     mov        ebp,esp
    256 
    257     mov        ebx,  [ebp + 24h]
    258     mov        dword [ebx], RendezvousFunnelProcStart
    259     mov        dword [ebx +  4h], Flat32Start - RendezvousFunnelProcStart
    260     mov        dword [ebx +  8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
    261     mov        dword [ebx + 0Ch], AsmRelocateApLoopStart
    262     mov        dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
    263 
    264     popad
    265     ret
    266 
    267 ;-------------------------------------------------------------------------------------
    268 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
    269 ;about to become an AP. It switches it'stack with the current AP.
    270 ;AsmExchangeRole (IN   CPU_EXCHANGE_INFO    *MyInfo, IN   CPU_EXCHANGE_INFO    *OthersInfo);
    271 ;-------------------------------------------------------------------------------------
    272 global ASM_PFX(AsmExchangeRole)
    273 ASM_PFX(AsmExchangeRole):
    274     ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
    275     ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
    276     pushad
    277     mov        ebp,esp
    278 
    279     ; esi contains MyInfo pointer
    280     mov        esi, [ebp + 24h]
    281 
    282     ; edi contains OthersInfo pointer
    283     mov        edi, [ebp + 28h]
    284 
    285     ;Store EFLAGS, GDTR and IDTR register to stack
    286     pushfd
    287     mov        eax, cr4
    288     push       eax       ; push cr4 firstly
    289     mov        eax, cr0
    290     push       eax
    291 
    292     sgdt       [esi + 8]
    293     sidt       [esi + 14]
    294 
    295     ; Store the its StackPointer
    296     mov        [esi + 4],esp
    297 
    298     ; update its switch state to STORED
    299     mov        byte [esi], CPU_SWITCH_STATE_STORED
    300 
    301 WaitForOtherStored:
    302     ; wait until the other CPU finish storing its state
    303     cmp        byte [edi], CPU_SWITCH_STATE_STORED
    304     jz         OtherStored
    305     pause
    306     jmp        WaitForOtherStored
    307 
    308 OtherStored:
    309     ; Since another CPU already stored its state, load them
    310     ; load GDTR value
    311     lgdt       [edi + 8]
    312 
    313     ; load IDTR value
    314     lidt       [edi + 14]
    315 
    316     ; load its future StackPointer
    317     mov        esp, [edi + 4]
    318 
    319     ; update the other CPU's switch state to LOADED
    320     mov        byte [edi], CPU_SWITCH_STATE_LOADED
    321 
    322 WaitForOtherLoaded:
    323     ; wait until the other CPU finish loading new state,
    324     ; otherwise the data in stack may corrupt
    325     cmp        byte [esi], CPU_SWITCH_STATE_LOADED
    326     jz         OtherLoaded
    327     pause
    328     jmp        WaitForOtherLoaded
    329 
    330 OtherLoaded:
    331     ; since the other CPU already get the data it want, leave this procedure
    332     pop        eax
    333     mov        cr0, eax
    334     pop        eax
    335     mov        cr4, eax
    336     popfd
    337 
    338     popad
    339     ret
    340