Files
system76-edk2/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.S
Yao, Jiewen fe5f194943 Eliminate EFI_IMAGE_MACHINE_TYPE_SUPPORTED.
Move Gdt initialization from InitializeMpServiceData() to CPU Arch specific function.
We create SmmFuncsArch.c for hold CPU specific function, so that
EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) can be removed.

For IA32 version, we always allocate new page for GDT entry, for easy maintenance.
For X64 version, we fixed TssBase in GDT entry to make sure TSS data is correct.
Remove TSS fixup for GDT in ASM file.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: "Yao, Jiewen" <jiewen.yao@intel.com>
Reviewed-by: "Fan, Jeff" <jeff.fan@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18937 6f19259b-4bc3-4df7-8a09-765794883524
2015-11-25 04:23:01 +00:00

210 lines
6.1 KiB
ArmAsm

#------------------------------------------------------------------------------
#
# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
# Module Name:
#
# SmiEntry.S
#
# Abstract:
#
# Code template of the SMI handler for a particular processor
#
#------------------------------------------------------------------------------
ASM_GLOBAL ASM_PFX(gcSmiHandlerTemplate)
ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
ASM_GLOBAL ASM_PFX(gSmiCr3)
ASM_GLOBAL ASM_PFX(gSmiStack)
ASM_GLOBAL ASM_PFX(gSmbase)
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
#
# Constants relating to PROCESSOR_SMM_DESCRIPTOR
#
.equ DSC_OFFSET, 0xfb00
.equ DSC_GDTPTR, 0x30
.equ DSC_GDTSIZ, 0x38
.equ DSC_CS, 14
.equ DSC_DS, 16
.equ DSC_SS, 18
.equ DSC_OTHERSEG, 20
#
# Constants relating to CPU State Save Area
#
.equ SSM_DR6, 0xffd0
.equ SSM_DR7, 0xffc8
.equ PROTECT_MODE_CS, 0x08
.equ PROTECT_MODE_DS, 0x20
.equ LONG_MODE_CS, 0x38
.equ TSS_SEGMENT, 0x40
.equ GDT_SIZE, 0x50
.text
ASM_PFX(gcSmiHandlerTemplate):
_SmiEntryPoint:
#
# The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
# bit addressing mode. And that coincidence has been used in the following
# "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
# base address register, it is actually BX that is referenced.
#
.byte 0xbb # mov bx, imm16
.word _GdtDesc - _SmiEntryPoint + 0x8000
#
# fix GDT descriptor
#
.byte 0x2e,0xa1 # mov ax, cs:[offset16]
.word DSC_OFFSET + DSC_GDTSIZ
.byte 0x48 # dec ax
.byte 0x2e
movl %eax, (%rdi) # mov cs:[bx], ax
.byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
.word DSC_OFFSET + DSC_GDTPTR
.byte 0x2e
movw %ax, 2(%rdi)
.byte 0x66,0x2e
lgdt (%rdi)
#
# Patch ProtectedMode Segment
#
.byte 0xb8
.word PROTECT_MODE_CS
.byte 0x2e
movl %eax, -2(%rdi)
#
# Patch ProtectedMode entry
#
.byte 0x66, 0xbf # mov edi, SMBASE
ASM_PFX(gSmbase): .space 4
lea ((ProtectedMode - _SmiEntryPoint) + 0x8000)(%edi), %ax
.byte 0x2e
movw %ax, -6(%rdi)
#
# Switch into ProtectedMode
#
movq %cr0, %rbx
.byte 0x66
andl $0x9ffafff3, %ebx
.byte 0x66
orl $0x00000023, %ebx
movq %rbx, %cr0
.byte 0x66, 0xea
.space 6
_GdtDesc: .space 6
ProtectedMode:
movw $PROTECT_MODE_DS, %ax
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %eax, %ss
.byte 0xbc # mov esp, imm32
ASM_PFX(gSmiStack): .space 4
jmp ProtFlatMode
ProtFlatMode:
.byte 0xb8
ASM_PFX(gSmiCr3): .space 4
movq %rax, %cr3
movl $0x668,%eax # as cr4.PGE is not set here, refresh cr3
movq %rax, %cr4 # in PreModifyMtrrs() to flush TLB.
# Load TSS
subl $8, %esp # reserve room in stack
sgdt (%rsp)
movl 2(%rsp), %eax # eax = GDT base
addl $8, %esp
movb $0x89, %dl
movb %dl, (TSS_SEGMENT + 5)(%rax) # clear busy flag
movl $TSS_SEGMENT, %eax
ltr %ax
#
# Switch to LongMode
#
pushq $LONG_MODE_CS # push cs hardcore here
call Base # push return address for retf later
Base:
addl $(LongMode - Base), (%rsp) # offset for far retf, seg is the 1st arg
movl $0xc0000080, %ecx
rdmsr
orb $1,%ah
wrmsr
movq %cr0, %rbx
btsl $31, %ebx
movq %rbx, %cr0
retf
LongMode: # long mode (64-bit code) starts here
movabsq $ASM_PFX(gSmiHandlerIdtr), %rax
lidt (%rax)
lea (DSC_OFFSET)(%rdi), %ebx
movw DSC_DS(%rbx), %ax
movl %eax,%ds
movw DSC_OTHERSEG(%rbx), %ax
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
movw DSC_SS(%rbx), %ax
movl %eax,%ss
# jmp _SmiHandler ; instruction is not needed
_SmiHandler:
movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
cmpb $0, (%rax)
jz L1
.byte 0x48, 0x8b, 0x0d # mov rcx, [rip + disp32]
.long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
.byte 0x48, 0x8b, 0x15 # mov rdx, [rip + disp32]
.long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
movq %rcx, %dr6
movq %rdx, %dr7
L1:
movabsq $ASM_PFX(SmiRendezvous), %rax
movq (%rsp), %rcx
# Save FP registers
subq $0x208, %rsp
.byte 0x48 # FXSAVE64
fxsave (%rsp)
addq $-0x20, %rsp
call *%rax
addq $0x20, %rsp
#
# Restore FP registers
#
.byte 0x48 # FXRSTOR64
fxrstor (%rsp)
movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
cmpb $0, (%rax)
jz L2
movq %dr7, %rdx
movq %dr6, %rcx
.byte 0x48, 0x89, 0x15 # mov [rip + disp32], rdx
.long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
.byte 0x48, 0x89, 0x0d # mov [rip + disp32], rcx
.long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
L2:
rsm
ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint