1 #------------------------------------------------------------------------------
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.
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.
18 # Code template of the SMI handler for a particular processor
20 #------------------------------------------------------------------------------
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)
31 # Constants relating to PROCESSOR_SMM_DESCRIPTOR
33 .equ DSC_OFFSET, 0xfb00
41 # Constants relating to CPU State Save Area
46 .equ PROTECT_MODE_CS, 0x08
47 .equ PROTECT_MODE_DS, 0x20
48 .equ LONG_MODE_CS, 0x38
49 .equ TSS_SEGMENT, 0x40
54 ASM_PFX(gcSmiHandlerTemplate):
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.
63 .byte 0xbb # mov bx, imm16
64 .word _GdtDesc - _SmiEntryPoint + 0x8000
68 .byte 0x2e,0xa1 # mov ax, cs:[offset16]
69 .word DSC_OFFSET + DSC_GDTSIZ
72 movl %eax, (%rdi) # mov cs:[bx], ax
73 .byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
74 .word DSC_OFFSET + DSC_GDTPTR
80 # Patch ProtectedMode Segment
87 # Patch ProtectedMode entry
89 .byte 0x66, 0xbf # mov edi, SMBASE
90 ASM_PFX(gSmbase): .space 4
91 lea ((ProtectedMode - _SmiEntryPoint) + 0x8000)(%edi), %ax
95 # Switch into ProtectedMode
99 andl $0x9ffafff3, %ebx
101 orl $0x00000023, %ebx
110 movw $PROTECT_MODE_DS, %ax
116 .byte 0xbc # mov esp, imm32
117 ASM_PFX(gSmiStack): .space 4
122 ASM_PFX(gSmiCr3): .space 4
124 movl $0x668,%eax # as cr4.PGE is not set here, refresh cr3
125 movq %rax, %cr4 # in PreModifyMtrrs() to flush TLB.
127 subl $8, %esp # reserve room in stack
129 movl 2(%rsp), %eax # eax = GDT base
133 movb %dl, (TSS_SEGMENT + 2)(%rax)
134 movb %dh, (TSS_SEGMENT + 3)(%rax)
135 .byte 0xc1, 0xea, 0x10 # shr edx, 16
136 movb %dl, (TSS_SEGMENT + 4)(%rax)
137 movb %dh, (TSS_SEGMENT + 7)(%rax)
140 movb %dl, (TSS_SEGMENT + 5)(%rax) # clear busy flag
141 movl $TSS_SEGMENT, %eax
147 pushq $LONG_MODE_CS # push cs hardcore here
148 call Base # push return address for retf later
150 addl $(LongMode - Base), (%rsp) # offset for far retf, seg is the 1st arg
151 movl $0xc0000080, %ecx
159 LongMode: # long mode (64-bit code) starts here
160 movabsq $ASM_PFX(gSmiHandlerIdtr), %rax
162 lea (DSC_OFFSET)(%rdi), %ebx
163 movw DSC_DS(%rbx), %ax
165 movw DSC_OTHERSEG(%rbx), %ax
169 movw DSC_SS(%rbx), %ax
171 # jmp _SmiHandler ; instruction is not needed
174 movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
178 .byte 0x48, 0x8b, 0x0d # mov rcx, [rip + disp32]
179 .long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
180 .byte 0x48, 0x8b, 0x15 # mov rdx, [rip + disp32]
181 .long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
186 movabsq $ASM_PFX(SmiRendezvous), %rax
191 .byte 0x48 # FXSAVE64
199 # Restore FP registers
201 .byte 0x48 # FXRSTOR64
204 movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
210 .byte 0x48, 0x89, 0x15 # mov [rip + disp32], rdx
211 .long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
212 .byte 0x48, 0x89, 0x0d # mov [rip + disp32], rcx
213 .long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
217 ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint