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

438 lines
11 KiB
NASM

;; @file
; This is the code that supports IA32 CPU architectural protocol
;
;******************************************************************************
;* 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.
;*
;******************************************************************************
page ,132
title CPU ARCHITECTURAL PEI ASSEMBLY HOOKS
;------------------------------------------------------------------------------
;
; Copyright (c) 1999 - 2011, Intel Corporation. All rights reserved.<BR>
; This software and associated documentation (if any) is furnished
; under a license and may only be used or copied in accordance
; with the terms of the license. Except as permitted by such
; license, no part of this software or documentation may be
; reproduced, stored in a retrieval system, or transmitted in any
; form or by any means without the express written consent of
; Intel Corporation.
;
; Module Name:
;
; CpuAsm.asm
;
; Abstract:
;
; Assembly code that supports IA32 CPU architectural Ppi
;
;------------------------------------------------------------------------------
.686p
.model flat
.data
ExternalVectorTablePtr DD ? ; Table of call backs
CommonInterruptEntry DD CommonEntry ; Address of CommonEntry
Idtr DW ? ; FWORD for IDT register
Idtr1 DD ? ; MUST BE IMMEDIATELY AFTER Idtr
EXTRN _mErrorCodeFlag:DWORD ; Error code flags for exceptions
.stack
.code
.MMX
.XMM
UINT8 TYPEDEF BYTE
UINT16 TYPEDEF WORD
UINT32 TYPEDEF DWORD
UINT64 TYPEDEF QWORD
UINTN TYPEDEF UINT32
;---------------------------------------;
; _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
;-----------------------------------------------------------------------------;
_InitializeIdt proc near public
push ebp ; C prolog
mov ebp, esp
push edi
mov eax, [ebp+8] ; Get ExternalVectorTable Address
mov ExternalVectorTablePtr, eax
mov ax, [ebp+10h] ; Get IDT Table limit
dec ax
mov Idtr, ax
mov eax, [ebp+0ch] ; Get Start of IDT
mov Idtr1, eax
mov edi, OFFSET Idtr ; Load IDT register
lidt FWORD PTR es:[edi]
pop edi
pop ebp
ret
_InitializeIdt endp
;----------------------------------------------------------------------------;
;
; 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:
push eax
;mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
DB 0b8h
VectorNumber:
DD 00h
jmp dword ptr [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
;
cmp eax, 32 ; Intel reserved vector for exceptions?
jae NoErrorCode
bt cs:_mErrorCodeFlag, eax
jc @F
NoErrorCode:
;
; Push a dummy error code on the stack
; to maintain coherent stack map
;
push [esp]
mov dword ptr [esp + 4], 0
@@:
push ebp
mov ebp, esp
;
; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
; is 16-byte aligned
;
and esp, 0fffffff0h
sub esp, 12
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
push dword ptr [ebp + 4] ; EAX
push ecx
push edx
push ebx
lea ecx, [ebp + 24]
push ecx ; ESP
push dword ptr [ebp] ; EBP
push esi
push edi
mov [ebp + 4], eax ; save vector number
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
mov eax, ss
push eax
movzx eax, word ptr [ebp + 16]
push eax
mov eax, ds
push eax
mov eax, es
push eax
mov eax, fs
push eax
mov eax, gs
push eax
;; UINT32 Eip;
push dword ptr [ebp + 12]
;; UINT32 Gdtr[2], Idtr[2];
sub esp, 8
sidt fword ptr [esp]
sub esp, 8
sgdt fword ptr [esp]
;; UINT32 Ldtr, Tr;
xor eax, eax
str ax
push eax
sldt ax
push eax
;; UINT32 EFlags;
push dword ptr [ebp + 20]
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
mov eax, cr4
or eax, 208h
mov cr4, eax
push eax
mov eax, cr3
push eax
mov eax, cr2
push eax
xor eax, eax
push eax
mov eax, cr0
push eax
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
mov eax, dr7
push eax
mov eax, dr6
push eax
mov eax, dr3
push eax
mov eax, dr2
push eax
mov eax, dr1
push eax
mov eax, dr0
push eax
;; FX_SAVE_STATE_IA32 FxSaveState;
sub esp, 512
mov edi, esp
db 0fh, 0aeh, 00000111y ;fxsave [edi]
;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
cld
;; UINT32 ExceptionData;
push dword ptr [ebp + 8]
;; call into exception handler
mov ebx, [ebp + 4]
mov eax, ExternalVectorTablePtr
mov eax, [eax + ebx * 4]
or eax, eax ; NULL?
je nonNullValue;
;; Prepare parameter and call
mov edx, esp
push edx
push ebx
call eax
add esp, 8
nonNullValue:
cli
;; UINT32 ExceptionData;
add esp, 4
;; FX_SAVE_STATE_IA32 FxSaveState;
mov esi, esp
db 0fh, 0aeh, 00001110y ; fxrstor [esi]
add esp, 512
;; 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
add esp, 4 * 6
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
pop eax
mov cr0, eax
add esp, 4 ; not for Cr1
pop eax
mov cr2, eax
pop eax
mov cr3, eax
pop eax
mov cr4, eax
;; UINT32 EFlags;
pop dword ptr [ebp + 20]
;; UINT32 Ldtr, Tr;
;; UINT32 Gdtr[2], Idtr[2];
;; Best not let anyone mess with these particular registers...
add esp, 24
;; UINT32 Eip;
pop dword ptr [ebp + 12]
;; 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.
;;
pop gs
pop fs
pop es
pop ds
pop dword ptr [ebp + 16]
pop ss
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
pop edi
pop esi
add esp, 4 ; not for ebp
add esp, 4 ; not for esp
pop ebx
pop edx
pop ecx
pop eax
mov esp, ebp
pop ebp
add esp, 8
iretd
;---------------------------------------;
; _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
;-----------------------------------------------------------------------------;
_GetTemplateAddressMap proc near public
push ebp ; C prolog
mov ebp, esp
pushad
mov ebx, dword ptr [ebp+08h]
mov dword ptr [ebx], TemplateStart
mov dword ptr [ebx+4h], TemplateEnd - TemplateStart
; if code in Template is updated, the value fills into the 3rd parameter
; also needs update
mov dword ptr [ebx+8h], VectorNumber - TemplateStart
popad
pop ebp
ret
_GetTemplateAddressMap endp
END