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
    "UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c".)

(8) The startup vector in "UefiCpuPkg/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>
---

Notes:
    v2:
    - Reword commit message: PiSmmCpuDxeSmm lives under UefiCpuPkg now. Plus
      Mike renamed PrepareAPStartupVector() to PrepareApStartupVector();
      update the reference in the commit message.

 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 be362d8..7440c2d 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 be362d8..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
-  UefiCpuPkg/UefiCpuPkg.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]
-  gUefiCpuPkgTokenSpaceGuid.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

Reply via email to