SmmCpuFeaturesLib.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /** @file
  2. Library that provides CPU specific functions to support the PiSmmCpuDxeSmm module.
  3. Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #ifndef __SMM_FEATURES_LIB_H__
  7. #define __SMM_FEATURES_LIB_H__
  8. #include <Protocol/MpService.h>
  9. #include <Protocol/SmmCpu.h>
  10. #include <Register/Intel/SmramSaveStateMap.h>
  11. #include <CpuHotPlugData.h>
  12. ///
  13. /// Enumeration of SMM registers that are accessed using the library functions
  14. /// SmmCpuFeaturesIsSmmRegisterSupported (), SmmCpuFeaturesGetSmmRegister (),
  15. /// and SmmCpuFeaturesSetSmmRegister ().
  16. ///
  17. typedef enum {
  18. ///
  19. /// Read-write register to provides access to MSR_SMM_FEATURE_CONTROL if the
  20. /// CPU supports this MSR.
  21. ///
  22. SmmRegFeatureControl,
  23. ///
  24. /// Read-only register that returns a non-zero value if the CPU is able to
  25. /// respond to SMIs.
  26. ///
  27. SmmRegSmmEnable,
  28. ///
  29. /// Read-only register that returns a non-zero value if the CPU is able to
  30. /// respond to SMIs, but is busy with other actions that are causing a delay
  31. /// in responding to an SMI. This register abstracts access to MSR_SMM_DELAYED
  32. /// if the CPU supports this MSR.
  33. ///
  34. SmmRegSmmDelayed,
  35. ///
  36. /// Read-only register that returns a non-zero value if the CPU is able to
  37. /// respond to SMIs, but is busy with other actions that are blocking its
  38. /// ability to respond to an SMI. This register abstracts access to
  39. /// MSR_SMM_BLOCKED if the CPU supports this MSR.
  40. ///
  41. SmmRegSmmBlocked
  42. } SMM_REG_NAME;
  43. /**
  44. Called during the very first SMI into System Management Mode to initialize
  45. CPU features, including SMBASE, for the currently executing CPU. Since this
  46. is the first SMI, the SMRAM Save State Map is at the default address of
  47. SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
  48. CPU is specified by CpuIndex and CpuIndex can be used to access information
  49. about the currently executing CPU in the ProcessorInfo array and the
  50. HotPlugCpuData data structure.
  51. @param[in] CpuIndex The index of the CPU to initialize. The value
  52. must be between 0 and the NumberOfCpus field in
  53. the System Management System Table (SMST).
  54. @param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
  55. was elected as monarch during System Management
  56. Mode initialization.
  57. FALSE if the CpuIndex is not the index of the CPU
  58. that was elected as monarch during System
  59. Management Mode initialization.
  60. @param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
  61. structures. ProcessorInfo[CpuIndex] contains the
  62. information for the currently executing CPU.
  63. @param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
  64. contains the ApidId and SmBase arrays.
  65. **/
  66. VOID
  67. EFIAPI
  68. SmmCpuFeaturesInitializeProcessor (
  69. IN UINTN CpuIndex,
  70. IN BOOLEAN IsMonarch,
  71. IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
  72. IN CPU_HOT_PLUG_DATA *CpuHotPlugData
  73. );
  74. /**
  75. This function updates the SMRAM save state on the currently executing CPU
  76. to resume execution at a specific address after an RSM instruction. This
  77. function must evaluate the SMRAM save state to determine the execution mode
  78. the RSM instruction resumes and update the resume execution address with
  79. either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
  80. flag in the SMRAM save state must always be cleared. This function returns
  81. the value of the instruction pointer from the SMRAM save state that was
  82. replaced. If this function returns 0, then the SMRAM save state was not
  83. modified.
  84. This function is called during the very first SMI on each CPU after
  85. SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
  86. to signal that the SMBASE of each CPU has been updated before the default
  87. SMBASE address is used for the first SMI to the next CPU.
  88. @param[in] CpuIndex The index of the CPU to hook. The value
  89. must be between 0 and the NumberOfCpus
  90. field in the System Management System Table
  91. (SMST).
  92. @param[in] CpuState Pointer to SMRAM Save State Map for the
  93. currently executing CPU.
  94. @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
  95. 32-bit execution mode from 64-bit SMM.
  96. @param[in] NewInstructionPointer Instruction pointer to use if resuming to
  97. same execution mode as SMM.
  98. @retval 0 This function did modify the SMRAM save state.
  99. @retval > 0 The original instruction pointer value from the SMRAM save state
  100. before it was replaced.
  101. **/
  102. UINT64
  103. EFIAPI
  104. SmmCpuFeaturesHookReturnFromSmm (
  105. IN UINTN CpuIndex,
  106. IN SMRAM_SAVE_STATE_MAP *CpuState,
  107. IN UINT64 NewInstructionPointer32,
  108. IN UINT64 NewInstructionPointer
  109. );
  110. /**
  111. Hook point in normal execution mode that allows the one CPU that was elected
  112. as monarch during System Management Mode initialization to perform additional
  113. initialization actions immediately after all of the CPUs have processed their
  114. first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
  115. into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
  116. **/
  117. VOID
  118. EFIAPI
  119. SmmCpuFeaturesSmmRelocationComplete (
  120. VOID
  121. );
  122. /**
  123. Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
  124. returned, then a custom SMI handler is not provided by this library,
  125. and the default SMI handler must be used.
  126. @retval 0 Use the default SMI handler.
  127. @retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
  128. The caller is required to allocate enough SMRAM for each CPU to
  129. support the size of the custom SMI handler.
  130. **/
  131. UINTN
  132. EFIAPI
  133. SmmCpuFeaturesGetSmiHandlerSize (
  134. VOID
  135. );
  136. /**
  137. Install a custom SMI handler for the CPU specified by CpuIndex. This function
  138. is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
  139. than zero and is called by the CPU that was elected as monarch during System
  140. Management Mode initialization.
  141. //
  142. // Append Shadow Stack after normal stack
  143. //
  144. // |= SmiStack
  145. // +--------------------------------------------------+---------------------------------------------------------------+
  146. // | Known Good Stack | Guard Page | SMM Stack | Known Good Shadow Stack | Guard Page | SMM Shadow Stack |
  147. // +--------------------------------------------------+---------------------------------------------------------------+
  148. // | |PcdCpuSmmStackSize| |PcdCpuSmmShadowStackSize|
  149. // |<-------------------- StackSize ----------------->|<------------------------- ShadowStackSize ------------------->|
  150. // | |
  151. // |<-------------------------------------------- Processor N ------------------------------------------------------->|
  152. // | low address (bottom) high address (top) |
  153. //
  154. @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
  155. The value must be between 0 and the NumberOfCpus field
  156. in the System Management System Table (SMST).
  157. @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
  158. @param[in] SmiStack The bottom of stack to use when an SMI is processed by the
  159. the CPU specified by CpuIndex.
  160. @param[in] StackSize The size, in bytes, if the stack used when an SMI is
  161. processed by the CPU specified by CpuIndex.
  162. StackSize should be PcdCpuSmmStackSize, with 2 more pages
  163. if PcdCpuSmmStackGuard is true.
  164. If ShadowStack is enabled, the shadow stack is allocated
  165. after the normal Stack. The size is PcdCpuSmmShadowStackSize.
  166. with 2 more pages if PcdCpuSmmStackGuard is true.
  167. @param[in] GdtBase The base address of the GDT to use when an SMI is
  168. processed by the CPU specified by CpuIndex.
  169. @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
  170. processed by the CPU specified by CpuIndex.
  171. @param[in] IdtBase The base address of the IDT to use when an SMI is
  172. processed by the CPU specified by CpuIndex.
  173. @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
  174. processed by the CPU specified by CpuIndex.
  175. @param[in] Cr3 The base address of the page tables to use when an SMI
  176. is processed by the CPU specified by CpuIndex.
  177. **/
  178. VOID
  179. EFIAPI
  180. SmmCpuFeaturesInstallSmiHandler (
  181. IN UINTN CpuIndex,
  182. IN UINT32 SmBase,
  183. IN VOID *SmiStack,
  184. IN UINTN StackSize,
  185. IN UINTN GdtBase,
  186. IN UINTN GdtSize,
  187. IN UINTN IdtBase,
  188. IN UINTN IdtSize,
  189. IN UINT32 Cr3
  190. );
  191. /**
  192. Determines if MTRR registers must be configured to set SMRAM cache-ability
  193. when executing in System Management Mode.
  194. @retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
  195. @retval FALSE MTRR registers do not need to be configured to set SMRAM
  196. cache-ability.
  197. **/
  198. BOOLEAN
  199. EFIAPI
  200. SmmCpuFeaturesNeedConfigureMtrrs (
  201. VOID
  202. );
  203. /**
  204. Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
  205. returns TRUE.
  206. **/
  207. VOID
  208. EFIAPI
  209. SmmCpuFeaturesDisableSmrr (
  210. VOID
  211. );
  212. /**
  213. Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
  214. returns TRUE.
  215. **/
  216. VOID
  217. EFIAPI
  218. SmmCpuFeaturesReenableSmrr (
  219. VOID
  220. );
  221. /**
  222. Processor specific hook point each time a CPU enters System Management Mode.
  223. @param[in] CpuIndex The index of the CPU that has entered SMM. The value
  224. must be between 0 and the NumberOfCpus field in the
  225. System Management System Table (SMST).
  226. **/
  227. VOID
  228. EFIAPI
  229. SmmCpuFeaturesRendezvousEntry (
  230. IN UINTN CpuIndex
  231. );
  232. /**
  233. Processor specific hook point each time a CPU exits System Management Mode.
  234. @param[in] CpuIndex The index of the CPU that is exiting SMM. The value must
  235. be between 0 and the NumberOfCpus field in the System
  236. Management System Table (SMST).
  237. **/
  238. VOID
  239. EFIAPI
  240. SmmCpuFeaturesRendezvousExit (
  241. IN UINTN CpuIndex
  242. );
  243. /**
  244. Check to see if an SMM register is supported by a specified CPU.
  245. @param[in] CpuIndex The index of the CPU to check for SMM register support.
  246. The value must be between 0 and the NumberOfCpus field
  247. in the System Management System Table (SMST).
  248. @param[in] RegName Identifies the SMM register to check for support.
  249. @retval TRUE The SMM register specified by RegName is supported by the CPU
  250. specified by CpuIndex.
  251. @retval FALSE The SMM register specified by RegName is not supported by the
  252. CPU specified by CpuIndex.
  253. **/
  254. BOOLEAN
  255. EFIAPI
  256. SmmCpuFeaturesIsSmmRegisterSupported (
  257. IN UINTN CpuIndex,
  258. IN SMM_REG_NAME RegName
  259. );
  260. /**
  261. Returns the current value of the SMM register for the specified CPU.
  262. If the SMM register is not supported, then 0 is returned.
  263. @param[in] CpuIndex The index of the CPU to read the SMM register. The
  264. value must be between 0 and the NumberOfCpus field in
  265. the System Management System Table (SMST).
  266. @param[in] RegName Identifies the SMM register to read.
  267. @return The value of the SMM register specified by RegName from the CPU
  268. specified by CpuIndex.
  269. **/
  270. UINT64
  271. EFIAPI
  272. SmmCpuFeaturesGetSmmRegister (
  273. IN UINTN CpuIndex,
  274. IN SMM_REG_NAME RegName
  275. );
  276. /**
  277. Sets the value of an SMM register on a specified CPU.
  278. If the SMM register is not supported, then no action is performed.
  279. @param[in] CpuIndex The index of the CPU to write the SMM register. The
  280. value must be between 0 and the NumberOfCpus field in
  281. the System Management System Table (SMST).
  282. @param[in] RegName Identifies the SMM register to write.
  283. registers are read-only.
  284. @param[in] Value The value to write to the SMM register.
  285. **/
  286. VOID
  287. EFIAPI
  288. SmmCpuFeaturesSetSmmRegister (
  289. IN UINTN CpuIndex,
  290. IN SMM_REG_NAME RegName,
  291. IN UINT64 Value
  292. );
  293. /**
  294. Read an SMM Save State register on the target processor. If this function
  295. returns EFI_UNSUPPORTED, then the caller is responsible for reading the
  296. SMM Save Sate register.
  297. @param[in] CpuIndex The index of the CPU to read the SMM Save State. The
  298. value must be between 0 and the NumberOfCpus field in
  299. the System Management System Table (SMST).
  300. @param[in] Register The SMM Save State register to read.
  301. @param[in] Width The number of bytes to read from the CPU save state.
  302. @param[out] Buffer Upon return, this holds the CPU register value read
  303. from the save state.
  304. @retval EFI_SUCCESS The register was read from Save State.
  305. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  306. @retval EFI_UNSUPPORTED This function does not support reading Register.
  307. **/
  308. EFI_STATUS
  309. EFIAPI
  310. SmmCpuFeaturesReadSaveStateRegister (
  311. IN UINTN CpuIndex,
  312. IN EFI_SMM_SAVE_STATE_REGISTER Register,
  313. IN UINTN Width,
  314. OUT VOID *Buffer
  315. );
  316. /**
  317. Writes an SMM Save State register on the target processor. If this function
  318. returns EFI_UNSUPPORTED, then the caller is responsible for writing the
  319. SMM Save Sate register.
  320. @param[in] CpuIndex The index of the CPU to write the SMM Save State. The
  321. value must be between 0 and the NumberOfCpus field in
  322. the System Management System Table (SMST).
  323. @param[in] Register The SMM Save State register to write.
  324. @param[in] Width The number of bytes to write to the CPU save state.
  325. @param[in] Buffer Upon entry, this holds the new CPU register value.
  326. @retval EFI_SUCCESS The register was written to Save State.
  327. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  328. @retval EFI_UNSUPPORTED This function does not support writing Register.
  329. **/
  330. EFI_STATUS
  331. EFIAPI
  332. SmmCpuFeaturesWriteSaveStateRegister (
  333. IN UINTN CpuIndex,
  334. IN EFI_SMM_SAVE_STATE_REGISTER Register,
  335. IN UINTN Width,
  336. IN CONST VOID *Buffer
  337. );
  338. /**
  339. This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
  340. notification is completely processed.
  341. **/
  342. VOID
  343. EFIAPI
  344. SmmCpuFeaturesCompleteSmmReadyToLock (
  345. VOID
  346. );
  347. /**
  348. This API provides a method for a CPU to allocate a specific region for storing page tables.
  349. This API can be called more once to allocate memory for page tables.
  350. Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
  351. allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
  352. is returned. If there is not enough memory remaining to satisfy the request, then NULL is
  353. returned.
  354. This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
  355. @param Pages The number of 4 KB pages to allocate.
  356. @return A pointer to the allocated buffer for page tables.
  357. @retval NULL Fail to allocate a specific region for storing page tables,
  358. Or there is no preference on where the page tables are allocated in SMRAM.
  359. **/
  360. VOID *
  361. EFIAPI
  362. SmmCpuFeaturesAllocatePageTableMemory (
  363. IN UINTN Pages
  364. );
  365. #endif