1 #------------------------------------------------------------------------------
3 # Copyright (c) 2009 - 2016, 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(mXdSupported)
28 ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
30 .equ MSR_IA32_MISC_ENABLE, 0x1A0
31 .equ MSR_EFER, 0xc0000080
32 .equ MSR_EFER_XD, 0x800
35 # Constants relating to PROCESSOR_SMM_DESCRIPTOR
37 .equ DSC_OFFSET, 0xfb00
45 # Constants relating to CPU State Save Area
50 .equ PROTECT_MODE_CS, 0x08
51 .equ PROTECT_MODE_DS, 0x20
52 .equ LONG_MODE_CS, 0x38
53 .equ TSS_SEGMENT, 0x40
58 ASM_PFX(gcSmiHandlerTemplate):
62 # The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
63 # bit addressing mode. And that coincidence has been used in the following
64 # "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
65 # base address register, it is actually BX that is referenced.
67 .byte 0xbb # mov bx, imm16
68 .word _GdtDesc - _SmiEntryPoint + 0x8000
72 .byte 0x2e,0xa1 # mov ax, cs:[offset16]
73 .word DSC_OFFSET + DSC_GDTSIZ
76 movl %eax, (%rdi) # mov cs:[bx], ax
77 .byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
78 .word DSC_OFFSET + DSC_GDTPTR
84 # Patch ProtectedMode Segment
91 # Patch ProtectedMode entry
93 .byte 0x66, 0xbf # mov edi, SMBASE
94 ASM_PFX(gSmbase): .space 4
95 lea ((ProtectedMode - _SmiEntryPoint) + 0x8000)(%edi), %ax
99 # Switch into ProtectedMode
103 andl $0x9ffafff3, %ebx
105 orl $0x00000023, %ebx
114 movw $PROTECT_MODE_DS, %ax
120 .byte 0xbc # mov esp, imm32
121 ASM_PFX(gSmiStack): .space 4
126 ASM_PFX(gSmiCr3): .space 4
128 movl $0x668,%eax # as cr4.PGE is not set here, refresh cr3
129 movq %rax, %cr4 # in PreModifyMtrrs() to flush TLB.
131 subl $8, %esp # reserve room in stack
133 movl 2(%rsp), %eax # eax = GDT base
136 movb %dl, (TSS_SEGMENT + 5)(%rax) # clear busy flag
137 movl $TSS_SEGMENT, %eax
140 # enable NXE if supported
141 .byte 0xb0 # mov al, imm8
142 ASM_PFX(mXdSupported): .byte 1
146 # Check XD disable bit
148 movl $MSR_IA32_MISC_ENABLE, %ecx
151 pushq %rdx # save MSR_IA32_MISC_ENABLE[63-32]
152 testl $BIT2, %edx # MSR_IA32_MISC_ENABLE[34]
154 andw $0x0FFFB, %dx # clear XD Disable bit if it is set
159 orw $MSR_EFER_XD,%ax # enable NXE
169 pushq $LONG_MODE_CS # push cs hardcore here
170 call Base # push return address for retf later
172 addl $(LongMode - Base), (%rsp) # offset for far retf, seg is the 1st arg
176 orb $1,%ah # enable LME
179 orl $0x080010023, %ebx # enable paging + WP + NE + MP + PE
182 LongMode: # long mode (64-bit code) starts here
183 movabsq $ASM_PFX(gSmiHandlerIdtr), %rax
185 lea (DSC_OFFSET)(%rdi), %ebx
186 movw DSC_DS(%rbx), %ax
188 movw DSC_OTHERSEG(%rbx), %ax
192 movw DSC_SS(%rbx), %ax
194 # jmp _SmiHandler ; instruction is not needed
201 .byte 0x48 # FXSAVE64
207 movabsq $ASM_PFX(CpuSmmDebugEntry), %rax
211 movabsq $ASM_PFX(SmiRendezvous), %rax
215 movabsq $ASM_PFX(CpuSmmDebugExit), %rax
221 # Restore FP registers
223 .byte 0x48 # FXRSTOR64
228 movabsq $ASM_PFX(mXdSupported), %rax
232 popq %rdx # get saved MSR_IA32_MISC_ENABLE[63-32]
235 movl $MSR_IA32_MISC_ENABLE, %ecx
237 orw $BIT2, %dx # set XD Disable bit if it was set before entering into SMM
243 ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint