dbce9ec520fed30e862633979ca0e777ed539a91
[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
423 //
424 // Copy of the PcdPteMemoryEncryptionAddressOrMask
425 //
426 extern UINT64 mAddressEncMask;
427
428 /**
429 Create 4G PageTable in SMRAM.
430
431 @param[in] Is32BitPageTable Whether the page table is 32-bit PAE
432 @return PageTable Address
433
434 **/
435 UINT32
436 Gen4GPageTable (
437 IN BOOLEAN Is32BitPageTable
438 );
439
440
441 /**
442 Initialize global data for MP synchronization.
443
444 @param Stacks Base address of SMI stack buffer for all processors.
445 @param StackSize Stack size for each processor in SMM.
446
447 **/
448 UINT32
449 InitializeMpServiceData (
450 IN VOID *Stacks,
451 IN UINTN StackSize
452 );
453
454 /**
455 Initialize Timer for SMM AP Sync.
456
457 **/
458 VOID
459 InitializeSmmTimer (
460 VOID
461 );
462
463 /**
464 Start Timer for SMM AP Sync.
465
466 **/
467 UINT64
468 EFIAPI
469 StartSyncTimer (
470 VOID
471 );
472
473 /**
474 Check if the SMM AP Sync timer is timeout.
475
476 @param Timer The start timer from the begin.
477
478 **/
479 BOOLEAN
480 EFIAPI
481 IsSyncTimerTimeout (
482 IN UINT64 Timer
483 );
484
485 /**
486 Initialize IDT for SMM Stack Guard.
487
488 **/
489 VOID
490 EFIAPI
491 InitializeIDTSmmStackGuard (
492 VOID
493 );
494
495 /**
496 Initialize Gdt for all processors.
497
498 @param[in] Cr3 CR3 value.
499 @param[out] GdtStepSize The step size for GDT table.
500
501 @return GdtBase for processor 0.
502 GdtBase for processor X is: GdtBase + (GdtStepSize * X)
503 **/
504 VOID *
505 InitGdt (
506 IN UINTN Cr3,
507 OUT UINTN *GdtStepSize
508 );
509
510 /**
511 This function sets GDT/IDT buffer to be RO and XP.
512 **/
513 VOID
514 PatchGdtIdtMap (
515 VOID
516 );
517
518 /**
519
520 Register the SMM Foundation entry point.
521
522 @param This Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
523 @param SmmEntryPoint SMM Foundation EntryPoint
524
525 @retval EFI_SUCCESS Successfully to register SMM foundation entry point
526
527 **/
528 EFI_STATUS
529 EFIAPI
530 RegisterSmmEntry (
531 IN CONST EFI_SMM_CONFIGURATION_PROTOCOL *This,
532 IN EFI_SMM_ENTRY_POINT SmmEntryPoint
533 );
534
535 /**
536 Create PageTable for SMM use.
537
538 @return PageTable Address
539
540 **/
541 UINT32
542 SmmInitPageTable (
543 VOID
544 );
545
546 /**
547 Schedule a procedure to run on the specified CPU.
548
549 @param Procedure The address of the procedure to run
550 @param CpuIndex Target CPU number
551 @param ProcArguments The parameter to pass to the procedure
552
553 @retval EFI_INVALID_PARAMETER CpuNumber not valid
554 @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
555 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
556 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
557 @retval EFI_SUCCESS - The procedure has been successfully scheduled
558
559 **/
560 EFI_STATUS
561 EFIAPI
562 SmmStartupThisAp (
563 IN EFI_AP_PROCEDURE Procedure,
564 IN UINTN CpuIndex,
565 IN OUT VOID *ProcArguments OPTIONAL
566 );
567
568 /**
569 Schedule a procedure to run on the specified CPU in a blocking fashion.
570
571 @param Procedure The address of the procedure to run
572 @param CpuIndex Target CPU Index
573 @param ProcArguments The parameter to pass to the procedure
574
575 @retval EFI_INVALID_PARAMETER CpuNumber not valid
576 @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
577 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
578 @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
579 @retval EFI_SUCCESS The procedure has been successfully scheduled
580
581 **/
582 EFI_STATUS
583 EFIAPI
584 SmmBlockingStartupThisAp (
585 IN EFI_AP_PROCEDURE Procedure,
586 IN UINTN CpuIndex,
587 IN OUT VOID *ProcArguments OPTIONAL
588 );
589
590 /**
591 This function sets the attributes for the memory region specified by BaseAddress and
592 Length from their current attributes to the attributes specified by Attributes.
593
594 @param[in] BaseAddress The physical address that is the start address of a memory region.
595 @param[in] Length The size in bytes of the memory region.
596 @param[in] Attributes The bit mask of attributes to set for the memory region.
597
598 @retval EFI_SUCCESS The attributes were set for the memory region.
599 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
600 BaseAddress and Length cannot be modified.
601 @retval EFI_INVALID_PARAMETER Length is zero.
602 Attributes specified an illegal combination of attributes that
603 cannot be set together.
604 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
605 the memory resource range.
606 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
607 resource range specified by BaseAddress and Length.
608 The bit mask of attributes is not support for the memory resource
609 range specified by BaseAddress and Length.
610
611 **/
612 EFI_STATUS
613 EFIAPI
614 SmmSetMemoryAttributes (
615 IN EFI_PHYSICAL_ADDRESS BaseAddress,
616 IN UINT64 Length,
617 IN UINT64 Attributes
618 );
619
620 /**
621 This function clears the attributes for the memory region specified by BaseAddress and
622 Length from their current attributes to the attributes specified by Attributes.
623
624 @param[in] BaseAddress The physical address that is the start address of a memory region.
625 @param[in] Length The size in bytes of the memory region.
626 @param[in] Attributes The bit mask of attributes to clear for the memory region.
627
628 @retval EFI_SUCCESS The attributes were cleared for the memory region.
629 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
630 BaseAddress and Length cannot be modified.
631 @retval EFI_INVALID_PARAMETER Length is zero.
632 Attributes specified an illegal combination of attributes that
633 cannot be set together.
634 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
635 the memory resource range.
636 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
637 resource range specified by BaseAddress and Length.
638 The bit mask of attributes is not support for the memory resource
639 range specified by BaseAddress and Length.
640
641 **/
642 EFI_STATUS
643 EFIAPI
644 SmmClearMemoryAttributes (
645 IN EFI_PHYSICAL_ADDRESS BaseAddress,
646 IN UINT64 Length,
647 IN UINT64 Attributes
648 );
649
650 /**
651 Initialize MP synchronization data.
652
653 **/
654 VOID
655 EFIAPI
656 InitializeMpSyncData (
657 VOID
658 );
659
660 /**
661
662 Find out SMRAM information including SMRR base and SMRR size.
663
664 @param SmrrBase SMRR base
665 @param SmrrSize SMRR size
666
667 **/
668 VOID
669 FindSmramInfo (
670 OUT UINT32 *SmrrBase,
671 OUT UINT32 *SmrrSize
672 );
673
674 /**
675 Relocate SmmBases for each processor.
676
677 Execute on first boot and all S3 resumes
678
679 **/
680 VOID
681 EFIAPI
682 SmmRelocateBases (
683 VOID
684 );
685
686 /**
687 Page Fault handler for SMM use.
688
689 @param InterruptType Defines the type of interrupt or exception that
690 occurred on the processor.This parameter is processor architecture specific.
691 @param SystemContext A pointer to the processor context when
692 the interrupt occurred on the processor.
693 **/
694 VOID
695 EFIAPI
696 SmiPFHandler (
697 IN EFI_EXCEPTION_TYPE InterruptType,
698 IN EFI_SYSTEM_CONTEXT SystemContext
699 );
700
701 /**
702 Perform the remaining tasks.
703
704 **/
705 VOID
706 PerformRemainingTasks (
707 VOID
708 );
709
710 /**
711 Perform the pre tasks.
712
713 **/
714 VOID
715 PerformPreTasks (
716 VOID
717 );
718
719 /**
720 Initialize MSR spin lock by MSR index.
721
722 @param MsrIndex MSR index value.
723
724 **/
725 VOID
726 InitMsrSpinLockByIndex (
727 IN UINT32 MsrIndex
728 );
729
730 /**
731 Hook return address of SMM Save State so that semaphore code
732 can be executed immediately after AP exits SMM to indicate to
733 the BSP that an AP has exited SMM after SMBASE relocation.
734
735 @param[in] CpuIndex The processor index.
736 @param[in] RebasedFlag A pointer to a flag that is set to TRUE
737 immediately after AP exits SMM.
738
739 **/
740 VOID
741 SemaphoreHook (
742 IN UINTN CpuIndex,
743 IN volatile BOOLEAN *RebasedFlag
744 );
745
746 /**
747 Configure SMM Code Access Check feature for all processors.
748 SMM Feature Control MSR will be locked after configuration.
749 **/
750 VOID
751 ConfigSmmCodeAccessCheck (
752 VOID
753 );
754
755 /**
756 Hook the code executed immediately after an RSM instruction on the currently
757 executing CPU. The mode of code executed immediately after RSM must be
758 detected, and the appropriate hook must be selected. Always clear the auto
759 HALT restart flag if it is set.
760
761 @param[in] CpuIndex The processor index for the currently
762 executing CPU.
763 @param[in] CpuState Pointer to SMRAM Save State Map for the
764 currently executing CPU.
765 @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
766 32-bit mode from 64-bit SMM.
767 @param[in] NewInstructionPointer Instruction pointer to use if resuming to
768 same mode as SMM.
769
770 @retval The value of the original instruction pointer before it was hooked.
771
772 **/
773 UINT64
774 EFIAPI
775 HookReturnFromSmm (
776 IN UINTN CpuIndex,
777 SMRAM_SAVE_STATE_MAP *CpuState,
778 UINT64 NewInstructionPointer32,
779 UINT64 NewInstructionPointer
780 );
781
782 /**
783 Get the size of the SMI Handler in bytes.
784
785 @retval The size, in bytes, of the SMI Handler.
786
787 **/
788 UINTN
789 EFIAPI
790 GetSmiHandlerSize (
791 VOID
792 );
793
794 /**
795 Install the SMI handler for the CPU specified by CpuIndex. This function
796 is called by the CPU that was elected as monarch during System Management
797 Mode initialization.
798
799 @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
800 The value must be between 0 and the NumberOfCpus field
801 in the System Management System Table (SMST).
802 @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
803 @param[in] SmiStack The stack to use when an SMI is processed by the
804 the CPU specified by CpuIndex.
805 @param[in] StackSize The size, in bytes, if the stack used when an SMI is
806 processed by the CPU specified by CpuIndex.
807 @param[in] GdtBase The base address of the GDT to use when an SMI is
808 processed by the CPU specified by CpuIndex.
809 @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
810 processed by the CPU specified by CpuIndex.
811 @param[in] IdtBase The base address of the IDT to use when an SMI is
812 processed by the CPU specified by CpuIndex.
813 @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
814 processed by the CPU specified by CpuIndex.
815 @param[in] Cr3 The base address of the page tables to use when an SMI
816 is processed by the CPU specified by CpuIndex.
817 **/
818 VOID
819 EFIAPI
820 InstallSmiHandler (
821 IN UINTN CpuIndex,
822 IN UINT32 SmBase,
823 IN VOID *SmiStack,
824 IN UINTN StackSize,
825 IN UINTN GdtBase,
826 IN UINTN GdtSize,
827 IN UINTN IdtBase,
828 IN UINTN IdtSize,
829 IN UINT32 Cr3
830 );
831
832 /**
833 Search module name by input IP address and output it.
834
835 @param CallerIpAddress Caller instruction pointer.
836
837 **/
838 VOID
839 DumpModuleInfoByIp (
840 IN UINTN CallerIpAddress
841 );
842
843 /**
844 This function sets memory attribute according to MemoryAttributesTable.
845 **/
846 VOID
847 SetMemMapAttributes (
848 VOID
849 );
850
851 /**
852 This function sets UEFI memory attribute according to UEFI memory map.
853 **/
854 VOID
855 SetUefiMemMapAttributes (
856 VOID
857 );
858
859 /**
860 Return if the Address is forbidden as SMM communication buffer.
861
862 @param[in] Address the address to be checked
863
864 @return TRUE The address is forbidden as SMM communication buffer.
865 @return FALSE The address is allowed as SMM communication buffer.
866 **/
867 BOOLEAN
868 IsSmmCommBufferForbiddenAddress (
869 IN UINT64 Address
870 );
871
872 /**
873 This function caches the UEFI memory map information.
874 **/
875 VOID
876 GetUefiMemoryMap (
877 VOID
878 );
879
880 /**
881 This function sets memory attribute for page table.
882 **/
883 VOID
884 SetPageTableAttributes (
885 VOID
886 );
887
888 /**
889 Return page table base.
890
891 @return page table base.
892 **/
893 UINTN
894 GetPageTableBase (
895 VOID
896 );
897
898 /**
899 This function sets the attributes for the memory region specified by BaseAddress and
900 Length from their current attributes to the attributes specified by Attributes.
901
902 @param[in] BaseAddress The physical address that is the start address of a memory region.
903 @param[in] Length The size in bytes of the memory region.
904 @param[in] Attributes The bit mask of attributes to set for the memory region.
905 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
906
907 @retval EFI_SUCCESS The attributes were set for the memory region.
908 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
909 BaseAddress and Length cannot be modified.
910 @retval EFI_INVALID_PARAMETER Length is zero.
911 Attributes specified an illegal combination of attributes that
912 cannot be set together.
913 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
914 the memory resource range.
915 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
916 resource range specified by BaseAddress and Length.
917 The bit mask of attributes is not support for the memory resource
918 range specified by BaseAddress and Length.
919
920 **/
921 EFI_STATUS
922 EFIAPI
923 SmmSetMemoryAttributesEx (
924 IN EFI_PHYSICAL_ADDRESS BaseAddress,
925 IN UINT64 Length,
926 IN UINT64 Attributes,
927 OUT BOOLEAN *IsSplitted OPTIONAL
928 );
929
930 /**
931 This function clears the attributes for the memory region specified by BaseAddress and
932 Length from their current attributes to the attributes specified by Attributes.
933
934 @param[in] BaseAddress The physical address that is the start address of a memory region.
935 @param[in] Length The size in bytes of the memory region.
936 @param[in] Attributes The bit mask of attributes to clear for the memory region.
937 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
938
939 @retval EFI_SUCCESS The attributes were cleared for the memory region.
940 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
941 BaseAddress and Length cannot be modified.
942 @retval EFI_INVALID_PARAMETER Length is zero.
943 Attributes specified an illegal combination of attributes that
944 cannot be set together.
945 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
946 the memory resource range.
947 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
948 resource range specified by BaseAddress and Length.
949 The bit mask of attributes is not support for the memory resource
950 range specified by BaseAddress and Length.
951
952 **/
953 EFI_STATUS
954 EFIAPI
955 SmmClearMemoryAttributesEx (
956 IN EFI_PHYSICAL_ADDRESS BaseAddress,
957 IN UINT64 Length,
958 IN UINT64 Attributes,
959 OUT BOOLEAN *IsSplitted OPTIONAL
960 );
961
962 /**
963 This API provides a way to allocate memory for page table.
964
965 This API can be called more once to allocate memory for page tables.
966
967 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
968 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
969 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
970 returned.
971
972 @param Pages The number of 4 KB pages to allocate.
973
974 @return A pointer to the allocated buffer or NULL if allocation fails.
975
976 **/
977 VOID *
978 AllocatePageTableMemory (
979 IN UINTN Pages
980 );
981
982 /**
983 Allocate pages for code.
984
985 @param[in] Pages Number of pages to be allocated.
986
987 @return Allocated memory.
988 **/
989 VOID *
990 AllocateCodePages (
991 IN UINTN Pages
992 );
993
994 /**
995 Allocate aligned pages for code.
996
997 @param[in] Pages Number of pages to be allocated.
998 @param[in] Alignment The requested alignment of the allocation.
999 Must be a power of two.
1000 If Alignment is zero, then byte alignment is used.
1001
1002 @return Allocated memory.
1003 **/
1004 VOID *
1005 AllocateAlignedCodePages (
1006 IN UINTN Pages,
1007 IN UINTN Alignment
1008 );
1009
1010
1011 //
1012 // S3 related global variable and function prototype.
1013 //
1014
1015 extern BOOLEAN mSmmS3Flag;
1016
1017 /**
1018 Initialize SMM S3 resume state structure used during S3 Resume.
1019
1020 @param[in] Cr3 The base address of the page tables to use in SMM.
1021
1022 **/
1023 VOID
1024 InitSmmS3ResumeState (
1025 IN UINT32 Cr3
1026 );
1027
1028 /**
1029 Get ACPI CPU data.
1030
1031 **/
1032 VOID
1033 GetAcpiCpuData (
1034 VOID
1035 );
1036
1037 /**
1038 Restore SMM Configuration in S3 boot path.
1039
1040 **/
1041 VOID
1042 RestoreSmmConfigurationInS3 (
1043 VOID
1044 );
1045
1046 /**
1047 Get ACPI S3 enable flag.
1048
1049 **/
1050 VOID
1051 GetAcpiS3EnableFlag (
1052 VOID
1053 );
1054
1055 /**
1056 Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
1057
1058 @param[in] ApHltLoopCode The address of the safe hlt-loop function.
1059 @param[in] TopOfStack A pointer to the new stack to use for the ApHltLoopCode.
1060 @param[in] NumberToFinishAddress Address of Semaphore of APs finish count.
1061
1062 **/
1063 VOID
1064 TransferApToSafeState (
1065 IN UINTN ApHltLoopCode,
1066 IN UINTN TopOfStack,
1067 IN UINTN NumberToFinishAddress
1068 );
1069
1070 #endif