1#------------------------------------------------------------------------------
2#
3# Copyright (c) 2009 - 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#   SmiEntry.S
15#
16# Abstract:
17#
18#   Code template of the SMI handler for a particular processor
19#
20#------------------------------------------------------------------------------
21
22ASM_GLOBAL  ASM_PFX(gcSmiHandlerTemplate)
23ASM_GLOBAL  ASM_PFX(gcSmiHandlerSize)
24ASM_GLOBAL  ASM_PFX(gSmiCr3)
25ASM_GLOBAL  ASM_PFX(gSmiStack)
26ASM_GLOBAL  ASM_PFX(gSmbase)
27ASM_GLOBAL  ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
28ASM_GLOBAL  ASM_PFX(gSmiHandlerIdtr)
29
30.equ            DSC_OFFSET, 0xfb00
31.equ            DSC_GDTPTR, 0x30
32.equ            DSC_GDTSIZ, 0x38
33.equ            DSC_CS, 14
34.equ            DSC_DS, 16
35.equ            DSC_SS, 18
36.equ            DSC_OTHERSEG, 20
37
38.equ            PROTECT_MODE_CS, 0x08
39.equ            PROTECT_MODE_DS, 0x20
40.equ            TSS_SEGMENT,     0x40
41
42    .text
43
44ASM_PFX(gcSmiHandlerTemplate):
45
46_SmiEntryPoint:
47    .byte 0xbb                          # mov bx, imm16
48    .word _GdtDesc - _SmiEntryPoint + 0x8000
49    .byte 0x2e,0xa1                     # mov ax, cs:[offset16]
50    .word DSC_OFFSET + DSC_GDTSIZ
51    decl    %eax
52    movl    %eax, %cs:(%edi)            # mov cs:[bx], ax
53    .byte 0x66,0x2e,0xa1                # mov eax, cs:[offset16]
54    .word   DSC_OFFSET + DSC_GDTPTR
55    movw    %ax, %cs:2(%edi)
56    movw    %ax, %bp                    # ebp = GDT base
57    .byte 0x66
58    lgdt    %cs:(%edi)
59# Patch ProtectedMode Segment
60    .byte   0xb8                        # mov ax, imm16
61    .word   PROTECT_MODE_CS             # set AX for segment directly
62    movl    %eax, %cs:-2(%edi)          # mov cs:[bx - 2], ax
63# Patch ProtectedMode entry
64    .byte 0x66, 0xbf                    # mov edi, SMBASE
65ASM_PFX(gSmbase): .space 4
66    .byte 0x67
67    lea     ((Start32bit - _SmiEntryPoint) + 0x8000)(%edi), %ax
68    movw     %ax, %cs:-6(%edi)
69    movl    %cr0, %ebx
70    .byte 0x66
71    andl    $0x9ffafff3, %ebx
72    .byte 0x66
73    orl     $0x23, %ebx
74    movl    %ebx, %cr0
75    .byte 0x66,0xea
76    .space  4
77    .space  2
78_GdtDesc:   .space 4
79            .space 2
80
81Start32bit:
82    movw    $PROTECT_MODE_DS, %ax
83    movl    %eax,%ds
84    movl    %eax,%es
85    movl    %eax,%fs
86    movl    %eax,%gs
87    movl    %eax,%ss
88    .byte   0xbc                          # mov esp, imm32
89ASM_PFX(gSmiStack): .space 4
90    movl    $ASM_PFX(gSmiHandlerIdtr), %eax
91    lidt    (%eax)
92    jmp     ProtFlatMode
93
94ProtFlatMode:
95    .byte   0xb8                           # mov eax, imm32
96ASM_PFX(gSmiCr3): .space 4
97    movl    %eax, %cr3
98#
99# Need to test for CR4 specific bit support
100#
101    movl    $1, %eax
102    cpuid                                  # use CPUID to determine if specific CR4 bits are supported
103    xorl    %eax, %eax                     # Clear EAX
104    testl   $BIT2, %edx                    # Check for DE capabilities
105    jz      L8
106    orl     $BIT3, %eax
107L8:
108    testl   $BIT6, %edx                    # Check for PAE capabilities
109    jz      L9
110    orl     $BIT5, %eax
111L9:
112    testl   $BIT7, %edx                    # Check for MCE capabilities
113    jz      L10
114    orl     $BIT6, %eax
115L10:
116    testl   $BIT24, %edx                   # Check for FXSR capabilities
117    jz      L11
118    orl     $BIT9, %eax
119L11:
120    testl   $BIT25, %edx                   # Check for SSE capabilities
121    jz      L12
122    orl     $BIT10, %eax
123L12:                                       # as cr4.PGE is not set here, refresh cr3
124    movl    %eax, %cr4                     # in PreModifyMtrrs() to flush TLB.
125    movl    %cr0, %ebx
126    orl     $0x080010000, %ebx             # enable paging + WP
127    movl    %ebx, %cr0
128    leal    DSC_OFFSET(%edi),%ebx
129    movw    DSC_DS(%ebx),%ax
130    movl    %eax, %ds
131    movw    DSC_OTHERSEG(%ebx),%ax
132    movl    %eax, %es
133    movl    %eax, %fs
134    movl    %eax, %gs
135    movw    DSC_SS(%ebx),%ax
136    movl    %eax, %ss
137
138    cmpb    $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
139    jz      L5
140
141# Load TSS
142    movb    $0x89, (TSS_SEGMENT + 5)(%ebp) # clear busy flag
143    movl    $TSS_SEGMENT, %eax
144    ltrw    %ax
145L5:
146
147#   jmp     _SmiHandler                 # instruction is not needed
148
149_SmiHandler:
150    movl    (%esp), %ebx
151
152    pushl   %ebx
153    movl    $ASM_PFX(CpuSmmDebugEntry), %eax
154    call    *%eax
155    popl    %ecx
156
157    pushl   %ebx
158    movl    $ASM_PFX(SmiRendezvous), %eax
159    call    *%eax
160    popl    %ecx
161
162    pushl   %ebx
163    movl    $ASM_PFX(CpuSmmDebugExit), %eax
164    call    *%eax
165    popl    %ecx
166
167    rsm
168
169ASM_PFX(gcSmiHandlerSize):    .word      . - _SmiEntryPoint
170