]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.S
Eliminate EFI_IMAGE_MACHINE_TYPE_SUPPORTED.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiEntry.S
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
22 ASM_GLOBAL ASM_PFX(gcSmiHandlerTemplate)
23 ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
24 ASM_GLOBAL ASM_PFX(gSmiCr3)
25 ASM_GLOBAL ASM_PFX(gSmiStack)
26 ASM_GLOBAL ASM_PFX(gSmbase)
27 ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
28 ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
29
30 #
31 # Constants relating to PROCESSOR_SMM_DESCRIPTOR
32 #
33 .equ DSC_OFFSET, 0xfb00
34 .equ DSC_GDTPTR, 0x30
35 .equ DSC_GDTSIZ, 0x38
36 .equ DSC_CS, 14
37 .equ DSC_DS, 16
38 .equ DSC_SS, 18
39 .equ DSC_OTHERSEG, 20
40 #
41 # Constants relating to CPU State Save Area
42 #
43 .equ SSM_DR6, 0xffd0
44 .equ SSM_DR7, 0xffc8
45
46 .equ PROTECT_MODE_CS, 0x08
47 .equ PROTECT_MODE_DS, 0x20
48 .equ LONG_MODE_CS, 0x38
49 .equ TSS_SEGMENT, 0x40
50 .equ GDT_SIZE, 0x50
51
52 .text
53
54 ASM_PFX(gcSmiHandlerTemplate):
55
56 _SmiEntryPoint:
57 #
58 # The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
59 # bit addressing mode. And that coincidence has been used in the following
60 # "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
61 # base address register, it is actually BX that is referenced.
62 #
63 .byte 0xbb # mov bx, imm16
64 .word _GdtDesc - _SmiEntryPoint + 0x8000
65 #
66 # fix GDT descriptor
67 #
68 .byte 0x2e,0xa1 # mov ax, cs:[offset16]
69 .word DSC_OFFSET + DSC_GDTSIZ
70 .byte 0x48 # dec ax
71 .byte 0x2e
72 movl %eax, (%rdi) # mov cs:[bx], ax
73 .byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
74 .word DSC_OFFSET + DSC_GDTPTR
75 .byte 0x2e
76 movw %ax, 2(%rdi)
77 .byte 0x66,0x2e
78 lgdt (%rdi)
79 #
80 # Patch ProtectedMode Segment
81 #
82 .byte 0xb8
83 .word PROTECT_MODE_CS
84 .byte 0x2e
85 movl %eax, -2(%rdi)
86 #
87 # Patch ProtectedMode entry
88 #
89 .byte 0x66, 0xbf # mov edi, SMBASE
90 ASM_PFX(gSmbase): .space 4
91 lea ((ProtectedMode - _SmiEntryPoint) + 0x8000)(%edi), %ax
92 .byte 0x2e
93 movw %ax, -6(%rdi)
94 #
95 # Switch into ProtectedMode
96 #
97 movq %cr0, %rbx
98 .byte 0x66
99 andl $0x9ffafff3, %ebx
100 .byte 0x66
101 orl $0x00000023, %ebx
102
103 movq %rbx, %cr0
104 .byte 0x66, 0xea
105 .space 6
106
107 _GdtDesc: .space 6
108
109 ProtectedMode:
110 movw $PROTECT_MODE_DS, %ax
111 movl %eax, %ds
112 movl %eax, %es
113 movl %eax, %fs
114 movl %eax, %gs
115 movl %eax, %ss
116 .byte 0xbc # mov esp, imm32
117 ASM_PFX(gSmiStack): .space 4
118 jmp ProtFlatMode
119
120 ProtFlatMode:
121 .byte 0xb8
122 ASM_PFX(gSmiCr3): .space 4
123 movq %rax, %cr3
124 movl $0x668,%eax # as cr4.PGE is not set here, refresh cr3
125 movq %rax, %cr4 # in PreModifyMtrrs() to flush TLB.
126 # Load TSS
127 subl $8, %esp # reserve room in stack
128 sgdt (%rsp)
129 movl 2(%rsp), %eax # eax = GDT base
130 addl $8, %esp
131 movb $0x89, %dl
132 movb %dl, (TSS_SEGMENT + 5)(%rax) # clear busy flag
133 movl $TSS_SEGMENT, %eax
134 ltr %ax
135
136 #
137 # Switch to LongMode
138 #
139 pushq $LONG_MODE_CS # push cs hardcore here
140 call Base # push return address for retf later
141 Base:
142 addl $(LongMode - Base), (%rsp) # offset for far retf, seg is the 1st arg
143 movl $0xc0000080, %ecx
144 rdmsr
145 orb $1,%ah
146 wrmsr
147 movq %cr0, %rbx
148 btsl $31, %ebx
149 movq %rbx, %cr0
150 retf
151 LongMode: # long mode (64-bit code) starts here
152 movabsq $ASM_PFX(gSmiHandlerIdtr), %rax
153 lidt (%rax)
154 lea (DSC_OFFSET)(%rdi), %ebx
155 movw DSC_DS(%rbx), %ax
156 movl %eax,%ds
157 movw DSC_OTHERSEG(%rbx), %ax
158 movl %eax,%es
159 movl %eax,%fs
160 movl %eax,%gs
161 movw DSC_SS(%rbx), %ax
162 movl %eax,%ss
163 # jmp _SmiHandler ; instruction is not needed
164
165 _SmiHandler:
166 movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
167 cmpb $0, (%rax)
168 jz L1
169
170 .byte 0x48, 0x8b, 0x0d # mov rcx, [rip + disp32]
171 .long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
172 .byte 0x48, 0x8b, 0x15 # mov rdx, [rip + disp32]
173 .long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
174 movq %rcx, %dr6
175 movq %rdx, %dr7
176 L1:
177
178 movabsq $ASM_PFX(SmiRendezvous), %rax
179 movq (%rsp), %rcx
180 # Save FP registers
181
182 subq $0x208, %rsp
183 .byte 0x48 # FXSAVE64
184 fxsave (%rsp)
185
186 addq $-0x20, %rsp
187 call *%rax
188 addq $0x20, %rsp
189
190 #
191 # Restore FP registers
192 #
193 .byte 0x48 # FXRSTOR64
194 fxrstor (%rsp)
195
196 movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
197 cmpb $0, (%rax)
198 jz L2
199
200 movq %dr7, %rdx
201 movq %dr6, %rcx
202 .byte 0x48, 0x89, 0x15 # mov [rip + disp32], rdx
203 .long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
204 .byte 0x48, 0x89, 0x0d # mov [rip + disp32], rcx
205 .long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
206 L2:
207 rsm
208
209 ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint