summaryrefslogtreecommitdiff
path: root/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s
diff options
context:
space:
mode:
Diffstat (limited to 'BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s')
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s761
1 files changed, 761 insertions, 0 deletions
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s
new file mode 100644
index 0000000000..9b62ca1688
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s
@@ -0,0 +1,761 @@
+## @file
+# Assembly code that supports IA32 CPU architectural protocol.
+#
+# Copyright (c) 1999 - 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
+#
+##
+
+.data
+
+ExternalVectorTablePtr: .space 4
+CommonInterruptEntry: .long CommonEntry
+Idtr: .space 2
+Idtr1: .space 4
+
+##include Htequ.inc
+
+.equ VacantFlag , 0x00
+.equ NotVacantFlag , 0xff
+.equ StartupApSignal , 0x6E750000
+.equ MonitorFilterSize, 0x10
+.equ ApCounterInit , 0
+.equ ApInHltLoop , 1
+.equ ApInMwaitLoop , 2
+.equ ApInRunLoop , 3
+
+.equ LockLocation , 0x1000 - 0x0400
+.equ StackStart , LockLocation + 0x4
+.equ StackSize , LockLocation + 0x8
+.equ RendezvousProc , LockLocation + 0x0C
+.equ GdtrProfile , LockLocation + 0x10
+.equ IdtrProfile , LockLocation + 0x16
+.equ BufferStart , LockLocation + 0x1C
+.equ Cr3Location , LockLocation + 0x20
+.equ InitFlag , LockLocation + 0x24
+.equ WakeUpApManner , LockLocation + 0x28
+.equ BistBuffer , LockLocation + 0x2C
+
+.macro PAUSE32
+ .byte 0xF3
+ .byte 0x90
+.endm
+
+.text
+
+#---------------------------------------#
+# _InitializeIdt #
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# InitializeIdt (
+# IN EFI_CPU_INTERRUPT_HANDLER TableStart,
+# IN UINTN *IdtTablePtr,
+# IN UINT16 IdtLimit
+# )
+#
+# Routine Description:
+#
+# Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
+# Table is initialized to intxx where xx is from 00 to number of entries or
+# 100h, whichever is smaller. After table has been initialized the LIDT
+# instruction is invoked.
+#
+# TableStart is the pointer to the callback table and is not used by
+# InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
+# does the context save and calls the callback entry, if non-NULL.
+# It is the responsibility of the callback routine to do hardware EOIs.
+#
+# Arguments:
+#
+# TableStart - Pointer to interrupt callback table
+#
+# IdtTablePtr - Pointer to IDT table
+#
+# IdtLimit - IDT Table limit = number of interrupt entries * 8
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+# [ebp][8] = TableStart
+# [ebp][0c] = *IdtTablePtr
+# [ebp][10] = IdtLimit
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+
+ASM_GLOBAL ASM_PFX(InitializeIdt)
+ASM_PFX(InitializeIdt):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushl %edi
+
+ movl 8(%ebp),%eax # Get ExternalVectorTable Address
+ movl %eax, ExternalVectorTablePtr
+
+ movw 0x10(%ebp),%ax # Get IDT Table limit
+ decw %ax
+ movw %ax, Idtr # Store %ax to Idtr
+
+ movl 0xc(%ebp),%eax # Get Start of IDT
+ movl %eax, Idtr1
+
+ movl $Idtr, %edi # Addr of Idtr -> %edi
+ lidt %es:(%edi)
+
+ popl %edi
+ popl %ebp
+ ret
+
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# None
+#
+# Routine Description:
+#
+# These routines handle the individual interrupts. These routines always
+# gain control on any interrupt or exception. They save EAX and place
+# the interrupt number in EAX. CommonEntry is then jumped to.
+# instruction is invoked.
+#
+# CommonEntry handles all interrupts,does the context save and calls the
+# callback entry, if non-NULL. It is the responsibility of the callback
+# routine to do hardware EOIs. Callbacks are entered into the table
+# located at TableStart. Entries are modified by the InstallInterruptHandler
+# and UninstallInterruptHandler protocols.
+#
+# Arguments to CommonEntry:
+#
+# EAX - Interrupt or exception number
+#
+# TableStart - Pointer to interrupt callback table
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+
+TemplateStart:
+ pushl %eax
+
+ #mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
+ .byte 0xb8
+VectorNumber:
+ .long 0x0
+
+ jmp *CommonInterruptEntry
+TemplateEnd:
+
+CommonEntry:
+
+#---------------------------------------#
+# _CommonEntry #
+#----------------------------------------------------------------------------#
+# The follow algorithm is used for the common interrupt routine.
+# Entry from each interrupt with a push eax and eax=interrupt number
+
+#
+# +---------------------+
+# + EFlags +
+# +---------------------+
+# + CS +
+# +---------------------+
+# + EIP +
+# +---------------------+
+# + Error Code +
+# +---------------------+
+# + EAX / Vector Number +
+# +---------------------+
+# + EBP +
+# +---------------------+ <-- EBP
+#
+
+ cli
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+ cmpl $32,%eax # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ btl %eax, %cs:ASM_PFX(mErrorCodeFlag)
+ jc L1
+
+NoErrorCode:
+ #
+ # Push a dummy error code on the stack
+ # to maintain coherent stack map
+ #
+ pushl (%esp) # Push the value %esp pointing to
+ movl $0, 4(%esp)
+L1:
+ pushl %ebp
+ movl %esp,%ebp
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0xfffffff0,%esp
+ subl $12,%esp
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax#
+ pushl 0x4(%ebp)
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ leal 24(%ebp),%ecx
+ pushl %ecx # ESP
+ pushl (%ebp)
+ pushl %esi
+ pushl %edi
+
+ movl %eax,4(%ebp) # save vector number
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss#
+ movl %ss,%eax
+ pushl %eax
+ movzwl 16(%ebp), %eax
+ pushl %eax
+ movl %ds,%eax
+ pushl %eax
+ movl %es,%eax
+ pushl %eax
+ movl %fs,%eax
+ pushl %eax
+ movl %gs,%eax
+ pushl %eax
+
+## UINT32 Eip#
+ pushl 12(%ebp)
+
+## UINT32 Gdtr[2], Idtr[2]#
+ subl $8,%esp
+ sidt (%esp)
+ subl $8,%esp
+ sgdt (%esp)
+
+## UINT32 Ldtr, Tr#
+ xorl %eax,%eax
+ strl %eax
+ pushl %eax
+ sldtl %eax
+ pushl %eax
+
+## UINT32 EFlags#
+ pushl 20(%ebp)
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4#
+ movl %cr4, %eax
+ orl $0x208,%eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax,%eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
+ movl %dr7, %eax
+ pushl %eax
+## clear Dr7 while executing debugger itself
+ xorl %eax, %eax
+ movl %eax, %dr7
+
+ movl %dr6, %eax
+ pushl %eax
+## insure all status bits in dr6 are clear...
+ xorl %eax, %eax
+ movl %eax, %dr6
+
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+## FX_SAVE_STATE_IA32 FxSaveState#
+ subl $512, %esp
+ movl %esp, %edi
+ .byte 0x0f, 0xae, 0x07
+
+## UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+## UINT32 ExceptionData#
+ pushl 8(%ebp)
+
+## call into exception handler
+ movl 4(%ebp), %ebx
+ movl ExternalVectorTablePtr, %eax
+ movl (%eax,%ebx,4), %eax
+ orl %eax, %eax # NULL?
+ je nonNullValue #
+
+## Prepare parameter and call
+ movl %esp, %edx
+ pushl %edx
+ pushl %ebx
+ call *%eax
+ addl $8, %esp
+
+nonNullValue:
+ cli
+
+## UINT32 ExceptionData#
+ addl $4,%esp
+
+## FX_SAVE_STATE_IA32 FxSaveState#
+ movl %esp, %esi
+ .byte 0x0f, 0xae, 0x0e
+ addl $512, %esp
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
+ popl %eax
+ movl %eax, %dr0
+ popl %eax
+ movl %eax, %dr1
+ popl %eax
+ movl %eax, %dr2
+ popl %eax
+ movl %eax, %dr3
+## skip restore of dr6. We cleared dr6 during the context save.
+ addl $4, %esp
+ popl %eax
+ movl %eax, %dr7
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4#
+ popl %eax
+ movl %eax, %cr0
+ addl $4,%esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+## UINT32 EFlags#
+ popl 20(%ebp)
+
+## UINT32 Ldtr, Tr#
+## UINT32 Gdtr[2], Idtr[2]#
+## Best not let anyone mess with these particular registers...
+ addl $24,%esp
+
+## UINT32 Eip#
+ pop 12(%ebp)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss#
+## NOTE - modified segment registers could hang the debugger... We
+## could attempt to insulate ourselves against this possibility,
+## but that poses risks as well.
+##
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl 16(%ebp)
+ popl %ss
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax#
+ popl %edi
+ popl %esi
+ addl $4, %esp # not for ebp
+ addl $4, %esp # not for esp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+
+ movl %ebp, %esp
+ popl %ebp
+ addl $8,%esp
+ iretl
+
+
+#---------------------------------------#
+# _GetTemplateAddressMap #
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# GetTemplateAddressMap (
+# INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+# )#
+#
+# Routine Description:
+#
+# Return address map of interrupt handler template so that C code can generate
+# interrupt handlers, and dynamically do address fix.
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
+ASM_PFX(GetTemplateAddressMap):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushal
+
+ movl 8(%ebp), %ebx
+ movl $TemplateStart, (%ebx)
+ movl $(TemplateEnd - TemplateStart), 4(%ebx)
+
+ # Note: if code in Template is updated, the value fills into the 3rd parameter
+ # also needs update
+ movl $(VectorNumber - TemplateStart), 8(%ebx)
+
+ popal
+ popl %ebp
+ ret
+
+
+
+#---------------------------------------#
+# _InitializeSelectors #
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# InitializeSelectors (
+# )
+#
+# Routine Description:
+#
+# Creates an new GDT in RAM. The problem is that our former selectors
+# were ROM based and the EFI OS Loader does not manipulate the machine state
+# to change them (as it would for a 16-bit PC/AT startup code that had to
+# go from Real Mode to flat mode).
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+
+.equ CODE_SELECTOR, 0x10
+.equ DATA_SELECTOR, 0x18
+
+ASM_GLOBAL ASM_PFX(InitializeSelectors)
+ASM_PFX(InitializeSelectors):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushal
+ movl $Gdtr, %edi
+
+ movw %cs,%ax # Get the selector data from our code image
+ .byte 0x66
+ movw %ax,%es
+ lgdt %es:(%edi)
+
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+ .long SelectorRld
+ .word CODE_SELECTOR
+SelectorRld:
+ movw $DATA_SELECTOR, %ax # Update the Base for the new selectors, too
+ .byte 0x66
+ movw %ax,%ds
+ .byte 0x66
+ movw %ax,%es
+ .byte 0x66
+ movw %ax,%fs
+ .byte 0x66
+ movw %ax,%gs
+ .byte 0x66
+ movw %ax,%ss
+
+ popal
+ popl %ebp
+ ret
+
+#------------------------------------------------------------------------------
+# VOID
+# CpuEnableInterrupt (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(CpuEnableInterrupt)
+ASM_PFX(CpuEnableInterrupt):
+ sti
+ ret
+#CpuEnableInterrupt ENDP
+
+
+#------------------------------------------------------------------------------
+# VOID
+# CpuDisableInterrupt (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(CpuDisableInterrupt)
+ASM_PFX(CpuDisableInterrupt):
+ cli
+ ret
+#CpuDisableInterrupt ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# CpuInitFloatPointUnit (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(CpuInitFloatPointUnit)
+ASM_PFX(CpuInitFloatPointUnit):
+ finit
+ ret
+#CpuInitFloatPointUnit ENDP
+
+#------------------------------------------------------------------------------
+# UINT16
+# GetCodeSegment (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(GetCodeSegment)
+ASM_PFX(GetCodeSegment):
+ movw %cs, %ax
+ ret
+#GetCodeSegment ENDP
+
+
+#------------------------------------------------------------------------------
+# VOID
+# EfiWbinvd (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(EfiWbinvd)
+ASM_PFX(EfiWbinvd):
+ wbinvd
+ ret
+#EfiWbinvd ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# EfiInvd (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(EfiInvd)
+ASM_PFX(EfiInvd):
+ invd
+ ret
+#EfiInvd ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# GetIdt (
+# IDT_INFORMATION *IdtInfo
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(GetIdt)
+ASM_PFX(GetIdt):
+ push %ebp # C prolog
+
+ movl %esp, %ebp
+ movl 8(%ebp), %eax
+ sidt (%eax)
+
+ popl %ebp
+ ret
+#GetIdt ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# C1eExceptionHandler (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(C1eExceptionHandler)
+ASM_PFX(C1eExceptionHandler):
+ pushl %ebp # C prolog
+ movl %esp, %ebp
+ pushfl
+ cli
+ pushal
+
+ # Verify if GPE was caused by C1e write.
+ # If not, pass control to real exception handler.
+ cmp $0, ASM_PFX(mWroteMsr)
+ je notourexception
+
+ # Fix the return address on stack to skip offending
+ # code which caused the exception.
+ movl 8(%ebp), %eax
+ addl $2, %eax
+ movl %eax, 8(%ebp)
+ jmp exit
+
+notourexception:
+ popal
+ popfl
+ popl %ebp
+
+ jmp ASM_PFX(mOriginalInt13)
+
+exit:
+
+ popal
+ popfl
+ popl %ebp
+ addl $4, %esp
+ iretl
+#C1eExceptionHandler ENDP
+
+
+ASM_GLOBAL ASM_PFX(GetCoreNumber)
+ASM_PFX(GetCoreNumber):
+
+ pushl %ebx
+
+ movl $4, %eax
+ movl $0, %ecx
+ cpuid
+
+ shrl $26, %eax
+ andl $0x3f, %eax
+ incb %al
+
+ popl %ebx
+
+ ret
+
+#GetCoreNumber ENDP
+
+#-----------------------------------------------------------------------------#
+# data
+#-----------------------------------------------------------------------------#
+
+ .p2align 4
+
+Gdtr: .word GDT_END - GDT_BASE - 1
+ .long GDT_BASE
+
+#-----------------------------------------------------------------------------#
+# global descriptor table (GDT)
+#-----------------------------------------------------------------------------#
+
+ .p2align 4
+
+GDT_BASE:
+# null descriptor
+# .equ NULL_SEL, $-GDT_BASE # Selector [0]
+ .word 0 # limit 15:0
+ .word 0 # base 15:0
+ .byte 0 # base 23:16
+ .byte 0 # type
+ .byte 0 # limit 19:16, flags
+ .byte 0 # base 31:24
+
+# linear data segment descriptor
+# .equ LINEAR_SEL, $-GDT_BASE # Selector [0x8]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# linear code segment descriptor
+# .equ LINEAR_CODE_SEL, $-GDT_BASE # Selector [0x10]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system data segment descriptor
+# .equ SYS_DATA_SEL, $-GDT_BASE # Selector [0x18]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system code segment descriptor
+# .equ SYS_CODE_SEL, $-GDT_BASE
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE3_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE4_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE5_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+GDT_END:
+