1#------------------------------------------------------------------------------
2#
3# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
4# This program and the accompanying materials
5# are licensed and made available under the terms and conditions of the BSD License
6# which accompanies this distribution.  The full text of the license may be found at
7# http://opensource.org/licenses/bsd-license.php.
8#
9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11#
12# Module Name:
13#
14#   MpFuncs.S
15#
16# Abstract:
17#
18#   This is the assembly code for Multi-processor S3 support
19#
20#------------------------------------------------------------------------------
21
22.equ                   VacantFlag,       0x0
23.equ                   NotVacantFlag,    0xff
24
25.equ                   LockLocation,     RendezvousFunnelProcEnd - RendezvousFunnelProcStart
26.equ                   StackStart,       RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x04
27.equ                   StackSize,        RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x08
28.equ                   RendezvousProc,   RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x0C
29.equ                   GdtrProfile,      RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x10
30.equ                   IdtrProfile,      RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x16
31.equ                   BufferStart,      RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x1C
32
33#-------------------------------------------------------------------------------------
34#RendezvousFunnelProc  procedure follows. All APs execute their procedure. This
35#procedure serializes all the AP processors through an Init sequence. It must be
36#noted that APs arrive here very raw...ie: real mode, no stack.
37#ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
38#IS IN MACHINE CODE.
39#-------------------------------------------------------------------------------------
40#RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
41
42ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)
43ASM_PFX(RendezvousFunnelProc):
44RendezvousFunnelProcStart:
45
46# At this point CS = 0x(vv00) and ip= 0x0.
47
48        .byte 0x8c,0xc8               # mov        ax,  cs
49        .byte 0x8e,0xd8               # mov        ds,  ax
50        .byte 0x8e,0xc0               # mov        es,  ax
51        .byte 0x8e,0xd0               # mov        ss,  ax
52        .byte 0x33,0xc0               # xor        ax,  ax
53        .byte 0x8e,0xe0               # mov        fs,  ax
54        .byte 0x8e,0xe8               # mov        gs,  ax
55
56flat32Start:
57
58        .byte 0xBE
59        .word BufferStart
60        .byte 0x66,0x8B,0x14          # mov        edx,dword ptr [si]          ; EDX is keeping the start address of wakeup buffer
61
62        .byte 0xBE
63        .word GdtrProfile
64        .byte 0x66                    # db         66h
65        .byte 0x2E,0xF,0x1,0x14       # lgdt       fword ptr cs:[si]
66
67        .byte 0xBE
68        .word IdtrProfile
69        .byte 0x66                    # db         66h
70        .byte 0x2E,0xF,0x1,0x1C       # lidt       fword ptr cs:[si]
71
72        .byte 0x33,0xC0               # xor        ax,  ax
73        .byte 0x8E,0xD8               # mov        ds,  ax
74
75        .byte 0xF,0x20,0xC0           # mov        eax, cr0                    ; Get control register 0
76        .byte 0x66,0x83,0xC8,0x1      # or         eax, 000000001h             ; Set PE bit (bit #0)
77        .byte 0xF,0x22,0xC0           # mov        cr0, eax
78
79FLAT32_JUMP:
80
81        .byte 0x66,0x67,0xEA          # far jump
82        .long 0x0                     # 32-bit offset
83        .word 0x20                    # 16-bit selector
84
85PMODE_ENTRY:                          # protected mode entry point
86
87        movw        $0x8,%ax
88        .byte       0x66
89        movw        %ax,%ds
90        .byte       0x66
91        movw        %ax,%es
92        .byte       0x66
93        movw        %ax,%fs
94        .byte       0x66
95        movw        %ax,%gs
96        .byte       0x66
97        movw        %ax,%ss           # Flat mode setup.
98
99        movl        %edx,%esi
100
101        movl        %esi,%edi
102        addl        $LockLocation, %edi
103        movb        $NotVacantFlag, %al
104TestLock:
105        xchgb       (%edi), %al
106        cmpb        $NotVacantFlag, %al
107        jz          TestLock
108
109ProgramStack:
110
111        movl        %esi,%edi
112        addl        $StackSize, %edi
113        movl        (%edi),%eax
114        movl        %esi,%edi
115        addl        $StackStart, %edi
116        addl        (%edi),%eax
117        movl        %eax,%esp
118        movl        %eax,(%edi)
119
120Releaselock:
121
122        movb        $VacantFlag, %al
123        movl        %esi,%edi
124        addl        $LockLocation, %edi
125        xchgb       (%edi), %al
126
127        #
128        # Call assembly function to initialize FPU.
129        #
130        lea         ASM_PFX(InitializeFloatingPointUnits), %ebx
131        call        *%ebx
132        #
133        # Call C Function
134        #
135        movl        %esi,%edi
136        addl        $RendezvousProc, %edi
137        movl        (%edi),%eax
138
139        testl       %eax,%eax
140        jz          GoToSleep
141        call        *%eax                         # Call C function
142
143GoToSleep:
144        cli
145        hlt
146        jmp         GoToSleep
147
148RendezvousFunnelProcEnd:
149#-------------------------------------------------------------------------------------
150#  AsmGetAddressMap (&AddressMap);
151#-------------------------------------------------------------------------------------
152ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
153ASM_PFX(AsmGetAddressMap):
154
155        pushal
156        movl        %esp,%ebp
157
158        movl        0x24(%ebp), %ebx
159        movl        $RendezvousFunnelProcStart, (%ebx)
160        movl        $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x4(%ebx)
161        movl        $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x8(%ebx)
162        movl        $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0x0c(%ebx)
163
164        popal
165        ret
166