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