186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/** @file
286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniThe CPU specific programming for PiSmmCpuDxeSmm module.
386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniCopyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniThis program and the accompanying materials
686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonziniare licensed and made available under the terms and conditions of the BSD License
786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonziniwhich accompanies this distribution.  The full text of the license may be found at
886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzinihttp://opensource.org/licenses/bsd-license.php
986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
1086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
1386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
1486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
1586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini#include <PiSmm.h>
1686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini#include <Library/SmmCpuFeaturesLib.h>
1786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini#include <Library/BaseLib.h>
184036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini#include <Library/BaseMemoryLib.h>
1986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini#include <Library/PcdLib.h>
2086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini#include <Library/MemoryAllocationLib.h>
214036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini#include <Library/SmmServicesTableLib.h>
2286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini#include <Library/DebugLib.h>
23c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini#include <Register/QemuSmramSaveStateMap.h>
2486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
254036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini//
264036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini// EFER register LMA bit
274036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini//
284036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini#define LMA BIT10
294036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
3086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
3186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  The constructor function
3286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
3386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in]  ImageHandle  The firmware allocated handle for the EFI image.
3486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in]  SystemTable  A pointer to the EFI System Table.
3586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
3686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_SUCCESS      The constructor always returns EFI_SUCCESS.
3786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
3886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
3986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFI_STATUS
4086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
4186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesLibConstructor (
4286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN EFI_HANDLE        ImageHandle,
4386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN EFI_SYSTEM_TABLE  *SystemTable
4486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
4586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
4686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
47d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // No need to program SMRRs on our virtual platform.
4886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
4986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  return EFI_SUCCESS;
5086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
5186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
5286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
5386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Called during the very first SMI into System Management Mode to initialize
5486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  CPU features, including SMBASE, for the currently executing CPU.  Since this
5586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  is the first SMI, the SMRAM Save State Map is at the default address of
5686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET.  The currently executing
5786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  CPU is specified by CpuIndex and CpuIndex can be used to access information
5886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  about the currently executing CPU in the ProcessorInfo array and the
5986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  HotPlugCpuData data structure.
6086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
6186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex        The index of the CPU to initialize.  The value
6286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             must be between 0 and the NumberOfCpus field in
6386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             the System Management System Table (SMST).
6486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] IsMonarch       TRUE if the CpuIndex is the index of the CPU that
6586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             was elected as monarch during System Management
6686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             Mode initialization.
6786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             FALSE if the CpuIndex is not the index of the CPU
6886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             that was elected as monarch during System
6986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             Management Mode initialization.
7086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] ProcessorInfo   Pointer to an array of EFI_PROCESSOR_INFORMATION
7186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             structures.  ProcessorInfo[CpuIndex] contains the
7286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             information for the currently executing CPU.
7386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuHotPlugData  Pointer to the CPU_HOT_PLUG_DATA structure that
7486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                             contains the ApidId and SmBase arrays.
7586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
7686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
7786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
7886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesInitializeProcessor (
7986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN                      CpuIndex,
8086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN BOOLEAN                    IsMonarch,
8186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN EFI_PROCESSOR_INFORMATION  *ProcessorInfo,
8286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN CPU_HOT_PLUG_DATA          *CpuHotPlugData
8386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
8486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
85c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  QEMU_SMRAM_SAVE_STATE_MAP  *CpuState;
8686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
8786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
8886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  // Configure SMBASE.
8986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
90c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  CpuState = (QEMU_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
91c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  if ((CpuState->x86.SMMRevId & 0xFFFF) == 0) {
92c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini    CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
93c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  } else {
94c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini    CpuState->x64.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
95c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  }
9686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
9786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
98d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // No need to program SMRRs on our virtual platform.
9986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
10086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
10186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
10286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
10386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  This function updates the SMRAM save state on the currently executing CPU
10486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  to resume execution at a specific address after an RSM instruction.  This
10586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  function must evaluate the SMRAM save state to determine the execution mode
10686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  the RSM instruction resumes and update the resume execution address with
10786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  either NewInstructionPointer32 or NewInstructionPoint.  The auto HALT restart
10886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  flag in the SMRAM save state must always be cleared.  This function returns
10986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  the value of the instruction pointer from the SMRAM save state that was
11086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  replaced.  If this function returns 0, then the SMRAM save state was not
11186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  modified.
11286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
11386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  This function is called during the very first SMI on each CPU after
11486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
11586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  to signal that the SMBASE of each CPU has been updated before the default
11686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  SMBASE address is used for the first SMI to the next CPU.
11786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
11886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex                 The index of the CPU to hook.  The value
11986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                                      must be between 0 and the NumberOfCpus
12086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                                      field in the System Management System Table
12186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                                      (SMST).
12286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuState                 Pointer to SMRAM Save State Map for the
12386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                                      currently executing CPU.
12486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
12586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                                      32-bit execution mode from 64-bit SMM.
12686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
12786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                                      same execution mode as SMM.
12886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
12986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval 0    This function did modify the SMRAM save state.
13086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval > 0  The original instruction pointer value from the SMRAM save state
13186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini               before it was replaced.
13286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
13386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniUINT64
13486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
13586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesHookReturnFromSmm (
13686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN                 CpuIndex,
13786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN SMRAM_SAVE_STATE_MAP  *CpuState,
13886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINT64                NewInstructionPointer32,
13986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINT64                NewInstructionPointer
14086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
14186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
142c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  UINT64                      OriginalInstructionPointer;
143c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  QEMU_SMRAM_SAVE_STATE_MAP  *CpuSaveState = (QEMU_SMRAM_SAVE_STATE_MAP *)CpuState;
1444036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
1454036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
1464036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    OriginalInstructionPointer = (UINT64)CpuSaveState->x86._EIP;
1474036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    CpuSaveState->x86._EIP = (UINT32)NewInstructionPointer;
1484036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
1494036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Clear the auto HALT restart flag so the RSM instruction returns
1504036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // program control to the instruction following the HLT instruction.
1514036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
1524036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if ((CpuSaveState->x86.AutoHALTRestart & BIT0) != 0) {
1534036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      CpuSaveState->x86.AutoHALTRestart &= ~BIT0;
1544036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
1554036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  } else {
1564036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    OriginalInstructionPointer = CpuSaveState->x64._RIP;
1574036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if ((CpuSaveState->x64.IA32_EFER & LMA) == 0) {
1584036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      CpuSaveState->x64._RIP = (UINT32)NewInstructionPointer32;
1594036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    } else {
1604036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      CpuSaveState->x64._RIP = (UINT32)NewInstructionPointer;
1614036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
1624036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
1634036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Clear the auto HALT restart flag so the RSM instruction returns
1644036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // program control to the instruction following the HLT instruction.
1654036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
1664036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if ((CpuSaveState->x64.AutoHALTRestart & BIT0) != 0) {
1674036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      CpuSaveState->x64.AutoHALTRestart &= ~BIT0;
1684036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
1694036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
1704036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  return OriginalInstructionPointer;
17186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
17286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
17386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
17486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Hook point in normal execution mode that allows the one CPU that was elected
17586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  as monarch during System Management Mode initialization to perform additional
17686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  initialization actions immediately after all of the CPUs have processed their
17786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
17886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
17986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
18086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
18186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
18286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesSmmRelocationComplete (
18386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  VOID
18486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
18586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
18686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
18786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
18886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
18986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Return the size, in bytes, of a custom SMI Handler in bytes.  If 0 is
19086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  returned, then a custom SMI handler is not provided by this library,
19186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  and the default SMI handler must be used.
19286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
19386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval 0    Use the default SMI handler.
19486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval > 0  Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
19586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini               The caller is required to allocate enough SMRAM for each CPU to
19686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini               support the size of the custom SMI handler.
19786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
19886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniUINTN
19986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
20086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesGetSmiHandlerSize (
20186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  VOID
20286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
20386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
20486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  return 0;
20586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
20686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
20786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
20886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Install a custom SMI handler for the CPU specified by CpuIndex.  This function
20986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
21086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  than zero and is called by the CPU that was elected as monarch during System
21186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Management Mode initialization.
21286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
21386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
21486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        The value must be between 0 and the NumberOfCpus field
21586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        in the System Management System Table (SMST).
21686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
21786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] SmiStack   The stack to use when an SMI is processed by the
21886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        the CPU specified by CpuIndex.
21986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
22086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        processed by the CPU specified by CpuIndex.
22186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] GdtBase    The base address of the GDT to use when an SMI is
22286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        processed by the CPU specified by CpuIndex.
22386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
22486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        processed by the CPU specified by CpuIndex.
22586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] IdtBase    The base address of the IDT to use when an SMI is
22686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        processed by the CPU specified by CpuIndex.
22786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
22886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        processed by the CPU specified by CpuIndex.
22986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] Cr3        The base address of the page tables to use when an SMI
23086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        is processed by the CPU specified by CpuIndex.
23186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
23286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
23386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
23486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesInstallSmiHandler (
23586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN   CpuIndex,
23686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINT32  SmBase,
23786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN VOID    *SmiStack,
23886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN   StackSize,
23986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN   GdtBase,
24086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN   GdtSize,
24186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN   IdtBase,
24286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN   IdtSize,
24386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINT32  Cr3
24486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
24586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
24686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
24786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
24886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
24986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Determines if MTRR registers must be configured to set SMRAM cache-ability
25086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  when executing in System Management Mode.
25186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
25286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval TRUE   MTRR registers must be configured to set SMRAM cache-ability.
25386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval FALSE  MTRR registers do not need to be configured to set SMRAM
25486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                 cache-ability.
25586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
25686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniBOOLEAN
25786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
25886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesNeedConfigureMtrrs (
25986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  VOID
26086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
26186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
262d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  return FALSE;
26386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
26486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
26586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
26686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
26786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  returns TRUE.
26886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
26986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
27086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
27186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesDisableSmrr (
27286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  VOID
27386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
27486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
275d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  //
276d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // No SMRR support, nothing to do
277d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  //
27886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
27986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
28086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
28186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
28286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  returns TRUE.
28386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
28486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
28586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
28686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesReenableSmrr (
28786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  VOID
28886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
28986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
290d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  //
291d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // No SMRR support, nothing to do
292d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  //
29386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
29486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
29586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
29686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Processor specific hook point each time a CPU enters System Management Mode.
29786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
29886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex  The index of the CPU that has entered SMM.  The value
29986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       must be between 0 and the NumberOfCpus field in the
30086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       System Management System Table (SMST).
30186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
30286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
30386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
30486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesRendezvousEntry (
30586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN  CpuIndex
30686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
30786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
30886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
309d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // No SMRR support, nothing to do
31086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  //
31186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
31286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
31386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
31486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Processor specific hook point each time a CPU exits System Management Mode.
31586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
31686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex  The index of the CPU that is exiting SMM.  The value must
31786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       be between 0 and the NumberOfCpus field in the System
31886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       Management System Table (SMST).
31986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
32086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
32186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
32286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesRendezvousExit (
32386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN  CpuIndex
32486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
32586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
32686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
32786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
32886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
32986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Check to see if an SMM register is supported by a specified CPU.
33086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
33186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex  The index of the CPU to check for SMM register support.
33286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       The value must be between 0 and the NumberOfCpus field
33386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       in the System Management System Table (SMST).
33486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] RegName   Identifies the SMM register to check for support.
33586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
33686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval TRUE   The SMM register specified by RegName is supported by the CPU
33786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                 specified by CpuIndex.
33886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval FALSE  The SMM register specified by RegName is not supported by the
33986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                 CPU specified by CpuIndex.
34086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
34186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniBOOLEAN
34286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
34386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesIsSmmRegisterSupported (
34486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN         CpuIndex,
34586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN SMM_REG_NAME  RegName
34686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
34786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
348d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  ASSERT (RegName == SmmRegFeatureControl);
34986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  return FALSE;
35086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
35186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
35286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
35386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Returns the current value of the SMM register for the specified CPU.
35486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  If the SMM register is not supported, then 0 is returned.
35586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
35686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex  The index of the CPU to read the SMM register.  The
35786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       value must be between 0 and the NumberOfCpus field in
35886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       the System Management System Table (SMST).
35986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] RegName   Identifies the SMM register to read.
36086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
36186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @return  The value of the SMM register specified by RegName from the CPU
36286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini           specified by CpuIndex.
36386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
36486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniUINT64
36586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
36686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesGetSmmRegister (
36786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN         CpuIndex,
36886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN SMM_REG_NAME  RegName
36986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
37086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
371d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  //
372d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // This is called for SmmRegSmmDelayed, SmmRegSmmBlocked, SmmRegSmmEnable.
373d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // The last of these should actually be SmmRegSmmDisable, so we can just
374d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  // return FALSE.
375d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  //
37686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  return 0;
37786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
37886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
37986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
38086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Sets the value of an SMM register on a specified CPU.
38186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  If the SMM register is not supported, then no action is performed.
38286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
38386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex  The index of the CPU to write the SMM register.  The
38486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       value must be between 0 and the NumberOfCpus field in
38586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       the System Management System Table (SMST).
38686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] RegName   Identifies the SMM register to write.
38786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       registers are read-only.
38886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] Value     The value to write to the SMM register.
38986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
39086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
39186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
39286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesSetSmmRegister (
39386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN         CpuIndex,
39486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN SMM_REG_NAME  RegName,
39586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINT64        Value
39686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
39786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
398d7e71b2925012c9706d1d044ca466173aac802a8Paolo Bonzini  ASSERT (FALSE);
39986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
40086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
4014036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4024036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
4034036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
404c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini#define SMM_CPU_OFFSET(Field) OFFSET_OF (QEMU_SMRAM_SAVE_STATE_MAP, Field)
4054036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4064036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4074036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_REGISTER_RANGE
4084036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4094036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini#define SMM_REGISTER_RANGE(Start, End) { Start, End, End - Start + 1 }
4104036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4114036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4124036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// Structure used to describe a range of registers
4134036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4144036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzinitypedef struct {
4154036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  EFI_SMM_SAVE_STATE_REGISTER  Start;
4164036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  EFI_SMM_SAVE_STATE_REGISTER  End;
4174036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINTN                        Length;
4184036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini} CPU_SMM_SAVE_STATE_REGISTER_RANGE;
4194036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4204036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4214036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// Structure used to build a lookup table to retrieve the widths and offsets
4224036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value
4234036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4244036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4254036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini#define SMM_SAVE_STATE_REGISTER_FIRST_INDEX             1
4264036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4274036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzinitypedef struct {
4284036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINT8   Width32;
4294036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINT8   Width64;
4304036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINT16  Offset32;
4314036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINT16  Offset64Lo;
4324036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINT16  Offset64Hi;
4334036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  BOOLEAN Writeable;
4344036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;
4354036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4364036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4374036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER
4384036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
4394036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4404036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzinistatic CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] = {
4414036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_SAVE_STATE_REGISTER_LDTINFO),
4424036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES,      EFI_SMM_SAVE_STATE_REGISTER_RIP),
4434036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS,  EFI_SMM_SAVE_STATE_REGISTER_CR4),
4444036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  { (EFI_SMM_SAVE_STATE_REGISTER)0, (EFI_SMM_SAVE_STATE_REGISTER)0, 0 }
4454036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini};
4464036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4474036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4484036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// Lookup table used to retrieve the widths and offsets associated with each
4494036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/// supported EFI_SMM_SAVE_STATE_REGISTER value
4504036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini///
4514036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzinistatic CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] = {
4524036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 0, 0, 0, 0, FALSE},                                                                                                     //  Reserved
4534036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4544036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
4554036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // CPU Save State registers defined in PI SMM CPU Protocol.
4564036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
457c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._GDTRBase) , SMM_CPU_OFFSET (x64._GDTRBase)  + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_GDTBASE  = 4
458c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._IDTRBase) , SMM_CPU_OFFSET (x64._IDTRBase)  + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_IDTBASE  = 5
459c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._LDTRBase) , SMM_CPU_OFFSET (x64._LDTRBase)  + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_LDTBASE  = 6
460c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 0, 0                            , SMM_CPU_OFFSET (x64._GDTRLimit), SMM_CPU_OFFSET (x64._GDTRLimit) + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7
461c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 0, 0                            , SMM_CPU_OFFSET (x64._IDTRLimit), SMM_CPU_OFFSET (x64._IDTRLimit) + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8
462c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 0, 0                            , SMM_CPU_OFFSET (x64._LDTRLimit), SMM_CPU_OFFSET (x64._LDTRLimit) + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9
463c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 0, 0                            , 0                              , 0                               + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_LDTINFO  = 10
4644036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4654036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._ES)     , SMM_CPU_OFFSET (x64._ES)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_ES       = 20
4664036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._CS)     , SMM_CPU_OFFSET (x64._CS)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_CS       = 21
4674036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._SS)     , SMM_CPU_OFFSET (x64._SS)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_SS       = 22
4684036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._DS)     , SMM_CPU_OFFSET (x64._DS)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_DS       = 23
4694036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._FS)     , SMM_CPU_OFFSET (x64._FS)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_FS       = 24
4704036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._GS)     , SMM_CPU_OFFSET (x64._GS)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_GS       = 25
4714036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 4, 0                            , SMM_CPU_OFFSET (x64._LDTR)   , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26
4724036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 4, SMM_CPU_OFFSET (x86._TR)     , SMM_CPU_OFFSET (x64._TR)     , 0                               , FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_TR_SEL   = 27
4734036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._DR7)    , SMM_CPU_OFFSET (x64._DR7)    , SMM_CPU_OFFSET (x64._DR7)    + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_DR7      = 28
4744036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._DR6)    , SMM_CPU_OFFSET (x64._DR6)    , SMM_CPU_OFFSET (x64._DR6)    + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_DR6      = 29
4754036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R8)     , SMM_CPU_OFFSET (x64._R8)     + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R8       = 30
4764036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R9)     , SMM_CPU_OFFSET (x64._R9)     + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R9       = 31
4774036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R10)    , SMM_CPU_OFFSET (x64._R10)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R10      = 32
4784036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R11)    , SMM_CPU_OFFSET (x64._R11)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R11      = 33
4794036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R12)    , SMM_CPU_OFFSET (x64._R12)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R12      = 34
4804036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R13)    , SMM_CPU_OFFSET (x64._R13)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R13      = 35
4814036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R14)    , SMM_CPU_OFFSET (x64._R14)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R14      = 36
4824036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {0, 8, 0                            , SMM_CPU_OFFSET (x64._R15)    , SMM_CPU_OFFSET (x64._R15)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_R15      = 37
4834036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EAX)    , SMM_CPU_OFFSET (x64._RAX)    , SMM_CPU_OFFSET (x64._RAX)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RAX      = 38
4844036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EBX)    , SMM_CPU_OFFSET (x64._RBX)    , SMM_CPU_OFFSET (x64._RBX)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RBX      = 39
4854036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._ECX)    , SMM_CPU_OFFSET (x64._RCX)    , SMM_CPU_OFFSET (x64._RCX)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RCX      = 40
4864036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EDX)    , SMM_CPU_OFFSET (x64._RDX)    , SMM_CPU_OFFSET (x64._RDX)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RDX      = 41
4874036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._ESP)    , SMM_CPU_OFFSET (x64._RSP)    , SMM_CPU_OFFSET (x64._RSP)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RSP      = 42
4884036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EBP)    , SMM_CPU_OFFSET (x64._RBP)    , SMM_CPU_OFFSET (x64._RBP)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RBP      = 43
4894036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._ESI)    , SMM_CPU_OFFSET (x64._RSI)    , SMM_CPU_OFFSET (x64._RSI)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RSI      = 44
4904036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EDI)    , SMM_CPU_OFFSET (x64._RDI)    , SMM_CPU_OFFSET (x64._RDI)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RDI      = 45
4914036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EIP)    , SMM_CPU_OFFSET (x64._RIP)    , SMM_CPU_OFFSET (x64._RIP)    + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RIP      = 46
4924036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4934036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._EFLAGS) , SMM_CPU_OFFSET (x64._RFLAGS) , SMM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE },  //  EFI_SMM_SAVE_STATE_REGISTER_RFLAGS   = 51
4944036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._CR0)    , SMM_CPU_OFFSET (x64._CR0)    , SMM_CPU_OFFSET (x64._CR0)    + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_CR0      = 52
4954036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  {4, 8, SMM_CPU_OFFSET (x86._CR3)    , SMM_CPU_OFFSET (x64._CR3)    , SMM_CPU_OFFSET (x64._CR3)    + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_CR3      = 53
496c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  {0, 4, 0                            , SMM_CPU_OFFSET (x64._CR4)    , SMM_CPU_OFFSET (x64._CR4)    + 4, FALSE},  //  EFI_SMM_SAVE_STATE_REGISTER_CR4      = 54
4974036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini};
4984036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
4994036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini//
5004036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini// No support for I/O restart
5014036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini//
5024036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5034036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/**
5044036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  Read information from the CPU save state.
5054036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5064036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @param  Register  Specifies the CPU register to read form the save state.
5074036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5084036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @retval 0   Register is not valid
5094036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @retval >0  Index into mSmmCpuWidthOffset[] associated with Register
5104036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5114036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini**/
5124036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzinistatic UINTN
5134036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo BonziniGetRegisterIndex (
5144036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  IN EFI_SMM_SAVE_STATE_REGISTER  Register
5154036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  )
5164036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini{
5174036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINTN  Index;
5184036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  UINTN  Offset;
5194036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5204036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  for (Index = 0, Offset = SMM_SAVE_STATE_REGISTER_FIRST_INDEX; mSmmCpuRegisterRanges[Index].Length != 0; Index++) {
5214036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Register >= mSmmCpuRegisterRanges[Index].Start && Register <= mSmmCpuRegisterRanges[Index].End) {
5224036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return Register - mSmmCpuRegisterRanges[Index].Start + Offset;
5234036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
5244036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    Offset += mSmmCpuRegisterRanges[Index].Length;
5254036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
5264036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  return 0;
5274036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini}
5284036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5294036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini/**
5304036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  Read a CPU Save State register on the target processor.
5314036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5324036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  This function abstracts the differences that whether the CPU Save State register is in the
5334036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  IA32 CPU Save State Map or X64 CPU Save State Map.
5344036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5354036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  This function supports reading a CPU Save State register in SMBase relocation handler.
5364036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5374036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
5384036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
5394036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @param[in]  Width          The number of bytes to read from the CPU save state.
5404036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
5414036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5424036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @retval EFI_SUCCESS           The register was read from Save State.
5434036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
5444036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
5454036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5464036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini**/
5474036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzinistatic EFI_STATUS
5484036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo BonziniReadSaveStateRegisterByIndex (
5494036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  IN UINTN   CpuIndex,
5504036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  IN UINTN   RegisterIndex,
5514036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  IN UINTN   Width,
5524036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  OUT VOID   *Buffer
5534036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  )
5544036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini{
555c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  QEMU_SMRAM_SAVE_STATE_MAP  *CpuSaveState;
5564036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
557c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  CpuSaveState = (QEMU_SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuIndex];
5584036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5594036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
5604036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5614036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If 32-bit mode width is zero, then the specified register can not be accessed
5624036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5634036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
5644036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_NOT_FOUND;
5654036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
5664036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5674036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5684036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
5694036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5704036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
5714036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_INVALID_PARAMETER;
5724036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
5734036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5744036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5754036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Write return buffer
5764036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5774036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    ASSERT(CpuSaveState != NULL);
5784036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    CopyMem(Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Width);
5794036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  } else {
5804036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5814036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If 64-bit mode width is zero, then the specified register can not be accessed
5824036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5834036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
5844036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_NOT_FOUND;
5854036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
5864036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5874036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5884036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
5894036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5904036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
5914036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_INVALID_PARAMETER;
5924036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
5934036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
5944036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5954036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Write lower 32-bits of return buffer
5964036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
5974036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    CopyMem(Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, MIN(4, Width));
5984036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width >= 4) {
5994036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      //
6004036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      // Write upper 32-bits of return buffer
6014036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      //
6024036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      CopyMem((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
6034036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
6044036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
6054036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  return EFI_SUCCESS;
6064036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini}
6074036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
60886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
60986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Read an SMM Save State register on the target processor.  If this function
61086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  returns EFI_UNSUPPORTED, then the caller is responsible for reading the
61186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  SMM Save Sate register.
61286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
61386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The
61486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        value must be between 0 and the NumberOfCpus field in
61586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        the System Management System Table (SMST).
61686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in]  Register  The SMM Save State register to read.
61786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in]  Width     The number of bytes to read from the CPU save state.
61886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[out] Buffer    Upon return, this holds the CPU register value read
61986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                        from the save state.
62086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
62186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_SUCCESS           The register was read from Save State.
62286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_INVALID_PARAMTER  Buffer is NULL.
62386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_UNSUPPORTED       This function does not support reading Register.
62486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
62586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
62686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFI_STATUS
62786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
62886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesReadSaveStateRegister (
62986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN  UINTN                        CpuIndex,
63086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
63186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN  UINTN                        Width,
63286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  OUT VOID                         *Buffer
63386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
63486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
635c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  UINTN                       RegisterIndex;
636c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  QEMU_SMRAM_SAVE_STATE_MAP  *CpuSaveState;
6374036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
6384036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
6394036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA
6404036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
6414036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
6424036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
6434036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Only byte access is supported for this register
6444036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
6454036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width != 1) {
6464036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_INVALID_PARAMETER;
6474036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
6484036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
649c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini    CpuSaveState = (QEMU_SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuIndex];
6504036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
6514036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
6524036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Check CPU mode
6534036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
6544036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
6554036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      *(UINT8 *)Buffer = 32;
6564036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    } else {
6574036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      *(UINT8 *)Buffer = 64;
6584036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
6594036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
6604036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return EFI_SUCCESS;
6614036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
6624036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
6634036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
6644036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO
6654036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
6664036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
6674036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return EFI_NOT_FOUND;
6684036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
6694036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
6704036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
6714036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Convert Register to a register lookup table index.  Let
6724036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // PiSmmCpuDxeSmm implement other special registers (currently
6734036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // there is only EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID).
6744036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
6754036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  RegisterIndex = GetRegisterIndex (Register);
6764036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (RegisterIndex == 0) {
6774036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return Register < EFI_SMM_SAVE_STATE_REGISTER_IO ? EFI_NOT_FOUND : EFI_UNSUPPORTED;
6784036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
6794036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
6804036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  return ReadSaveStateRegisterByIndex (CpuIndex, RegisterIndex, Width, Buffer);
68186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
68286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
68386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
68486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Writes an SMM Save State register on the target processor.  If this function
68586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  returns EFI_UNSUPPORTED, then the caller is responsible for writing the
68686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  SMM Save Sate register.
68786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
68886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The
68986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       value must be between 0 and the NumberOfCpus field in
69086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                       the System Management System Table (SMST).
69186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] Register  The SMM Save State register to write.
69286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] Width     The number of bytes to write to the CPU save state.
69386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param[in] Buffer    Upon entry, this holds the new CPU register value.
69486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
69586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_SUCCESS           The register was written to Save State.
69686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_INVALID_PARAMTER  Buffer is NULL.
69786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval EFI_UNSUPPORTED       This function does not support writing Register.
69886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
69986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFI_STATUS
70086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
70186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesWriteSaveStateRegister (
70286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN                        CpuIndex,
70386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN EFI_SMM_SAVE_STATE_REGISTER  Register,
70486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN                        Width,
70586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN CONST VOID                   *Buffer
70686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
70786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
708c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  UINTN                       RegisterIndex;
709c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  QEMU_SMRAM_SAVE_STATE_MAP  *CpuSaveState;
7104036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7114036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7124036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored
7134036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7144036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
7154036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return EFI_SUCCESS;
7164036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
7174036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7184036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7194036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported
7204036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7214036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
7224036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return EFI_NOT_FOUND;
7234036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
7244036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7254036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7264036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Convert Register to a register lookup table index.  Let
7274036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // PiSmmCpuDxeSmm implement other special registers (currently
7284036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // there is only EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID).
7294036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7304036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  RegisterIndex = GetRegisterIndex (Register);
7314036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (RegisterIndex == 0) {
7324036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return Register < EFI_SMM_SAVE_STATE_REGISTER_IO ? EFI_NOT_FOUND : EFI_UNSUPPORTED;
7334036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
7344036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
735c1fcd80bf42e6b1e91c1c742d222f1ba421b1d1dPaolo Bonzini  CpuSaveState = (QEMU_SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuIndex];
7364036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7374036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7384036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Do not write non-writable SaveState, because it will cause exception.
7394036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7404036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) {
7414036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    return EFI_UNSUPPORTED;
7424036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
7434036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7444036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7454036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  // Check CPU mode
7464036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  //
7474036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
7484036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7494036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If 32-bit mode width is zero, then the specified register can not be accessed
7504036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7514036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
7524036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_NOT_FOUND;
7534036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
7544036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7554036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7564036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
7574036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7584036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
7594036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_INVALID_PARAMETER;
7604036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
7614036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7624036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Write SMM State register
7634036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7644036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    ASSERT (CpuSaveState != NULL);
7654036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);
7664036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  } else {
7674036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7684036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If 64-bit mode width is zero, then the specified register can not be accessed
7694036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7704036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
7714036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_NOT_FOUND;
7724036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
7734036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7744036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7754036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
7764036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7774036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
7784036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      return EFI_INVALID_PARAMETER;
7794036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
7804036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini
7814036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7824036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    // Write lower 32-bits of SMM State register
7834036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    //
7844036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));
7854036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    if (Width >= 4) {
7864036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      //
7874036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      // Write upper 32-bits of SMM State register
7884036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      //
7894036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini      CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
7904036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini    }
7914036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  }
7924036b4e57ccef4e0fa48d8389acf6390826c2bedPaolo Bonzini  return EFI_SUCCESS;
79386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
79486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
79586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
79686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
79786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  notification is completely processed.
79886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
79986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID
80086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
80186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesCompleteSmmReadyToLock (
80286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  VOID
80386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
80486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
80586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
80686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
80786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini/**
80886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  This API provides a method for a CPU to allocate a specific region for storing page tables.
80986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
81086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  This API can be called more once to allocate memory for page tables.
81186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
81286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
81386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
81486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
81586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  returned.
81686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
81786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
81886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
81986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @param  Pages                 The number of 4 KB pages to allocate.
82086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
82186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @return A pointer to the allocated buffer for page tables.
82286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  @retval NULL      Fail to allocate a specific region for storing page tables,
82386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini                    Or there is no preference on where the page tables are allocated in SMRAM.
82486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
82586d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini**/
82686d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniVOID *
82786d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniEFIAPI
82886d71589c1fdb099c04a0f9e548fe868a2fef266Paolo BonziniSmmCpuFeaturesAllocatePageTableMemory (
82986d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  IN UINTN           Pages
83086d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  )
83186d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini{
83286d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini  return NULL;
83386d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini}
83486d71589c1fdb099c04a0f9e548fe868a2fef266Paolo Bonzini
835