UefiCpuPkg/PiSmmCpuDxeSmm: Fix memory protection crash
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.h
1 /** @file
2 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
3
4 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #ifndef _CPU_PISMMCPUDXESMM_H_
18 #define _CPU_PISMMCPUDXESMM_H_
19
20 #include <PiSmm.h>
21
22 #include <Protocol/MpService.h>
23 #include <Protocol/SmmConfiguration.h>
24 #include <Protocol/SmmCpu.h>
25 #include <Protocol/SmmAccess2.h>
26 #include <Protocol/SmmReadyToLock.h>
27 #include <Protocol/SmmCpuService.h>
28
29 #include <Guid/AcpiS3Context.h>
30 #include <Guid/PiSmmMemoryAttributesTable.h>
31
32 #include <Library/BaseLib.h>
33 #include <Library/IoLib.h>
34 #include <Library/TimerLib.h>
35 #include <Library/SynchronizationLib.h>
36 #include <Library/DebugLib.h>
37 #include <Library/BaseMemoryLib.h>
38 #include <Library/PcdLib.h>
39 #include <Library/CacheMaintenanceLib.h>
40 #include <Library/MtrrLib.h>
41 #include <Library/SmmCpuPlatformHookLib.h>
42 #include <Library/SmmServicesTableLib.h>
43 #include <Library/MemoryAllocationLib.h>
44 #include <Library/UefiBootServicesTableLib.h>
45 #include <Library/UefiRuntimeServicesTableLib.h>
46 #include <Library/DebugAgentLib.h>
47 #include <Library/HobLib.h>
48 #include <Library/LocalApicLib.h>
49 #include <Library/UefiCpuLib.h>
50 #include <Library/CpuExceptionHandlerLib.h>
51 #include <Library/ReportStatusCodeLib.h>
52 #include <Library/SmmCpuFeaturesLib.h>
53 #include <Library/PeCoffGetEntryPointLib.h>
54
55 #include <AcpiCpuData.h>
56 #include <CpuHotPlugData.h>
57
58 #include <Register/Cpuid.h>
59 #include <Register/Msr.h>
60
61 #include "CpuService.h"
62 #include "SmmProfile.h"
63
64 //
65 // MSRs required for configuration of SMM Code Access Check
66 //
67 #define EFI_MSR_SMM_MCA_CAP 0x17D
68 #define SMM_CODE_ACCESS_CHK_BIT BIT58
69
70 #define SMM_FEATURE_CONTROL_LOCK_BIT BIT0
71 #define SMM_CODE_CHK_EN_BIT BIT2
72
73 ///
74 /// Page Table Entry
75 ///
76 #define IA32_PG_P BIT0
77 #define IA32_PG_RW BIT1
78 #define IA32_PG_U BIT2
79 #define IA32_PG_WT BIT3
80 #define IA32_PG_CD BIT4
81 #define IA32_PG_A BIT5
82 #define IA32_PG_D BIT6
83 #define IA32_PG_PS BIT7
84 #define IA32_PG_PAT_2M BIT12
85 #define IA32_PG_PAT_4K IA32_PG_PS
86 #define IA32_PG_PMNT BIT62
87 #define IA32_PG_NX BIT63
88
89 #define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
90 //
91 // Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
92 // X64 PAE PDPTE does not have such restriction
93 //
94 #define IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P)
95
96 #define PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)
97
98 #define PAGING_4K_MASK 0xFFF
99 #define PAGING_2M_MASK 0x1FFFFF
100 #define PAGING_1G_MASK 0x3FFFFFFF
101
102 #define PAGING_PAE_INDEX_MASK 0x1FF
103
104 #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
105 #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
106 #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
107
108 #define SMRR_MAX_ADDRESS BASE_4GB
109
110 typedef enum {
111 PageNone,
112 Page4K,
113 Page2M,
114 Page1G,
115 } PAGE_ATTRIBUTE;
116
117 typedef struct {
118 PAGE_ATTRIBUTE Attribute;
119 UINT64 Length;
120 UINT64 AddressMask;
121 } PAGE_ATTRIBUTE_TABLE;
122
123 //
124 // Size of Task-State Segment defined in IA32 Manual
125 //
126 #define TSS_SIZE 104
127 #define TSS_X64_IST1_OFFSET 36
128 #define TSS_IA32_CR3_OFFSET 28
129 #define TSS_IA32_ESP_OFFSET 56
130
131 #define CR0_WP BIT16
132
133 //
134 // Code select value
135 //
136 #define PROTECT_MODE_CODE_SEGMENT 0x08
137 #define LONG_MODE_CODE_SEGMENT 0x38
138
139 //
140 // The size 0x20 must be bigger than
141 // the size of template code of SmmInit. Currently,
142 // the size of SmmInit requires the 0x16 Bytes buffer
143 // at least.
144 //
145 #define BACK_BUF_SIZE 0x20
146
147 #define EXCEPTION_VECTOR_NUMBER 0x20
148
149 #define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
150
151 typedef UINT32 SMM_CPU_ARRIVAL_EXCEPTIONS;
152 #define ARRIVAL_EXCEPTION_BLOCKED 0x1
153 #define ARRIVAL_EXCEPTION_DELAYED 0x2
154 #define ARRIVAL_EXCEPTION_SMI_DISABLED 0x4
155
156 //
157 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
158 // Contains the SMM Configuration Protocols that is produced.
159 // Contains a mix of DXE and SMM contents. All the fields must be used properly.
160 //
161 #define SMM_CPU_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('s', 'c', 'p', 'u')
162
163 typedef struct {
164 UINTN Signature;
165
166 EFI_HANDLE SmmCpuHandle;
167
168 EFI_PROCESSOR_INFORMATION *ProcessorInfo;
169 SMM_CPU_OPERATION *Operation;
170 UINTN *CpuSaveStateSize;
171 VOID **CpuSaveState;
172
173 EFI_SMM_RESERVED_SMRAM_REGION SmmReservedSmramRegion[1];
174 EFI_SMM_ENTRY_CONTEXT SmmCoreEntryContext;
175 EFI_SMM_ENTRY_POINT SmmCoreEntry;
176
177 EFI_SMM_CONFIGURATION_PROTOCOL SmmConfiguration;
178 } SMM_CPU_PRIVATE_DATA;
179
180 extern SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate;
181 extern CPU_HOT_PLUG_DATA mCpuHotPlugData;
182 extern UINTN mMaxNumberOfCpus;
183 extern UINTN mNumberOfCpus;
184 extern EFI_SMM_CPU_PROTOCOL mSmmCpu;
185
186 ///
187 /// The mode of the CPU at the time an SMI occurs
188 ///
189 extern UINT8 mSmmSaveStateRegisterLma;
190
191 //
192 // SMM CPU Protocol function prototypes.
193 //
194
195 /**
196 Read information from the CPU save state.
197
198 @param This EFI_SMM_CPU_PROTOCOL instance
199 @param Width The number of bytes to read from the CPU save state.
200 @param Register Specifies the CPU register to read form the save state.
201 @param CpuIndex Specifies the zero-based index of the CPU save state
202 @param Buffer Upon return, this holds the CPU register value read from the save state.
203
204 @retval EFI_SUCCESS The register was read from Save State
205 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
206 @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
207
208 **/
209 EFI_STATUS
210 EFIAPI
211 SmmReadSaveState (
212 IN CONST EFI_SMM_CPU_PROTOCOL *This,
213 IN UINTN Width,
214 IN EFI_SMM_SAVE_STATE_REGISTER Register,
215 IN UINTN CpuIndex,
216 OUT VOID *Buffer
217 );
218
219 /**
220 Write data to the CPU save state.
221
222 @param This EFI_SMM_CPU_PROTOCOL instance
223 @param Width The number of bytes to read from the CPU save state.
224 @param Register Specifies the CPU register to write to the save state.
225 @param CpuIndex Specifies the zero-based index of the CPU save state
226 @param Buffer Upon entry, this holds the new CPU register value.
227
228 @retval EFI_SUCCESS The register was written from Save State
229 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
230 @retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct
231
232 **/
233 EFI_STATUS
234 EFIAPI
235 SmmWriteSaveState (
236 IN CONST EFI_SMM_CPU_PROTOCOL *This,
237 IN UINTN Width,
238 IN EFI_SMM_SAVE_STATE_REGISTER Register,
239 IN UINTN CpuIndex,
240 IN CONST VOID *Buffer
241 );
242
243 /**
244 Read a CPU Save State register on the target processor.
245
246 This function abstracts the differences that whether the CPU Save State register is in the
247 IA32 CPU Save State Map or X64 CPU Save State Map.
248
249 This function supports reading a CPU Save State register in SMBase relocation handler.
250
251 @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
252 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.
253 @param[in] Width The number of bytes to read from the CPU save state.
254 @param[out] Buffer Upon return, this holds the CPU register value read from the save state.
255
256 @retval EFI_SUCCESS The register was read from Save State.
257 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
258 @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
259
260 **/
261 EFI_STATUS
262 EFIAPI
263 ReadSaveStateRegister (
264 IN UINTN CpuIndex,
265 IN EFI_SMM_SAVE_STATE_REGISTER Register,
266 IN UINTN Width,
267 OUT VOID *Buffer
268 );
269
270 /**
271 Write value to a CPU Save State register on the target processor.
272
273 This function abstracts the differences that whether the CPU Save State register is in the
274 IA32 CPU Save State Map or X64 CPU Save State Map.
275
276 This function supports writing a CPU Save State register in SMBase relocation handler.
277
278 @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
279 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.
280 @param[in] Width The number of bytes to read from the CPU save state.
281 @param[in] Buffer Upon entry, this holds the new CPU register value.
282
283 @retval EFI_SUCCESS The register was written to Save State.
284 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
285 @retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct.
286
287 **/
288 EFI_STATUS
289 EFIAPI
290 WriteSaveStateRegister (
291 IN UINTN CpuIndex,
292 IN EFI_SMM_SAVE_STATE_REGISTER Register,
293 IN UINTN Width,
294 IN CONST VOID *Buffer
295 );
296
297 //
298 //
299 //
300 typedef struct {
301 UINT32 Offset;
302 UINT16 Segment;
303 UINT16 Reserved;
304 } IA32_FAR_ADDRESS;
305
306 extern IA32_FAR_ADDRESS gSmmJmpAddr;
307
308 extern CONST UINT8 gcSmmInitTemplate[];
309 extern CONST UINT16 gcSmmInitSize;
310 extern UINT32 gSmmCr0;
311 extern UINT32 gSmmCr3;
312 extern UINT32 gSmmCr4;
313 extern UINTN gSmmInitStack;
314
315 /**
316 Semaphore operation for all processor relocate SMMBase.
317 **/
318 VOID
319 EFIAPI
320 SmmRelocationSemaphoreComplete (
321 VOID
322 );
323
324 ///
325 /// The type of SMM CPU Information
326 ///
327 typedef struct {
328 SPIN_LOCK *Busy;
329 volatile EFI_AP_PROCEDURE Procedure;
330 volatile VOID *Parameter;
331 volatile UINT32 *Run;
332 volatile BOOLEAN *Present;
333 } SMM_CPU_DATA_BLOCK;
334
335 typedef enum {
336 SmmCpuSyncModeTradition,
337 SmmCpuSyncModeRelaxedAp,
338 SmmCpuSyncModeMax
339 } SMM_CPU_SYNC_MODE;
340
341 typedef struct {
342 //
343 // Pointer to an array. The array should be located immediately after this structure
344 // so that UC cache-ability can be set together.
345 //
346 SMM_CPU_DATA_BLOCK *CpuData;
347 volatile UINT32 *Counter;
348 volatile UINT32 BspIndex;
349 volatile BOOLEAN *InsideSmm;
350 volatile BOOLEAN *AllCpusInSync;
351 volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;
352 volatile BOOLEAN SwitchBsp;
353 volatile BOOLEAN *CandidateBsp;
354 } SMM_DISPATCHER_MP_SYNC_DATA;
355
356 #define MSR_SPIN_LOCK_INIT_NUM 15
357
358 typedef struct {
359 SPIN_LOCK *SpinLock;
360 UINT32 MsrIndex;
361 } MP_MSR_LOCK;
362
363 #define SMM_PSD_OFFSET 0xfb00
364
365 ///
366 /// All global semaphores' pointer
367 ///
368 typedef struct {
369 volatile UINT32 *Counter;
370 volatile BOOLEAN *InsideSmm;
371 volatile BOOLEAN *AllCpusInSync;
372 SPIN_LOCK *PFLock;
373 SPIN_LOCK *CodeAccessCheckLock;
374 SPIN_LOCK *MemoryMappedLock;
375 } SMM_CPU_SEMAPHORE_GLOBAL;
376
377 ///
378 /// All semaphores for each processor
379 ///
380 typedef struct {
381 SPIN_LOCK *Busy;
382 volatile UINT32 *Run;
383 volatile BOOLEAN *Present;
384 } SMM_CPU_SEMAPHORE_CPU;
385
386 ///
387 /// All MSRs semaphores' pointer and counter
388 ///
389 typedef struct {
390 SPIN_LOCK *Msr;
391 UINTN AvailableCounter;
392 } SMM_CPU_SEMAPHORE_MSR;
393
394 ///
395 /// All semaphores' information
396 ///
397 typedef struct {
398 SMM_CPU_SEMAPHORE_GLOBAL SemaphoreGlobal;
399 SMM_CPU_SEMAPHORE_CPU SemaphoreCpu;
400 SMM_CPU_SEMAPHORE_MSR SemaphoreMsr;
401 } SMM_CPU_SEMAPHORES;
402
403 extern IA32_DESCRIPTOR gcSmiGdtr;
404 extern EFI_PHYSICAL_ADDRESS mGdtBuffer;
405 extern UINTN mGdtBufferSize;
406 extern IA32_DESCRIPTOR gcSmiIdtr;
407 extern VOID *gcSmiIdtrPtr;
408 extern UINT64 gPhyMask;
409 extern SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData;
410 extern UINTN mSmmStackArrayBase;
411 extern UINTN mSmmStackArrayEnd;
412 extern UINTN mSmmStackSize;
413 extern EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService;
414 extern IA32_DESCRIPTOR gcSmiInitGdtr;
415 extern SMM_CPU_SEMAPHORES mSmmCpuSemaphores;
416 extern UINTN mSemaphoreSize;
417 extern SPIN_LOCK *mPFLock;
418 extern SPIN_LOCK *mConfigSmmCodeAccessCheckLock;
419 extern SPIN_LOCK *mMemoryMappedLock;
420 extern EFI_SMRAM_DESCRIPTOR *mSmmCpuSmramRanges;
421 extern UINTN mSmmCpuSmramRangeCount;
422 extern UINT8 mPhysicalAddressBits;
423
424 //
425 // Copy of the PcdPteMemoryEncryptionAddressOrMask
426 //
427 extern UINT64 mAddressEncMask;
428
429 /**
430 Create 4G PageTable in SMRAM.
431
432 @param[in] Is32BitPageTable Whether the page table is 32-bit PAE
433 @return PageTable Address
434
435 **/
436 UINT32
437 Gen4GPageTable (
438 IN BOOLEAN Is32BitPageTable
439 );
440
441
442 /**
443 Initialize global data for MP synchronization.
444
445 @param Stacks Base address of SMI stack buffer for all processors.
446 @param StackSize Stack size for each processor in SMM.
447
448 **/
449 UINT32
450 InitializeMpServiceData (
451 IN VOID *Stacks,
452 IN UINTN StackSize
453 );
454
455 /**
456 Initialize Timer for SMM AP Sync.
457
458 **/
459 VOID
460 InitializeSmmTimer (
461 VOID
462 );
463
464 /**
465 Start Timer for SMM AP Sync.
466
467 **/
468 UINT64
469 EFIAPI
470 StartSyncTimer (
471 VOID
472 );
473
474 /**
475 Check if the SMM AP Sync timer is timeout.
476
477 @param Timer The start timer from the begin.
478
479 **/
480 BOOLEAN
481 EFIAPI
482 IsSyncTimerTimeout (
483 IN UINT64 Timer
484 );
485
486 /**
487 Initialize IDT for SMM Stack Guard.
488
489 **/
490 VOID
491 EFIAPI
492 InitializeIDTSmmStackGuard (
493 VOID
494 );
495
496 /**
497 Initialize Gdt for all processors.
498
499 @param[in] Cr3 CR3 value.
500 @param[out] GdtStepSize The step size for GDT table.
501
502 @return GdtBase for processor 0.
503 GdtBase for processor X is: GdtBase + (GdtStepSize * X)
504 **/
505 VOID *
506 InitGdt (
507 IN UINTN Cr3,
508 OUT UINTN *GdtStepSize
509 );
510
511 /**
512 This function sets GDT/IDT buffer to be RO and XP.
513 **/
514 VOID
515 PatchGdtIdtMap (
516 VOID
517 );
518
519 /**
520
521 Register the SMM Foundation entry point.
522
523 @param This Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
524 @param SmmEntryPoint SMM Foundation EntryPoint
525
526 @retval EFI_SUCCESS Successfully to register SMM foundation entry point
527
528 **/
529 EFI_STATUS
530 EFIAPI
531 RegisterSmmEntry (
532 IN CONST EFI_SMM_CONFIGURATION_PROTOCOL *This,
533 IN EFI_SMM_ENTRY_POINT SmmEntryPoint
534 );
535
536 /**
537 Create PageTable for SMM use.
538
539 @return PageTable Address
540
541 **/
542 UINT32
543 SmmInitPageTable (
544 VOID
545 );
546
547 /**
548 Schedule a procedure to run on the specified CPU.
549
550 @param Procedure The address of the procedure to run
551 @param CpuIndex Target CPU number
552 @param ProcArguments The parameter to pass to the procedure
553
554 @retval EFI_INVALID_PARAMETER CpuNumber not valid
555 @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
556 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
557 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
558 @retval EFI_SUCCESS - The procedure has been successfully scheduled
559
560 **/
561 EFI_STATUS
562 EFIAPI
563 SmmStartupThisAp (
564 IN EFI_AP_PROCEDURE Procedure,
565 IN UINTN CpuIndex,
566 IN OUT VOID *ProcArguments OPTIONAL
567 );
568
569 /**
570 Schedule a procedure to run on the specified CPU in a blocking fashion.
571
572 @param Procedure The address of the procedure to run
573 @param CpuIndex Target CPU Index
574 @param ProcArguments The parameter to pass to the procedure
575
576 @retval EFI_INVALID_PARAMETER CpuNumber not valid
577 @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
578 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
579 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
580 @retval EFI_SUCCESS The procedure has been successfully scheduled
581
582 **/
583 EFI_STATUS
584 EFIAPI
585 SmmBlockingStartupThisAp (
586 IN EFI_AP_PROCEDURE Procedure,
587 IN UINTN CpuIndex,
588 IN OUT VOID *ProcArguments OPTIONAL
589 );
590
591 /**
592 This function sets the attributes for the memory region specified by BaseAddress and
593 Length from their current attributes to the attributes specified by Attributes.
594
595 @param[in] BaseAddress The physical address that is the start address of a memory region.
596 @param[in] Length The size in bytes of the memory region.
597 @param[in] Attributes The bit mask of attributes to set for the memory region.
598
599 @retval EFI_SUCCESS The attributes were set for the memory region.
600 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
601 BaseAddress and Length cannot be modified.
602 @retval EFI_INVALID_PARAMETER Length is zero.
603 Attributes specified an illegal combination of attributes that
604 cannot be set together.
605 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
606 the memory resource range.
607 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
608 resource range specified by BaseAddress and Length.
609 The bit mask of attributes is not support for the memory resource
610 range specified by BaseAddress and Length.
611
612 **/
613 EFI_STATUS
614 EFIAPI
615 SmmSetMemoryAttributes (
616 IN EFI_PHYSICAL_ADDRESS BaseAddress,
617 IN UINT64 Length,
618 IN UINT64 Attributes
619 );
620
621 /**
622 This function clears the attributes for the memory region specified by BaseAddress and
623 Length from their current attributes to the attributes specified by Attributes.
624
625 @param[in] BaseAddress The physical address that is the start address of a memory region.
626 @param[in] Length The size in bytes of the memory region.
627 @param[in] Attributes The bit mask of attributes to clear for the memory region.
628
629 @retval EFI_SUCCESS The attributes were cleared for the memory region.
630 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
631 BaseAddress and Length cannot be modified.
632 @retval EFI_INVALID_PARAMETER Length is zero.
633 Attributes specified an illegal combination of attributes that
634 cannot be set together.
635 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
636 the memory resource range.
637 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
638 resource range specified by BaseAddress and Length.
639 The bit mask of attributes is not support for the memory resource
640 range specified by BaseAddress and Length.
641
642 **/
643 EFI_STATUS
644 EFIAPI
645 SmmClearMemoryAttributes (
646 IN EFI_PHYSICAL_ADDRESS BaseAddress,
647 IN UINT64 Length,
648 IN UINT64 Attributes
649 );
650
651 /**
652 Initialize MP synchronization data.
653
654 **/
655 VOID
656 EFIAPI
657 InitializeMpSyncData (
658 VOID
659 );
660
661 /**
662
663 Find out SMRAM information including SMRR base and SMRR size.
664
665 @param SmrrBase SMRR base
666 @param SmrrSize SMRR size
667
668 **/
669 VOID
670 FindSmramInfo (
671 OUT UINT32 *SmrrBase,
672 OUT UINT32 *SmrrSize
673 );
674
675 /**
676 Relocate SmmBases for each processor.
677
678 Execute on first boot and all S3 resumes
679
680 **/
681 VOID
682 EFIAPI
683 SmmRelocateBases (
684 VOID
685 );
686
687 /**
688 Page Fault handler for SMM use.
689
690 @param InterruptType Defines the type of interrupt or exception that
691 occurred on the processor.This parameter is processor architecture specific.
692 @param SystemContext A pointer to the processor context when
693 the interrupt occurred on the processor.
694 **/
695 VOID
696 EFIAPI
697 SmiPFHandler (
698 IN EFI_EXCEPTION_TYPE InterruptType,
699 IN EFI_SYSTEM_CONTEXT SystemContext
700 );
701
702 /**
703 Perform the remaining tasks.
704
705 **/
706 VOID
707 PerformRemainingTasks (
708 VOID
709 );
710
711 /**
712 Perform the pre tasks.
713
714 **/
715 VOID
716 PerformPreTasks (
717 VOID
718 );
719
720 /**
721 Initialize MSR spin lock by MSR index.
722
723 @param MsrIndex MSR index value.
724
725 **/
726 VOID
727 InitMsrSpinLockByIndex (
728 IN UINT32 MsrIndex
729 );
730
731 /**
732 Hook return address of SMM Save State so that semaphore code
733 can be executed immediately after AP exits SMM to indicate to
734 the BSP that an AP has exited SMM after SMBASE relocation.
735
736 @param[in] CpuIndex The processor index.
737 @param[in] RebasedFlag A pointer to a flag that is set to TRUE
738 immediately after AP exits SMM.
739
740 **/
741 VOID
742 SemaphoreHook (
743 IN UINTN CpuIndex,
744 IN volatile BOOLEAN *RebasedFlag
745 );
746
747 /**
748 Configure SMM Code Access Check feature for all processors.
749 SMM Feature Control MSR will be locked after configuration.
750 **/
751 VOID
752 ConfigSmmCodeAccessCheck (
753 VOID
754 );
755
756 /**
757 Hook the code executed immediately after an RSM instruction on the currently
758 executing CPU. The mode of code executed immediately after RSM must be
759 detected, and the appropriate hook must be selected. Always clear the auto
760 HALT restart flag if it is set.
761
762 @param[in] CpuIndex The processor index for the currently
763 executing CPU.
764 @param[in] CpuState Pointer to SMRAM Save State Map for the
765 currently executing CPU.
766 @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
767 32-bit mode from 64-bit SMM.
768 @param[in] NewInstructionPointer Instruction pointer to use if resuming to
769 same mode as SMM.
770
771 @retval The value of the original instruction pointer before it was hooked.
772
773 **/
774 UINT64
775 EFIAPI
776 HookReturnFromSmm (
777 IN UINTN CpuIndex,
778 SMRAM_SAVE_STATE_MAP *CpuState,
779 UINT64 NewInstructionPointer32,
780 UINT64 NewInstructionPointer
781 );
782
783 /**
784 Get the size of the SMI Handler in bytes.
785
786 @retval The size, in bytes, of the SMI Handler.
787
788 **/
789 UINTN
790 EFIAPI
791 GetSmiHandlerSize (
792 VOID
793 );
794
795 /**
796 Install the SMI handler for the CPU specified by CpuIndex. This function
797 is called by the CPU that was elected as monarch during System Management
798 Mode initialization.
799
800 @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
801 The value must be between 0 and the NumberOfCpus field
802 in the System Management System Table (SMST).
803 @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
804 @param[in] SmiStack The stack to use when an SMI is processed by the
805 the CPU specified by CpuIndex.
806 @param[in] StackSize The size, in bytes, if the stack used when an SMI is
807 processed by the CPU specified by CpuIndex.
808 @param[in] GdtBase The base address of the GDT to use when an SMI is
809 processed by the CPU specified by CpuIndex.
810 @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
811 processed by the CPU specified by CpuIndex.
812 @param[in] IdtBase The base address of the IDT to use when an SMI is
813 processed by the CPU specified by CpuIndex.
814 @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
815 processed by the CPU specified by CpuIndex.
816 @param[in] Cr3 The base address of the page tables to use when an SMI
817 is processed by the CPU specified by CpuIndex.
818 **/
819 VOID
820 EFIAPI
821 InstallSmiHandler (
822 IN UINTN CpuIndex,
823 IN UINT32 SmBase,
824 IN VOID *SmiStack,
825 IN UINTN StackSize,
826 IN UINTN GdtBase,
827 IN UINTN GdtSize,
828 IN UINTN IdtBase,
829 IN UINTN IdtSize,
830 IN UINT32 Cr3
831 );
832
833 /**
834 Search module name by input IP address and output it.
835
836 @param CallerIpAddress Caller instruction pointer.
837
838 **/
839 VOID
840 DumpModuleInfoByIp (
841 IN UINTN CallerIpAddress
842 );
843
844 /**
845 This function sets memory attribute according to MemoryAttributesTable.
846 **/
847 VOID
848 SetMemMapAttributes (
849 VOID
850 );
851
852 /**
853 This function sets UEFI memory attribute according to UEFI memory map.
854 **/
855 VOID
856 SetUefiMemMapAttributes (
857 VOID
858 );
859
860 /**
861 Return if the Address is forbidden as SMM communication buffer.
862
863 @param[in] Address the address to be checked
864
865 @return TRUE The address is forbidden as SMM communication buffer.
866 @return FALSE The address is allowed as SMM communication buffer.
867 **/
868 BOOLEAN
869 IsSmmCommBufferForbiddenAddress (
870 IN UINT64 Address
871 );
872
873 /**
874 This function caches the UEFI memory map information.
875 **/
876 VOID
877 GetUefiMemoryMap (
878 VOID
879 );
880
881 /**
882 This function sets memory attribute for page table.
883 **/
884 VOID
885 SetPageTableAttributes (
886 VOID
887 );
888
889 /**
890 Return page table base.
891
892 @return page table base.
893 **/
894 UINTN
895 GetPageTableBase (
896 VOID
897 );
898
899 /**
900 This function sets the attributes for the memory region specified by BaseAddress and
901 Length from their current attributes to the attributes specified by Attributes.
902
903 @param[in] BaseAddress The physical address that is the start address of a memory region.
904 @param[in] Length The size in bytes of the memory region.
905 @param[in] Attributes The bit mask of attributes to set for the memory region.
906 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
907
908 @retval EFI_SUCCESS The attributes were set for the memory region.
909 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
910 BaseAddress and Length cannot be modified.
911 @retval EFI_INVALID_PARAMETER Length is zero.
912 Attributes specified an illegal combination of attributes that
913 cannot be set together.
914 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
915 the memory resource range.
916 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
917 resource range specified by BaseAddress and Length.
918 The bit mask of attributes is not support for the memory resource
919 range specified by BaseAddress and Length.
920
921 **/
922 EFI_STATUS
923 EFIAPI
924 SmmSetMemoryAttributesEx (
925 IN EFI_PHYSICAL_ADDRESS BaseAddress,
926 IN UINT64 Length,
927 IN UINT64 Attributes,
928 OUT BOOLEAN *IsSplitted OPTIONAL
929 );
930
931 /**
932 This function clears the attributes for the memory region specified by BaseAddress and
933 Length from their current attributes to the attributes specified by Attributes.
934
935 @param[in] BaseAddress The physical address that is the start address of a memory region.
936 @param[in] Length The size in bytes of the memory region.
937 @param[in] Attributes The bit mask of attributes to clear for the memory region.
938 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
939
940 @retval EFI_SUCCESS The attributes were cleared for the memory region.
941 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
942 BaseAddress and Length cannot be modified.
943 @retval EFI_INVALID_PARAMETER Length is zero.
944 Attributes specified an illegal combination of attributes that
945 cannot be set together.
946 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
947 the memory resource range.
948 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
949 resource range specified by BaseAddress and Length.
950 The bit mask of attributes is not support for the memory resource
951 range specified by BaseAddress and Length.
952
953 **/
954 EFI_STATUS
955 EFIAPI
956 SmmClearMemoryAttributesEx (
957 IN EFI_PHYSICAL_ADDRESS BaseAddress,
958 IN UINT64 Length,
959 IN UINT64 Attributes,
960 OUT BOOLEAN *IsSplitted OPTIONAL
961 );
962
963 /**
964 This API provides a way to allocate memory for page table.
965
966 This API can be called more once to allocate memory for page tables.
967
968 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
969 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
970 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
971 returned.
972
973 @param Pages The number of 4 KB pages to allocate.
974
975 @return A pointer to the allocated buffer or NULL if allocation fails.
976
977 **/
978 VOID *
979 AllocatePageTableMemory (
980 IN UINTN Pages
981 );
982
983 /**
984 Allocate pages for code.
985
986 @param[in] Pages Number of pages to be allocated.
987
988 @return Allocated memory.
989 **/
990 VOID *
991 AllocateCodePages (
992 IN UINTN Pages
993 );
994
995 /**
996 Allocate aligned pages for code.
997
998 @param[in] Pages Number of pages to be allocated.
999 @param[in] Alignment The requested alignment of the allocation.
1000 Must be a power of two.
1001 If Alignment is zero, then byte alignment is used.
1002
1003 @return Allocated memory.
1004 **/
1005 VOID *
1006 AllocateAlignedCodePages (
1007 IN UINTN Pages,
1008 IN UINTN Alignment
1009 );
1010
1011
1012 //
1013 // S3 related global variable and function prototype.
1014 //
1015
1016 extern BOOLEAN mSmmS3Flag;
1017
1018 /**
1019 Initialize SMM S3 resume state structure used during S3 Resume.
1020
1021 @param[in] Cr3 The base address of the page tables to use in SMM.
1022
1023 **/
1024 VOID
1025 InitSmmS3ResumeState (
1026 IN UINT32 Cr3
1027 );
1028
1029 /**
1030 Get ACPI CPU data.
1031
1032 **/
1033 VOID
1034 GetAcpiCpuData (
1035 VOID
1036 );
1037
1038 /**
1039 Restore SMM Configuration in S3 boot path.
1040
1041 **/
1042 VOID
1043 RestoreSmmConfigurationInS3 (
1044 VOID
1045 );
1046
1047 /**
1048 Get ACPI S3 enable flag.
1049
1050 **/
1051 VOID
1052 GetAcpiS3EnableFlag (
1053 VOID
1054 );
1055
1056 /**
1057 Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
1058
1059 @param[in] ApHltLoopCode The address of the safe hlt-loop function.
1060 @param[in] TopOfStack A pointer to the new stack to use for the ApHltLoopCode.
1061 @param[in] NumberToFinishAddress Address of Semaphore of APs finish count.
1062
1063 **/
1064 VOID
1065 TransferApToSafeState (
1066 IN UINTN ApHltLoopCode,
1067 IN UINTN TopOfStack,
1068 IN UINTN NumberToFinishAddress
1069 );
1070
1071 #endif