alder_lake_bios/Intel/AlderLake/AlderLakeChipsetPkg/CpuArchPei/IA32/CpuAsm.S

395 lines
9.3 KiB
ArmAsm

#******************************************************************************
#* Copyright (c) 2015, Insyde Software Corporation. All Rights Reserved.
#*
#* You may not reproduce, distribute, publish, display, perform, modify, adapt,
#* transmit, broadcast, present, recite, release, license or otherwise exploit
#* any part of this publication in any form, by any means, without the prior
#* written permission of Insyde Software Corporation.
#*
#******************************************************************************
.data
ExternalVectorTablePtr: .space 4
CommonInterruptEntry: .long CommonEntry
Idtr: .space 2
Idtr1: .space 4
.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
movl 0xc(%ebp),%eax # Get Start of IDT
movl %eax, Idtr1
movl $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)
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 0x10(%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
movl %dr6, %eax
pushl %eax
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;
## Skip restoration of DRx registers to support in-circuit emualators
## or debuggers set breakpoint in interrupt/exception context
addl $24, %esp
## 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