In this patch we incorporate code from Quark_EDKII_v1.1.0/IA32FamilyCpuBasePkg/CpuMpDxe that populates the following fields in ACPI_CPU_DATA for PiSmmCpuDxeSmm:
- ACPI_CPU_DATA.GdtrProfile - ACPI_CPU_DATA.IdtrProfile - ACPI_CPU_DATA.ApMachineCheckHandlerBase - ACPI_CPU_DATA.ApMachineCheckHandlerSize The patch performs the following steps: (1) In the entry point call stack of the driver, allocate an AcpiNVS block, and copy the BSP's GDT and IDT into it. (2) Additionally, tack on a small Machine Check Exception handler routine that we provide in assembly. Hook this handler into the copied IDT mentined in (1) as well. (3) In the EFI_SMM_CONFIGURATION_PROTOCOL installation callback, GDTR and IDTR fields of the MP_CPU_SAVED_DATA AcpiNVS object that embeds ACPI_CPU_DATA are pointed to the copied GDT and IDT mentioned in (1). (4) In the same callback, the latter two fields of the ACPI_CPU_DATA object are pointed to the MCE handler described in (2). The former two fields (which are doubly indirect pointers) are pointed to the MP_CPU_SAVED_DATA pointer fields described in (3). The PiSmmCpuDxeSmm driver acts upon the data as follows: (5) In the SmmReadyToLockEventNotify() function, during normal boot, PiSmmCpuDxeSmm loads these data from AcpiNVS memory, and stashes them all in SMRAM. (6) When the S3 resume PEIM transfers control to SmmRestoreCpu(), on the resume path, the GDT, IDT and MCE handler are restored from SMRAM to the AcpiNVS block allocated in (1). (7) IDTR and GDTR values saved in (3) and then stashed in (5) are written to the AP startup routine parameter / communication block. (See "mExchangeInfo" in PrepareAPStartupVector() in "OvmfPkg/QuarkPort/PiSmmCpuDxeSmm/CpuS3.c".) (8) The startup vector in "OvmfPkg/QuarkPort/PiSmmCpuDxeSmm/Ia32/MpFuncs.S" loads these values (identically for all APs) with the LGDT and LIDT instructions. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf | 3 + OvmfPkg/QuarkPort/CpuS3DataDxe/Cpu.h | 24 ++++ OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecificDef.h | 57 ++++++++++ OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.h | 74 +++++++++++++ OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecific.c | 48 ++++++++ OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.c | 115 ++++++++++++++++++++ OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c | 15 +++ OvmfPkg/QuarkPort/CpuS3DataDxe/{CpuS3DataDxe.inf => IA32/CpuAsm.S} | 77 ++++--------- OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.asm | 69 ++++++++++++ 9 files changed, 426 insertions(+), 56 deletions(-) diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf b/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf index f1f122b..5ceb03b 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf @@ -56,6 +56,9 @@ [Sources] Cpu.h [Sources.Ia32] + IA32/CpuAsm.asm + IA32/CpuAsm.S + IA32/ArchSpecificDef.h IA32/ArchSpecific.c [Packages] diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/Cpu.h b/OvmfPkg/QuarkPort/CpuS3DataDxe/Cpu.h index 62faa0b..904e646 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/Cpu.h +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/Cpu.h @@ -70,4 +70,28 @@ SaveCpuS3Data ( VOID *Context ); +/** + Label of start of AP machine check handler. + + This is just a label of start of AP machine check handler. + +**/ +VOID +EFIAPI +ApMachineCheckHandler ( + VOID + ); + +/** + Label of end of AP machine check handler. + + This is just a label of end of AP machine check handler. + +**/ +VOID +EFIAPI +ApMachineCheckHandlerEnd ( + VOID + ); + #endif diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecificDef.h b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecificDef.h new file mode 100644 index 0000000..2bed3d3 --- /dev/null +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecificDef.h @@ -0,0 +1,57 @@ +/** @file + +Copyright (C) 2015, Red Hat, Inc. +Copyright (c) 2013-2015 Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Module Name: + + ProcessorDef.h + +Abstract: + + Definition for IA32 processor + +**/ + +#ifndef _PROCESSOR_DEF_H_ +#define _PROCESSOR_DEF_H_ + +#pragma pack(1) + +typedef struct { + UINT16 OffsetLow; + UINT16 SegmentSelector; + UINT16 Attributes; + UINT16 OffsetHigh; +} INTERRUPT_GATE_DESCRIPTOR; + +#pragma pack() + +#endif diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.h b/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.h index beb30f4..bb4a0f8 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.h +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.h @@ -40,6 +40,7 @@ #include <Library/BaseLib.h> +#include "ArchSpecificDef.h" #include <AcpiCpuData.h> #include <Protocol/LegacyBios.h> @@ -51,6 +52,30 @@ #include <Library/MemoryAllocationLib.h> #include <Library/UefiBootServicesTableLib.h> +#define INTERRUPT_HANDLER_MACHINE_CHECK 0x12 + +#pragma pack(1) + +typedef struct { + UINT16 LimitLow; + UINT16 BaseLow; + UINT8 BaseMiddle; + UINT8 Attributes1; + UINT8 Attributes2; + UINT8 BaseHigh; +} SEGMENT_DESCRIPTOR; + +#pragma pack() + +typedef struct { + IA32_DESCRIPTOR GdtrProfile; + IA32_DESCRIPTOR IdtrProfile; +} MP_CPU_EXCHANGE_INFO; + +extern MP_CPU_EXCHANGE_INFO *mExchangeInfo; +extern EFI_PHYSICAL_ADDRESS mApMachineCheckHandlerBase; +extern UINT32 mApMachineCheckHandlerSize; + /** Allocates startup vector for APs. @@ -65,6 +90,38 @@ AllocateStartupVector ( ); /** + Creates a copy of GDT and IDT for all APs. + + This function creates a copy of GDT and IDT for all APs. + + @param Gdtr Base and limit of GDT for AP + @param Idtr Base and limit of IDT for AP + +**/ +VOID +PrepareGdtIdtForAP ( + OUT IA32_DESCRIPTOR *Gdtr, + OUT IA32_DESCRIPTOR *Idtr + ); + +/** + Allocate aligned ACPI NVS memory below 4G. + + This function allocates aligned ACPI NVS memory below 4G. + + @param Size Size of memory region to allocate + @param Alignment Alignment in bytes + + @return Base address of the allocated region + +**/ +VOID* +AllocateAlignedAcpiNvsMemory ( + IN UINTN Size, + IN UINTN Alignment + ); + +/** Prepares Startup Vector for APs. This function prepares Startup Vector for APs. @@ -76,6 +133,23 @@ PrepareAPStartupVector ( ); /** + Sets specified IDT entry with given function pointer. + + This function sets specified IDT entry with given function pointer. + + @param FunctionPointer Function pointer for IDT entry. + @param IdtEntry The IDT entry to update. + + @return The original IDT entry value. + +**/ +UINTN +SetIdtEntry ( + IN UINTN FunctionPointer, + OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry + ); + +/** Allocate EfiACPIMemoryNVS below 4G memory address. This function allocates EfiACPIMemoryNVS below 4G memory address. diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecific.c b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecific.c index 8bf991b..a0652c7 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecific.c +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/ArchSpecific.c @@ -38,6 +38,17 @@ #include "Cpu.h" #include "MpService.h" +// +// OVMF port note: in this driver we don't actually use this buffer for +// communicating between the BSP and the APs, we only allocate it as auxiliary +// storage between the entry point and the EFI_SMM_CONFIGURATION_PROTOCOL +// installation callback, for setting up various parameters of the AP startup +// vector that is to be used by PiSmmCpuDxeSmm. +// +STATIC +MP_CPU_EXCHANGE_INFO mExchangeInfoBuffer; +MP_CPU_EXCHANGE_INFO *mExchangeInfo = &mExchangeInfoBuffer; + /** Prepares Startup Vector for APs. @@ -54,4 +65,41 @@ PrepareAPStartupVector ( // The region contains AP startup code and exchange data between BSP and AP. // AllocateStartupVector (SIZE_4KB); + + // + // Get the start address of exchange data between BSP and AP. + // + ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO)); + + PrepareGdtIdtForAP ( + (IA32_DESCRIPTOR *) (UINTN) &mExchangeInfo->GdtrProfile, + (IA32_DESCRIPTOR *) (UINTN) &mExchangeInfo->IdtrProfile + ); +} + +/** + Sets specified IDT entry with given function pointer. + + This function sets specified IDT entry with given function pointer. + + @param FunctionPointer Function pointer for IDT entry. + @param IdtEntry The IDT entry to update. + + @return The original IDT entry value. + +**/ +UINTN +SetIdtEntry ( + IN UINTN FunctionPointer, + OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry +) +{ + UINTN OriginalEntry; + + OriginalEntry = ((UINT32) IdtEntry->OffsetHigh << 16) + IdtEntry->OffsetLow; + + IdtEntry->OffsetLow = (UINT16) FunctionPointer; + IdtEntry->OffsetHigh = (UINT16) (FunctionPointer >> 16); + + return OriginalEntry; } diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.c b/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.c index 6f06628..50838cc 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.c +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/MpCommon.c @@ -39,6 +39,8 @@ #include "Cpu.h" UINTN mStartupVectorSize; +EFI_PHYSICAL_ADDRESS mApMachineCheckHandlerBase; +UINT32 mApMachineCheckHandlerSize; /** Allocates startup vector for APs. @@ -145,6 +147,36 @@ ReAllocateMemoryForAP ( } /** + Allocate aligned ACPI NVS memory below 4G. + + This function allocates aligned ACPI NVS memory below 4G. + + @param Size Size of memory region to allocate + @param Alignment Alignment in bytes + + @return Base address of the allocated region + +**/ +VOID* +AllocateAlignedAcpiNvsMemory ( + IN UINTN Size, + IN UINTN Alignment + ) +{ + UINTN PointerValue; + VOID *Pointer; + + Pointer = AllocateAcpiNvsMemoryBelow4G (Size + Alignment - 1); + + PointerValue = (UINTN) Pointer; + PointerValue = (PointerValue + Alignment - 1) / Alignment * Alignment; + + Pointer = (VOID *) PointerValue; + + return Pointer; +} + +/** Allocate EfiACPIMemoryNVS below 4G memory address. This function allocates EfiACPIMemoryNVS below 4G memory address. @@ -181,3 +213,86 @@ AllocateAcpiNvsMemoryBelow4G ( return Buffer; } +/** + Creates a copy of GDT and IDT for all APs. + + This function creates a copy of GDT and IDT for all APs. + + @param Gdtr Base and limit of GDT for AP + @param Idtr Base and limit of IDT for AP + +**/ +VOID +PrepareGdtIdtForAP ( + OUT IA32_DESCRIPTOR *Gdtr, + OUT IA32_DESCRIPTOR *Idtr + ) +{ + SEGMENT_DESCRIPTOR *GdtForAP; + INTERRUPT_GATE_DESCRIPTOR *IdtForAP; + IA32_DESCRIPTOR GdtrForBSP; + IA32_DESCRIPTOR IdtrForBSP; + VOID *MachineCheckHandlerBuffer; + + // + // Get the BSP's data of GDT and IDT + // + AsmReadGdtr ((IA32_DESCRIPTOR *) &GdtrForBSP); + AsmReadIdtr ((IA32_DESCRIPTOR *) &IdtrForBSP); + + // + // Allocate ACPI NVS memory for GDT, IDT, and machine check handler. + // Combine allocation for ACPI NVS memory under 4G to save memory. + // + GdtForAP = AllocateAlignedAcpiNvsMemory ( + ((GdtrForBSP.Limit + 1) + + (IdtrForBSP.Limit + 1) + + (UINTN) ApMachineCheckHandlerEnd - + (UINTN) ApMachineCheckHandler), + 8 + ); + + // + // GDT base is 8-bype aligned, and its size is multiple of 8-bype, so IDT + // base here is also 8-bype aligned. + // + IdtForAP = (INTERRUPT_GATE_DESCRIPTOR *) + ((UINTN) GdtForAP + GdtrForBSP.Limit + 1); + MachineCheckHandlerBuffer = (VOID *) ((UINTN) GdtForAP + + (GdtrForBSP.Limit + 1) + + (IdtrForBSP.Limit + 1)); + // + // Make copy for APs' GDT & IDT + // + CopyMem (GdtForAP, (VOID *) GdtrForBSP.Base, GdtrForBSP.Limit + 1); + CopyMem (IdtForAP, (VOID *) IdtrForBSP.Base, IdtrForBSP.Limit + 1); + + // + // Copy code for AP's machine check handler to ACPI NVS memory, and register + // in IDT + // + CopyMem ( + MachineCheckHandlerBuffer, + (VOID *) (UINTN) ApMachineCheckHandler, + (UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler + ); + SetIdtEntry ((UINTN) MachineCheckHandlerBuffer, + &IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK]); + + // + // Set AP's profile for GDTR and IDTR + // + Gdtr->Base = (UINTN) GdtForAP; + Gdtr->Limit = GdtrForBSP.Limit; + + Idtr->Base = (UINTN) IdtForAP; + Idtr->Limit = IdtrForBSP.Limit; + + // + // Save the AP's machine check handler information + // + mApMachineCheckHandlerBase = + (EFI_PHYSICAL_ADDRESS) (UINTN) MachineCheckHandlerBuffer; + mApMachineCheckHandlerSize = + (UINT32) ((UINTN)ApMachineCheckHandlerEnd - (UINTN)ApMachineCheckHandler); +} diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c b/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c index 9ad98ff..f1f07b0 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c @@ -202,6 +202,21 @@ SaveCpuS3Data ( // mAcpiCpuData = &(MpCpuSavedData->AcpiCpuData); mAcpiCpuData->StartupVector = mStartupVector; + mAcpiCpuData->GdtrProfile = + (EFI_PHYSICAL_ADDRESS) (UINTN) &(MpCpuSavedData->GdtrProfile); + mAcpiCpuData->IdtrProfile = + (EFI_PHYSICAL_ADDRESS) (UINTN) &(MpCpuSavedData->IdtrProfile); + + mAcpiCpuData->ApMachineCheckHandlerBase = mApMachineCheckHandlerBase; + mAcpiCpuData->ApMachineCheckHandlerSize = mApMachineCheckHandlerSize; + + // + // Copy GDTR and IDTR profiles + // + CopyMem ((VOID *) (UINTN) mAcpiCpuData->GdtrProfile, + (VOID *) (UINTN) &mExchangeInfo->GdtrProfile, sizeof (IA32_DESCRIPTOR)); + CopyMem ((VOID *) (UINTN) mAcpiCpuData->IdtrProfile, + (VOID *) (UINTN) &mExchangeInfo->IdtrProfile, sizeof (IA32_DESCRIPTOR)); // // Set the base address of CPU S3 data to PcdCpuS3DataAddress diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.S similarity index 51% copy from OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf copy to OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.S index f1f122b..c89dfb1 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.S @@ -1,10 +1,5 @@ -## @file +#------------------------------------------------------------------------------ # -# DXE driver that populates ACPI_CPU_DATA for PiSmmCpuDxeSmm. -# -# Based on Quark_EDKII_v1.1.0/IA32FamilyCpuBasePkg/CpuMpDxe. -# -# Copyright (C) 2015, Red Hat, Inc. # Copyright (c) 2013-2015 Intel Corporation. # # Redistribution and use in source and binary forms, with or without @@ -33,59 +28,29 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = CpuS3DataDxe - FILE_GUID = B16CB1D2-8583-43BB-9F2C-27D8E2528F71 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = CpuS3DataInitialize - -# The following information is for reference only and not required by the build -# tools. +# Module Name: # -# VALID_ARCHITECTURES = IA32 X64 - -[Sources] - ProcessorConfig.c - MpService.h - MpCommon.h - MpCommon.c - Cpu.h - -[Sources.Ia32] - IA32/ArchSpecific.c - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - OvmfPkg/OvmfPkg.dec - -[LibraryClasses] - UefiBootServicesTableLib - MemoryAllocationLib - UefiDriverEntryPoint - BaseMemoryLib - UefiLib - DebugLib - BaseLib - -[Guids] +# CpuAsm.S +# +# Abstract: +# +# Assembly code that supports IA32 CPU architectural protocol +# +#------------------------------------------------------------------------------ -[Protocols] - gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES - gEfiSmmConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED +ASM_GLOBAL ASM_PFX(ApMachineCheckHandler) +ASM_PFX(ApMachineCheckHandler): + # + # Clear MCIP flag of IA32_MCG_STATUS register + # + movl $0x17a,%ecx + rdmsr + btrl $2,%eax + wrmsr -[FeaturePcd] + iret -[FixedPcd] +ASM_GLOBAL ASM_PFX(ApMachineCheckHandlerEnd) -[Pcd] - gQuarkPortCpuTokenSpaceGuid.PcdCpuS3DataAddress - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize +ASM_PFX(ApMachineCheckHandlerEnd): -[Depex] - TRUE diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.asm b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.asm new file mode 100644 index 0000000..9a079ed --- /dev/null +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/IA32/CpuAsm.asm @@ -0,0 +1,69 @@ + page ,132 + title CPU ARCHITECTURAL DXE PROTOCOL ASSEMBLY HOOKS +;------------------------------------------------------------------------------ +; +; Copyright (c) 2013-2015 Intel Corporation. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; +; Module Name: +; +; CpuAsm.asm +; +; Abstract: +; +; Assembly code that supports IA32 CPU architectural protocol +; +;------------------------------------------------------------------------------ + +.686p +.model flat + +.stack +.code +.MMX +.XMM + +ApMachineCheckHandler PROC C PUBLIC + ; + ; Clear MCIP flag of IA32_MCG_STATUS register + ; + mov ecx, 17ah + rdmsr + btr eax, 2 + wrmsr + + iretd + +ApMachineCheckHandler ENDP + +EXTERNDEF C ApMachineCheckHandlerEnd:BYTE + +ApMachineCheckHandlerEnd LABEL BYTE + + end + -- 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel