/** @file | |
STM API definition | |
Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
@par Specification Reference: | |
SMI Transfer Monitor (STM) User Guide Revision 1.00 | |
**/ | |
#ifndef _INTEL_STM_API_H_ | |
#define _INTEL_STM_API_H_ | |
#include <Register/Intel/StmStatusCode.h> | |
#include <Register/Intel/StmResourceDescriptor.h> | |
#include <Register/Intel/ArchitecturalMsr.h> | |
#pragma pack (1) | |
/** | |
STM Header Structures | |
**/ | |
typedef struct { | |
UINT32 Intel64ModeSupported : 1; /// > bitfield | |
UINT32 EptSupported : 1; /// > bitfield | |
UINT32 Reserved : 30; /// > must be 0 | |
} STM_FEAT; | |
#define STM_SPEC_VERSION_MAJOR 1 | |
#define STM_SPEC_VERSION_MINOR 0 | |
typedef struct { | |
UINT8 StmSpecVerMajor; | |
UINT8 StmSpecVerMinor; | |
/// | |
/// Must be zero | |
/// | |
UINT16 Reserved; | |
UINT32 StaticImageSize; | |
UINT32 PerProcDynamicMemorySize; | |
UINT32 AdditionalDynamicMemorySize; | |
STM_FEAT StmFeatures; | |
UINT32 NumberOfRevIDs; | |
UINT32 StmSmmRevID[1]; | |
/// | |
/// The total STM_HEADER should be 4K. | |
/// | |
} SOFTWARE_STM_HEADER; | |
typedef struct { | |
MSEG_HEADER HwStmHdr; | |
SOFTWARE_STM_HEADER SwStmHdr; | |
} STM_HEADER; | |
/** | |
VMCALL API Numbers | |
API number convention: BIOS facing VMCALL interfaces have bit 16 clear | |
**/ | |
/** | |
StmMapAddressRange enables a SMM guest to create a non-1:1 virtual to | |
physical mapping of an address range into the SMM guest's virtual | |
memory space. | |
@param EAX #STM_API_MAP_ADDRESS_RANGE (0x00000001) | |
@param EBX Low 32 bits of physical address of caller allocated | |
STM_MAP_ADDRESS_RANGE_DESCRIPTOR structure. | |
@param ECX High 32 bits of physical address of caller allocated | |
STM_MAP_ADDRESS_RANGE_DESCRIPTOR structure. If Intel64Mode is | |
clear (0), ECX must be 0. | |
@note All fields of STM_MAP_ADDRESS_RANGE_DESCRIPTOR are inputs only. They | |
are not modified by StmMapAddressRange. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. | |
The memory range was mapped as requested. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_SECURITY_VIOLATION | |
The requested mapping contains a protected resource. | |
@retval EAX #ERROR_STM_CACHE_TYPE_NOT_SUPPORTED | |
The requested cache type could not be satisfied. | |
@retval EAX #ERROR_STM_PAGE_NOT_FOUND | |
Page count must not be zero. | |
@retval EAX #ERROR_STM_FUNCTION_NOT_SUPPORTED | |
STM supports EPT and has not implemented StmMapAddressRange(). | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_MAP_ADDRESS_RANGE 0x00000001 | |
/** | |
STM Map Address Range Descriptor for #STM_API_MAP_ADDRESS_RANGE VMCALL | |
**/ | |
typedef struct { | |
UINT64 PhysicalAddress; | |
UINT64 VirtualAddress; | |
UINT32 PageCount; | |
UINT32 PatCacheType; | |
} STM_MAP_ADDRESS_RANGE_DESCRIPTOR; | |
/** | |
Define values for PatCacheType field of #STM_MAP_ADDRESS_RANGE_DESCRIPTOR | |
@{ | |
**/ | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_ST_UC 0x00 | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_WC 0x01 | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_WT 0x04 | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_WP 0x05 | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_WB 0x06 | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_UC 0x07 | |
#define STM_MAP_ADDRESS_RANGE_PAT_CACHE_TYPE_FOLLOW_MTRR 0xFFFFFFFF | |
/// @} | |
/** | |
StmUnmapAddressRange enables a SMM guest to remove mappings from its page | |
table. | |
If TXT_PROCESSOR_SMM_DESCRIPTOR.EptEnabled bit is set by the STM, BIOS can | |
control its own page tables. In this case, the STM implementation may | |
optionally return ERROR_STM_FUNCTION_NOT_SUPPORTED. | |
@param EAX #STM_API_UNMAP_ADDRESS_RANGE (0x00000002) | |
@param EBX Low 32 bits of virtual address of caller allocated | |
STM_UNMAP_ADDRESS_RANGE_DESCRIPTOR structure. | |
@param ECX High 32 bits of virtual address of caller allocated | |
STM_UNMAP_ADDRESS_RANGE_DESCRIPTOR structure. If Intel64Mode is | |
clear (0), ECX must be zero. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. The memory range was unmapped | |
as requested. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_FUNCTION_NOT_SUPPORTED | |
STM supports EPT and has not implemented StmUnmapAddressRange(). | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_UNMAP_ADDRESS_RANGE 0x00000002 | |
/** | |
STM Unmap Address Range Descriptor for #STM_API_UNMAP_ADDRESS_RANGE VMCALL | |
**/ | |
typedef struct { | |
UINT64 VirtualAddress; | |
UINT32 Length; | |
} STM_UNMAP_ADDRESS_RANGE_DESCRIPTOR; | |
/** | |
Since the normal OS environment runs with a different set of page tables than | |
the SMM guest, virtual mappings will certainly be different. In order to do a | |
guest virtual to host physical translation of an address from the normal OS | |
code (EIP for example), it is necessary to walk the page tables governing the | |
OS page mappings. Since the SMM guest has no direct access to the page tables, | |
it must ask the STM to do this page table walk. This is supported via the | |
StmAddressLookup VMCALL. All OS page table formats need to be supported, | |
(e.g. PAE, PSE, Intel64, EPT, etc.) | |
StmAddressLookup takes a CR3 value and a virtual address from the interrupted | |
code as input and returns the corresponding physical address. It also | |
optionally maps the physical address into the SMM guest's virtual address | |
space. This new mapping persists ONLY for the duration of the SMI and if | |
needed in subsequent SMIs it must be remapped. PAT cache types follow the | |
interrupted environment's page table. | |
If EPT is enabled, OS CR3 only provides guest physical address information, | |
but the SMM guest might also need to know the host physical address. Since | |
SMM does not have direct access rights to EPT (it is protected by the STM), | |
SMM can input InterruptedEptp to let STM help to walk through it, and output | |
the host physical address. | |
@param EAX #STM_API_ADDRESS_LOOKUP (0x00000003) | |
@param EBX Low 32 bits of virtual address of caller allocated | |
STM_ADDRESS_LOOKUP_DESCRIPTOR structure. | |
@param ECX High 32 bits of virtual address of caller allocated | |
STM_ADDRESS_LOOKUP_DESCRIPTOR structure. If Intel64Mode is | |
clear (0), ECX must be zero. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. PhysicalAddress contains the | |
host physical address determined by walking the interrupted SMM | |
guest's page tables. SmmGuestVirtualAddress contains the SMM | |
guest's virtual mapping of the requested address. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_SECURITY_VIOLATION | |
The requested page was a protected page. | |
@retval EAX #ERROR_STM_PAGE_NOT_FOUND | |
The requested virtual address did not exist in the page given | |
page table. | |
@retval EAX #ERROR_STM_BAD_CR3 | |
The CR3 input was invalid. CR3 values must be from one of the | |
interrupted guest, or from the interrupted guest of another | |
processor. | |
@retval EAX #ERROR_STM_PHYSICAL_OVER_4G | |
The resulting physical address is greater than 4G and no virtual | |
address was supplied. The STM could not determine what address | |
within the SMM guest's virtual address space to do the mapping. | |
STM_ADDRESS_LOOKUP_DESCRIPTOR field PhysicalAddress contains the | |
physical address determined by walking the interrupted | |
environment's page tables. | |
@retval EAX #ERROR_STM_VIRTUAL_SPACE_TOO_SMALL | |
A specific virtual mapping was requested, but | |
SmmGuestVirtualAddress + Length exceeds 4G and the SMI handler | |
is running in 32 bit mode. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_ADDRESS_LOOKUP 0x00000003 | |
/** | |
STM Lookup Address Range Descriptor for #STM_API_ADDRESS_LOOKUP VMCALL | |
**/ | |
typedef struct { | |
UINT64 InterruptedGuestVirtualAddress; | |
UINT32 Length; | |
UINT64 InterruptedCr3; | |
UINT64 InterruptedEptp; | |
UINT32 MapToSmmGuest : 2; | |
UINT32 InterruptedCr4Pae : 1; | |
UINT32 InterruptedCr4Pse : 1; | |
UINT32 InterruptedIa32eMode : 1; | |
UINT32 Reserved1 : 27; | |
UINT32 Reserved2; | |
UINT64 PhysicalAddress; | |
UINT64 SmmGuestVirtualAddress; | |
} STM_ADDRESS_LOOKUP_DESCRIPTOR; | |
/** | |
Define values for the MapToSmmGuest field of #STM_ADDRESS_LOOKUP_DESCRIPTOR | |
@{ | |
**/ | |
#define STM_ADDRESS_LOOKUP_DESCRIPTOR_DO_NOT_MAP 0 | |
#define STM_ADDRESS_LOOKUP_DESCRIPTOR_ONE_TO_ONE 1 | |
#define STM_ADDRESS_LOOKUP_DESCRIPTOR_VIRTUAL_ADDRESS_SPECIFIED 3 | |
/// @} | |
/** | |
When returning from a protection exception (see section 6.2), the SMM guest | |
can instruct the STM to take one of two paths. It can either request a value | |
be logged to the TXT.ERRORCODE register and subsequently reset the machine | |
(indicating it couldn't resolve the problem), or it can request that the STM | |
resume the SMM guest again with the specified register state. | |
Unlike other VMCALL interfaces, StmReturnFromProtectionException behaves more | |
like a jump or an IRET instruction than a "call". It does not return directly | |
to the caller, but indirectly to a different location specified on the | |
caller's stack (see section 6.2) or not at all. | |
If the SMM guest STM protection exception handler itself causes a protection | |
exception (e.g. a single nested exception), or more than 100 un-nested | |
exceptions occur within the scope of a single SMI event, the STM must write | |
STM_CRASH_PROTECTION_EXCEPTION_FAILURE to the TXT.ERRORCODE register and | |
assert TXT.CMD.SYS_RESET. The reason for these restrictions is to simplify | |
the code requirements while still enabling a reasonable debugging capability. | |
@param EAX #STM_API_RETURN_FROM_PROTECTION_EXCEPTION (0x00000004) | |
@param EBX If 0, resume SMM guest using register state found on exception | |
stack. If in range 0x01..0x0F, EBX contains a BIOS error code | |
which the STM must record in the TXT.ERRORCODE register and | |
subsequently reset the system via TXT.CMD.SYS_RESET. The value | |
of the TXT.ERRORCODE register is calculated as follows: | |
TXT.ERRORCODE = (EBX & 0x0F) | STM_CRASH_BIOS_PANIC | |
Values 0x10..0xFFFFFFFF are reserved, do not use. | |
**/ | |
#define STM_API_RETURN_FROM_PROTECTION_EXCEPTION 0x00000004 | |
/** | |
VMCALL API Numbers | |
API number convention: MLE facing VMCALL interfaces have bit 16 set. | |
The STM configuration lifecycle is as follows: | |
1. SENTER->SINIT->MLE: MLE begins execution with SMI disabled (masked). | |
2. MLE invokes #STM_API_INITIALIZE_PROTECTION VMCALL to prepare STM for | |
setup of initial protection profile. This is done on a single CPU and | |
has global effect. | |
3. MLE invokes #STM_API_PROTECT_RESOURCE VMCALL to define the initial | |
protection profile. The protection profile is global across all CPUs. | |
4. MLE invokes #STM_API_START VMCALL to enable the STM to begin receiving | |
SMI events. This must be done on every logical CPU. | |
5. MLE may invoke #STM_API_PROTECT_RESOURCE VMCALL or | |
#STM_API_UNPROTECT_RESOURCE VMCALL during runtime as many times as | |
necessary. | |
6. MLE invokes #STM_API_STOP VMCALL to disable the STM. SMI is again masked | |
following #STM_API_STOP VMCALL. | |
**/ | |
/** | |
StartStmVmcall() is used to configure an STM that is present in MSEG. SMIs | |
should remain disabled from the invocation of GETSEC[SENTER] until they are | |
re-enabled by StartStmVMCALL(). When StartStmVMCALL() returns, SMI is | |
enabled and the STM has been started and is active. Prior to invoking | |
StartStmVMCALL(), the MLE root should first invoke | |
InitializeProtectionVMCALL() followed by as many iterations of | |
ProtectResourceVMCALL() as necessary to establish the initial protection | |
profile. StartStmVmcall() must be invoked on all processor threads. | |
@param EAX #STM_API_START (0x00010001) | |
@param EDX STM configuration options. These provide the MLE with the | |
ability to pass configuration parameters to the STM. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. The STM has been configured | |
and is now active and the guarding all requested resources. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_ALREADY_STARTED | |
The STM is already configured and active. STM remains active and | |
guarding previously enabled resource list. | |
@retval EAX #ERROR_STM_WITHOUT_SMX_UNSUPPORTED | |
The StartStmVMCALL() was invoked from VMX root mode, but outside | |
of SMX. This error code indicates the STM or platform does not | |
support the STM outside of SMX. The SMI handler remains active | |
and operates in legacy mode. See Appendix C | |
@retval EAX #ERROR_STM_UNSUPPORTED_MSR_BIT | |
The CPU doesn't support the MSR bit. The STM is not active. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_START (BIT16 | 1) | |
/** | |
Bit values for EDX input parameter to #STM_API_START VMCALL | |
@{ | |
**/ | |
#define STM_CONFIG_SMI_UNBLOCKING_BY_VMX_OFF BIT0 | |
/// @} | |
/** | |
The StopStmVMCALL() is invoked by the MLE to teardown an active STM. This is | |
normally done as part of a full teardown of the SMX environment when the | |
system is being shut down. At the time the call is invoked, SMI is enabled | |
and the STM is active. When the call returns, the STM has been stopped and | |
all STM context is discarded and SMI is disabled. | |
@param EAX #STM_API_STOP (0x00010002) | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. The STM has been stopped and | |
is no longer processing SMI events. SMI is blocked. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_STOPPED | |
The STM was not active. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_STOP (BIT16 | 2) | |
/** | |
The ProtectResourceVMCALL() is invoked by the MLE root to request protection | |
of specific resources. The request is defined by a STM_RESOURCE_LIST, which | |
may contain more than one resource descriptor. Each resource descriptor is | |
processed separately by the STM. Whether or not protection for any specific | |
resource is granted is returned by the STM via the ReturnStatus bit in the | |
associated STM_RSC_DESC_HEADER. | |
@param EAX #STM_API_PROTECT_RESOURCE (0x00010003) | |
@param EBX Low 32 bits of physical address of caller allocated | |
STM_RESOURCE_LIST. Bits 11:0 are ignored and assumed to be zero, | |
making the buffer 4K aligned. | |
@param ECX High 32 bits of physical address of caller allocated | |
STM_RESOURCE_LIST. | |
@note All fields of STM_RESOURCE_LIST are inputs only, except for the | |
ReturnStatus bit. On input, the ReturnStatus bit must be clear. On | |
return, the ReturnStatus bit is set for each resource request granted, | |
and clear for each resource request denied. There are no other fields | |
modified by ProtectResourceVMCALL(). The STM_RESOURCE_LIST must be | |
contained entirely within a single 4K page. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. The STM has successfully | |
merged the entire protection request into the active protection | |
profile. There is therefore no need to check the ReturnStatus | |
bits in the STM_RESOURCE_LIST. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_UNPROTECTABLE_RESOURCE | |
At least one of the requested resource protections intersects a | |
BIOS required resource. Therefore, the caller must walk through | |
the STM_RESOURCE_LIST to determine which of the requested | |
resources was not granted protection. The entire list must be | |
traversed since there may be multiple failures. | |
@retval EAX #ERROR_STM_MALFORMED_RESOURCE_LIST | |
The resource list could not be parsed correctly, or did not | |
terminate before crossing a 4K page boundary. The caller must | |
walk through the STM_RESOURCE_LIST to determine which of the | |
requested resources was not granted protection. The entire list | |
must be traversed since there may be multiple failures. | |
@retval EAX #ERROR_STM_OUT_OF_RESOURCES | |
The STM has encountered an internal error and cannot complete | |
the request. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_PROTECT_RESOURCE (BIT16 | 3) | |
/** | |
The UnProtectResourceVMCALL() is invoked by the MLE root to request that the | |
STM allow the SMI handler access to the specified resources. | |
@param EAX #STM_API_UNPROTECT_RESOURCE (0x00010004) | |
@param EBX Low 32 bits of physical address of caller allocated | |
STM_RESOURCE_LIST. Bits 11:0 are ignored and assumed to be zero, | |
making the buffer 4K aligned. | |
@param ECX High 32 bits of physical address of caller allocated | |
STM_RESOURCE_LIST. | |
@note All fields of STM_RESOURCE_LIST are inputs only, except for the | |
ReturnStatus bit. On input, the ReturnStatus bit must be clear. On | |
return, the ReturnStatus bit is set for each resource processed. For | |
a properly formed STM_RESOURCE_LIST, this should be all resources | |
listed. There are no other fields modified by | |
UnProtectResourceVMCALL(). The STM_RESOURCE_LIST must be contained | |
entirely within a single 4K page. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. The requested resources are | |
not being guarded by the STM. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_MALFORMED_RESOURCE_LIST | |
The resource list could not be parsed correctly, or did not | |
terminate before crossing a 4K page boundary. The caller must | |
walk through the STM_RESOURCE_LIST to determine which of the | |
requested resources were not able to be unprotected. The entire | |
list must be traversed since there may be multiple failures. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_UNPROTECT_RESOURCE (BIT16 | 4) | |
/** | |
The GetBiosResourcesVMCALL() is invoked by the MLE root to request the list | |
of BIOS required resources from the STM. | |
@param EAX #STM_API_GET_BIOS_RESOURCES (0x00010005) | |
@param EBX Low 32 bits of physical address of caller allocated destination | |
buffer. Bits 11:0 are ignored and assumed to be zero, making the | |
buffer 4K aligned. | |
@param ECX High 32 bits of physical address of caller allocated destination | |
buffer. | |
@param EDX Indicates which page of the BIOS resource list to copy into the | |
destination buffer. The first page is indicated by 0, the second | |
page by 1, etc. | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. The destination buffer | |
contains the BIOS required resources. If the page retrieved is | |
the last page, EDX will be cleared to 0. If there are more pages | |
to retrieve, EDX is incremented to the next page index. Calling | |
software should iterate on GetBiosResourcesVMCALL() until EDX is | |
returned cleared to 0. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_PAGE_NOT_FOUND | |
The page index supplied in EDX input was out of range. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@retval EDX Page index of next page to read. A return of EDX=0 signifies | |
that the entire list has been read. | |
@note EDX is both an input and an output register. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_GET_BIOS_RESOURCES (BIT16 | 5) | |
/** | |
The ManageVmcsDatabaseVMCALL() is invoked by the MLE root to add or remove an | |
MLE guest (including the MLE root) from the list of protected domains. | |
@param EAX #STM_API_MANAGE_VMCS_DATABASE (0x00010006) | |
@param EBX Low 32 bits of physical address of caller allocated | |
STM_VMCS_DATABASE_REQUEST. Bits 11:0 are ignored and assumed to | |
be zero, making the buffer 4K aligned. | |
@param ECX High 32 bits of physical address of caller allocated | |
STM_VMCS_DATABASE_REQUEST. | |
@note All fields of STM_VMCS_DATABASE_REQUEST are inputs only. They are not | |
modified by ManageVmcsDatabaseVMCALL(). | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_INVALID_VMCS | |
Indicates a request to remove a VMCS from the database was made, | |
but the referenced VMCS was not found in the database. | |
@retval EAX #ERROR_STM_VMCS_PRESENT | |
Indicates a request to add a VMCS to the database was made, but | |
the referenced VMCS was already present in the database. | |
@retval EAX #ERROR_INVALID_PARAMETER | |
Indicates non-zero reserved field. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_MANAGE_VMCS_DATABASE (BIT16 | 6) | |
/** | |
STM VMCS Database Request for #STM_API_MANAGE_VMCS_DATABASE VMCALL | |
**/ | |
typedef struct { | |
/// | |
/// bits 11:0 are reserved and must be 0 | |
/// | |
UINT64 VmcsPhysPointer; | |
UINT32 DomainType : 4; | |
UINT32 XStatePolicy : 2; | |
UINT32 DegradationPolicy : 4; | |
/// | |
/// Must be 0 | |
/// | |
UINT32 Reserved1 : 22; | |
UINT32 AddOrRemove; | |
} STM_VMCS_DATABASE_REQUEST; | |
/** | |
Values for the DomainType field of #STM_VMCS_DATABASE_REQUEST | |
@{ | |
**/ | |
#define DOMAIN_UNPROTECTED 0 | |
#define DOMAIN_DISALLOWED_IO_OUT BIT0 | |
#define DOMAIN_DISALLOWED_IO_IN BIT1 | |
#define DOMAIN_INTEGRITY BIT2 | |
#define DOMAIN_CONFIDENTIALITY BIT3 | |
#define DOMAIN_INTEGRITY_PROT_OUT_IN (DOMAIN_INTEGRITY) | |
#define DOMAIN_FULLY_PROT_OUT_IN (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY) | |
#define DOMAIN_FULLY_PROT (DOMAIN_FULLY_PROT_OUT_IN | DOMAIN_DISALLOWED_IO_IN | DOMAIN_DISALLOWED_IO_OUT) | |
/// @} | |
/** | |
Values for the XStatePolicy field of #STM_VMCS_DATABASE_REQUEST | |
@{ | |
**/ | |
#define XSTATE_READWRITE 0x00 | |
#define XSTATE_READONLY 0x01 | |
#define XSTATE_SCRUB 0x03 | |
/// @} | |
/** | |
Values for the AddOrRemove field of #STM_VMCS_DATABASE_REQUEST | |
@{ | |
**/ | |
#define STM_VMCS_DATABASE_REQUEST_ADD 1 | |
#define STM_VMCS_DATABASE_REQUEST_REMOVE 0 | |
/// @} | |
/** | |
InitializeProtectionVMCALL() prepares the STM for setup of the initial | |
protection profile which is subsequently communicated via one or more | |
invocations of ProtectResourceVMCALL(), prior to invoking StartStmVMCALL(). | |
It is only necessary to invoke InitializeProtectionVMCALL() on one processor | |
thread. InitializeProtectionVMCALL() does not alter whether SMIs are masked | |
or unmasked. The STM should return back to the MLE with "Blocking by SMI" set | |
to 1 in the GUEST_INTERRUPTIBILITY field for the VMCS the STM created for the | |
MLE guest. | |
@param EAX #STM_API_INITIALIZE_PROTECTION (0x00010007) | |
@retval CF 0 | |
No error, EAX set to STM_SUCCESS, EBX bits set to indicate STM | |
capabilities as defined below. The STM has set up an empty | |
protection profile, except for the resources that it sets up to | |
protect itself. The STM must not allow the SMI handler to map | |
any pages from the MSEG Base to the top of TSEG. The STM must | |
also not allow SMI handler access to those MSRs which the STM | |
requires for its own protection. | |
@retval CF 1 | |
An error occurred, EAX holds relevant error value. | |
@retval EAX #ERROR_STM_ALREADY_STARTED | |
The STM is already configured and active. The STM remains active | |
and guarding the previously enabled resource list. | |
@retval EAX #ERROR_STM_UNPROTECTABLE | |
The STM determines that based on the platform configuration, the | |
STM is unable to protect itself. For example, the BIOS required | |
resource list contains memory pages in MSEG. | |
@retval EAX #ERROR_STM_UNSPECIFIED | |
An unspecified error occurred. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_INITIALIZE_PROTECTION (BIT16 | 7) | |
/** | |
Byte granular support bits returned in EBX from #STM_API_INITIALIZE_PROTECTION | |
@{ | |
**/ | |
#define STM_RSC_BGI BIT1 | |
#define STM_RSC_BGM BIT2 | |
#define STM_RSC_MSR BIT3 | |
/// @} | |
/** | |
The ManageEventLogVMCALL() is invoked by the MLE root to control the logging | |
feature. It consists of several sub-functions to facilitate establishment of | |
the log itself, configuring what events will be logged, and functions to | |
start, stop, and clear the log. | |
@param EAX #STM_API_MANAGE_EVENT_LOG (0x00010008) | |
@param EBX Low 32 bits of physical address of caller allocated | |
STM_EVENT_LOG_MANAGEMENT_REQUEST. Bits 11:0 are ignored and | |
assumed to be zero, making the buffer 4K aligned. | |
@param ECX High 32 bits of physical address of caller allocated | |
STM_EVENT_LOG_MANAGEMENT_REQUEST. | |
@retval CF=0 | |
No error, EAX set to STM_SUCCESS. | |
@retval CF=1 | |
An error occurred, EAX holds relevant error value. See subfunction | |
descriptions below for details. | |
@note All other registers unmodified. | |
**/ | |
#define STM_API_MANAGE_EVENT_LOG (BIT16 | 8) | |
/// | |
/// STM Event Log Management Request for #STM_API_MANAGE_EVENT_LOG VMCALL | |
/// | |
typedef struct { | |
UINT32 SubFunctionIndex; | |
union { | |
struct { | |
UINT32 PageCount; | |
// | |
// number of elements is PageCount | |
// | |
UINT64 Pages[]; | |
} LogBuffer; | |
// | |
// bitmap of EVENT_TYPE | |
// | |
UINT32 EventEnableBitmap; | |
} Data; | |
} STM_EVENT_LOG_MANAGEMENT_REQUEST; | |
/** | |
Defines values for the SubFunctionIndex field of | |
#STM_EVENT_LOG_MANAGEMENT_REQUEST | |
@{ | |
**/ | |
#define STM_EVENT_LOG_MANAGEMENT_REQUEST_NEW_LOG 1 | |
#define STM_EVENT_LOG_MANAGEMENT_REQUEST_CONFIGURE_LOG 2 | |
#define STM_EVENT_LOG_MANAGEMENT_REQUEST_START_LOG 3 | |
#define STM_EVENT_LOG_MANAGEMENT_REQUEST_STOP_LOG 4 | |
#define STM_EVENT_LOG_MANAGEMENT_REQUEST_CLEAR_LOG 5 | |
#define STM_EVENT_LOG_MANAGEMENT_REQUEST_DELETE_LOG 6 | |
/// @} | |
/** | |
Log Entry Header | |
**/ | |
typedef struct { | |
UINT32 EventSerialNumber; | |
UINT16 Type; | |
UINT16 Lock : 1; | |
UINT16 Valid : 1; | |
UINT16 ReadByMle : 1; | |
UINT16 Wrapped : 1; | |
UINT16 Reserved : 12; | |
} LOG_ENTRY_HEADER; | |
/** | |
Enum values for the Type field of #LOG_ENTRY_HEADER | |
**/ | |
typedef enum { | |
EvtLogStarted, | |
EvtLogStopped, | |
EvtLogInvalidParameterDetected, | |
EvtHandledProtectionException, | |
/// | |
/// unhandled protection exceptions result in reset & cannot be logged | |
/// | |
EvtBiosAccessToUnclaimedResource, | |
EvtMleResourceProtectionGranted, | |
EvtMleResourceProtectionDenied, | |
EvtMleResourceUnprotect, | |
EvtMleResourceUnprotectError, | |
EvtMleDomainTypeDegraded, | |
/// | |
/// add more here | |
/// | |
EvtMleMax, | |
/// | |
/// Not used | |
/// | |
EvtInvalid = 0xFFFFFFFF, | |
} EVENT_TYPE; | |
typedef struct { | |
UINT32 Reserved; | |
} ENTRY_EVT_LOG_STARTED; | |
typedef struct { | |
UINT32 Reserved; | |
} ENTRY_EVT_LOG_STOPPED; | |
typedef struct { | |
UINT32 VmcallApiNumber; | |
} ENTRY_EVT_LOG_INVALID_PARAM; | |
typedef struct { | |
STM_RSC Resource; | |
} ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION; | |
typedef struct { | |
STM_RSC Resource; | |
} ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC; | |
typedef struct { | |
STM_RSC Resource; | |
} ENTRY_EVT_MLE_RSC_PROT_GRANTED; | |
typedef struct { | |
STM_RSC Resource; | |
} ENTRY_EVT_MLE_RSC_PROT_DENIED; | |
typedef struct { | |
STM_RSC Resource; | |
} ENTRY_EVT_MLE_RSC_UNPROT; | |
typedef struct { | |
STM_RSC Resource; | |
} ENTRY_EVT_MLE_RSC_UNPROT_ERROR; | |
typedef struct { | |
UINT64 VmcsPhysPointer; | |
UINT8 ExpectedDomainType; | |
UINT8 DegradedDomainType; | |
} ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED; | |
typedef union { | |
ENTRY_EVT_LOG_STARTED Started; | |
ENTRY_EVT_LOG_STOPPED Stopped; | |
ENTRY_EVT_LOG_INVALID_PARAM InvalidParam; | |
ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION HandledProtectionException; | |
ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC BiosUnclaimedRsc; | |
ENTRY_EVT_MLE_RSC_PROT_GRANTED MleRscProtGranted; | |
ENTRY_EVT_MLE_RSC_PROT_DENIED MleRscProtDenied; | |
ENTRY_EVT_MLE_RSC_UNPROT MleRscUnprot; | |
ENTRY_EVT_MLE_RSC_UNPROT_ERROR MleRscUnprotError; | |
ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED MleDomainTypeDegraded; | |
} LOG_ENTRY_DATA; | |
typedef struct { | |
LOG_ENTRY_HEADER Hdr; | |
LOG_ENTRY_DATA Data; | |
} STM_LOG_ENTRY; | |
/** | |
Maximum STM Log Entry Size | |
**/ | |
#define STM_LOG_ENTRY_SIZE 256 | |
/** | |
STM Protection Exception Stack Frame Structures | |
**/ | |
typedef struct { | |
UINT32 Rdi; | |
UINT32 Rsi; | |
UINT32 Rbp; | |
UINT32 Rdx; | |
UINT32 Rcx; | |
UINT32 Rbx; | |
UINT32 Rax; | |
UINT32 Cr3; | |
UINT32 Cr2; | |
UINT32 Cr0; | |
UINT32 VmcsExitInstructionInfo; | |
UINT32 VmcsExitInstructionLength; | |
UINT64 VmcsExitQualification; | |
/// | |
/// An TXT_SMM_PROTECTION_EXCEPTION_TYPE num value | |
/// | |
UINT32 ErrorCode; | |
UINT32 Rip; | |
UINT32 Cs; | |
UINT32 Rflags; | |
UINT32 Rsp; | |
UINT32 Ss; | |
} STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32; | |
typedef struct { | |
UINT64 R15; | |
UINT64 R14; | |
UINT64 R13; | |
UINT64 R12; | |
UINT64 R11; | |
UINT64 R10; | |
UINT64 R9; | |
UINT64 R8; | |
UINT64 Rdi; | |
UINT64 Rsi; | |
UINT64 Rbp; | |
UINT64 Rdx; | |
UINT64 Rcx; | |
UINT64 Rbx; | |
UINT64 Rax; | |
UINT64 Cr8; | |
UINT64 Cr3; | |
UINT64 Cr2; | |
UINT64 Cr0; | |
UINT64 VmcsExitInstructionInfo; | |
UINT64 VmcsExitInstructionLength; | |
UINT64 VmcsExitQualification; | |
/// | |
/// An TXT_SMM_PROTECTION_EXCEPTION_TYPE num value | |
/// | |
UINT64 ErrorCode; | |
UINT64 Rip; | |
UINT64 Cs; | |
UINT64 Rflags; | |
UINT64 Rsp; | |
UINT64 Ss; | |
} STM_PROTECTION_EXCEPTION_STACK_FRAME_X64; | |
typedef union { | |
STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32 *Ia32StackFrame; | |
STM_PROTECTION_EXCEPTION_STACK_FRAME_X64 *X64StackFrame; | |
} STM_PROTECTION_EXCEPTION_STACK_FRAME; | |
/** | |
Enum values for the ErrorCode field in | |
#STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32 and | |
#STM_PROTECTION_EXCEPTION_STACK_FRAME_X64 | |
**/ | |
typedef enum { | |
TxtSmmPageViolation = 1, | |
TxtSmmMsrViolation, | |
TxtSmmRegisterViolation, | |
TxtSmmIoViolation, | |
TxtSmmPciViolation | |
} TXT_SMM_PROTECTION_EXCEPTION_TYPE; | |
/** | |
TXT Pocessor SMM Descriptor (PSD) structures | |
**/ | |
typedef struct { | |
UINT64 SpeRip; | |
UINT64 SpeRsp; | |
UINT16 SpeSs; | |
UINT16 PageViolationException : 1; | |
UINT16 MsrViolationException : 1; | |
UINT16 RegisterViolationException : 1; | |
UINT16 IoViolationException : 1; | |
UINT16 PciViolationException : 1; | |
UINT16 Reserved1 : 11; | |
UINT32 Reserved2; | |
} STM_PROTECTION_EXCEPTION_HANDLER; | |
typedef struct { | |
UINT8 ExecutionDisableOutsideSmrr : 1; | |
UINT8 Intel64Mode : 1; | |
UINT8 Cr4Pae : 1; | |
UINT8 Cr4Pse : 1; | |
UINT8 Reserved1 : 4; | |
} STM_SMM_ENTRY_STATE; | |
typedef struct { | |
UINT8 SmramToVmcsRestoreRequired : 1; /// > BIOS restore hint | |
UINT8 ReinitializeVmcsRequired : 1; /// > BIOS request | |
UINT8 Reserved2 : 6; | |
} STM_SMM_RESUME_STATE; | |
typedef struct { | |
UINT8 DomainType : 4; /// > STM input to BIOS on each SMI | |
UINT8 XStatePolicy : 2; /// > STM input to BIOS on each SMI | |
UINT8 EptEnabled : 1; | |
UINT8 Reserved3 : 1; | |
} STM_SMM_STATE; | |
#define TXT_SMM_PSD_OFFSET 0xfb00 | |
#define TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE SIGNATURE_64('T', 'X', 'T', 'P', 'S', 'S', 'I', 'G') | |
#define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR 1 | |
#define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR 0 | |
typedef struct { | |
UINT64 Signature; | |
UINT16 Size; | |
UINT8 SmmDescriptorVerMajor; | |
UINT8 SmmDescriptorVerMinor; | |
UINT32 LocalApicId; | |
STM_SMM_ENTRY_STATE SmmEntryState; | |
STM_SMM_RESUME_STATE SmmResumeState; | |
STM_SMM_STATE StmSmmState; | |
UINT8 Reserved4; | |
UINT16 SmmCs; | |
UINT16 SmmDs; | |
UINT16 SmmSs; | |
UINT16 SmmOtherSegment; | |
UINT16 SmmTr; | |
UINT16 Reserved5; | |
UINT64 SmmCr3; | |
UINT64 SmmStmSetupRip; | |
UINT64 SmmStmTeardownRip; | |
UINT64 SmmSmiHandlerRip; | |
UINT64 SmmSmiHandlerRsp; | |
UINT64 SmmGdtPtr; | |
UINT32 SmmGdtSize; | |
UINT32 RequiredStmSmmRevId; | |
STM_PROTECTION_EXCEPTION_HANDLER StmProtectionExceptionHandler; | |
UINT64 Reserved6; | |
UINT64 BiosHwResourceRequirementsPtr; | |
// extend area | |
UINT64 AcpiRsdp; | |
UINT8 PhysicalAddressBits; | |
} TXT_PROCESSOR_SMM_DESCRIPTOR; | |
#pragma pack () | |
#endif |