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
210 lines
6.1 KiB
ArmAsm
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
|