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