Changeset 101291 in vbox for trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg
- Timestamp:
- Sep 27, 2023 1:34:02 PM (17 months ago)
- svn:sync-xref-src-repo-rev:
- 159276
- Location:
- trunk/src/VBox/Devices/EFI/FirmwareNew
- Files:
-
- 23 added
- 10 deleted
- 96 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/FirmwareNew
-
Property svn:mergeinfo
changed from (toggle deleted branches)
to (toggle deleted branches)/vendor/edk2/current 103735-103757,103769-103776,129194-156846 /vendor/edk2/current 103735-103757,103769-103776,129194-159268
-
Property svn:mergeinfo
changed from (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Application/Cpuid/Cpuid.c
r99404 r101291 2 2 UEFI Application to display CPUID leaf information. 3 3 4 Copyright (c) 2016 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 218 218 DisplayFamily = Eax.Bits.FamilyId; 219 219 if (Eax.Bits.FamilyId == 0x0F) { 220 DisplayFamily |= (Eax.Bits.ExtendedFamilyId << 4);220 DisplayFamily += Eax.Bits.ExtendedFamilyId; 221 221 } 222 222 223 223 DisplayModel = Eax.Bits.Model; 224 224 if ((Eax.Bits.FamilyId == 0x06) || (Eax.Bits.FamilyId == 0x0f)) { 225 DisplayModel |= (Eax.Bits.ExtendedModelId << 4);225 DisplayModel += (Eax.Bits.ExtendedModelId << 4); 226 226 } 227 227 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxe/CpuDxe.c
r99404 r101291 2 2 CPU DXE Module to produce CPU ARCH Protocol. 3 3 4 Copyright (c) 2008 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 506 506 ) 507 507 { 508 UINT32 RegEax; 509 UINT8 PhysicalAddressBits; 510 511 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); 512 513 if (RegEax >= 0x80000008) { 514 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); 515 516 PhysicalAddressBits = (UINT8)RegEax; 508 UINT32 MaxExtendedFunction; 509 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; 510 UINT32 MaxFunction; 511 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX ExtendedFeatureFlagsEcx; 512 MSR_IA32_TME_ACTIVATE_REGISTER TmeActivate; 513 514 AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL); 515 516 if (MaxExtendedFunction >= CPUID_VIR_PHY_ADDRESS_SIZE) { 517 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL); 517 518 } else { 518 PhysicalAddressBits = 36; 519 } 520 521 mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1; 519 VirPhyAddressSize.Bits.PhysicalAddressBits = 36; 520 } 521 522 // 523 // CPUID enumeration of MAX_PA is unaffected by TME-MK activation and will continue 524 // to report the maximum physical address bits available for software to use, 525 // irrespective of the number of KeyID bits. 526 // So, we need to check if TME is enabled and adjust the PA size accordingly. 527 // 528 AsmCpuid (CPUID_SIGNATURE, &MaxFunction, NULL, NULL, NULL); 529 if (MaxFunction >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) { 530 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, NULL, &ExtendedFeatureFlagsEcx.Uint32, NULL); 531 if (ExtendedFeatureFlagsEcx.Bits.TME_EN == 1) { 532 TmeActivate.Uint64 = AsmReadMsr64 (MSR_IA32_TME_ACTIVATE); 533 if (TmeActivate.Bits.TmeEnable == 1) { 534 VirPhyAddressSize.Bits.PhysicalAddressBits -= TmeActivate.Bits.MkTmeKeyidBits; 535 } 536 } 537 } 538 539 mValidMtrrBitsMask = LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits) - 1; 522 540 mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL; 523 541 } … … 1061 1079 "%a: %a: add [%Lx, %Lx): %r\n", 1062 1080 gEfiCallerBaseName, 1063 __ FUNCTION__,1081 __func__, 1064 1082 IntersectionBase, 1065 1083 IntersectionEnd, … … 1074 1092 "with aperture [%Lx, %Lx) cap %Lx\n", 1075 1093 gEfiCallerBaseName, 1076 __ FUNCTION__,1094 __func__, 1077 1095 Descriptor->BaseAddress, 1078 1096 Descriptor->BaseAddress + Descriptor->Length, … … 1115 1133 "%a: %a: GetMemorySpaceMap(): %r\n", 1116 1134 gEfiCallerBaseName, 1117 __ FUNCTION__,1135 __func__, 1118 1136 Status 1119 1137 )); … … 1198 1216 "%a: %a: AllocateMemorySpace() Status - %r\n", 1199 1217 gEfiCallerBaseName, 1200 __ FUNCTION__,1218 __func__, 1201 1219 Status 1202 1220 )); -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxe/CpuDxe.h
r99404 r101291 2 2 CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol. 3 3 4 Copyright (c) 2008 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 14 14 #include <Protocol/Cpu.h> 15 15 #include <Protocol/MpService.h> 16 #include <Register/Intel/Cpuid.h> 16 17 #include <Register/Intel/Msr.h> 17 18 … … 29 30 #include <Library/MtrrLib.h> 30 31 #include <Library/LocalApicLib.h> 31 #include <Library/UefiCpuLib.h>32 32 #include <Library/UefiLib.h> 33 33 #include <Library/CpuExceptionHandlerLib.h> -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxe/CpuDxe.inf
r99404 r101291 34 34 UefiDriverEntryPoint 35 35 LocalApicLib 36 UefiCpuLib37 36 UefiLib 38 37 CpuExceptionHandlerLib -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c
r99404 r101291 297 297 ) 298 298 { 299 DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __FUNCTION__)); 300 return EFI_SUCCESS; 299 return RiscVSetMemoryAttributes (BaseAddress, Length, Attributes); 301 300 } 302 301 … … 329 328 } 330 329 331 DEBUG ((DEBUG_INFO, " %a: Firmware Context is at 0x%x.\n", __ FUNCTION__, FirmwareContext));330 DEBUG ((DEBUG_INFO, " %a: Firmware Context is at 0x%x.\n", __func__, FirmwareContext)); 332 331 333 332 mBootHartId = FirmwareContext->BootHartId; 334 DEBUG ((DEBUG_INFO, " %a: mBootHartId = 0x%x.\n", __ FUNCTION__, mBootHartId));333 DEBUG ((DEBUG_INFO, " %a: mBootHartId = 0x%x.\n", __func__, mBootHartId)); 335 334 336 335 InitializeCpuExceptionHandlers (NULL); … … 340 339 // 341 340 DisableInterrupts (); 341 342 // 343 // Enable MMU 344 // 345 Status = RiscVConfigureMmu (); 346 ASSERT_EFI_ERROR (Status); 342 347 343 348 // -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h
r99404 r101291 16 16 #include <Protocol/RiscVBootProtocol.h> 17 17 #include <Library/BaseRiscVSbiLib.h> 18 #include <Library/BaseRiscVMmuLib.h> 18 19 #include <Library/BaseLib.h> 19 20 #include <Library/CpuExceptionHandlerLib.h> … … 21 22 #include <Library/UefiBootServicesTableLib.h> 22 23 #include <Library/UefiDriverEntryPoint.h> 24 #include <Register/RiscV64/RiscVEncoding.h> 23 25 24 26 /** -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf
r99404 r101291 38 38 PeCoffGetEntryPointLib 39 39 RiscVSbiLib 40 RiscVMmuLib 41 CacheMaintenanceLib 40 42 41 43 [Sources] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuBist.c
r99404 r101291 176 176 EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstanceInHob; 177 177 178 MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors); 178 Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors); 179 ASSERT_EFI_ERROR (Status); 180 181 if (EFI_ERROR (Status)) { 182 NumberOfProcessors = 1; 183 NumberOfEnabledProcessors = 1; 184 } 179 185 180 186 BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) + -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuMpPei.c
r99404 r101291 474 474 } 475 475 476 MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL); 476 Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL); 477 ASSERT_EFI_ERROR (Status); 478 479 if (EFI_ERROR (Status)) { 480 NumberOfProcessors = 1; 481 } 482 477 483 SwitchStackData = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT))); 478 484 ASSERT (SwitchStackData != NULL); -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuMpPei.h
r99404 r101291 29 29 #include <Library/BaseMemoryLib.h> 30 30 #include <Library/MemoryAllocationLib.h> 31 #include <Library/CpuPageTableLib.h> 31 32 32 33 extern EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
r89983 r101291 47 47 CpuLib 48 48 MemoryAllocationLib 49 CpuPageTableLib 49 50 50 51 [Guids] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuPaging.c
r99404 r101291 147 147 148 148 /** 149 Get the address width supported by current processor.150 151 @retval 32 If processor is in 32-bit mode.152 @retval 36-48 If processor is in 64-bit mode.153 154 **/155 UINTN156 GetPhysicalAddressWidth (157 VOID158 )159 {160 UINT32 RegEax;161 162 if (sizeof (UINTN) == 4) {163 return 32;164 }165 166 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);167 if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {168 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);169 RegEax &= 0xFF;170 if (RegEax > 48) {171 return 48;172 }173 174 return (UINTN)RegEax;175 }176 177 return 36;178 }179 180 /**181 149 Get the type of top level page table. 182 150 … … 445 413 446 414 /** 447 Get maximum size of page memory supported by current processor. 448 449 @param[in] TopLevelType The type of top level page entry. 450 451 @retval Page1G If processor supports 1G page and PML4. 452 @retval Page2M For all other situations. 453 454 **/ 455 PAGE_ATTRIBUTE 456 GetMaxMemoryPage ( 457 IN PAGE_ATTRIBUTE TopLevelType 458 ) 459 { 460 UINT32 RegEax; 461 UINT32 RegEdx; 462 463 if (TopLevelType == Page512G) { 464 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); 465 if (RegEax >= CPUID_EXTENDED_CPU_SIG) { 466 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx); 467 if ((RegEdx & BIT26) != 0) { 468 return Page1G; 469 } 470 } 471 } 472 473 return Page2M; 474 } 475 476 /** 477 Create PML4 or PAE page table. 478 479 @return The address of page table. 480 481 **/ 482 UINTN 483 CreatePageTable ( 415 Enable PAE Page Table. 416 417 @retval EFI_SUCCESS The PAE Page Table was enabled successfully. 418 @retval EFI_OUT_OF_RESOURCES The PAE Page Table could not be enabled due to lack of available memory. 419 420 **/ 421 EFI_STATUS 422 EnablePaePageTable ( 484 423 VOID 485 424 ) 486 425 { 487 RETURN_STATUS Status; 488 UINTN PhysicalAddressBits; 489 UINTN NumberOfEntries; 490 PAGE_ATTRIBUTE TopLevelPageAttr; 491 UINTN PageTable; 492 PAGE_ATTRIBUTE MaxMemoryPage; 493 UINTN Index; 494 UINT64 AddressEncMask; 495 UINT64 *PageEntry; 496 EFI_PHYSICAL_ADDRESS PhysicalAddress; 497 498 TopLevelPageAttr = (PAGE_ATTRIBUTE)GetPageTableTopLevelType (); 499 PhysicalAddressBits = GetPhysicalAddressWidth (); 500 NumberOfEntries = (UINTN)1 << (PhysicalAddressBits - 501 mPageAttributeTable[TopLevelPageAttr].AddressBitOffset); 502 503 PageTable = (UINTN)AllocatePageTableMemory (1); 504 if (PageTable == 0) { 505 return 0; 506 } 507 508 AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); 509 AddressEncMask &= mPageAttributeTable[TopLevelPageAttr].AddressMask; 510 MaxMemoryPage = GetMaxMemoryPage (TopLevelPageAttr); 511 PageEntry = (UINT64 *)PageTable; 512 513 PhysicalAddress = 0; 514 for (Index = 0; Index < NumberOfEntries; ++Index) { 515 *PageEntry = PhysicalAddress | AddressEncMask | PAGE_ATTRIBUTE_BITS; 516 517 // 518 // Split the top page table down to the maximum page size supported 519 // 520 if (MaxMemoryPage < TopLevelPageAttr) { 521 Status = SplitPage (PageEntry, TopLevelPageAttr, MaxMemoryPage, TRUE); 522 ASSERT_EFI_ERROR (Status); 523 } 524 525 if (TopLevelPageAttr == Page1G) { 526 // 527 // PDPTE[2:1] (PAE Paging) must be 0. SplitPage() might change them to 1. 528 // 529 *PageEntry &= ~(UINT64)(IA32_PG_RW | IA32_PG_U); 530 } 531 532 PageEntry += 1; 533 PhysicalAddress += mPageAttributeTable[TopLevelPageAttr].Length; 534 } 535 536 return PageTable; 537 } 538 539 /** 540 Setup page tables and make them work. 541 542 **/ 543 VOID 544 EnablePaging ( 545 VOID 546 ) 547 { 548 UINTN PageTable; 549 550 PageTable = CreatePageTable (); 551 ASSERT (PageTable != 0); 552 if (PageTable != 0) { 553 AsmWriteCr3 (PageTable); 554 AsmWriteCr4 (AsmReadCr4 () | BIT5); // CR4.PAE 555 AsmWriteCr0 (AsmReadCr0 () | BIT31); // CR0.PG 556 } 426 EFI_STATUS Status; 427 428 UINTN PageTable; 429 VOID *Buffer; 430 UINTN BufferSize; 431 IA32_MAP_ATTRIBUTE MapAttribute; 432 IA32_MAP_ATTRIBUTE MapMask; 433 434 PageTable = 0; 435 Buffer = NULL; 436 BufferSize = 0; 437 MapAttribute.Uint64 = 0; 438 MapMask.Uint64 = MAX_UINT64; 439 MapAttribute.Bits.Present = 1; 440 MapAttribute.Bits.ReadWrite = 1; 441 442 // 443 // 1:1 map 4GB in 32bit mode 444 // 445 Status = PageTableMap (&PageTable, PagingPae, 0, &BufferSize, 0, SIZE_4GB, &MapAttribute, &MapMask, NULL); 446 ASSERT (Status == EFI_BUFFER_TOO_SMALL); 447 if (Status != EFI_BUFFER_TOO_SMALL) { 448 return Status; 449 } 450 451 // 452 // Allocate required Buffer. 453 // 454 Buffer = AllocatePageTableMemory (EFI_SIZE_TO_PAGES (BufferSize)); 455 ASSERT (Buffer != NULL); 456 if (Buffer == NULL) { 457 return EFI_OUT_OF_RESOURCES; 458 } 459 460 Status = PageTableMap (&PageTable, PagingPae, Buffer, &BufferSize, 0, SIZE_4GB, &MapAttribute, &MapMask, NULL); 461 ASSERT_EFI_ERROR (Status); 462 if (EFI_ERROR (Status) || (PageTable == 0)) { 463 return EFI_OUT_OF_RESOURCES; 464 } 465 466 // 467 // Write the Pagetable to CR3. 468 // 469 AsmWriteCr3 (PageTable); 470 471 // 472 // Enable CR4.PAE 473 // 474 AsmWriteCr4 (AsmReadCr4 () | BIT5); 475 476 // 477 // Enable CR0.PG 478 // 479 AsmWriteCr0 (AsmReadCr0 () | BIT31); 480 481 DEBUG (( 482 DEBUG_INFO, 483 "EnablePaePageTable: Created PageTable = 0x%x, BufferSize = %x\n", 484 PageTable, 485 BufferSize 486 )); 487 488 return Status; 557 489 } 558 490 … … 600 532 UINTN Bsp; 601 533 UINTN Index; 534 EFI_STATUS Status; 602 535 603 536 // … … 609 542 } 610 543 611 MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL); 544 Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL); 545 ASSERT_EFI_ERROR (Status); 546 547 if (EFI_ERROR (Status)) { 548 NumberOfProcessors = 1; 549 } 550 612 551 MpInitLibWhoAmI (&Bsp); 613 552 for (Index = 0; Index < NumberOfProcessors; ++Index) { … … 679 618 EDKII_MIGRATED_FV_INFO *MigratedFvInfo; 680 619 EFI_PEI_HOB_POINTERS Hob; 620 IA32_CR0 Cr0; 681 621 682 622 // … … 692 632 } 693 633 694 if (InitStackGuard || (Hob.Raw != NULL)) { 695 EnablePaging (); 634 // 635 // Some security features depend on the page table enabling. So, here 636 // is to enable paging if it is not enabled (only in 32bit mode). 637 // 638 Cr0.UintN = AsmReadCr0 (); 639 if ((Cr0.Bits.PG == 0) && (InitStackGuard || (Hob.Raw != NULL))) { 640 ASSERT (sizeof (UINTN) == sizeof (UINT32)); 641 642 Status = EnablePaePageTable (); 643 if (EFI_ERROR (Status)) { 644 DEBUG ((DEBUG_ERROR, "MemoryDiscoveredPpiNotifyCallback: Failed to enable PAE page table: %r.\n", Status)); 645 CpuDeadLoop (); 646 } 696 647 } 697 648 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
r99404 r101291 128 128 ASSERT_EFI_ERROR (Status); 129 129 130 DEBUG ((DEBUG_VERBOSE, "%a\n", __ FUNCTION__));130 DEBUG ((DEBUG_VERBOSE, "%a\n", __func__)); 131 131 MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable); 132 132 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf
r99404 r101291 41 41 Timer.c 42 42 43 [Pcd] 44 gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES 45 43 46 [Protocols] 44 47 gEfiCpuArchProtocolGuid ## CONSUMES -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuTimerDxeRiscV64/Timer.c
r99404 r101291 10 10 #include <Library/BaseLib.h> 11 11 #include <Library/BaseRiscVSbiLib.h> 12 #include <Library/UefiLib.h> 12 13 #include "Timer.h" 13 14 … … 41 42 // The current period of the timer interrupt 42 43 // 43 STATIC UINT64 mTimerPeriod = 0; 44 STATIC UINT64 mTimerPeriod = 0; 45 STATIC UINT64 mLastPeriodStart = 0; 44 46 45 47 /** … … 57 59 { 58 60 EFI_TPL OriginalTPL; 59 UINT64 RiscvTimer; 61 UINT64 PeriodStart; 62 63 PeriodStart = RiscVReadTimer (); 60 64 61 65 OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); 62 66 if (mTimerNotifyFunction != NULL) { 63 mTimerNotifyFunction (mTimerPeriod); 67 // 68 // For any number of reasons, the ticks could be coming 69 // in slower than mTimerPeriod. For example, some code 70 // is doing a *lot* of stuff inside an EFI_TPL_HIGH 71 // critical section, and this should not cause the EFI 72 // time to increment slower. So when we take an interrupt, 73 // account for the actual time passed. 74 // 75 mTimerNotifyFunction ( 76 DivU64x32 ( 77 EFI_TIMER_PERIOD_SECONDS (PeriodStart - mLastPeriodStart), 78 PcdGet64 (PcdCpuCoreCrystalClockFrequency) 79 ) 80 ); 64 81 } 65 82 66 RiscVDisableTimerInterrupt (); // Disable SMode timer int67 RiscVClearPendingTimerInterrupt ();68 83 if (mTimerPeriod == 0) { 84 RiscVDisableTimerInterrupt (); 69 85 gBS->RestoreTPL (OriginalTPL); 70 RiscVDisableTimerInterrupt (); // Disable SMode timer int71 86 return; 72 87 } 73 88 74 RiscvTimer = RiscVReadTimer (); 75 SbiSetTimer (RiscvTimer += mTimerPeriod); 89 mLastPeriodStart = PeriodStart; 90 PeriodStart += DivU64x32 ( 91 MultU64x32 ( 92 mTimerPeriod, 93 PcdGet64 (PcdCpuCoreCrystalClockFrequency) 94 ), 95 1000000u 96 ); // convert to tick 97 SbiSetTimer (PeriodStart); 98 RiscVEnableTimerInterrupt (); // enable SMode timer int 76 99 gBS->RestoreTPL (OriginalTPL); 77 RiscVEnableTimerInterrupt (); // enable SMode timer int78 100 } 79 101 … … 155 177 ) 156 178 { 157 UINT64 RiscvTimer;179 UINT64 PeriodStart; 158 180 159 181 DEBUG ((DEBUG_INFO, "TimerDriverSetTimerPeriod(0x%lx)\n", TimerPeriod)); … … 165 187 } 166 188 167 mTimerPeriod = TimerPeriod / 10; // convert unit from 100ns to 1us 168 RiscvTimer = RiscVReadTimer (); 169 SbiSetTimer (RiscvTimer + mTimerPeriod); 189 mTimerPeriod = TimerPeriod / 10; // convert unit from 100ns to 1us 190 191 mLastPeriodStart = RiscVReadTimer (); 192 PeriodStart = mLastPeriodStart; 193 PeriodStart += DivU64x32 ( 194 MultU64x32 ( 195 mTimerPeriod, 196 PcdGet64 (PcdCpuCoreCrystalClockFrequency) 197 ), 198 1000000u 199 ); // convert to tick 200 SbiSetTimer (PeriodStart); 170 201 171 202 mCpu->EnableInterrupt (mCpu); … … 272 303 // Install interrupt handler for RISC-V Timer. 273 304 // 274 Status = mCpu->RegisterInterruptHandler (mCpu, EXCEPT_RISCV_TIMER_INT, TimerInterruptHandler); 305 Status = mCpu->RegisterInterruptHandler ( 306 mCpu, 307 EXCEPT_RISCV_IRQ_TIMER_FROM_SMODE, 308 TimerInterruptHandler 309 ); 275 310 ASSERT_EFI_ERROR (Status); 276 311 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuTimerDxeRiscV64/Timer.h
r99404 r101291 22 22 23 23 // 24 // RISC-V use 100 us timer.24 // RISC-V use 100ns timer. 25 25 // The default timer tick duration is set to 10 ms = 10 * 1000 * 10 100 ns units 26 26 // -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Include/Library/CpuPageTableLib.h
r99404 r101291 2 2 Public include file for PageTableLib library. 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 12 12 typedef union { 13 13 struct { 14 UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory 15 UINT64 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 16 UINT64 UserSupervisor : 1; // 0 = Supervisor, 1=User 17 UINT64 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching 18 UINT64 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached 19 UINT64 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU) 20 UINT64 Dirty : 1; // 0 = Not dirty, 1 = Dirty (set by CPU) 21 UINT64 Pat : 1; // PAT 14 UINT32 Present : 1; // 0 = Not present in memory, 1 = Present in memory 15 UINT32 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 16 UINT32 UserSupervisor : 1; // 0 = Supervisor, 1=User 17 UINT32 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching 18 UINT32 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached 19 UINT32 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU) 20 UINT32 Dirty : 1; // 0 = Not dirty, 1 = Dirty (set by CPU) 21 UINT32 Pat : 1; // PAT 22 UINT32 Global : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1) 23 UINT32 Reserved1 : 3; // Ignored 24 UINT32 PageTableBaseAddressLow : 20; // Page Table Base Address Low 22 25 23 UINT64 Global : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1) 24 UINT64 Reserved1 : 3; // Ignored 25 26 UINT64 PageTableBaseAddress : 40; // Page Table Base Address 27 UINT64 Reserved2 : 7; // Ignored 28 UINT64 ProtectionKey : 4; // Protection key 29 UINT64 Nx : 1; // No Execute bit 26 UINT32 PageTableBaseAddressHigh : 20; // Page Table Base Address High 27 UINT32 Reserved2 : 7; // Ignored 28 UINT32 ProtectionKey : 4; // Protection key 29 UINT32 Nx : 1; // No Execute bit 30 30 } Bits; 31 31 UINT64 Uint64; … … 75 75 when a new physical base address is set. 76 76 @param[in] Mask The mask used for attribute. The corresponding field in Attribute is ignored if that in Mask is 0. 77 @param[out] IsModified TRUE means page table is modified. FALSE means page table is not modified. 77 78 78 79 @retval RETURN_UNSUPPORTED PagingMode is not supported. 79 80 @retval RETURN_INVALID_PARAMETER PageTable, BufferSize, Attribute or Mask is NULL. 81 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 0 but some other attributes are provided. 82 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are not provided. 83 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are provided. 84 @retval RETURN_INVALID_PARAMETER For present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are provided. 80 85 @retval RETURN_INVALID_PARAMETER *BufferSize is not multiple of 4KB. 81 86 @retval RETURN_BUFFER_TOO_SMALL The buffer is too small for page table creation/updating. 82 87 BufferSize is updated to indicate the expected buffer size. 83 88 Caller may still get RETURN_BUFFER_TOO_SMALL with the new BufferSize. 84 @retval RETURN_SUCCESS PageTable is created/updated successfully .89 @retval RETURN_SUCCESS PageTable is created/updated successfully or the input Length is 0. 85 90 **/ 86 91 RETURN_STATUS … … 94 99 IN UINT64 Length, 95 100 IN IA32_MAP_ATTRIBUTE *Attribute, 96 IN IA32_MAP_ATTRIBUTE *Mask 101 IN IA32_MAP_ATTRIBUTE *Mask, 102 OUT BOOLEAN *IsModified OPTIONAL 97 103 ); 98 104 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Include/Library/LocalApicLib.h
r99404 r101291 5 5 handles cases where local APIC is disabled. 6 6 7 Copyright (c) 2010 - 20 19, Intel Corporation. All rights reserved.<BR>7 Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR> 8 8 SPDX-License-Identifier: BSD-2-Clause-Patent 9 9 … … 184 184 SendInitIpiAllExcludingSelf ( 185 185 VOID 186 ); 187 188 /** 189 Send a Start-up IPI to all processors excluding self. 190 This function returns after the IPI has been accepted by the target processors. 191 if StartupRoutine >= 1M, then ASSERT. 192 if StartupRoutine is not multiple of 4K, then ASSERT. 193 @param StartupRoutine Points to a start-up routine which is below 1M physical 194 address and 4K aligned. 195 **/ 196 197 VOID 198 EFIAPI 199 SendStartupIpiAllExcludingSelf ( 200 IN UINT32 StartupRoutine 186 201 ); 187 202 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h
r99404 r101291 326 326 327 327 /** 328 Read an SMM Save State register on the target processor. If this function329 returns EFI_UNSUPPORTED, then the caller is responsible for reading the330 SMM Save Sate register.331 332 @param[in] CpuIndex The index of the CPU to read the SMM Save State. The333 value must be between 0 and the NumberOfCpus field in334 the System Management System Table (SMST).335 @param[in] Register The SMM Save State register to read.336 @param[in] Width The number of bytes to read from the CPU save state.337 @param[out] Buffer Upon return, this holds the CPU register value read338 from the save state.339 340 @retval EFI_SUCCESS The register was read from Save State.341 @retval EFI_INVALID_PARAMETER Buffer is NULL.342 @retval EFI_UNSUPPORTED This function does not support reading Register.343 344 **/345 EFI_STATUS346 EFIAPI347 SmmCpuFeaturesReadSaveStateRegister (348 IN UINTN CpuIndex,349 IN EFI_SMM_SAVE_STATE_REGISTER Register,350 IN UINTN Width,351 OUT VOID *Buffer352 );353 354 /**355 Writes an SMM Save State register on the target processor. If this function356 returns EFI_UNSUPPORTED, then the caller is responsible for writing the357 SMM Save Sate register.358 359 @param[in] CpuIndex The index of the CPU to write the SMM Save State. The360 value must be between 0 and the NumberOfCpus field in361 the System Management System Table (SMST).362 @param[in] Register The SMM Save State register to write.363 @param[in] Width The number of bytes to write to the CPU save state.364 @param[in] Buffer Upon entry, this holds the new CPU register value.365 366 @retval EFI_SUCCESS The register was written to Save State.367 @retval EFI_INVALID_PARAMETER Buffer is NULL.368 @retval EFI_UNSUPPORTED This function does not support writing Register.369 **/370 EFI_STATUS371 EFIAPI372 SmmCpuFeaturesWriteSaveStateRegister (373 IN UINTN CpuIndex,374 IN EFI_SMM_SAVE_STATE_REGISTER Register,375 IN UINTN Width,376 IN CONST VOID *Buffer377 );378 379 /**380 328 This function is hook point called after the gEfiSmmReadyToLockProtocolGuid 381 329 notification is completely processed. -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/CpuExceptionHandlerLib.c
r99404 r101291 12 12 #include <Library/DebugLib.h> 13 13 #include <Library/BaseLib.h> 14 #include <Library/SerialPortLib.h> 15 #include <Library/PrintLib.h> 14 16 #include <Register/RiscV64/RiscVEncoding.h> 15 16 17 #include "CpuExceptionHandlerLib.h" 17 18 18 STATIC EFI_CPU_INTERRUPT_HANDLER mInterruptHandlers[2]; 19 // 20 // Define the maximum message length 21 // 22 #define MAX_DEBUG_MESSAGE_LENGTH 0x100 23 24 STATIC EFI_CPU_INTERRUPT_HANDLER mExceptionHandlers[EXCEPT_RISCV_MAX_EXCEPTIONS + 1]; 25 STATIC EFI_CPU_INTERRUPT_HANDLER mIrqHandlers[EXCEPT_RISCV_MAX_IRQS + 1]; 26 27 STATIC CONST CHAR8 mExceptionOrIrqUnknown[] = "Unknown"; 28 STATIC CONST CHAR8 *mExceptionNameStr[EXCEPT_RISCV_MAX_EXCEPTIONS + 1] = { 29 "EXCEPT_RISCV_INST_MISALIGNED", 30 "EXCEPT_RISCV_INST_ACCESS_FAULT", 31 "EXCEPT_RISCV_ILLEGAL_INST", 32 "EXCEPT_RISCV_BREAKPOINT", 33 "EXCEPT_RISCV_LOAD_ADDRESS_MISALIGNED", 34 "EXCEPT_RISCV_LOAD_ACCESS_FAULT", 35 "EXCEPT_RISCV_STORE_AMO_ADDRESS_MISALIGNED", 36 "EXCEPT_RISCV_STORE_AMO_ACCESS_FAULT", 37 "EXCEPT_RISCV_ENV_CALL_FROM_UMODE", 38 "EXCEPT_RISCV_ENV_CALL_FROM_SMODE", 39 "EXCEPT_RISCV_ENV_CALL_FROM_VS_MODE", 40 "EXCEPT_RISCV_ENV_CALL_FROM_MMODE", 41 "EXCEPT_RISCV_INST_ACCESS_PAGE_FAULT", 42 "EXCEPT_RISCV_LOAD_ACCESS_PAGE_FAULT", 43 "EXCEPT_RISCV_14", 44 "EXCEPT_RISCV_STORE_ACCESS_PAGE_FAULT", 45 "EXCEPT_RISCV_16", 46 "EXCEPT_RISCV_17", 47 "EXCEPT_RISCV_18", 48 "EXCEPT_RISCV_19", 49 "EXCEPT_RISCV_INST_GUEST_PAGE_FAULT", 50 "EXCEPT_RISCV_LOAD_GUEST_PAGE_FAULT", 51 "EXCEPT_RISCV_VIRTUAL_INSTRUCTION", 52 "EXCEPT_RISCV_STORE_GUEST_PAGE_FAULT" 53 }; 54 55 STATIC CONST CHAR8 *mIrqNameStr[EXCEPT_RISCV_MAX_IRQS + 1] = { 56 "EXCEPT_RISCV_IRQ_0", 57 "EXCEPT_RISCV_IRQ_SOFT_FROM_SMODE", 58 "EXCEPT_RISCV_IRQ_SOFT_FROM_VSMODE", 59 "EXCEPT_RISCV_IRQ_SOFT_FROM_MMODE", 60 "EXCEPT_RISCV_IRQ_4", 61 "EXCEPT_RISCV_IRQ_TIMER_FROM_SMODE", 62 }; 63 64 /** 65 Prints a message to the serial port. 66 67 @param Format Format string for the message to print. 68 @param ... Variable argument list whose contents are accessed 69 based on the format string specified by Format. 70 71 **/ 72 STATIC 73 VOID 74 EFIAPI 75 InternalPrintMessage ( 76 IN CONST CHAR8 *Format, 77 ... 78 ) 79 { 80 CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; 81 VA_LIST Marker; 82 83 // 84 // Convert the message to an ASCII String 85 // 86 VA_START (Marker, Format); 87 AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); 88 VA_END (Marker); 89 90 // 91 // Send the print string to a Serial Port 92 // 93 SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); 94 } 95 96 /** 97 Get ASCII format string exception name by exception type. 98 99 @param ExceptionType Exception type. 100 101 @return ASCII format string exception name. 102 **/ 103 STATIC 104 CONST CHAR8 * 105 GetExceptionNameStr ( 106 IN EFI_EXCEPTION_TYPE ExceptionType 107 ) 108 { 109 if (EXCEPT_RISCV_IS_IRQ (ExceptionType)) { 110 if (EXCEPT_RISCV_IRQ_INDEX (ExceptionType) > EXCEPT_RISCV_MAX_IRQS) { 111 return mExceptionOrIrqUnknown; 112 } 113 114 return mIrqNameStr[EXCEPT_RISCV_IRQ_INDEX (ExceptionType)]; 115 } 116 117 if (ExceptionType > EXCEPT_RISCV_MAX_EXCEPTIONS) { 118 return mExceptionOrIrqUnknown; 119 } 120 121 return mExceptionNameStr[ExceptionType]; 122 } 123 124 /** 125 Display CPU information. This can be called by 3rd-party handlers 126 set by RegisterCpuInterruptHandler. 127 128 @param ExceptionType Exception type. 129 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. 130 **/ 131 VOID 132 EFIAPI 133 DumpCpuContext ( 134 IN EFI_EXCEPTION_TYPE ExceptionType, 135 IN EFI_SYSTEM_CONTEXT SystemContext 136 ) 137 { 138 UINTN Printed; 139 SMODE_TRAP_REGISTERS *Regs; 140 141 Printed = 0; 142 Regs = (SMODE_TRAP_REGISTERS *)SystemContext.SystemContextRiscV64; 143 144 InternalPrintMessage ( 145 "!!!! RISCV64 Exception Type - %016x(%a) !!!!\n", 146 ExceptionType, 147 GetExceptionNameStr (ExceptionType) 148 ); 149 150 DEBUG_CODE_BEGIN (); 151 152 #define REGS() \ 153 REG (t0); REG (t1); REG (t2); REG (t3); REG (t4); REG (t5); REG (t6); \ 154 REG (s0); REG (s1); REG (s2); REG (s3); REG (s4); REG (s5); REG (s6); \ 155 REG (s7); REG (s8); REG (s9); REG (s10); REG (s11); \ 156 REG (a0); REG (a1); REG (a2); REG (a3); REG (a4); REG (a5); REG (a6); \ 157 REG (a7); \ 158 REG (zero); REG (ra); REG (sp); REG (gp); REG (tp); \ 159 REG (sepc); REG (sstatus); REG (stval); 160 161 #define REG(x) do { \ 162 InternalPrintMessage ("%7a = 0x%017lx%c", #x, Regs->x, \ 163 (++Printed % 2) ? L'\t' : L'\n'); \ 164 } while (0); 165 166 REGS (); 167 if (Printed % 2 != 0) { 168 InternalPrintMessage ("\n"); 169 } 170 171 #undef REG 172 #undef REGS 173 174 DEBUG_CODE_END (); 175 } 19 176 20 177 /** … … 48 205 49 206 This function registers and enables the handler specified by InterruptHandler for a processor 50 interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the51 handler for the processor interrupt or exception type specified by InterruptType is uninstalled.207 interrupt or exception type specified by ExceptionType. If InterruptHandler is NULL, then the 208 handler for the processor interrupt or exception type specified by ExceptionType is uninstalled. 52 209 The installed handler is called once for each processor interrupt or exception. 53 210 NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or 54 211 InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned. 55 212 56 @param[in] InterruptType Defines which interrupt or exception to hook.213 @param[in] ExceptionType Defines which interrupt or exception to hook. 57 214 @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called 58 215 when a processor interrupt occurs. If this parameter is NULL, then the handler … … 60 217 61 218 @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. 62 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was219 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for ExceptionType was 63 220 previously installed. 64 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not221 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for ExceptionType was not 65 222 previously installed. 66 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,223 @retval EFI_UNSUPPORTED The interrupt specified by ExceptionType is not supported, 67 224 or this function is not supported. 68 225 **/ … … 70 227 EFIAPI 71 228 RegisterCpuInterruptHandler ( 72 IN EFI_EXCEPTION_TYPE InterruptType,229 IN EFI_EXCEPTION_TYPE ExceptionType, 73 230 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler 74 231 ) 75 232 { 76 DEBUG ((DEBUG_INFO, "%a: Type:%x Handler: %x\n", __FUNCTION__, InterruptType, InterruptHandler)); 77 mInterruptHandlers[InterruptType] = InterruptHandler; 233 DEBUG ((DEBUG_INFO, "%a: Type:%x Handler: %x\n", __func__, ExceptionType, InterruptHandler)); 234 if (EXCEPT_RISCV_IS_IRQ (ExceptionType)) { 235 if (EXCEPT_RISCV_IRQ_INDEX (ExceptionType) > EXCEPT_RISCV_MAX_IRQS) { 236 return EFI_UNSUPPORTED; 237 } 238 239 if (mIrqHandlers[EXCEPT_RISCV_IRQ_INDEX (ExceptionType)] != NULL) { 240 return EFI_ALREADY_STARTED; 241 } else if (InterruptHandler == NULL) { 242 return EFI_INVALID_PARAMETER; 243 } 244 245 mIrqHandlers[EXCEPT_RISCV_IRQ_INDEX (ExceptionType)] = InterruptHandler; 246 } else { 247 if (ExceptionType > EXCEPT_RISCV_MAX_EXCEPTIONS) { 248 return EFI_UNSUPPORTED; 249 } 250 251 if (mExceptionHandlers[ExceptionType] != NULL) { 252 return EFI_ALREADY_STARTED; 253 } else if (InterruptHandler == NULL) { 254 return EFI_INVALID_PARAMETER; 255 } 256 257 mExceptionHandlers[ExceptionType] = InterruptHandler; 258 } 259 78 260 return EFI_SUCCESS; 79 261 } … … 114 296 ) 115 297 { 116 UINTN SCause;298 EFI_EXCEPTION_TYPE ExceptionType; 117 299 EFI_SYSTEM_CONTEXT RiscVSystemContext; 300 UINTN IrqIndex; 118 301 119 302 RiscVSystemContext.SystemContextRiscV64 = (EFI_SYSTEM_CONTEXT_RISCV64 *)SmodeTrapReg; 120 // 121 // Check scasue register. 122 // 123 SCause = (UINTN)RiscVGetSupervisorTrapCause (); 124 if ((SCause & (1UL << (sizeof (UINTN) * 8- 1))) != 0) { 125 // 126 // This is interrupt event. 127 // 128 SCause &= ~(1UL << (sizeof (UINTN) * 8- 1)); 129 if ((SCause == IRQ_S_TIMER) && (mInterruptHandlers[EXCEPT_RISCV_TIMER_INT] != NULL)) { 130 mInterruptHandlers[EXCEPT_RISCV_TIMER_INT](EXCEPT_RISCV_TIMER_INT, RiscVSystemContext); 131 } 132 } 133 } 303 ExceptionType = (UINTN)RiscVGetSupervisorTrapCause (); 304 305 if (EXCEPT_RISCV_IS_IRQ (ExceptionType)) { 306 IrqIndex = EXCEPT_RISCV_IRQ_INDEX (ExceptionType); 307 308 if ((IrqIndex <= EXCEPT_RISCV_MAX_IRQS) && 309 (mIrqHandlers[IrqIndex] != NULL)) 310 { 311 mIrqHandlers[IrqIndex](ExceptionType, RiscVSystemContext); 312 return; 313 } 314 } else { 315 if ((ExceptionType <= EXCEPT_RISCV_MAX_EXCEPTIONS) && 316 (mExceptionHandlers[ExceptionType] != 0)) 317 { 318 mExceptionHandlers[ExceptionType](ExceptionType, RiscVSystemContext); 319 return; 320 } 321 } 322 323 DumpCpuContext (ExceptionType, RiscVSystemContext); 324 CpuDeadLoop (); 325 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/CpuExceptionHandlerLib.h
r99404 r101291 60 60 #define SMODE_TRAP_REGS_sepc 32 61 61 #define SMODE_TRAP_REGS_sstatus 33 62 #define SMODE_TRAP_REGS_s ie3462 #define SMODE_TRAP_REGS_stval 34 63 63 #define SMODE_TRAP_REGS_last 35 64 64 … … 69 69 typedef struct { 70 70 // 71 // Below are follow the format of EFI_SYSTEM_CONTEXT71 // Below follow the format of EFI_SYSTEM_CONTEXT. 72 72 // 73 73 UINT64 zero; … … 103 103 UINT64 t5; 104 104 UINT64 t6; 105 //106 // Below are the additional information to107 // EFI_SYSTEM_CONTEXT, private to supervisor mode trap108 // and not public to EFI environment.109 //110 105 UINT64 sepc; 111 106 UINT64 sstatus; 112 UINT64 s ie;107 UINT64 stval; 113 108 } SMODE_TRAP_REGISTERS; 114 109 #pragma pack() -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/SupervisorTrapHandler.S
r99404 r101291 21 21 22 22 csrr t0, CSR_SSTATUS 23 and t0, t0, (SSTATUS_SIE | SSTATUS_SPIE)24 23 sd t0, SMODE_TRAP_REGS_OFFSET(sstatus)(sp) 25 24 csrr t0, CSR_SEPC 26 25 sd t0, SMODE_TRAP_REGS_OFFSET(sepc)(sp) 27 csrr t0, CSR_S IE28 sd t0, SMODE_TRAP_REGS_OFFSET(s ie)(sp)26 csrr t0, CSR_STVAL 27 sd t0, SMODE_TRAP_REGS_OFFSET(stval)(sp) 29 28 ld t0, SMODE_TRAP_REGS_OFFSET(t0)(sp) 30 29 30 sd zero, SMODE_TRAP_REGS_OFFSET(zero)(sp) 31 31 sd ra, SMODE_TRAP_REGS_OFFSET(ra)(sp) 32 32 sd gp, SMODE_TRAP_REGS_OFFSET(gp)(sp) … … 60 60 61 61 /* Call to Supervisor mode trap handler in CpuExceptionHandlerLib.c */ 62 mv a0, sp 62 63 call RiscVSupervisorModeTrapHandler 63 64 … … 67 68 ld tp, SMODE_TRAP_REGS_OFFSET(tp)(sp) 68 69 ld t2, SMODE_TRAP_REGS_OFFSET(t2)(sp) 70 ld t1, SMODE_TRAP_REGS_OFFSET(t1)(sp) 69 71 ld s0, SMODE_TRAP_REGS_OFFSET(s0)(sp) 70 72 ld s1, SMODE_TRAP_REGS_OFFSET(s1)(sp) … … 94 96 ld t0, SMODE_TRAP_REGS_OFFSET(sepc)(sp) 95 97 csrw CSR_SEPC, t0 96 ld t0, SMODE_TRAP_REGS_OFFSET(sie)(sp) 97 csrw CSR_SIE, t0 98 csrr t0, CSR_SSTATUS 99 ld t1, SMODE_TRAP_REGS_OFFSET(sstatus)(sp) 100 or t0, t0, t1 98 ld t0, SMODE_TRAP_REGS_OFFSET(sstatus)(sp) 101 99 csrw CSR_SSTATUS, t0 102 ld t1, SMODE_TRAP_REGS_OFFSET(t1)(sp) 100 ld t0, SMODE_TRAP_REGS_OFFSET(stval)(sp) 101 csrw CSR_STVAL, t0 103 102 ld t0, SMODE_TRAP_REGS_OFFSET(t0)(sp) 104 103 addi sp, sp, SMODE_TRAP_REGS_SIZE -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/CpuTimerLib.c
r99404 r101291 23 23 24 24 **/ 25 STATIC 25 26 VOID 26 27 InternalRiscVTimerDelay ( 27 IN UINT 32Delay28 IN UINT64 Delay 28 29 ) 29 30 { 30 UINT32 Ticks; 31 UINT32 Times; 31 UINT64 Ticks; 32 32 33 Times = Delay >> (RISCV_TIMER_COMPARE_BITS - 2); 34 Delay &= ((1 << (RISCV_TIMER_COMPARE_BITS - 2)) - 1); 35 do { 36 // 37 // The target timer count is calculated here 38 // 39 Ticks = RiscVReadTimer () + Delay; 40 Delay = 1 << (RISCV_TIMER_COMPARE_BITS - 2); 41 while (((Ticks - RiscVReadTimer ()) & (1 << (RISCV_TIMER_COMPARE_BITS - 1))) == 0) { 42 CpuPause (); 43 } 44 } while (Times-- > 0); 33 Ticks = RiscVReadTimer () + Delay; 34 35 while (RiscVReadTimer () <= Ticks) { 36 CpuPause (); 37 } 45 38 } 46 39 … … 62 55 { 63 56 InternalRiscVTimerDelay ( 64 (UINT32)DivU64x32 (65 66 67 68 69 70 57 DivU64x32 ( 58 MultU64x32 ( 59 MicroSeconds, 60 PcdGet64 (PcdCpuCoreCrystalClockFrequency) 61 ), 62 1000000u 63 ) 71 64 ); 72 65 return MicroSeconds; … … 90 83 { 91 84 InternalRiscVTimerDelay ( 92 (UINT32)DivU64x32 (93 94 95 96 97 98 85 DivU64x32 ( 86 MultU64x32 ( 87 NanoSeconds, 88 PcdGet64 (PcdCpuCoreCrystalClockFrequency) 89 ), 90 1000000000u 91 ) 99 92 ); 100 93 return NanoSeconds; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
r99404 r101291 4 4 This local APIC library instance supports xAPIC mode only. 5 5 6 Copyright (c) 2010 - 20 19, Intel Corporation. All rights reserved.<BR>6 Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR> 7 7 Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR> 8 8 … … 23 23 #include <Library/PcdLib.h> 24 24 #include <Library/CpuLib.h> 25 #include <Library/UefiCpuLib.h>26 25 27 26 // … … 494 493 IcrLow.Uint32 = 0; 495 494 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT; 495 IcrLow.Bits.Level = 1; 496 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 497 SendIpi (IcrLow.Uint32, 0); 498 } 499 500 /** 501 Send a Start-up IPI to all processors excluding self. 502 This function returns after the IPI has been accepted by the target processors. 503 if StartupRoutine >= 1M, then ASSERT. 504 if StartupRoutine is not multiple of 4K, then ASSERT. 505 @param StartupRoutine Points to a start-up routine which is below 1M physical 506 address and 4K aligned. 507 **/ 508 VOID 509 EFIAPI 510 SendStartupIpiAllExcludingSelf ( 511 IN UINT32 StartupRoutine 512 ) 513 { 514 LOCAL_APIC_ICR_LOW IcrLow; 515 516 ASSERT (StartupRoutine < 0x100000); 517 ASSERT ((StartupRoutine & 0xfff) == 0); 518 519 IcrLow.Uint32 = 0; 520 IcrLow.Bits.Vector = (StartupRoutine >> 12); 521 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; 496 522 IcrLow.Bits.Level = 1; 497 523 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; … … 553 579 ) 554 580 { 555 LOCAL_APIC_ICR_LOW IcrLow;556 557 ASSERT (StartupRoutine < 0x100000);558 ASSERT ((StartupRoutine & 0xfff) == 0);559 560 581 SendInitIpiAllExcludingSelf (); 561 582 MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds)); 562 IcrLow.Uint32 = 0; 563 IcrLow.Bits.Vector = (StartupRoutine >> 12); 564 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; 565 IcrLow.Bits.Level = 1; 566 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 567 SendIpi (IcrLow.Uint32, 0); 583 SendStartupIpiAllExcludingSelf (StartupRoutine); 568 584 if (!StandardSignatureIsAuthenticAMD ()) { 569 585 MicroSecondDelay (200); 570 Send Ipi (IcrLow.Uint32, 0);586 SendStartupIpiAllExcludingSelf (StartupRoutine); 571 587 } 572 588 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
r99404 r101291 40 40 PcdLib 41 41 CpuLib 42 UefiCpuLib43 42 44 43 [Pcd] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
r99404 r101291 5 5 which have xAPIC and x2APIC modes. 6 6 7 Copyright (c) 2010 - 20 19, Intel Corporation. All rights reserved.<BR>7 Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR> 8 8 Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR> 9 9 … … 24 24 #include <Library/PcdLib.h> 25 25 #include <Library/CpuLib.h> 26 #include <Library/UefiCpuLib.h>27 26 #include <IndustryStandard/Tdx.h> 28 27 … … 739 738 740 739 /** 740 Send a Start-up IPI to all processors excluding self. 741 This function returns after the IPI has been accepted by the target processors. 742 if StartupRoutine >= 1M, then ASSERT. 743 if StartupRoutine is not multiple of 4K, then ASSERT. 744 @param StartupRoutine Points to a start-up routine which is below 1M physical 745 address and 4K aligned. 746 **/ 747 VOID 748 EFIAPI 749 SendStartupIpiAllExcludingSelf ( 750 IN UINT32 StartupRoutine 751 ) 752 { 753 LOCAL_APIC_ICR_LOW IcrLow; 754 755 ASSERT (StartupRoutine < 0x100000); 756 ASSERT ((StartupRoutine & 0xfff) == 0); 757 758 IcrLow.Uint32 = 0; 759 IcrLow.Bits.Vector = (StartupRoutine >> 12); 760 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; 761 IcrLow.Bits.Level = 1; 762 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 763 SendIpi (IcrLow.Uint32, 0); 764 } 765 766 /** 741 767 Send an INIT-Start-up-Start-up IPI sequence to a specified target processor. 742 768 … … 792 818 ) 793 819 { 794 LOCAL_APIC_ICR_LOW IcrLow;795 796 ASSERT (StartupRoutine < 0x100000);797 ASSERT ((StartupRoutine & 0xfff) == 0);798 799 820 SendInitIpiAllExcludingSelf (); 800 821 MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds)); 801 IcrLow.Uint32 = 0; 802 IcrLow.Bits.Vector = (StartupRoutine >> 12); 803 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; 804 IcrLow.Bits.Level = 1; 805 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 806 SendIpi (IcrLow.Uint32, 0); 822 SendStartupIpiAllExcludingSelf (StartupRoutine); 807 823 if (!StandardSignatureIsAuthenticAMD ()) { 808 824 MicroSecondDelay (200); 809 Send Ipi (IcrLow.Uint32, 0);825 SendStartupIpiAllExcludingSelf (StartupRoutine); 810 826 } 811 827 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
r99404 r101291 40 40 PcdLib 41 41 CpuLib 42 UefiCpuLib43 42 44 43 [Pcd] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf
r85718 r101291 5 5 # Architectures Software Developer's Manual. 6 6 # 7 # Copyright (c) 2017 - 20 19, Intel Corporation. All rights reserved.<BR>7 # Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR> 8 8 # 9 9 # SPDX-License-Identifier: BSD-2-Clause-Patent … … 59 59 60 60 [Pcd] 61 gUefiCpuPkgTokenSpaceGuid.PcdCpuClockModulationDutyCycle ## SOMETIMES_CONSUMES 62 gUefiCpuPkgTokenSpaceGuid.PcdIsPowerOnReset ## SOMETIMES_CONSUMES 63 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceOutputScheme ## SOMETIMES_CONSUMES 64 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceMemSize ## SOMETIMES_CONSUMES 61 gUefiCpuPkgTokenSpaceGuid.PcdCpuClockModulationDutyCycle ## SOMETIMES_CONSUMES 62 gUefiCpuPkgTokenSpaceGuid.PcdIsPowerOnReset ## SOMETIMES_CONSUMES 63 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceOutputScheme ## SOMETIMES_CONSUMES 64 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceMemSize ## SOMETIMES_CONSUMES 65 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceBspOnly ## SOMETIMES_CONSUMES 66 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTracePerformanceCollecting ## SOMETIMES_CONSUMES -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuCommonFeaturesLib/ProcTrace.c
r99404 r101291 2 2 Intel Processor Trace feature. 3 3 4 Copyright (c) 2017 - 20 18, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 34 34 MSR_IA32_RTIT_OUTPUT_BASE_REGISTER RtitOutputBase; 35 35 MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER RtitOutputMaskPtrs; 36 BOOLEAN CycPacketSupported; 36 37 } PROC_TRACE_PROCESSOR_DATA; 37 38 … … 46 47 47 48 UINTN *TopaMemArray; 49 50 BOOLEAN EnableOnBspOnly; 51 BOOLEAN EnablePerformanceCollecting; 48 52 49 53 PROC_TRACE_PROCESSOR_DATA *ProcessorData; … … 75 79 ConfigData->ProcessorData = (PROC_TRACE_PROCESSOR_DATA *)((UINT8 *)ConfigData + sizeof (PROC_TRACE_DATA)); 76 80 77 ConfigData->NumberOfProcessors = (UINT32)NumberOfProcessors; 78 ConfigData->ProcTraceMemSize = PcdGet32 (PcdCpuProcTraceMemSize); 79 ConfigData->ProcTraceOutputScheme = PcdGet8 (PcdCpuProcTraceOutputScheme); 81 ConfigData->NumberOfProcessors = (UINT32)NumberOfProcessors; 82 ConfigData->ProcTraceMemSize = PcdGet32 (PcdCpuProcTraceMemSize); 83 ConfigData->ProcTraceOutputScheme = PcdGet8 (PcdCpuProcTraceOutputScheme); 84 ConfigData->EnableOnBspOnly = PcdGetBool (PcdCpuProcTraceBspOnly); 85 ConfigData->EnablePerformanceCollecting = PcdGetBool (PcdCpuProcTracePerformanceCollecting); 80 86 81 87 return ConfigData; … … 109 115 PROC_TRACE_DATA *ProcTraceData; 110 116 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX Ebx; 111 CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX Ecx; 117 CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX ProcTraceEcx; 118 CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_EBX ProcTraceEbx; 112 119 113 120 // … … 130 137 } 131 138 132 AsmCpuidEx (CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF, NULL, NULL, &Ecx.Uint32, NULL);133 ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported = (BOOLEAN)( Ecx.Bits.RTIT == 1);134 ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN)( Ecx.Bits.SingleRangeOutput == 1);139 AsmCpuidEx (CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF, NULL, &ProcTraceEbx.Uint32, &ProcTraceEcx.Uint32, NULL); 140 ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported = (BOOLEAN)(ProcTraceEcx.Bits.RTIT == 1); 141 ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN)(ProcTraceEcx.Bits.SingleRangeOutput == 1); 135 142 if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) || 136 143 (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange))) … … 139 146 ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_BASE); 140 147 ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_MASK_PTRS); 148 ProcTraceData->ProcessorData[ProcessorNumber].CycPacketSupported = (BOOLEAN)(ProcTraceEbx.Bits.ConfigurablePsb == 1); 149 141 150 return TRUE; 142 151 } … … 189 198 MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER OutputMaskPtrsReg; 190 199 RTIT_TOPA_TABLE_ENTRY *TopaEntryPtr; 200 BOOLEAN IsBsp; 191 201 192 202 // … … 237 247 } 238 248 249 IsBsp = (CpuInfo->ProcessorInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? TRUE : FALSE; 250 251 if (ProcTraceData->EnableOnBspOnly && !IsBsp) { 252 return RETURN_SUCCESS; 253 } 254 239 255 MemRegionBaseAddr = 0; 240 256 FirstIn = FALSE; … … 261 277 // aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 cleared. 262 278 // 263 ThreadMemRegionTable = (UINTN *)AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *)); 264 if (ThreadMemRegionTable == NULL) { 265 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n")); 266 return RETURN_OUT_OF_RESOURCES; 267 } 268 269 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable; 270 271 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) { 272 Pages = EFI_SIZE_TO_PAGES (MemRegionSize); 273 Alignment = MemRegionSize; 274 AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment); 275 if (AlignedAddress == 0) { 276 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads)); 277 if (Index == 0) { 278 // 279 // Could not allocate for BSP even 280 // 281 FreePool ((VOID *)ThreadMemRegionTable); 282 ThreadMemRegionTable = NULL; 283 return RETURN_OUT_OF_RESOURCES; 279 280 Pages = EFI_SIZE_TO_PAGES (MemRegionSize); 281 Alignment = MemRegionSize; 282 if (ProcTraceData->EnableOnBspOnly) { 283 // 284 // When only enable ProcTrace on BSP, this is the first and only time ProcTraceInitialize() runs. 285 // 286 MemRegionBaseAddr = (UINTN)AllocateAlignedReservedPages (Pages, Alignment); 287 if (MemRegionBaseAddr == 0) { 288 // 289 // Could not allocate for BSP even 290 // 291 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, failed to allocate buffer for BSP\n")); 292 return RETURN_OUT_OF_RESOURCES; 293 } 294 295 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT MemRegionBaseAddr(aligned) for BSP only: 0x%llX.\n", (UINT64)MemRegionBaseAddr)); 296 } else { 297 ThreadMemRegionTable = (UINTN *)AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *)); 298 if (ThreadMemRegionTable == NULL) { 299 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n")); 300 return RETURN_OUT_OF_RESOURCES; 301 } 302 303 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable; 304 305 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) { 306 AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment); 307 if (AlignedAddress == 0) { 308 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads)); 309 if (Index == 0) { 310 // 311 // Could not allocate for BSP even 312 // 313 FreePool ((VOID *)ThreadMemRegionTable); 314 ThreadMemRegionTable = NULL; 315 return RETURN_OUT_OF_RESOURCES; 316 } 317 318 break; 284 319 } 285 320 286 break; 321 ThreadMemRegionTable[Index] = AlignedAddress; 322 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64)ThreadMemRegionTable[Index])); 287 323 } 288 324 289 ThreadMemRegionTable[Index] = AlignedAddress; 290 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64)ThreadMemRegionTable[Index])); 291 } 292 293 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads)); 294 } 295 296 if (ProcessorNumber < ProcTraceData->AllocatedThreads) { 297 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber]; 298 } else { 299 return RETURN_SUCCESS; 325 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads)); 326 } 327 } 328 329 if (!ProcTraceData->EnableOnBspOnly) { 330 if (ProcessorNumber < ProcTraceData->AllocatedThreads) { 331 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber]; 332 } else { 333 return RETURN_SUCCESS; 334 } 300 335 } 301 336 … … 368 403 if (FirstIn) { 369 404 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n")); 370 // 371 // Let BSP allocate ToPA table mem for all threads 372 // 373 TopaMemArray = (UINTN *)AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *)); 374 if (TopaMemArray == NULL) { 375 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n")); 376 return RETURN_OUT_OF_RESOURCES; 405 406 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE)); 407 Alignment = 0x1000; 408 409 if (ProcTraceData->EnableOnBspOnly) { 410 // 411 // When only enable ProcTrace on BSP, this is the first and only time ProcTraceInitialize() runs. 412 // 413 TopaTableBaseAddr = (UINTN)AllocateAlignedReservedPages (Pages, Alignment); 414 if (TopaTableBaseAddr == 0) { 415 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, failed to allocate ToPA mem for BSP")); 416 return RETURN_OUT_OF_RESOURCES; 417 } 418 419 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for BSP only: 0x%llX \n", (UINT64)TopaTableBaseAddr)); 420 } else { 421 // 422 // Let BSP allocate ToPA table mem for all threads 423 // 424 TopaMemArray = (UINTN *)AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *)); 425 if (TopaMemArray == NULL) { 426 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n")); 427 return RETURN_OUT_OF_RESOURCES; 428 } 429 430 ProcTraceData->TopaMemArray = TopaMemArray; 431 432 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) { 433 AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment); 434 if (AlignedAddress == 0) { 435 if (Index < ProcTraceData->AllocatedThreads) { 436 ProcTraceData->AllocatedThreads = Index; 437 } 438 439 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads)); 440 if (Index == 0) { 441 // 442 // Could not allocate for BSP even 443 // 444 FreePool ((VOID *)TopaMemArray); 445 TopaMemArray = NULL; 446 return RETURN_OUT_OF_RESOURCES; 447 } 448 449 break; 450 } 451 452 TopaMemArray[Index] = AlignedAddress; 453 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64)TopaMemArray[Index])); 454 } 455 456 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads)); 377 457 } 378 379 ProcTraceData->TopaMemArray = TopaMemArray; 380 381 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) { 382 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE)); 383 Alignment = 0x1000; 384 AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment); 385 if (AlignedAddress == 0) { 386 if (Index < ProcTraceData->AllocatedThreads) { 387 ProcTraceData->AllocatedThreads = Index; 388 } 389 390 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads)); 391 if (Index == 0) { 392 // 393 // Could not allocate for BSP even 394 // 395 FreePool ((VOID *)TopaMemArray); 396 TopaMemArray = NULL; 397 return RETURN_OUT_OF_RESOURCES; 398 } 399 400 break; 401 } 402 403 TopaMemArray[Index] = AlignedAddress; 404 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64)TopaMemArray[Index])); 458 } 459 460 if (!ProcTraceData->EnableOnBspOnly) { 461 if (ProcessorNumber < ProcTraceData->AllocatedThreads) { 462 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber]; 463 } else { 464 return RETURN_SUCCESS; 405 465 } 406 407 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));408 }409 410 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {411 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];412 } else {413 return RETURN_SUCCESS;414 466 } 415 467 … … 472 524 CtrlReg.Bits.BranchEn = 1; 473 525 CtrlReg.Bits.TraceEn = 1; 526 527 // 528 // Generate CYC/TSC timing packets to collect performance data. 529 // 530 if (ProcTraceData->EnablePerformanceCollecting) { 531 if (ProcTraceData->ProcessorData[ProcessorNumber].CycPacketSupported) { 532 CtrlReg.Bits.CYCEn = 1; 533 CtrlReg.Bits.CYCThresh = 5; 534 } 535 536 // 537 // Write to TSCEn is always supported 538 // 539 CtrlReg.Bits.TSCEn = 1; 540 } 541 474 542 CPU_REGISTER_TABLE_WRITE64 ( 475 543 ProcessorNumber, -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
r99404 r101291 29 29 30 30 [Sources.X64] 31 X64/ Xcode5ExceptionHandlerAsm.nasm31 X64/ExceptionHandlerAsm.nasm 32 32 X64/ArchExceptionHandler.c 33 33 X64/ArchInterruptDefs.h … … 62 62 DebugLib 63 63 CcExitLib 64 65 [BuildOptions] 66 XCODE:*_*_X64_NASM_FLAGS = -D NO_ABSOLUTE_RELOCS_IN_TEXT -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
r99404 r101291 29 29 30 30 [Sources.X64] 31 X64/ Xcode5ExceptionHandlerAsm.nasm31 X64/SecPeiExceptionHandlerAsm.nasm 32 32 X64/ArchExceptionHandler.c 33 33 X64/ArchInterruptDefs.h … … 63 63 gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES 64 64 65 [BuildOptions] 66 XCODE:*_*_X64_NASM_FLAGS = -D NO_ABSOLUTE_RELOCS_IN_TEXT -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
r99404 r101291 29 29 30 30 [Sources.X64] 31 X64/ ExceptionHandlerAsm.nasm31 X64/SecPeiExceptionHandlerAsm.nasm 32 32 X64/ArchExceptionHandler.c 33 33 X64/ArchInterruptDefs.h … … 59 59 gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES 60 60 61 [BuildOptions] 62 XCODE:*_*_X64_NASM_FLAGS = -D NO_ABSOLUTE_RELOCS_IN_TEXT -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
r99404 r101291 29 29 30 30 [Sources.X64] 31 X64/ Xcode5ExceptionHandlerAsm.nasm31 X64/ExceptionHandlerAsm.nasm 32 32 X64/ArchExceptionHandler.c 33 33 X64/ArchInterruptDefs.h … … 62 62 gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES 63 63 64 [BuildOptions] 65 XCODE:*_*_X64_NASM_FLAGS = -D NO_ABSOLUTE_RELOCS_IN_TEXT -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTestCommon.c
r99404 r101291 293 293 DEBUG_INFO, 294 294 "%a: Bsp StackBase = 0x%016lx StackSize = 0x%016lx\n", 295 __ FUNCTION__,295 __func__, 296 296 MemoryHob->AllocDescriptor.MemoryBaseAddress, 297 297 MemoryHob->AllocDescriptor.MemoryLength -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
r99404 r101291 14 14 ; 15 15 ;------------------------------------------------------------------------------ 16 %include "Nasm.inc" 17 18 ; 19 ; Equivalent NASM structure of IA32_DESCRIPTOR 20 ; 21 struc IA32_DESCRIPTOR 22 .Limit CTYPE_UINT16 1 23 .Base CTYPE_UINTN 1 24 endstruc 25 26 ; 27 ; Equivalent NASM structure of IA32_IDT_GATE_DESCRIPTOR 28 ; 29 struc IA32_IDT_GATE_DESCRIPTOR 30 .OffsetLow CTYPE_UINT16 1 31 .Selector CTYPE_UINT16 1 32 .Reserved_0 CTYPE_UINT8 1 33 .GateType CTYPE_UINT8 1 34 .OffsetHigh CTYPE_UINT16 1 35 .OffsetUpper CTYPE_UINT32 1 36 .Reserved_1 CTYPE_UINT32 1 37 endstruc 16 38 17 39 ; … … 32 54 ALIGN 8 33 55 34 ; Generate 32 IDT vectors. 35 ; 32 IDT vectors are enough because interrupts (32+) are not enabled in SEC and PEI phase. 56 ; Generate 256 IDT vectors. 36 57 AsmIdtVectorBegin: 37 58 %assign Vector 0 38 %rep 32 39 push byte %[Vector] 40 push rax 59 %rep 256 60 push strict dword %[Vector] ; This instruction pushes sign-extended 8-byte value on stack 61 push rax 62 %ifdef NO_ABSOLUTE_RELOCS_IN_TEXT 63 mov rax, strict qword 0 ; mov rax, ASM_PFX(CommonInterruptEntry) 64 %else 41 65 mov rax, ASM_PFX(CommonInterruptEntry) 66 %endif 42 67 jmp rax 43 68 %assign Vector Vector+1 … … 46 71 47 72 HookAfterStubHeaderBegin: 48 db 0x6a ; push 49 @VectorNum: 50 db 0 ; 0 will be fixed 51 push rax 73 push strict dword 0 ; 0 will be fixed 74 VectorNum: 75 push rax 76 %ifdef NO_ABSOLUTE_RELOCS_IN_TEXT 77 mov rax, strict qword 0 ; mov rax, HookAfterStubHeaderEnd 78 JmpAbsoluteAddress: 79 %else 52 80 mov rax, HookAfterStubHeaderEnd 81 %endif 53 82 jmp rax 54 83 HookAfterStubHeaderEnd: … … 277 306 ; 278 307 sub rsp, 4 * 8 + 8 279 mov rax, ASM_PFX(CommonExceptionHandler) 280 call rax 308 call ASM_PFX(CommonExceptionHandler) 281 309 add rsp, 4 * 8 + 8 310 311 ; The follow algorithm is used for clear shadow stack token busy bit. 312 ; The comment is based on the sample shadow stack. 313 ; Shadow stack is 32 bytes aligned. 314 ; The sample shadow stack layout : 315 ; Address | Context 316 ; +-------------------------+ 317 ; 0xFB8 | FREE | It is 0xFC0|0x02|(LMA & CS.L), after SAVEPREVSSP. 318 ; +-------------------------+ 319 ; 0xFC0 | Prev SSP | 320 ; +-------------------------+ 321 ; 0xFC8 | RIP | 322 ; +-------------------------+ 323 ; 0xFD0 | CS | 324 ; +-------------------------+ 325 ; 0xFD8 | 0xFD8 | BUSY | BUSY flag cleared after CLRSSBSY 326 ; +-------------------------+ 327 ; 0xFE0 | 0xFC0|0x02|(LMA & CS.L) | 328 ; +-------------------------+ 329 ; Instructions for Intel Control Flow Enforcement Technology (CET) are supported since NASM version 2.15.01. 330 cmp qword [ASM_PFX(mDoFarReturnFlag)], 0 331 jz CetDone 332 mov rax, cr4 333 and rax, 0x800000 ; Check if CET is enabled 334 jz CetDone 335 sub rsp, 0x10 336 sidt [rsp] 337 mov rcx, qword [rsp + IA32_DESCRIPTOR.Base]; Get IDT base address 338 add rsp, 0x10 339 mov rax, qword [rbp + 8]; Get exception number 340 sal rax, 0x04 ; Get IDT offset 341 add rax, rcx ; Get IDT gate descriptor address 342 mov al, byte [rax + IA32_IDT_GATE_DESCRIPTOR.Reserved_0] 343 and rax, 0x01 ; Check IST field 344 jz CetDone 345 ; SSP should be 0xFC0 at this point 346 mov rax, 0x04 ; advance past cs:lip:prevssp;supervisor shadow stack token 347 incsspq rax ; After this SSP should be 0xFE0 348 saveprevssp ; now the shadow stack restore token will be created at 0xFB8 349 rdsspq rax ; Read new SSP, SSP should be 0xFE8 350 sub rax, 0x10 351 clrssbsy [rax] ; Clear token at 0xFD8, SSP should be 0 after this 352 sub rax, 0x20 353 rstorssp [rax] ; Restore to token at 0xFB8, new SSP will be 0xFB8 354 mov rax, 0x01 ; Pop off the new save token created 355 incsspq rax ; SSP should be 0xFC0 now 356 CetDone: 282 357 283 358 cli … … 385 460 global ASM_PFX(AsmGetTemplateAddressMap) 386 461 ASM_PFX(AsmGetTemplateAddressMap): 387 mov rax, AsmIdtVectorBegin462 lea rax, [AsmIdtVectorBegin] 388 463 mov qword [rcx], rax 389 mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32390 mov rax, HookAfterStubHeaderBegin464 mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 256 465 lea rax, [HookAfterStubHeaderBegin] 391 466 mov qword [rcx + 0x10], rax 467 468 %ifdef NO_ABSOLUTE_RELOCS_IN_TEXT 469 ; Fix up CommonInterruptEntry address 470 lea rax, [ASM_PFX(CommonInterruptEntry)] 471 lea rcx, [AsmIdtVectorBegin] 472 %rep 256 473 mov qword [rcx + (JmpAbsoluteAddress - 8 - HookAfterStubHeaderBegin)], rax 474 add rcx, (AsmIdtVectorEnd - AsmIdtVectorBegin) / 256 475 %endrep 476 ; Fix up HookAfterStubHeaderEnd 477 lea rax, [HookAfterStubHeaderEnd] 478 lea rcx, [JmpAbsoluteAddress] 479 mov qword [rcx - 8], rax 480 %endif 481 392 482 ret 393 483 … … 398 488 ASM_PFX(AsmVectorNumFixup): 399 489 mov rax, rdx 400 mov [rcx + ( @VectorNum- HookAfterStubHeaderBegin)], al490 mov [rcx + (VectorNum - 4 - HookAfterStubHeaderBegin)], al 401 491 ret 402 492 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
r99404 r101291 2 2 Internal header for CpuPageTableLib. 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 20 20 21 21 #define REGION_LENGTH(l) LShiftU64 (1, (l) * 9 + 3) 22 23 #define MAX_PAE_PDPTE_NUM 4 22 24 23 25 typedef enum { … … 30 32 31 33 typedef struct { 32 UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory 33 UINT64 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 34 UINT64 UserSupervisor : 1; // 0 = Supervisor, 1=User 35 UINT64 Reserved : 58; 36 UINT64 Nx : 1; // No Execute bit 34 UINT32 Present : 1; // 0 = Not present in memory, 1 = Present in memory 35 UINT32 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 36 UINT32 UserSupervisor : 1; // 0 = Supervisor, 1=User 37 UINT32 Reserved0 : 29; 38 UINT32 Reserved1 : 31; 39 UINT32 Nx : 1; // No Execute bit 37 40 } IA32_PAGE_COMMON_ENTRY; 38 41 … … 42 45 typedef union { 43 46 struct { 44 UINT 64 Present : 1;// 0 = Not present in memory, 1 = Present in memory45 UINT 64 ReadWrite : 1;// 0 = Read-Only, 1= Read/Write46 UINT 64 UserSupervisor : 1;// 0 = Supervisor, 1=User47 UINT 64 WriteThrough : 1;// 0 = Write-Back caching, 1=Write-Through caching48 UINT 64 CacheDisabled : 1;// 0 = Cached, 1=Non-Cached49 UINT 64 Accessed : 1;// 0 = Not accessed, 1 = Accessed (set by CPU)50 UINT 64 Available0 : 1;// Ignored51 UINT 64 MustBeZero : 1;// Must Be Zero52 53 UINT 64 Available2 : 4; // Ignored54 55 UINT 64 PageTableBaseAddress : 40; // Page Table Base Address56 UINT 64 Available3: 11; // Ignored57 UINT 64 Nx: 1; // No Execute bit47 UINT32 Present : 1; // 0 = Not present in memory, 1 = Present in memory 48 UINT32 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 49 UINT32 UserSupervisor : 1; // 0 = Supervisor, 1=User 50 UINT32 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching 51 UINT32 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached 52 UINT32 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU) 53 UINT32 Available0 : 1; // Ignored 54 UINT32 MustBeZero : 1; // Must Be Zero 55 UINT32 Available2 : 4; // Ignored 56 UINT32 PageTableBaseAddressLow : 20; // Page Table Base Address Low 57 58 UINT32 PageTableBaseAddressHigh : 20; // Page Table Base Address High 59 UINT32 Available3 : 11; // Ignored 60 UINT32 Nx : 1; // No Execute bit 58 61 } Bits; 59 62 UINT64 Uint64; … … 87 90 typedef union { 88 91 struct { 89 UINT 64 Present : 1;// 0 = Not present in memory, 1 = Present in memory90 UINT 64 ReadWrite : 1;// 0 = Read-Only, 1= Read/Write91 UINT 64 UserSupervisor : 1;// 0 = Supervisor, 1=User92 UINT 64 WriteThrough : 1;// 0 = Write-Back caching, 1=Write-Through caching93 UINT 64 CacheDisabled : 1;// 0 = Cached, 1=Non-Cached94 UINT 64 Accessed : 1;// 0 = Not accessed, 1 = Accessed (set by CPU)95 UINT 64 Dirty : 1;// 0 = Not dirty, 1 = Dirty (set by CPU)96 UINT 64 MustBeOne : 1;// Page Size. Must Be One97 98 UINT 64 Global : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1)99 UINT 64 Available1 : 3; // Ignored100 UINT 64 Pat : 1; // PAT101 102 UINT 64 PageTableBaseAddress : 39; // Page Table Base Address103 UINT 64 Available3: 7; // Ignored104 UINT 64 ProtectionKey: 4; // Protection key105 UINT 64 Nx: 1; // No Execute bit92 UINT32 Present : 1; // 0 = Not present in memory, 1 = Present in memory 93 UINT32 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 94 UINT32 UserSupervisor : 1; // 0 = Supervisor, 1=User 95 UINT32 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching 96 UINT32 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached 97 UINT32 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU) 98 UINT32 Dirty : 1; // 0 = Not dirty, 1 = Dirty (set by CPU) 99 UINT32 MustBeOne : 1; // Page Size. Must Be One 100 UINT32 Global : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1) 101 UINT32 Available1 : 3; // Ignored 102 UINT32 Pat : 1; // PAT 103 UINT32 PageTableBaseAddressLow : 19; // Page Table Base Address Low 104 105 UINT32 PageTableBaseAddressHigh : 20; // Page Table Base Address High 106 UINT32 Available3 : 7; // Ignored 107 UINT32 ProtectionKey : 4; // Protection key 108 UINT32 Nx : 1; // No Execute bit 106 109 } Bits; 107 110 UINT64 Uint64; … … 124 127 typedef union { 125 128 struct { 126 UINT 64 Present : 1;// 0 = Not present in memory, 1 = Present in memory127 UINT 64 ReadWrite : 1;// 0 = Read-Only, 1= Read/Write128 UINT 64 UserSupervisor : 1;// 0 = Supervisor, 1=User129 UINT 64 WriteThrough : 1;// 0 = Write-Back caching, 1=Write-Through caching130 UINT 64 CacheDisabled : 1;// 0 = Cached, 1=Non-Cached131 UINT 64 Accessed : 1;// 0 = Not accessed, 1 = Accessed (set by CPU)132 UINT 64 Dirty : 1;// 0 = Not dirty, 1 = Dirty (set by CPU)133 UINT 64 Pat : 1;// PAT134 135 UINT 64 Global : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1)136 UINT 64 Available1 : 3; // Ignored137 138 UINT 64 PageTableBaseAddress : 40; // Page Table Base Address139 UINT 64 Available3: 7; // Ignored140 UINT 64 ProtectionKey: 4; // Protection key141 UINT 64 Nx: 1; // No Execute bit129 UINT32 Present : 1; // 0 = Not present in memory, 1 = Present in memory 130 UINT32 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write 131 UINT32 UserSupervisor : 1; // 0 = Supervisor, 1=User 132 UINT32 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching 133 UINT32 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached 134 UINT32 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU) 135 UINT32 Dirty : 1; // 0 = Not dirty, 1 = Dirty (set by CPU) 136 UINT32 Pat : 1; // PAT 137 UINT32 Global : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1) 138 UINT32 Available1 : 3; // Ignored 139 UINT32 PageTableBaseAddressLow : 20; // Page Table Base Address Low 140 141 UINT32 PageTableBaseAddressHigh : 20; // Page Table Base Address High 142 UINT32 Available3 : 7; // Ignored 143 UINT32 ProtectionKey : 4; // Protection key 144 UINT32 Nx : 1; // No Execute bit 142 145 } Bits; 143 146 UINT64 Uint64; … … 150 153 typedef union { 151 154 struct { 152 UINT 64 Present : 1;// 0 = Not present in memory, 1 = Present in memory153 UINT 64 MustBeZero : 2;// Must Be Zero154 UINT 64 WriteThrough : 1;// 0 = Write-Back caching, 1=Write-Through caching155 UINT 64 CacheDisabled : 1;// 0 = Cached, 1=Non-Cached156 UINT 64 MustBeZero2 : 4;// Must Be Zero157 158 UINT 64 Available : 3; // Ignored159 160 UINT 64 PageTableBaseAddress : 40; // Page Table Base Address161 UINT 64 MustBeZero3: 12; // Must Be Zero155 UINT32 Present : 1; // 0 = Not present in memory, 1 = Present in memory 156 UINT32 MustBeZero : 2; // Must Be Zero 157 UINT32 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching 158 UINT32 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached 159 UINT32 MustBeZero2 : 4; // Must Be Zero 160 UINT32 Available : 3; // Ignored 161 UINT32 PageTableBaseAddressLow : 20; // Page Table Base Address Low 162 163 UINT32 PageTableBaseAddressHigh : 20; // Page Table Base Address High 164 UINT32 MustBeZero3 : 12; // Must Be Zero 162 165 } Bits; 163 166 UINT64 Uint64; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
r99404 r101291 2 2 This library implements CpuPageTableLib that are generic for IA32 family CPU. 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 27 27 ) 28 28 { 29 if (Mask->Bits.PageTableBaseAddress ) {29 if (Mask->Bits.PageTableBaseAddressLow || Mask->Bits.PageTableBaseAddressHigh) { 30 30 Pte4K->Uint64 = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) | (Pte4K->Uint64 & ~IA32_PE_BASE_ADDRESS_MASK_40); 31 31 } … … 94 94 ) 95 95 { 96 if (Mask->Bits.PageTableBaseAddress ) {96 if (Mask->Bits.PageTableBaseAddressLow || Mask->Bits.PageTableBaseAddressHigh) { 97 97 PleB->Uint64 = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) | (PleB->Uint64 & ~IA32_PE_BASE_ADDRESS_MASK_39); 98 98 } … … 203 203 } 204 204 205 Pnle->Bits.Accessed = 0; 205 Pnle->Bits.Accessed = 0; 206 Pnle->Bits.MustBeZero = 0; 206 207 207 208 // … … 213 214 Pnle->Bits.WriteThrough = 0; 214 215 Pnle->Bits.CacheDisabled = 0; 216 } 217 218 /** 219 Check if the combination for Attribute and Mask is valid for non-present entry. 220 1.Mask.Present is 0 but some other attributes is provided. This case should be invalid. 221 2.Map non-present range to present. In this case, all attributes should be provided. 222 223 @param[in] Attribute The attribute of the linear address range. 224 @param[in] Mask The mask used for attribute to check. 225 226 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 0 but some other attributes are provided. 227 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are not provided. 228 @retval RETURN_SUCCESS The combination for Attribute and Mask is valid. 229 **/ 230 RETURN_STATUS 231 IsAttributesAndMaskValidForNonPresentEntry ( 232 IN IA32_MAP_ATTRIBUTE *Attribute, 233 IN IA32_MAP_ATTRIBUTE *Mask 234 ) 235 { 236 if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) { 237 // 238 // Creating new page table or remapping non-present range to present. 239 // 240 if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) || 241 (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) || 242 ((Mask->Bits.PageTableBaseAddressLow == 0) && (Mask->Bits.PageTableBaseAddressHigh == 0)) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0)) 243 { 244 return RETURN_INVALID_PARAMETER; 245 } 246 } else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) { 247 // 248 // Only change other attributes for non-present range is not permitted. 249 // 250 return RETURN_INVALID_PARAMETER; 251 } 252 253 return RETURN_SUCCESS; 215 254 } 216 255 … … 236 275 when a new physical base address is set. 237 276 @param[in] Mask The mask used for attribute. The corresponding field in Attribute is ignored if that in Mask is 0. 238 277 @param[out] IsModified TRUE means page table is modified. FALSE means page table is not modified. 278 279 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 0 but some other attributes are provided. 280 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are not provided. 239 281 @retval RETURN_SUCCESS PageTable is created/updated successfully. 240 282 **/ … … 252 294 IN UINT64 Offset, 253 295 IN IA32_MAP_ATTRIBUTE *Attribute, 254 IN IA32_MAP_ATTRIBUTE *Mask 296 IN IA32_MAP_ATTRIBUTE *Mask, 297 OUT BOOLEAN *IsModified 255 298 ) 256 299 { … … 259 302 UINTN Index; 260 303 IA32_PAGING_ENTRY *PagingEntry; 304 UINTN PagingEntryIndex; 305 UINTN PagingEntryIndexEnd; 261 306 IA32_PAGING_ENTRY *CurrentPagingEntry; 262 307 UINT64 RegionLength; … … 274 319 IA32_MAP_ATTRIBUTE CurrentMask; 275 320 IA32_MAP_ATTRIBUTE LocalParentAttribute; 321 UINT64 PhysicalAddrInEntry; 322 UINT64 PhysicalAddrInAttr; 323 IA32_PAGING_ENTRY OriginalParentPagingEntry; 324 IA32_PAGING_ENTRY OriginalCurrentPagingEntry; 276 325 277 326 ASSERT (Level != 0); … … 289 338 ParentAttribute = &LocalParentAttribute; 290 339 340 OriginalParentPagingEntry.Uint64 = ParentPagingEntry->Uint64; 341 342 // 343 // RegionLength: 256T (1 << 48) 512G (1 << 39), 1G (1 << 30), 2M (1 << 21) or 4K (1 << 12). 344 // 345 BitStart = 12 + (Level - 1) * 9; 346 PagingEntryIndex = (UINTN)BitFieldRead64 (LinearAddress + Offset, BitStart, BitStart + 9 - 1); 347 RegionLength = REGION_LENGTH (Level); 348 RegionMask = RegionLength - 1; 349 291 350 // 292 351 // ParentPagingEntry ONLY is deferenced for checking Present and MustBeOne bits 293 352 // when Modify is FALSE. 294 353 // 295 296 if (ParentPagingEntry->Pce.Present == 0) { 297 // 298 // The parent entry is CR3 or PML5E/PML4E/PDPTE/PDE. 354 if ((ParentPagingEntry->Pce.Present == 0) || IsPle (ParentPagingEntry, Level + 1)) { 355 // 356 // When ParentPagingEntry is non-present, parent entry is CR3 or PML5E/PML4E/PDPTE/PDE. 299 357 // It does NOT point to an existing page directory. 300 // 358 // When ParentPagingEntry is present, parent entry is leaf PDPTE_1G or PDE_2M. Split to 2M or 4K pages. 359 // Note: it's impossible the parent entry is a PTE_4K. 360 // 361 PleBAttribute.Uint64 = PageTableLibGetPleBMapAttribute (&ParentPagingEntry->PleB, ParentAttribute); 362 if (ParentPagingEntry->Pce.Present == 0) { 363 // 364 // [LinearAddress, LinearAddress + Length] contains non-present range. 365 // 366 Status = IsAttributesAndMaskValidForNonPresentEntry (Attribute, Mask); 367 if (RETURN_ERROR (Status)) { 368 return Status; 369 } 370 371 OneOfPagingEntry.Pnle.Uint64 = 0; 372 } else { 373 PageTableLibSetPle (Level, &OneOfPagingEntry, 0, &PleBAttribute, &AllOneMask); 374 } 375 376 // 377 // Check if the attribute, the physical address calculated by ParentPagingEntry is equal to 378 // the attribute, the physical address calculated by input Attribue and Mask. 379 // 380 if ((IA32_MAP_ATTRIBUTE_ATTRIBUTES (&PleBAttribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask)) 381 == (IA32_MAP_ATTRIBUTE_ATTRIBUTES (Attribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask))) 382 { 383 if ((Mask->Bits.PageTableBaseAddressLow == 0) && (Mask->Bits.PageTableBaseAddressHigh == 0)) { 384 return RETURN_SUCCESS; 385 } 386 387 // 388 // Non-present entry won't reach there since: 389 // 1.When map non-present entry to present, the attribute must be different. 390 // 2.When still map non-present entry to non-present, PageTableBaseAddressLow and High in Mask must be 0. 391 // 392 ASSERT (ParentPagingEntry->Pce.Present == 1); 393 PhysicalAddrInEntry = IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&PleBAttribute) + MultU64x32 (RegionLength, (UINT32)PagingEntryIndex); 394 PhysicalAddrInAttr = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) & (~RegionMask); 395 if (PhysicalAddrInEntry == PhysicalAddrInAttr) { 396 return RETURN_SUCCESS; 397 } 398 } 399 301 400 ASSERT (Buffer == NULL || *BufferSize >= SIZE_4KB); 302 401 CreateNew = TRUE; … … 304 403 305 404 if (Modify) { 306 ParentPagingEntry->Uintn = (UINTN)Buffer + *BufferSize; 307 ZeroMem ((VOID *)ParentPagingEntry->Uintn, SIZE_4KB); 308 // 309 // Set default attribute bits for PML5E/PML4E/PDPTE/PDE. 310 // 311 PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute, &AllOneMask); 312 } else { 313 // 314 // Just make sure Present and MustBeZero (PageSize) bits are accurate. 315 // 316 OneOfPagingEntry.Pnle.Uint64 = 0; 317 } 318 } else if (IsPle (ParentPagingEntry, Level + 1)) { 319 // 320 // The parent entry is a PDPTE_1G or PDE_2M. Split to 2M or 4K pages. 321 // Note: it's impossible the parent entry is a PTE_4K. 322 // 323 // 324 // Use NOP attributes as the attribute of grand-parents because CPU will consider 325 // the actual attributes of grand-parents when determing the memory type. 326 // 327 PleBAttribute.Uint64 = PageTableLibGetPleBMapAttribute (&ParentPagingEntry->PleB, ParentAttribute); 328 if ((IA32_MAP_ATTRIBUTE_ATTRIBUTES (&PleBAttribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask)) 329 == (IA32_MAP_ATTRIBUTE_ATTRIBUTES (Attribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask))) 330 { 331 // 332 // This function is called when the memory length is less than the region length of the parent level. 333 // No need to split the page when the attributes equal. 334 // 335 return RETURN_SUCCESS; 336 } 337 338 ASSERT (Buffer == NULL || *BufferSize >= SIZE_4KB); 339 CreateNew = TRUE; 340 *BufferSize -= SIZE_4KB; 341 PageTableLibSetPle (Level, &OneOfPagingEntry, 0, &PleBAttribute, &AllOneMask); 342 if (Modify) { 343 // 344 // Create 512 child-level entries that map to 2M/4K. 345 // 346 ParentPagingEntry->Uintn = (UINTN)Buffer + *BufferSize; 347 ZeroMem ((VOID *)ParentPagingEntry->Uintn, SIZE_4KB); 405 PagingEntry = (IA32_PAGING_ENTRY *)((UINTN)Buffer + *BufferSize); 406 ZeroMem (PagingEntry, SIZE_4KB); 407 408 if (ParentPagingEntry->Pce.Present) { 409 // 410 // Create 512 child-level entries that map to 2M/4K. 411 // 412 for (SubOffset = 0, Index = 0; Index < 512; Index++) { 413 PagingEntry[Index].Uint64 = OneOfPagingEntry.Uint64 + SubOffset; 414 SubOffset += RegionLength; 415 } 416 } 348 417 349 418 // … … 352 421 // will make the entire region read-only even the child entries set the RW bit. 353 422 // 423 // Non-leaf entry doesn't have PAT bit. So use ~IA32_PE_BASE_ADDRESS_MASK_40 is to make sure PAT bit 424 // (bit12) in original big-leaf entry is not assigned to PageTableBaseAddress field of non-leaf entry. 425 // 354 426 PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute, &AllOneMask); 355 356 RegionLength = REGION_LENGTH (Level); 357 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle); 358 for (SubOffset = 0, Index = 0; Index < 512; Index++) { 359 PagingEntry[Index].Uint64 = OneOfPagingEntry.Uint64 + SubOffset; 360 SubOffset += RegionLength; 361 } 427 ParentPagingEntry->Uint64 = ((UINTN)(VOID *)PagingEntry) | (ParentPagingEntry->Uint64 & (~IA32_PE_BASE_ADDRESS_MASK_40)); 362 428 } 363 429 } else { 430 // 431 // If (LinearAddress + Length - 1) is not in the same ParentPagingEntry with (LinearAddress + Offset), then the remaining child PagingEntry 432 // starting from PagingEntryIndex of ParentPagingEntry is all covered by [LinearAddress + Offset, LinearAddress + Length - 1]. 433 // 434 PagingEntryIndexEnd = (BitFieldRead64 (LinearAddress + Length - 1, BitStart + 9, 63) != BitFieldRead64 (LinearAddress + Offset, BitStart + 9, 63)) ? 511 : 435 (UINTN)BitFieldRead64 (LinearAddress + Length - 1, BitStart, BitStart + 9 - 1); 436 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle); 437 for (Index = PagingEntryIndex; Index <= PagingEntryIndexEnd; Index++) { 438 if (PagingEntry[Index].Pce.Present == 0) { 439 // 440 // [LinearAddress, LinearAddress + Length] contains non-present range. 441 // 442 Status = IsAttributesAndMaskValidForNonPresentEntry (Attribute, Mask); 443 if (RETURN_ERROR (Status)) { 444 return Status; 445 } 446 447 break; 448 } 449 } 450 364 451 // 365 452 // It's a non-leaf entry … … 376 463 // when PDPTE[0].Nx = 1 but caller wants to map [0-2MB] as Nx = 0 (PDT[0].Nx = 0) 377 464 // we need to change PDPTE[0].Nx = 0 and let all PDE[0-255].Nx = 1 in this step. 378 if ((ParentPagingEntry->Pnle.Bits.Present == 0) && (Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {379 if (Modify) {380 ParentPagingEntry->Pnle.Bits.Present = 1;381 }382 383 ChildAttribute.Bits.Present = 0;384 ChildMask.Bits.Present = 1;385 }386 387 465 if ((ParentPagingEntry->Pnle.Bits.ReadWrite == 0) && (Mask->Bits.ReadWrite == 1) && (Attribute->Bits.ReadWrite == 1)) { 388 466 if (Modify) { … … 418 496 // e.g.: Set PDE[0-255].ReadWrite = 0 419 497 // 420 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle);421 498 for (Index = 0; Index < 512; Index++) { 422 499 if (PagingEntry[Index].Pce.Present == 0) { … … 435 512 436 513 // 437 // RegionLength: 256T (1 << 48) 512G (1 << 39), 1G (1 << 30), 2M (1 << 21) or 4K (1 << 12).438 514 // RegionStart: points to the linear address that's aligned on RegionLength and lower than (LinearAddress + Offset). 439 515 // 440 BitStart = 12 + (Level - 1) * 9; 441 Index = (UINTN)BitFieldRead64 (LinearAddress + Offset, BitStart, BitStart + 9 - 1); 442 RegionLength = LShiftU64 (1, BitStart); 443 RegionMask = RegionLength - 1; 444 RegionStart = (LinearAddress + Offset) & ~RegionMask; 445 516 Index = PagingEntryIndex; 517 RegionStart = (LinearAddress + Offset) & ~RegionMask; 446 518 ParentAttribute->Uint64 = PageTableLibGetPnleMapAttribute (&ParentPagingEntry->Pnle, ParentAttribute); 447 519 … … 492 564 } 493 565 566 // 567 // Check if any leaf PagingEntry is modified. 568 // 569 OriginalCurrentPagingEntry.Uint64 = CurrentPagingEntry->Uint64; 494 570 PageTableLibSetPle (Level, CurrentPagingEntry, Offset, Attribute, &CurrentMask); 571 572 if (OriginalCurrentPagingEntry.Uint64 != CurrentPagingEntry->Uint64) { 573 *IsModified = TRUE; 574 } 495 575 } 496 576 } else { … … 515 595 Offset, 516 596 Attribute, 517 Mask 597 Mask, 598 IsModified 518 599 ); 519 600 if (RETURN_ERROR (Status)) { … … 525 606 RegionStart += RegionLength; 526 607 Index++; 608 } 609 610 // 611 // Check if ParentPagingEntry entry is modified here is enough. Except the changes happen in leaf PagingEntry during 612 // the while loop, if there is any other change happens in page table, the ParentPagingEntry must has been modified. 613 // 614 if (OriginalParentPagingEntry.Uint64 != ParentPagingEntry->Uint64) { 615 *IsModified = TRUE; 527 616 } 528 617 … … 547 636 when a new physical base address is set. 548 637 @param[in] Mask The mask used for attribute. The corresponding field in Attribute is ignored if that in Mask is 0. 638 @param[out] IsModified TRUE means page table is modified. FALSE means page table is not modified. 549 639 550 640 @retval RETURN_UNSUPPORTED PagingMode is not supported. 551 641 @retval RETURN_INVALID_PARAMETER PageTable, BufferSize, Attribute or Mask is NULL. 642 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 0 but some other attributes are provided. 643 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are not provided. 644 @retval RETURN_INVALID_PARAMETER For non-present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are provided. 645 @retval RETURN_INVALID_PARAMETER For present range, Mask->Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are provided. 552 646 @retval RETURN_INVALID_PARAMETER *BufferSize is not multiple of 4KB. 553 647 @retval RETURN_BUFFER_TOO_SMALL The buffer is too small for page table creation/updating. 554 648 BufferSize is updated to indicate the expected buffer size. 555 649 Caller may still get RETURN_BUFFER_TOO_SMALL with the new BufferSize. 556 @retval RETURN_SUCCESS PageTable is created/updated successfully .650 @retval RETURN_SUCCESS PageTable is created/updated successfully or the input Length is 0. 557 651 **/ 558 652 RETURN_STATUS … … 566 660 IN UINT64 Length, 567 661 IN IA32_MAP_ATTRIBUTE *Attribute, 568 IN IA32_MAP_ATTRIBUTE *Mask 662 IN IA32_MAP_ATTRIBUTE *Mask, 663 OUT BOOLEAN *IsModified OPTIONAL 569 664 ) 570 665 { … … 576 671 IA32_PAGE_LEVEL MaxLeafLevel; 577 672 IA32_MAP_ATTRIBUTE ParentAttribute; 578 579 if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) { 673 BOOLEAN LocalIsModified; 674 UINTN Index; 675 IA32_PAGING_ENTRY *PagingEntry; 676 UINT8 BufferInStack[SIZE_4KB - 1 + MAX_PAE_PDPTE_NUM * sizeof (IA32_PAGING_ENTRY)]; 677 678 if (Length == 0) { 679 return RETURN_SUCCESS; 680 } 681 682 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) { 580 683 // 581 684 // 32bit paging is never supported. 582 // PAE paging will be supported later.583 685 // 584 686 return RETURN_UNSUPPORTED; … … 596 698 } 597 699 598 if (( LinearAddress % SIZE_4KB != 0) || (Length % SIZE_4KB != 0)) {700 if (((UINTN)LinearAddress % SIZE_4KB != 0) || ((UINTN)Length % SIZE_4KB != 0)) { 599 701 // 600 702 // LinearAddress and Length should be multiple of 4K. … … 607 709 } 608 710 711 // 712 // If to map [LinearAddress, LinearAddress + Length] as non-present, 713 // all attributes except Present should not be provided. 714 // 715 if ((Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) { 716 return RETURN_INVALID_PARAMETER; 717 } 718 609 719 MaxLeafLevel = (IA32_PAGE_LEVEL)(UINT8)PagingMode; 610 720 MaxLevel = (IA32_PAGE_LEVEL)(UINT8)(PagingMode >> 8); 611 MaxLinearAddress = LShiftU64 (1, 12 + MaxLevel * 9);721 MaxLinearAddress = (PagingMode == PagingPae) ? LShiftU64 (1, 32) : LShiftU64 (1, 12 + MaxLevel * 9); 612 722 613 723 if ((LinearAddress > MaxLinearAddress) || (Length > MaxLinearAddress - LinearAddress)) { 614 724 // 615 // Maximum linear address is (1 << 48) or (1 << 57)725 // Maximum linear address is (1 << 32), (1 << 48) or (1 << 57) 616 726 // 617 727 return RETURN_INVALID_PARAMETER; … … 620 730 TopPagingEntry.Uintn = *PageTable; 621 731 if (TopPagingEntry.Uintn != 0) { 732 if (PagingMode == PagingPae) { 733 // 734 // Create 4 temporary PDPTE at a 4k-aligned address. 735 // Copy the original PDPTE content and set ReadWrite, UserSupervisor to 1, set Nx to 0. 736 // 737 TopPagingEntry.Uintn = ALIGN_VALUE ((UINTN)BufferInStack, BASE_4KB); 738 PagingEntry = (IA32_PAGING_ENTRY *)(TopPagingEntry.Uintn); 739 CopyMem (PagingEntry, (VOID *)(*PageTable), MAX_PAE_PDPTE_NUM * sizeof (IA32_PAGING_ENTRY)); 740 for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) { 741 PagingEntry[Index].Pnle.Bits.ReadWrite = 1; 742 PagingEntry[Index].Pnle.Bits.UserSupervisor = 1; 743 PagingEntry[Index].Pnle.Bits.Nx = 0; 744 } 745 } 746 622 747 TopPagingEntry.Pce.Present = 1; 623 748 TopPagingEntry.Pce.ReadWrite = 1; … … 626 751 } 627 752 628 ParentAttribute.Uint64 = 0; 629 ParentAttribute.Bits.PageTableBaseAddress = 1; 630 ParentAttribute.Bits.Present = 1; 631 ParentAttribute.Bits.ReadWrite = 1; 632 ParentAttribute.Bits.UserSupervisor = 1; 633 ParentAttribute.Bits.Nx = 0; 753 if (IsModified == NULL) { 754 IsModified = &LocalIsModified; 755 } 756 757 *IsModified = FALSE; 758 759 ParentAttribute.Uint64 = 0; 760 ParentAttribute.Bits.PageTableBaseAddressLow = 1; 761 ParentAttribute.Bits.Present = 1; 762 ParentAttribute.Bits.ReadWrite = 1; 763 ParentAttribute.Bits.UserSupervisor = 1; 764 ParentAttribute.Bits.Nx = 0; 634 765 635 766 // … … 649 780 0, 650 781 Attribute, 651 Mask 782 Mask, 783 IsModified 652 784 ); 785 ASSERT (*IsModified == FALSE); 653 786 if (RETURN_ERROR (Status)) { 654 787 return Status; … … 681 814 0, 682 815 Attribute, 683 Mask 816 Mask, 817 IsModified 684 818 ); 819 685 820 if (!RETURN_ERROR (Status)) { 686 *PageTable = (UINTN)(TopPagingEntry.Uintn & IA32_PE_BASE_ADDRESS_MASK_40); 821 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)(TopPagingEntry.Uintn & IA32_PE_BASE_ADDRESS_MASK_40); 822 823 if (PagingMode == PagingPae) { 824 // 825 // These MustBeZero fields are treated as RW and other attributes by the common map logic. So they might be set to 1. 826 // 827 for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) { 828 PagingEntry[Index].PdptePae.Bits.MustBeZero = 0; 829 PagingEntry[Index].PdptePae.Bits.MustBeZero2 = 0; 830 PagingEntry[Index].PdptePae.Bits.MustBeZero3 = 0; 831 } 832 833 if (*PageTable != 0) { 834 // 835 // Copy temp PDPTE to original PDPTE. 836 // 837 CopyMem ((VOID *)(*PageTable), PagingEntry, MAX_PAE_PDPTE_NUM * sizeof (IA32_PAGING_ENTRY)); 838 } 839 } 840 841 if (*PageTable == 0) { 842 // 843 // Do not assign the *PageTable when it's an existing page table. 844 // If it's an existing PAE page table, PagingEntry is the temp buffer in stack. 845 // 846 *PageTable = (UINTN)PagingEntry; 847 } 687 848 } 688 849 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c
r99404 r101291 2 2 This library implements CpuPageTableLib that are generic for IA32 family CPU. 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 159 159 IN UINT64 PageTableBaseAddress, 160 160 IN UINTN Level, 161 IN UINTN MaxLevel, 161 162 IN UINT64 RegionStart, 162 163 IN IA32_MAP_ATTRIBUTE *ParentMapAttribute, … … 172 173 IA32_MAP_ATTRIBUTE MapAttribute; 173 174 UINT64 RegionLength; 175 UINTN PagingEntryNumber; 174 176 175 177 ASSERT (OneEntry != NULL); 176 178 177 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTableBaseAddress; 178 RegionLength = REGION_LENGTH (Level); 179 180 for (Index = 0; Index < 512; Index++, RegionStart += RegionLength) { 179 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTableBaseAddress; 180 RegionLength = REGION_LENGTH (Level); 181 PagingEntryNumber = ((MaxLevel == 3) && (Level == 3)) ? MAX_PAE_PDPTE_NUM : 512; 182 183 for (Index = 0; Index < PagingEntryNumber; Index++, RegionStart += RegionLength) { 181 184 if (PagingEntry[Index].Pce.Present == 0) { 182 185 continue; … … 229 232 IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry[Index].Pnle), 230 233 Level - 1, 234 MaxLevel, 231 235 RegionStart, 232 236 &MapAttribute, … … 270 274 IA32_MAP_ENTRY OneEntry; 271 275 UINTN MaxLevel; 276 UINTN Index; 277 IA32_PAGING_ENTRY BufferInStack[MAX_PAE_PDPTE_NUM]; 272 278 273 279 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) { … … 289 295 *MapCount = 0; 290 296 return RETURN_SUCCESS; 297 } 298 299 if (PagingMode == PagingPae) { 300 CopyMem (BufferInStack, (VOID *)PageTable, sizeof (BufferInStack)); 301 for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) { 302 BufferInStack[Index].Pnle.Bits.ReadWrite = 1; 303 BufferInStack[Index].Pnle.Bits.UserSupervisor = 1; 304 BufferInStack[Index].Pnle.Bits.Nx = 0; 305 } 306 307 PageTable = (UINTN)BufferInStack; 291 308 } 292 309 … … 320 337 *MapCount = 0; 321 338 LastEntry = NULL; 322 PageTableLibParsePnle ((UINT64)PageTable, MaxLevel, 0, &NopAttribute, Map, MapCount, MapCapacity, &LastEntry, &OneEntry);339 PageTableLibParsePnle ((UINT64)PageTable, MaxLevel, MaxLevel, 0, &NopAttribute, Map, MapCount, MapCapacity, &LastEntry, &OneEntry); 323 340 324 341 if (*MapCount > MapCapacity) { -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/CpuPageTableLibUnitTestHost.c
r99404 r101291 2 2 Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 10 10 11 11 // ----------------------------------------------------------------------- PageMode--TestCount-TestRangeCount---RandomOptions 12 static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging4Level = { Paging4Level, 100, 20, ONLY_ONE_ONE_MAPPING|USE_RANDOM_ARRAY }; 13 static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging4Level1GB = { Paging4Level1GB, 100, 20, ONLY_ONE_ONE_MAPPING|USE_RANDOM_ARRAY }; 14 static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging5Level = { Paging5Level, 100, 20, ONLY_ONE_ONE_MAPPING|USE_RANDOM_ARRAY }; 15 static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging5Level1GB = { Paging5Level1GB, 100, 20, ONLY_ONE_ONE_MAPPING|USE_RANDOM_ARRAY }; 12 // static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging4Level = { Paging4Level, 30, 20, USE_RANDOM_ARRAY }; 13 // static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging4Level1GB = { Paging4Level1GB, 30, 20, USE_RANDOM_ARRAY }; 14 // static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging5Level = { Paging5Level, 30, 20, USE_RANDOM_ARRAY }; 15 // static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging5Level1GB = { Paging5Level1GB, 30, 20, USE_RANDOM_ARRAY }; 16 // static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPagingPae = { PagingPae, 30, 20, USE_RANDOM_ARRAY }; 16 17 17 18 /** … … 52 53 // If the input linear address is not 4K align, it should return invalid parameter 53 54 // 54 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, &MapMask ), RETURN_INVALID_PARAMETER);55 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, &MapMask, NULL), RETURN_INVALID_PARAMETER); 55 56 56 57 // … … 58 59 // 59 60 PageTableBufferSize = 10; 60 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 0, SIZE_4KB, &MapAttribute, &MapMask ), RETURN_INVALID_PARAMETER);61 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 0, SIZE_4KB, &MapAttribute, &MapMask, NULL), RETURN_INVALID_PARAMETER); 61 62 62 63 // … … 65 66 PageTableBufferSize = 0; 66 67 PagingMode = Paging32bit; 67 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, &MapMask ), RETURN_UNSUPPORTED);68 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, &MapMask, NULL), RETURN_UNSUPPORTED); 68 69 69 70 // … … 71 72 // 72 73 PagingMode = Paging5Level1GB; 73 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, NULL ), RETURN_INVALID_PARAMETER);74 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, NULL, NULL), RETURN_INVALID_PARAMETER); 74 75 75 76 return UNIT_TEST_PASSED; … … 120 121 // Create page table to cover [0, 10M], it should have 5 PTE 121 122 // 122 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_2MB * 5, &MapAttribute, &MapMask );123 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_2MB * 5, &MapAttribute, &MapMask, NULL); 123 124 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 124 125 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 125 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_2MB * 5, &MapAttribute, &MapMask );126 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_2MB * 5, &MapAttribute, &MapMask, NULL); 126 127 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 127 128 TestStatus = IsPageTableValid (PageTable, PagingMode); … … 135 136 // 136 137 Buffer = NULL; 137 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_4KB, &MapAttribute, &MapMask );138 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_4KB, &MapAttribute, &MapMask, NULL); 138 139 UT_ASSERT_EQUAL (PageTableBufferSize, 0); 139 140 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); … … 149 150 MapMask.Bits.Nx = 0; 150 151 PageTableBufferSize = 0; 151 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, (UINT64)SIZE_4KB, &MapAttribute, &MapMask );152 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, (UINT64)SIZE_4KB, &MapAttribute, &MapMask, NULL); 152 153 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 153 154 UT_ASSERT_EQUAL (PageTableBufferSize, 0); … … 165 166 MapMask.Bits.Accessed = 1; 166 167 PageTableBufferSize = 0; 167 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)SIZE_2MB, (UINT64)SIZE_2MB, &MapAttribute, &MapMask );168 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)SIZE_2MB, (UINT64)SIZE_2MB, &MapAttribute, &MapMask, NULL); 168 169 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 169 170 UT_ASSERT_EQUAL (PageTableBufferSize, 0); … … 218 219 MapMask.Bits.Present = 1; 219 220 MapMask.Uint64 = MAX_UINT64; 220 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask );221 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL); 221 222 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 222 223 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 223 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask );224 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL); 224 225 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 225 226 … … 282 283 // Create Page table to cover [0,2G], with ReadWrite = 1 283 284 // 284 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask );285 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL); 285 286 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 286 287 BackupPageTableBufferSize = PageTableBufferSize; 287 288 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 288 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask );289 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL); 289 290 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 290 291 IsPageTableValid (PageTable, PagingMode); … … 332 333 // 333 334 MapAttribute.Bits.ReadWrite = 0; 334 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, SIZE_2MB, &MapAttribute, &MapMask );335 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, SIZE_2MB, &MapAttribute, &MapMask, NULL); 335 336 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 336 337 IsPageTableValid (PageTable, PagingMode); … … 361 362 MapAttribute.Bits.ReadWrite = 1; 362 363 PageTableBufferSize = 0; 363 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, SIZE_2MB, &MapAttribute, &MapMask );364 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, SIZE_2MB, &MapAttribute, &MapMask, NULL); 364 365 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 365 366 IsPageTableValid (PageTable, PagingMode); … … 423 424 IA32_PAGING_ENTRY *PagingEntry; 424 425 425 PagingMode = Paging4Level; 426 PageTableBufferSize = 0; 427 PageTable = 0; 428 Buffer = NULL; 429 MapAttribute.Uint64 = 0; 430 MapMask.Uint64 = MAX_UINT64; 431 MapAttribute.Bits.Present = 1; 432 MapAttribute.Bits.ReadWrite = 1; 433 MapAttribute.Bits.PageTableBaseAddress = (SIZE_2MB - SIZE_4KB) >> 12; 426 PagingMode = Paging4Level; 427 PageTableBufferSize = 0; 428 PageTable = 0; 429 Buffer = NULL; 430 MapMask.Uint64 = MAX_UINT64; 431 MapAttribute.Uint64 = (SIZE_2MB - SIZE_4KB); 432 MapAttribute.Bits.Present = 1; 433 MapAttribute.Bits.ReadWrite = 1; 434 434 // 435 435 // Create Page table to cover [2M-4K, 4M], with ReadWrite = 1 436 436 // 437 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB + SIZE_2MB, &MapAttribute, &MapMask );437 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB + SIZE_2MB, &MapAttribute, &MapMask, NULL); 438 438 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 439 439 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 440 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB + SIZE_2MB, &MapAttribute, &MapMask );440 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB + SIZE_2MB, &MapAttribute, &MapMask, NULL); 441 441 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 442 442 IsPageTableValid (PageTable, PagingMode); … … 461 461 // [2M ,4M], R/W = 1 462 462 // 463 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable; 464 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN) (PagingEntry->Pnle.Bits.PageTableBaseAddress << 12); // Get 3 level entry465 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN) (PagingEntry->Pnle.Bits.PageTableBaseAddress << 12); // Get 2 level entry463 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable; // Get 4 level entry 464 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (PagingEntry); // Get 3 level entry 465 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (PagingEntry); // Get 2 level entry 466 466 PagingEntry->Uint64 = PagingEntry->Uint64 & (~(UINT64)0x2); 467 467 MapCount = 0; … … 481 481 UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_2MB); 482 482 UT_ASSERT_EQUAL (Map[1].Length, SIZE_2MB); 483 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64; 484 ExpectedMapAttribute.Bits.ReadWrite = 1; 485 ExpectedMapAttribute.Bits.PageTableBaseAddress = SIZE_2MB >> 12; 483 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64 + SIZE_4KB; 484 ExpectedMapAttribute.Bits.ReadWrite = 1; 486 485 UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64); 487 486 … … 490 489 // Just need to set [2M-4K,2M], won't need extra size, so the status should be success 491 490 // 492 MapAttribute. Bits.Present = 1;493 MapAttribute.Bits. ReadWrite= 1;494 PageTableBufferSize = 0;495 MapAttribute.Bits.PageTableBaseAddress = (SIZE_2MB - SIZE_4KB) >> 12;496 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB * 2, &MapAttribute, &MapMask);491 MapAttribute.Uint64 = SIZE_2MB - SIZE_4KB; 492 MapAttribute.Bits.Present = 1; 493 MapAttribute.Bits.ReadWrite = 1; 494 PageTableBufferSize = 0; 495 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB * 2, &MapAttribute, &MapMask, NULL); 497 496 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 498 497 return UNIT_TEST_PASSED; … … 541 540 // Create Page table to cover [0,4M], and [4M, 1G] is not present 542 541 // 543 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB * 2, &MapAttribute, &MapMask );542 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB * 2, &MapAttribute, &MapMask, NULL); 544 543 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 545 544 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 546 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB * 2, &MapAttribute, &MapMask );545 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB * 2, &MapAttribute, &MapMask, NULL); 547 546 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 548 547 TestStatus = IsPageTableValid (PageTable, PagingMode); … … 556 555 // 557 556 PageTableBufferSize = 0; 558 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask );557 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL); 559 558 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 560 559 TestStatus = IsPageTableValid (PageTable, PagingMode); … … 565 564 MapAttribute.Bits.Accessed = 1; 566 565 PageTableBufferSize = 0; 567 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB, &MapAttribute, &MapMask );566 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB, &MapAttribute, &MapMask, NULL); 568 567 // 569 568 // If it didn't use a big 1G entry to cover whole range, only change [0,2M] for some attribute won't need extra memory … … 620 619 // Create Page table to cover [0,2G], with Nx = 0 621 620 // 622 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB * 2, &MapAttribute, &MapMask );621 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB * 2, &MapAttribute, &MapMask, NULL); 623 622 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 624 623 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 625 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB * 2, &MapAttribute, &MapMask );624 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB * 2, &MapAttribute, &MapMask, NULL); 626 625 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 627 626 TestStatus = IsPageTableValid (PageTable, PagingMode); … … 667 666 // Call library to change Nx to 0 for [0,1G] 668 667 // 669 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask );668 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL); 670 669 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 671 670 TestStatus = IsPageTableValid (PageTable, PagingMode); … … 699 698 700 699 /** 700 Check if the input Mask and Attribute is as expected when creating new page table or 701 updating existing page table. 702 703 @param[in] Context [Optional] An optional parameter that enables: 704 1) test-case reuse with varied parameters and 705 2) test-case re-entry for Target tests that need a 706 reboot. This parameter is a VOID* and it is the 707 responsibility of the test author to ensure that the 708 contents are well understood by all test cases that may 709 consume it. 710 711 @retval UNIT_TEST_PASSED The Unit test has completed and the test 712 case was successful. 713 @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. 714 **/ 715 UNIT_TEST_STATUS 716 EFIAPI 717 TestCaseToCheckMapMaskAndAttr ( 718 IN UNIT_TEST_CONTEXT Context 719 ) 720 { 721 UINTN PageTable; 722 PAGING_MODE PagingMode; 723 VOID *Buffer; 724 UINTN PageTableBufferSize; 725 IA32_MAP_ATTRIBUTE MapAttribute; 726 IA32_MAP_ATTRIBUTE ExpectedMapAttribute; 727 IA32_MAP_ATTRIBUTE MapMask; 728 RETURN_STATUS Status; 729 IA32_MAP_ENTRY *Map; 730 UINTN MapCount; 731 732 PagingMode = Paging4Level; 733 PageTableBufferSize = 0; 734 PageTable = 0; 735 Buffer = NULL; 736 MapAttribute.Uint64 = 0; 737 MapAttribute.Bits.Present = 1; 738 MapMask.Uint64 = 0; 739 MapMask.Bits.Present = 1; 740 // 741 // Create Page table to cover [0, 2G]. All fields of MapMask should be set. 742 // 743 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL); 744 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 745 MapMask.Uint64 = MAX_UINT64; 746 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL); 747 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 748 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 749 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL); 750 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 751 752 // 753 // Update Page table to set [2G - 8K, 2G] from present to non-present. All fields of MapMask except present should not be set. 754 // 755 PageTableBufferSize = 0; 756 MapAttribute.Uint64 = 0; 757 MapMask.Uint64 = 0; 758 MapMask.Bits.Present = 1; 759 MapMask.Bits.ReadWrite = 1; 760 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 761 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 762 MapMask.Bits.ReadWrite = 0; 763 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 764 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 765 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 766 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 767 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 768 769 // 770 // Still set [2G - 8K, 2G] as not present, this case is permitted. But set [2G - 8K, 2G] as RW is not permitted. 771 // 772 PageTableBufferSize = 0; 773 MapAttribute.Uint64 = 0; 774 MapMask.Uint64 = 0; 775 MapMask.Bits.Present = 1; 776 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 777 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 778 MapAttribute.Bits.ReadWrite = 1; 779 MapMask.Bits.ReadWrite = 1; 780 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 781 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 782 783 // 784 // Update Page table to set [2G - 8K, 2G] as present and RW. All fields of MapMask should be set. 785 // 786 PageTableBufferSize = 0; 787 MapAttribute.Uint64 = SIZE_2GB - SIZE_8KB; 788 MapAttribute.Bits.ReadWrite = 1; 789 MapAttribute.Bits.Present = 1; 790 MapMask.Uint64 = 0; 791 MapMask.Bits.ReadWrite = 1; 792 MapMask.Bits.Present = 1; 793 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 794 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 795 MapMask.Uint64 = MAX_UINT64; 796 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL); 797 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 798 799 MapCount = 0; 800 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount); 801 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 802 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount* sizeof (IA32_MAP_ENTRY))); 803 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount); 804 UT_ASSERT_EQUAL (Status, RETURN_SUCCESS); 805 806 // 807 // There should be two ranges [0, 2G-8k] with RW = 0 and [2G-8k, 2G] with RW = 1 808 // 809 UT_ASSERT_EQUAL (MapCount, 2); 810 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0); 811 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB - SIZE_8KB); 812 ExpectedMapAttribute.Uint64 = 0; 813 ExpectedMapAttribute.Bits.Present = 1; 814 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64); 815 UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_2GB - SIZE_8KB); 816 UT_ASSERT_EQUAL (Map[1].Length, SIZE_8KB); 817 ExpectedMapAttribute.Uint64 = SIZE_2GB - SIZE_8KB; 818 ExpectedMapAttribute.Bits.Present = 1; 819 ExpectedMapAttribute.Bits.ReadWrite = 1; 820 UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64); 821 return UNIT_TEST_PASSED; 822 } 823 824 /** 701 825 Initialize the unit test framework, suite, and unit tests for the 702 826 sample unit tests and run the unit tests. … … 747 871 AddTestCase (ManualTestCase, "Check if the parent entry has different Nx attribute", "Manual Test Case6", TestCaseManualChangeNx, NULL, NULL, NULL); 748 872 AddTestCase (ManualTestCase, "Check if the needed size is expected", "Manual Test Case7", TestCaseManualSizeNotMatch, NULL, NULL, NULL); 749 873 AddTestCase (ManualTestCase, "Check MapMask when creating new page table or mapping not-present range", "Manual Test Case8", TestCaseToCheckMapMaskAndAttr, NULL, NULL, NULL); 750 874 // 751 875 // Populate the Random Test Cases. … … 758 882 } 759 883 760 AddTestCase (RandomTestCase, "Random Test for Paging4Level", "Random Test Case1", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging4Level); 761 AddTestCase (RandomTestCase, "Random Test for Paging4Level1G", "Random Test Case2", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging4Level1GB); 762 AddTestCase (RandomTestCase, "Random Test for Paging5Level", "Random Test Case3", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging5Level); 763 AddTestCase (RandomTestCase, "Random Test for Paging5Level1G", "Random Test Case4", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging5Level1GB); 884 // AddTestCase (RandomTestCase, "Random Test for Paging4Level", "Random Test Case1", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging4Level); 885 // AddTestCase (RandomTestCase, "Random Test for Paging4Level1G", "Random Test Case2", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging4Level1GB); 886 // AddTestCase (RandomTestCase, "Random Test for Paging5Level", "Random Test Case3", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging5Level); 887 // AddTestCase (RandomTestCase, "Random Test for Paging5Level1G", "Random Test Case4", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging5Level1GB); 888 // AddTestCase (RandomTestCase, "Random Test for PagingPae", "Random Test Case5", TestCaseforRandomTest, NULL, NULL, &mTestContextPagingPae); 764 889 765 890 // -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c
r99404 r101291 2 2 Random test case for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 83 83 84 84 /** 85 Return a random boolean.86 87 @return boolean88 **/89 BOOLEAN90 RandomBoolean (91 VOID92 )93 {94 BOOLEAN Value;95 96 LocalRandomBytes ((UINT8 *)&Value, sizeof (BOOLEAN));97 return Value%2;98 }99 100 /**101 85 Return a 32bit random number. 102 86 … … 138 122 139 123 return (UINT64)(Value % (Limit - Start + 1)) + Start; 124 } 125 126 /** 127 Returns true with the percentage of input Probability. 128 129 @param[in] Probability The percentage to return true. 130 131 @return boolean 132 **/ 133 BOOLEAN 134 RandomBoolean ( 135 UINT8 Probability 136 ) 137 { 138 return ((Probability > ((UINT8)Random64 (0, 100))) ? TRUE : FALSE); 140 139 } 141 140 … … 159 158 { 160 159 UINT64 Index; 161 UINT64 TempPhysicalBase; 160 UINT32 PageTableBaseAddressLow; 161 UINT32 PageTableBaseAddressHigh; 162 162 IA32_PAGING_ENTRY *ChildPageEntry; 163 163 UNIT_TEST_STATUS Status; … … 179 179 } 180 180 181 if ((RandomNumber < 100) && RandomBoolean ( )) {181 if ((RandomNumber < 100) && RandomBoolean (50)) { 182 182 RandomNumber++; 183 183 if (Level == 1) { 184 TempPhysicalBase = PagingEntry->Pte4K.Bits.PageTableBaseAddress; 184 PageTableBaseAddressLow = PagingEntry->Pte4K.Bits.PageTableBaseAddressLow; 185 PageTableBaseAddressHigh = PagingEntry->Pte4K.Bits.PageTableBaseAddressHigh; 185 186 } else { 186 TempPhysicalBase = PagingEntry->PleB.Bits.PageTableBaseAddress; 187 PageTableBaseAddressLow = PagingEntry->PleB.Bits.PageTableBaseAddressLow; 188 PageTableBaseAddressHigh = PagingEntry->PleB.Bits.PageTableBaseAddressHigh; 187 189 } 188 190 … … 190 192 PagingEntry->Pte4K.Bits.Present = 1; 191 193 if (Level == 1) { 192 PagingEntry->Pte4K.Bits.PageTableBaseAddress = TempPhysicalBase; 194 PagingEntry->Pte4K.Bits.PageTableBaseAddressLow = PageTableBaseAddressLow; 195 PagingEntry->Pte4K.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh; 193 196 } else { 194 PagingEntry->PleB.Bits.PageTableBaseAddress = TempPhysicalBase; 197 PagingEntry->PleB.Bits.PageTableBaseAddressLow = PageTableBaseAddressLow; 198 PagingEntry->PleB.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh; 195 199 } 196 200 … … 212 216 } 213 217 214 if ((RandomNumber < 100) && RandomBoolean ( )) {218 if ((RandomNumber < 100) && RandomBoolean (50)) { 215 219 RandomNumber++; 216 TempPhysicalBase = PagingEntry->Pnle.Bits.PageTableBaseAddress; 217 218 PagingEntry->Uint64 = Random64 (0, MAX_UINT64) & mValidMaskNoLeaf[Level].Uint64; 219 PagingEntry->Pnle.Bits.Present = 1; 220 PagingEntry->Pnle.Bits.PageTableBaseAddress = TempPhysicalBase; 220 PageTableBaseAddressLow = PagingEntry->PleB.Bits.PageTableBaseAddressLow; 221 PageTableBaseAddressHigh = PagingEntry->PleB.Bits.PageTableBaseAddressHigh; 222 223 PagingEntry->Uint64 = Random64 (0, MAX_UINT64) & mValidMaskNoLeaf[Level].Uint64; 224 PagingEntry->Pnle.Bits.Present = 1; 225 PagingEntry->PleB.Bits.PageTableBaseAddressLow = PageTableBaseAddressLow; 226 PagingEntry->PleB.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh; 221 227 ASSERT ((PagingEntry->Uint64 & mValidMaskLeafFlag[Level].Uint64) != mValidMaskLeafFlag[Level].Uint64); 222 228 } 223 229 224 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)( (PagingEntry->Pnle.Bits.PageTableBaseAddress) << 12);230 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)(IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry->Pnle)); 225 231 for (Index = 0; Index < 512; Index++) { 226 232 Status = ValidateAndRandomeModifyPageTablePageTableEntry (&ChildPageEntry[Index], Level-1, MaxLeafLevel, Address + (Index<<(9*(Level-1) + 3))); … … 253 259 IA32_PAGING_ENTRY *PagingEntry; 254 260 255 if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode>= PagingModeMax)) {261 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) { 256 262 // 257 263 // 32bit paging is never supported. 258 // PAE paging will be supported later.259 264 // 260 265 return UNIT_TEST_ERROR_TEST_FAILED; … … 276 281 277 282 /** 283 Remove the last MAP_ENTRY in MapEntrys. 284 285 @param MapEntrys Pointer to MapEntrys buffer 286 **/ 287 VOID 288 RemoveLastMapEntry ( 289 IN OUT MAP_ENTRYS *MapEntrys 290 ) 291 { 292 UINTN MapsIndex; 293 294 if (MapEntrys->Count == 0) { 295 return; 296 } 297 298 MapsIndex = MapEntrys->Count - 1; 299 ZeroMem (&(MapEntrys->Maps[MapsIndex]), sizeof (MAP_ENTRY)); 300 MapEntrys->Count = MapsIndex; 301 } 302 303 /** 278 304 Generate single random map entry. 279 305 The map entry can be the input of function PageTableMap … … 300 326 // use AlignedTable to avoid that a random number can be very hard to be 1G or 2M aligned 301 327 // 302 if ((MapsIndex != 0) && (RandomBoolean ( ))) {328 if ((MapsIndex != 0) && (RandomBoolean (50))) { 303 329 FormerLinearAddress = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].LinearAddress; 304 330 if (FormerLinearAddress < 2 * (UINT64)SIZE_1GB) { … … 324 350 MapEntrys->Maps[MapsIndex].Length = Random64 (0, MIN (MaxAddress - MapEntrys->Maps[MapsIndex].LinearAddress, 10 * (UINT64)SIZE_1GB)) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)]; 325 351 326 if ((MapsIndex != 0) && (RandomBoolean ( ))) {352 if ((MapsIndex != 0) && (RandomBoolean (50))) { 327 353 MapEntrys->Maps[MapsIndex].Attribute.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Attribute.Uint64; 328 354 MapEntrys->Maps[MapsIndex].Mask.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64; 329 355 } else { 330 356 MapEntrys->Maps[MapsIndex].Attribute.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64; 331 MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64; 357 if (RandomBoolean (5)) { 358 // 359 // The probability to get random Mask should be small since all bits of a random number 360 // have a high probability of containing 0, which may be a invalid input. 361 // 362 MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64; 363 } else { 364 MapEntrys->Maps[MapsIndex].Mask.Uint64 = MAX_UINT64; 365 } 366 332 367 if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) { 333 368 MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF; … … 336 371 337 372 if (mRandomOption & ONLY_ONE_ONE_MAPPING) { 338 MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = MapEntrys->Maps[MapsIndex].LinearAddress >> 12; 339 MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0xFFFFFFFFFF; 373 MapEntrys->Maps[MapsIndex].Attribute.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK); 374 MapEntrys->Maps[MapsIndex].Attribute.Uint64 |= MapEntrys->Maps[MapsIndex].LinearAddress; 375 MapEntrys->Maps[MapsIndex].Mask.Uint64 |= IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK; 340 376 } else { 341 // 342 // Todo: If the mask bit for base address is zero, when dump the pagetable, every entry mapping to physical address zeor. 343 // This means the map count will be a large number, and impossible to finish in proper time. 344 // Need to avoid such case when remove the Random option ONLY_ONE_ONE_MAPPING 345 // 346 MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)])>> 12; 347 if (RandomBoolean ()) { 348 MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0; 349 } 377 MapEntrys->Maps[MapsIndex].Attribute.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK); 378 MapEntrys->Maps[MapsIndex].Attribute.Uint64 |= (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)]); 350 379 } 351 380 … … 394 423 for (Index = 0; Index < MapCount; Index++) { 395 424 if ((Address >= Map[Index].LinearAddress) && (Address < (Map[Index].LinearAddress + Map[Index].Length))) { 396 AttributeInMap.Uint64 = (Map[Index].Attribute.Uint64 & mSupportedBit.Uint64); 397 AttributeInMap.Bits.PageTableBaseAddress = ((Address - Map[Index].LinearAddress) >> 12) + Map[Index].Attribute.Bits.PageTableBaseAddress; 425 AttributeInMap.Uint64 = (Map[Index].Attribute.Uint64 & mSupportedBit.Uint64); 426 AttributeInMap.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK); 427 AttributeInMap.Uint64 |= (Address - Map[Index].LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&Map[Index].Attribute)) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK; 398 428 break; 399 429 } … … 405 435 for (Index = 0; Index < InitMapCount; Index++) { 406 436 if ((Address >= InitMap[Index].LinearAddress) && (Address < (InitMap[Index].LinearAddress + InitMap[Index].Length))) { 407 AttributeInInitMap.Uint64 = (InitMap[Index].Attribute.Uint64 & mSupportedBit.Uint64); 408 AttributeInInitMap.Bits.PageTableBaseAddress = ((Address - InitMap[Index].LinearAddress) >> 12) + InitMap[Index].Attribute.Bits.PageTableBaseAddress; 437 AttributeInInitMap.Uint64 = (InitMap[Index].Attribute.Uint64 & mSupportedBit.Uint64); 438 AttributeInInitMap.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK); 439 AttributeInInitMap.Uint64 |= (Address - InitMap[Index].LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&InitMap[Index].Attribute)) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK; 440 409 441 break; 410 442 } … … 423 455 AttributeInMapEntrys.Uint64 &= (~MapEntrys->Maps[Index].Mask.Uint64); 424 456 AttributeInMapEntrys.Uint64 |= (MapEntrys->Maps[Index].Attribute.Uint64 & MapEntrys->Maps[Index].Mask.Uint64); 425 if (MapEntrys->Maps[Index].Mask.Bits.PageTableBaseAddress != 0) { 426 AttributeInMapEntrys.Bits.PageTableBaseAddress = ((Address - MapEntrys->Maps[Index].LinearAddress) >> 12) + MapEntrys->Maps[Index].Attribute.Bits.PageTableBaseAddress; 457 if (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&MapEntrys->Maps[Index].Mask) != 0) { 458 AttributeInMapEntrys.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK); 459 AttributeInMapEntrys.Uint64 |= (Address - MapEntrys->Maps[Index].LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&MapEntrys->Maps[Index].Attribute)) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK; 427 460 } 428 461 } … … 438 471 DEBUG ((DEBUG_INFO, "======detailed information begin=====\n")); 439 472 DEBUG ((DEBUG_INFO, "\nError: Detect different attribute on a point with linear address: 0x%lx\n", Address)); 440 DEBUG ((DEBUG_INFO, "By parsing page table, the point has Attribute 0x%lx, and map to physical address 0x%lx\n", IA32_MAP_ATTRIBUTE_ATTRIBUTES (&AttributeInMap) & MaskInMapEntrys.Uint64, AttributeInMap.Bits.PageTableBaseAddress));441 DEBUG ((DEBUG_INFO, "While according to inputs, the point should Attribute 0x%lx, and should map to physical address 0x%lx\n", IA32_MAP_ATTRIBUTE_ATTRIBUTES (&AttributeInMapEntrys) & MaskInMapEntrys.Uint64, AttributeInMapEntrys.Bits.PageTableBaseAddress));473 DEBUG ((DEBUG_INFO, "By parsing page table, the point has Attribute 0x%lx, and map to physical address 0x%lx\n", IA32_MAP_ATTRIBUTE_ATTRIBUTES (&AttributeInMap) & MaskInMapEntrys.Uint64, IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&AttributeInMap))); 474 DEBUG ((DEBUG_INFO, "While according to inputs, the point should Attribute 0x%lx, and should map to physical address 0x%lx\n", IA32_MAP_ATTRIBUTE_ATTRIBUTES (&AttributeInMapEntrys) & MaskInMapEntrys.Uint64, IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&AttributeInMapEntrys))); 442 475 DEBUG ((DEBUG_INFO, "The total Mask is 0x%lx\n", MaskInMapEntrys.Uint64)); 443 476 … … 610 643 ) 611 644 { 612 UINTN MapsIndex; 613 RETURN_STATUS Status; 614 UINTN PageTableBufferSize; 615 VOID *Buffer; 616 IA32_MAP_ENTRY *Map; 617 UINTN MapCount; 618 UINTN Index; 619 UINTN KeyPointCount; 620 UINTN NewKeyPointCount; 621 UINT64 *KeyPointBuffer; 622 UINTN Level; 623 UINT64 Value; 624 UNIT_TEST_STATUS TestStatus; 625 626 MapsIndex = MapEntrys->Count; 645 UINTN MapsIndex; 646 RETURN_STATUS Status; 647 UINTN PageTableBufferSize; 648 VOID *Buffer; 649 IA32_MAP_ENTRY *Map; 650 UINTN MapCount; 651 IA32_MAP_ENTRY *Map2; 652 UINTN MapCount2; 653 UINTN Index; 654 UINTN KeyPointCount; 655 UINTN NewKeyPointCount; 656 UINT64 *KeyPointBuffer; 657 UINTN Level; 658 UINT64 Value; 659 UNIT_TEST_STATUS TestStatus; 660 MAP_ENTRY *LastMapEntry; 661 IA32_MAP_ATTRIBUTE *Mask; 662 IA32_MAP_ATTRIBUTE *Attribute; 663 UINT64 LastNotPresentRegionStart; 664 BOOLEAN IsNotPresent; 665 BOOLEAN IsModified; 666 667 MapsIndex = MapEntrys->Count; 668 MapCount = 0; 669 LastNotPresentRegionStart = 0; 670 IsNotPresent = FALSE; 671 IsModified = FALSE; 627 672 628 673 GenerateSingleRandomMapEntry (MaxAddress, MapEntrys); 674 LastMapEntry = &MapEntrys->Maps[MapsIndex]; 675 Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount); 676 677 if (MapCount != 0) { 678 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 679 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY))); 680 ASSERT (Map != NULL); 681 Status = PageTableParse (*PageTable, PagingMode, Map, &MapCount); 682 } 683 684 // 685 // Check if the generated MapEntrys->Maps[MapsIndex] contains not-present range. 686 // 687 if (LastMapEntry->Length > 0) { 688 for (Index = 0; Index < MapCount; Index++) { 689 if ((LastNotPresentRegionStart < Map[Index].LinearAddress) && 690 (LastMapEntry->LinearAddress < Map[Index].LinearAddress) && (LastMapEntry->LinearAddress + LastMapEntry->Length > LastNotPresentRegionStart)) 691 { 692 // 693 // MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table. 694 // 695 break; 696 } 697 698 LastNotPresentRegionStart = Map[Index].LinearAddress + Map[Index].Length; 699 } 700 701 // 702 // Either LastMapEntry overlaps with the not-present region in the very end 703 // Or it overlaps with one in the middle 704 if (LastNotPresentRegionStart < LastMapEntry->LinearAddress + LastMapEntry->Length) { 705 IsNotPresent = TRUE; 706 } 707 } 629 708 630 709 PageTableBufferSize = 0; … … 634 713 NULL, 635 714 &PageTableBufferSize, 636 MapEntrys->Maps[MapsIndex].LinearAddress, 637 MapEntrys->Maps[MapsIndex].Length, 638 &MapEntrys->Maps[MapsIndex].Attribute, 639 &MapEntrys->Maps[MapsIndex].Mask 715 LastMapEntry->LinearAddress, 716 LastMapEntry->Length, 717 &LastMapEntry->Attribute, 718 &LastMapEntry->Mask, 719 &IsModified 640 720 ); 721 722 Attribute = &LastMapEntry->Attribute; 723 Mask = &LastMapEntry->Mask; 724 // 725 // If set [LinearAddress, LinearAddress+Attribute] to not preset, all 726 // other attributes should not be provided. 727 // 728 if ((LastMapEntry->Length > 0) && (Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) { 729 RemoveLastMapEntry (MapEntrys); 730 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 731 return UNIT_TEST_PASSED; 732 } 733 734 // 735 // Return Status for non-present range also should be InvalidParameter when: 736 // 1. Some of attributes are not provided when mapping non-present range to present. 737 // 2. Set any other attribute without setting the non-present range to Present. 738 // 739 if (IsNotPresent) { 740 if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) { 741 // 742 // Creating new page table or remapping non-present range to present. 743 // 744 if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) || 745 (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) || 746 ((Mask->Bits.PageTableBaseAddressLow == 0) && (Mask->Bits.PageTableBaseAddressHigh == 0)) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0)) 747 { 748 RemoveLastMapEntry (MapEntrys); 749 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 750 return UNIT_TEST_PASSED; 751 } 752 } else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) { 753 // 754 // Only change other attributes for non-present range is not permitted. 755 // 756 RemoveLastMapEntry (MapEntrys); 757 UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); 758 return UNIT_TEST_PASSED; 759 } 760 } 761 641 762 if (PageTableBufferSize != 0) { 642 763 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); … … 653 774 Buffer, 654 775 &PageTableBufferSize, 655 MapEntrys->Maps[MapsIndex].LinearAddress, 656 MapEntrys->Maps[MapsIndex].Length, 657 &MapEntrys->Maps[MapsIndex].Attribute, 658 &MapEntrys->Maps[MapsIndex].Mask 776 LastMapEntry->LinearAddress, 777 LastMapEntry->Length, 778 &LastMapEntry->Attribute, 779 &LastMapEntry->Mask, 780 &IsModified 659 781 ); 660 782 } … … 670 792 } 671 793 672 MapCount = 0;673 Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount);674 if (MapCount != 0) {794 MapCount2 = 0; 795 Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount2); 796 if (MapCount2 != 0) { 675 797 UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); 676 798 677 799 // 678 // Allocate memory for Map s800 // Allocate memory for Map2 679 801 // Note the memory is only used in this one Single MapEntry Test 680 802 // 681 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY))); 682 ASSERT (Map != NULL); 683 Status = PageTableParse (*PageTable, PagingMode, Map, &MapCount); 803 Map2 = AllocatePages (EFI_SIZE_TO_PAGES (MapCount2 * sizeof (IA32_MAP_ENTRY))); 804 ASSERT (Map2 != NULL); 805 Status = PageTableParse (*PageTable, PagingMode, Map2, &MapCount2); 806 } 807 808 // 809 // Check if PageTable has been modified. 810 // 811 if (MapCount2 != MapCount) { 812 UT_ASSERT_EQUAL (IsModified, TRUE); 813 } else { 814 if (CompareMem (Map, Map2, MapCount2 * sizeof (IA32_MAP_ENTRY)) != 0) { 815 UT_ASSERT_EQUAL (IsModified, TRUE); 816 } else { 817 UT_ASSERT_EQUAL (IsModified, FALSE); 818 } 684 819 } 685 820 … … 691 826 // 692 827 KeyPointCount = 0; 693 GetKeyPointList (MapEntrys, Map , MapCount, NULL, &KeyPointCount);828 GetKeyPointList (MapEntrys, Map2, MapCount2, NULL, &KeyPointCount); 694 829 KeyPointBuffer = AllocatePages (EFI_SIZE_TO_PAGES (KeyPointCount * sizeof (UINT64))); 695 830 ASSERT (KeyPointBuffer != NULL); 696 831 NewKeyPointCount = 0; 697 GetKeyPointList (MapEntrys, Map , MapCount, KeyPointBuffer, &NewKeyPointCount);832 GetKeyPointList (MapEntrys, Map2, MapCount2, KeyPointBuffer, &NewKeyPointCount); 698 833 699 834 // … … 701 836 // 702 837 for (Index = 0; Index < NewKeyPointCount; Index++) { 703 if (!CompareEntrysforOnePoint (KeyPointBuffer[Index], MapEntrys, Map , MapCount, InitMap, InitMapCount)) {838 if (!CompareEntrysforOnePoint (KeyPointBuffer[Index], MapEntrys, Map2, MapCount2, InitMap, InitMapCount)) { 704 839 DEBUG ((DEBUG_INFO, "Error happens at below key point\n")); 705 840 DEBUG ((DEBUG_INFO, "Index = %d KeyPointBuffer[Index] = 0x%lx\n", Index, KeyPointBuffer[Index])); … … 713 848 if (MapCount != 0) { 714 849 FreePages (Map, EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY))); 850 } 851 852 if (MapCount2 != 0) { 853 FreePages (Map2, EFI_SIZE_TO_PAGES (MapCount2 * sizeof (IA32_MAP_ENTRY))); 715 854 } 716 855 … … 890 1029 UT_ASSERT_TRUE ((Random32 (9, 10) >= 9) & (Random32 (9, 10) <= 10)); 891 1030 UT_ASSERT_TRUE ((Random64 (9, 10) >= 9) & (Random64 (9, 10) <= 10)); 892 893 mSupportedBit.Bits.Present = 1; 894 mSupportedBit.Bits.ReadWrite = 1; 895 mSupportedBit.Bits.UserSupervisor = 1; 896 mSupportedBit.Bits.WriteThrough = 1; 897 mSupportedBit.Bits.CacheDisabled = 1; 898 mSupportedBit.Bits.Accessed = 1; 899 mSupportedBit.Bits.Dirty = 1; 900 mSupportedBit.Bits.Pat = 1; 901 mSupportedBit.Bits.Global = 1; 902 mSupportedBit.Bits.Reserved1 = 0; 903 mSupportedBit.Bits.PageTableBaseAddress = 0; 904 mSupportedBit.Bits.Reserved2 = 0; 905 mSupportedBit.Bits.ProtectionKey = 0xF; 906 mSupportedBit.Bits.Nx = 1; 1031 mSupportedBit.Uint64 = 0; 1032 mSupportedBit.Bits.Present = 1; 1033 mSupportedBit.Bits.ReadWrite = 1; 1034 mSupportedBit.Bits.UserSupervisor = 1; 1035 mSupportedBit.Bits.WriteThrough = 1; 1036 mSupportedBit.Bits.CacheDisabled = 1; 1037 mSupportedBit.Bits.Accessed = 1; 1038 mSupportedBit.Bits.Dirty = 1; 1039 mSupportedBit.Bits.Pat = 1; 1040 mSupportedBit.Bits.Global = 1; 1041 mSupportedBit.Bits.ProtectionKey = 0xF; 1042 mSupportedBit.Bits.Nx = 1; 907 1043 908 1044 mRandomOption = ((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->RandomOption; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c
r99404 r101291 2 2 helper file for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class 3 3 4 Copyright (c) 2022 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 141 141 } 142 142 143 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)( ((UINTN)(PagingEntry->Pnle.Bits.PageTableBaseAddress)) << 12);143 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)(IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry->Pnle)); 144 144 for (Index = 0; Index < 512; Index++) { 145 145 Status = IsPageTableEntryValid (&ChildPageEntry[Index], Level-1, MaxLeafLevel, Address + (Index<<(9*(Level-1) + 3))); … … 172 172 IA32_PAGING_ENTRY *PagingEntry; 173 173 174 if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) { 174 if (PageTable == 0) { 175 return UNIT_TEST_PASSED; 176 } 177 178 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) { 175 179 // 176 180 // 32bit paging is never supported. 177 // PAE paging will be supported later.178 181 // 179 182 return UNIT_TEST_ERROR_TEST_FAILED; … … 184 187 185 188 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable; 186 for (Index = 0; Index < 512; Index++) { 189 for (Index = 0; Index < ((PagingMode == PagingPae) ? 4 : 512); Index++) { 190 if (PagingMode == PagingPae) { 191 UT_ASSERT_EQUAL (PagingEntry[Index].PdptePae.Bits.MustBeZero, 0); 192 UT_ASSERT_EQUAL (PagingEntry[Index].PdptePae.Bits.MustBeZero2, 0); 193 } 194 187 195 Status = IsPageTableEntryValid (&PagingEntry[Index], MaxLevel, MaxLeafLevel, Index << (9 * MaxLevel + 3)); 188 196 if (Status != UNIT_TEST_PASSED) { … … 230 238 // Not a leaf 231 239 // 232 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)( ((UINTN)(PagingEntry->Pnle.Bits.PageTableBaseAddress)) << 12);240 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)(IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry->Pnle)); 233 241 *Level = *Level -1; 234 242 Index = Address >> (*Level * 9 + 3); … … 261 269 IA32_PAGING_ENTRY *PagingEntry; 262 270 263 if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode>= PagingModeMax)) {271 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) { 264 272 // 265 273 // 32bit paging is never supported. -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/AmdSev.c
r99404 r101291 261 261 } 262 262 } 263 264 /** 265 Get pointer to CPU MP Data structure from GUIDed HOB. 266 267 @param[in] CpuMpData The pointer to CPU MP Data structure. 268 **/ 269 VOID 270 AmdSevUpdateCpuMpData ( 271 IN CPU_MP_DATA *CpuMpData 272 ) 273 { 274 CPU_MP_DATA *OldCpuMpData; 275 276 OldCpuMpData = GetCpuMpDataFromGuidedHob (); 277 278 OldCpuMpData->NewCpuMpData = CpuMpData; 279 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
r99404 r101291 2 2 # MP Initialize Library instance for DXE driver. 3 3 # 4 # Copyright (c) 2016 - 202 1, Intel Corporation. All rights reserved.<BR>4 # Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 # SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 # … … 25 25 Ia32/AmdSev.c 26 26 Ia32/MpFuncs.nasm 27 Ia32/CreatePageTable.c 27 28 28 29 [Sources.X64] 29 30 X64/AmdSev.c 30 31 X64/MpFuncs.nasm 32 X64/CreatePageTable.c 31 33 32 34 [Sources.common] … … 37 39 MpLib.h 38 40 Microcode.c 41 MpHandOff.h 39 42 40 43 [Packages] … … 50 53 MtrrLib 51 54 CpuLib 52 UefiCpuLib53 55 UefiBootServicesTableLib 54 56 DebugAgentLib … … 57 59 CcExitLib 58 60 MicrocodeLib 61 [LibraryClasses.X64] 62 CpuPageTableLib 59 63 60 64 [Protocols] … … 78 82 gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures ## CONSUMES 79 83 gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES 84 gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi ## CONSUMES 80 85 gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES 81 86 gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
r99404 r101291 2 2 MP initialize support functions for DXE phase. 3 3 4 Copyright (c) 2016 - 202 0, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 21 21 #define AP_SAFE_STACK_SIZE 128 22 22 23 CPU_MP_DATA *mCpuMpData = NULL; 24 EFI_EVENT mCheckAllApsEvent = NULL; 25 EFI_EVENT mMpInitExitBootServicesEvent = NULL; 26 EFI_EVENT mLegacyBootEvent = NULL; 27 volatile BOOLEAN mStopCheckAllApsStatus = TRUE; 28 VOID *mReservedApLoopFunc = NULL; 29 UINTN mReservedTopOfApStack; 30 volatile UINT32 mNumberToFinish = 0; 23 CPU_MP_DATA *mCpuMpData = NULL; 24 EFI_EVENT mCheckAllApsEvent = NULL; 25 EFI_EVENT mMpInitExitBootServicesEvent = NULL; 26 EFI_EVENT mLegacyBootEvent = NULL; 27 volatile BOOLEAN mStopCheckAllApsStatus = TRUE; 28 RELOCATE_AP_LOOP_ENTRY mReservedApLoop; 29 UINTN mReservedTopOfApStack; 30 volatile UINT32 mNumberToFinish = 0; 31 UINTN mApPageTable; 31 32 32 33 // … … 379 380 ) 380 381 { 381 CPU_MP_DATA *CpuMpData; 382 BOOLEAN MwaitSupport; 383 ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; 384 UINTN ProcessorNumber; 385 UINTN StackStart; 382 CPU_MP_DATA *CpuMpData; 383 BOOLEAN MwaitSupport; 384 UINTN ProcessorNumber; 385 UINTN StackStart; 386 386 387 387 MpInitLibWhoAmI (&ProcessorNumber); … … 389 389 MwaitSupport = IsMwaitSupport (); 390 390 if (CpuMpData->UseSevEsAPMethod) { 391 // 392 // 64-bit AMD processors with SEV-ES 393 // 391 394 StackStart = CpuMpData->SevEsAPResetStackStart; 395 mReservedApLoop.AmdSevEntry ( 396 MwaitSupport, 397 CpuMpData->ApTargetCState, 398 CpuMpData->PmCodeSegment, 399 StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, 400 (UINTN)&mNumberToFinish, 401 CpuMpData->Pm16CodeSegment, 402 CpuMpData->SevEsAPBuffer, 403 CpuMpData->WakeupBuffer 404 ); 392 405 } else { 406 // 407 // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES 408 // 393 409 StackStart = mReservedTopOfApStack; 394 } 395 396 AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP)(UINTN)mReservedApLoopFunc; 397 AsmRelocateApLoopFunc ( 398 MwaitSupport, 399 CpuMpData->ApTargetCState, 400 CpuMpData->PmCodeSegment, 401 StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, 402 (UINTN)&mNumberToFinish, 403 CpuMpData->Pm16CodeSegment, 404 CpuMpData->SevEsAPBuffer, 405 CpuMpData->WakeupBuffer 406 ); 410 mReservedApLoop.GenericEntry ( 411 MwaitSupport, 412 CpuMpData->ApTargetCState, 413 StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, 414 (UINTN)&mNumberToFinish, 415 mApPageTable 416 ); 417 } 418 407 419 // 408 420 // It should never reach here … … 452 464 } 453 465 454 DEBUG ((DEBUG_INFO, "%a() done!\n", __ FUNCTION__));466 DEBUG ((DEBUG_INFO, "%a() done!\n", __func__)); 455 467 } 456 468 … … 467 479 EFI_STATUS Status; 468 480 EFI_PHYSICAL_ADDRESS Address; 469 UINTN ApSafeBufferSize;470 481 UINTN Index; 471 482 EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; 472 483 UINTN StackBase; 473 484 CPU_INFO_IN_HOB *CpuInfoInHob; 485 MP_ASSEMBLY_ADDRESS_MAP *AddressMap; 486 UINT8 *ApLoopFunc; 487 UINTN ApLoopFuncSize; 488 UINTN StackPages; 489 UINTN FuncPages; 474 490 475 491 SaveCpuMpData (CpuMpData); … … 526 542 } 527 543 544 AddressMap = &CpuMpData->AddressMap; 545 if (CpuMpData->UseSevEsAPMethod) { 546 // 547 // 64-bit AMD processors with SEV-ES 548 // 549 Address = BASE_4GB - 1; 550 ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev; 551 ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev; 552 } else { 553 // 554 // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES 555 // 556 Address = MAX_ADDRESS; 557 ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric; 558 ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric; 559 } 560 528 561 // 529 562 // Avoid APs access invalid buffer data which allocated by BootServices, … … 534 567 // Exit Boot Services callback function. 535 568 // 536 ApSafeBufferSize = EFI_PAGES_TO_SIZE ( 537 EFI_SIZE_TO_PAGES ( 538 CpuMpData->AddressMap.RelocateApLoopFuncSize 539 ) 540 ); 541 Address = BASE_4GB - 1; 542 Status = gBS->AllocatePages ( 543 AllocateMaxAddress, 544 EfiReservedMemoryType, 545 EFI_SIZE_TO_PAGES (ApSafeBufferSize), 546 &Address 547 ); 569 // +------------+ (TopOfApStack) 570 // | Stack * N | 571 // +------------+ (stack base, 4k aligned) 572 // | Padding | 573 // +------------+ 574 // | Ap Loop | 575 // +------------+ ((low address, 4k-aligned) 576 // 577 578 StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE); 579 FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize); 580 581 Status = gBS->AllocatePages ( 582 AllocateMaxAddress, 583 EfiReservedMemoryType, 584 StackPages + FuncPages, 585 &Address 586 ); 548 587 ASSERT_EFI_ERROR (Status); 549 550 mReservedApLoopFunc = (VOID *)(UINTN)Address;551 ASSERT (mReservedApLoopFunc != NULL);552 588 553 589 // … … 562 598 gDS->SetMemorySpaceAttributes ( 563 599 Address, 564 ApSafeBufferSize,600 EFI_PAGES_TO_SIZE (FuncPages), 565 601 MemDesc.Attributes & (~EFI_MEMORY_XP) 566 602 ); 567 603 } 568 604 569 ApSafeBufferSize = EFI_PAGES_TO_SIZE ( 570 EFI_SIZE_TO_PAGES ( 571 CpuMpData->CpuCount * AP_SAFE_STACK_SIZE 572 ) 573 ); 574 Address = BASE_4GB - 1; 575 Status = gBS->AllocatePages ( 576 AllocateMaxAddress, 577 EfiReservedMemoryType, 578 EFI_SIZE_TO_PAGES (ApSafeBufferSize), 579 &Address 580 ); 581 ASSERT_EFI_ERROR (Status); 582 583 mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize; 605 mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages); 584 606 ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); 585 CopyMem ( 586 mReservedApLoopFunc, 587 CpuMpData->AddressMap.RelocateApLoopFuncAddress, 588 CpuMpData->AddressMap.RelocateApLoopFuncSize 589 ); 607 mReservedApLoop.Data = (VOID *)(UINTN)Address; 608 ASSERT (mReservedApLoop.Data != NULL); 609 CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize); 610 if (!CpuMpData->UseSevEsAPMethod) { 611 // 612 // processors without SEV-ES 613 // 614 mApPageTable = CreatePageTable ( 615 (UINTN)Address, 616 EFI_PAGES_TO_SIZE (StackPages+FuncPages) 617 ); 618 } 590 619 591 620 Status = gBS->CreateEvent ( -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
r99404 r101291 1 1 ;------------------------------------------------------------------------------ ; 2 ; Copyright (c) 2015 - 202 2, Intel Corporation. All rights reserved.<BR>2 ; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR> 3 3 ; SPDX-License-Identifier: BSD-2-Clause-Patent 4 4 ; … … 198 198 push ebx ; Push ApIndex 199 199 mov eax, esi 200 add eax, MP_CPU_EXCHANGE_INFO_ OFFSET201 push eax ; push address of exchange info data buffer200 add eax, MP_CPU_EXCHANGE_INFO_FIELD (CpuMpData) 201 push dword [eax] ; push address of CpuMpData 202 202 203 203 mov edi, esi … … 220 220 221 221 ;------------------------------------------------------------------------------------- 222 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);222 ; AsmRelocateApLoopGeneric (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); 223 223 ; 224 224 ; The last three parameters (Pm16CodeSegment, SevEsAPJumpTable and WakeupBuffer) are 225 225 ; specific to SEV-ES support and are not applicable on IA32. 226 226 ;------------------------------------------------------------------------------------- 227 AsmRelocateApLoop Start:227 AsmRelocateApLoopGenericStart: 228 228 mov eax, esp 229 mov esp, [eax + 1 6] ; TopOfApStack229 mov esp, [eax + 12] ; TopOfApStack 230 230 push dword [eax] ; push return address for stack trace 231 231 push ebp … … 233 233 mov ebx, [eax + 8] ; ApTargetCState 234 234 mov ecx, [eax + 4] ; MwaitSupport 235 mov eax, [eax + 20] ; CountTofinish235 mov eax, [eax + 16] ; CountTofinish 236 236 lock dec dword [eax] ; (*CountTofinish)-- 237 237 cmp cl, 1 ; Check mwait-monitor support 238 jnz HltLoop 239 MwaitLoop :238 jnz HltLoopGeneric 239 MwaitLoopGeneric: 240 240 cli 241 241 mov eax, esp … … 246 246 shl eax, 4 247 247 mwait 248 jmp MwaitLoop 249 HltLoop :248 jmp MwaitLoopGeneric 249 HltLoopGeneric: 250 250 cli 251 251 hlt 252 jmp HltLoop 253 AsmRelocateApLoop End:252 jmp HltLoopGeneric 253 AsmRelocateApLoopGenericEnd: 254 254 255 255 ;------------------------------------------------------------------------------------- … … 265 265 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], Flat32Start - RendezvousFunnelProcStart 266 266 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart 267 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress ], AsmRelocateApLoopStart268 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize ], AsmRelocateApLoopEnd - AsmRelocateApLoopStart267 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], AsmRelocateApLoopGenericStart 268 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart 269 269 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart 270 270 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/Microcode.c
r99404 r101291 171 171 DEBUG_INFO, 172 172 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n", 173 __ FUNCTION__,173 __func__, 174 174 CpuMpData->MicrocodePatchAddress, 175 175 CpuMpData->MicrocodePatchRegionSize … … 306 306 DEBUG_INFO, 307 307 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n", 308 __ FUNCTION__,308 __func__, 309 309 PatchCount, 310 310 TotalLoadSize … … 366 366 GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid); 367 367 if (GuidHob == NULL) { 368 DEBUG ((DEBUG_INFO, "%a: Microcode patch cache HOB is not found.\n", __ FUNCTION__));368 DEBUG ((DEBUG_INFO, "%a: Microcode patch cache HOB is not found.\n", __func__)); 369 369 return FALSE; 370 370 } … … 378 378 DEBUG_INFO, 379 379 "%a: MicrocodeBase = 0x%lx, MicrocodeSize = 0x%lx\n", 380 __ FUNCTION__,380 __func__, 381 381 *Address, 382 382 *RegionSize -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
r99404 r101291 1 1 ;------------------------------------------------------------------------------ ; 2 ; Copyright (c) 2015 - 202 2, Intel Corporation. All rights reserved.<BR>2 ; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR> 3 3 ; SPDX-License-Identifier: BSD-2-Clause-Patent 4 4 ; … … 22 22 ; 23 23 struc MP_ASSEMBLY_ADDRESS_MAP 24 .RendezvousFunnelAddress CTYPE_UINTN 1 25 .ModeEntryOffset CTYPE_UINTN 1 26 .RendezvousFunnelSize CTYPE_UINTN 1 27 .RelocateApLoopFuncAddress CTYPE_UINTN 1 28 .RelocateApLoopFuncSize CTYPE_UINTN 1 29 .ModeTransitionOffset CTYPE_UINTN 1 30 .SwitchToRealNoNxOffset CTYPE_UINTN 1 31 .SwitchToRealPM16ModeOffset CTYPE_UINTN 1 32 .SwitchToRealPM16ModeSize CTYPE_UINTN 1 24 .RendezvousFunnelAddress CTYPE_UINTN 1 25 .ModeEntryOffset CTYPE_UINTN 1 26 .RendezvousFunnelSize CTYPE_UINTN 1 27 .RelocateApLoopFuncAddressGeneric CTYPE_UINTN 1 28 .RelocateApLoopFuncSizeGeneric CTYPE_UINTN 1 29 .RelocateApLoopFuncAddressAmdSev CTYPE_UINTN 1 30 .RelocateApLoopFuncSizeAmdSev CTYPE_UINTN 1 31 .ModeTransitionOffset CTYPE_UINTN 1 32 .SwitchToRealNoNxOffset CTYPE_UINTN 1 33 .SwitchToRealPM16ModeOffset CTYPE_UINTN 1 34 .SwitchToRealPM16ModeSize CTYPE_UINTN 1 33 35 endstruc 34 36 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/MpLib.c
r99404 r101291 19 19 20 20 EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID; 21 EFI_GUID mMpHandOffGuid = MP_HANDOFF_GUID; 21 22 22 23 /** … … 669 670 670 671 /** 672 This function place APs in Halt loop. 673 674 @param[in] CpuMpData Pointer to CPU MP Data 675 **/ 676 VOID 677 PlaceAPInHltLoop ( 678 IN CPU_MP_DATA *CpuMpData 679 ) 680 { 681 while (TRUE) { 682 DisableInterrupts (); 683 if (CpuMpData->UseSevEsAPMethod) { 684 SevEsPlaceApHlt (CpuMpData); 685 } else { 686 CpuSleep (); 687 } 688 689 CpuPause (); 690 } 691 } 692 693 /** 694 This function place APs in Mwait or Run loop. 695 696 @param[in] ApLoopMode Ap Loop Mode 697 @param[in] ApStartupSignalBuffer Pointer to Ap Startup Signal Buffer 698 @param[in] ApTargetCState Ap Target CState 699 **/ 700 VOID 701 PlaceAPInMwaitLoopOrRunLoop ( 702 IN UINT8 ApLoopMode, 703 IN volatile UINT32 *ApStartupSignalBuffer, 704 IN UINT8 ApTargetCState 705 ) 706 { 707 while (TRUE) { 708 DisableInterrupts (); 709 if (ApLoopMode == ApInMwaitLoop) { 710 // 711 // Place AP in MWAIT-loop 712 // 713 AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0); 714 if ((*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) && (*ApStartupSignalBuffer != MP_HAND_OFF_SIGNAL)) { 715 // 716 // Check AP start-up signal again. 717 // If AP start-up signal is not set, place AP into 718 // the specified C-state 719 // 720 AsmMwait (ApTargetCState << 4, 0); 721 } 722 } else if (ApLoopMode == ApInRunLoop) { 723 // 724 // Place AP in Run-loop 725 // 726 CpuPause (); 727 } else { 728 ASSERT (FALSE); 729 } 730 731 // 732 // If AP start-up signal is written, AP is waken up 733 // otherwise place AP in loop again 734 // 735 if ((*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) || (*ApStartupSignalBuffer == MP_HAND_OFF_SIGNAL)) { 736 break; 737 } 738 } 739 } 740 741 /** 671 742 This function will be called from AP reset code if BSP uses WakeUpAP. 672 743 673 @param[in] ExchangeInfo Pointer to the MP exchange info buffer744 @param[in] CpuMpData Pointer to CPU MP Data 674 745 @param[in] ApIndex Number of current executing AP 675 746 **/ … … 677 748 EFIAPI 678 749 ApWakeupFunction ( 679 IN MP_CPU_EXCHANGE_INFO *ExchangeInfo, 680 IN UINTN ApIndex 681 ) 682 { 683 CPU_MP_DATA *CpuMpData; 750 IN CPU_MP_DATA *CpuMpData, 751 IN UINTN ApIndex 752 ) 753 { 684 754 UINTN ProcessorNumber; 685 755 EFI_AP_PROCEDURE Procedure; … … 691 761 UINTN CurrentApicMode; 692 762 AP_STACK_DATA *ApStackData; 693 694 // 695 // AP finished assembly code and begin to execute C code 696 // 697 CpuMpData = ExchangeInfo->CpuMpData; 763 UINT32 OriginalValue; 698 764 699 765 // … … 736 802 // 737 803 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; 804 OriginalValue = InterlockedCompareExchange32 ( 805 (UINT32 *)ApStartupSignalBuffer, 806 MP_HAND_OFF_SIGNAL, 807 0 808 ); 809 if (OriginalValue == MP_HAND_OFF_SIGNAL) { 810 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateReady); 811 } 812 738 813 InterlockedCompareExchange32 ( 739 814 (UINT32 *)ApStartupSignalBuffer, … … 844 919 // 845 920 if (CpuMpData->ApLoopMode == ApInHltLoop) { 846 // 847 // Place AP in HLT-loop 848 // 849 while (TRUE) { 850 DisableInterrupts (); 851 if (CpuMpData->UseSevEsAPMethod) { 852 SevEsPlaceApHlt (CpuMpData); 853 } else { 854 CpuSleep (); 855 } 856 857 CpuPause (); 858 } 859 } 860 861 while (TRUE) { 862 DisableInterrupts (); 863 if (CpuMpData->ApLoopMode == ApInMwaitLoop) { 864 // 865 // Place AP in MWAIT-loop 866 // 867 AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0); 868 if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) { 869 // 870 // Check AP start-up signal again. 871 // If AP start-up signal is not set, place AP into 872 // the specified C-state 873 // 874 AsmMwait (CpuMpData->ApTargetCState << 4, 0); 875 } 876 } else if (CpuMpData->ApLoopMode == ApInRunLoop) { 877 // 878 // Place AP in Run-loop 879 // 880 CpuPause (); 881 } else { 882 ASSERT (FALSE); 883 } 884 885 // 886 // If AP start-up signal is written, AP is waken up 887 // otherwise place AP in loop again 888 // 889 if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) { 890 break; 891 } 892 } 893 } 921 PlaceAPInHltLoop (CpuMpData); 922 // 923 // Never run here 924 // 925 } else { 926 PlaceAPInMwaitLoopOrRunLoop (CpuMpData->ApLoopMode, ApStartupSignalBuffer, CpuMpData->ApTargetCState); 927 } 928 } 929 } 930 931 /** 932 This function serves as the entry point for APs when 933 they are awakened by the stores in the memory address 934 indicated by the MP_HANDOFF_INFO structure. 935 936 @param[in] CpuMpData Pointer to PEI CPU MP Data 937 **/ 938 VOID 939 EFIAPI 940 DxeApEntryPoint ( 941 CPU_MP_DATA *CpuMpData 942 ) 943 { 944 UINTN ProcessorNumber; 945 946 GetProcessorNumber (CpuMpData, &ProcessorNumber); 947 InterlockedIncrement ((UINT32 *)&CpuMpData->FinishedCount); 948 RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE); 949 PlaceAPInMwaitLoopOrRunLoop ( 950 CpuMpData->ApLoopMode, 951 CpuMpData->CpuData[ProcessorNumber].StartupApSignal, 952 CpuMpData->ApTargetCState 953 ); 954 ApWakeupFunction (CpuMpData, ProcessorNumber); 894 955 } 895 956 … … 1265 1326 SevSnpCreateAP (CpuMpData, -1); 1266 1327 } else { 1267 SendInitSipiSipiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStart); 1328 if ((CpuMpData->InitFlag == ApInitConfig) && FixedPcdGetBool (PcdFirstTimeWakeUpAPsBySipi)) { 1329 // 1330 // SIPI can be used for the first time wake up after reset to reduce boot time. 1331 // 1332 SendStartupIpiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStart); 1333 } else { 1334 SendInitSipiSipiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStart); 1335 } 1268 1336 } 1269 1337 } … … 1465 1533 1466 1534 /** 1535 Switch Context for each AP. 1536 1537 **/ 1538 VOID 1539 EFIAPI 1540 SwitchContextPerAp ( 1541 VOID 1542 ) 1543 { 1544 UINTN ProcessorNumber; 1545 CPU_MP_DATA *CpuMpData; 1546 CPU_INFO_IN_HOB *CpuInfoInHob; 1547 1548 CpuMpData = GetCpuMpData (); 1549 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; 1550 GetProcessorNumber (CpuMpData, &ProcessorNumber); 1551 1552 SwitchStack ( 1553 (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeApEntryPoint, 1554 (VOID *)(UINTN)CpuMpData, 1555 NULL, 1556 (VOID *)((UINTN)CpuInfoInHob[ProcessorNumber].ApTopOfStack) 1557 ); 1558 } 1559 1560 /** 1467 1561 Checks whether timeout expires. 1468 1562 … … 1569 1663 DEBUG_VERBOSE, 1570 1664 "%a: reached FinishedApLimit=%u in %Lu microseconds\n", 1571 __ FUNCTION__,1665 __func__, 1572 1666 FinishedApLimit, 1573 1667 DivU64x64Remainder ( … … 1817 1911 1818 1912 /** 1913 This function Get BspNumber. 1914 1915 @param[in] MpHandOff Pointer to MpHandOff 1916 @return BspNumber 1917 **/ 1918 UINT32 1919 GetBspNumber ( 1920 IN CONST MP_HAND_OFF *MpHandOff 1921 ) 1922 { 1923 UINT32 ApicId; 1924 UINT32 BspNumber; 1925 UINT32 Index; 1926 1927 // 1928 // Get the processor number for the BSP 1929 // 1930 BspNumber = MAX_UINT32; 1931 ApicId = GetInitialApicId (); 1932 for (Index = 0; Index < MpHandOff->CpuCount; Index++) { 1933 if (MpHandOff->Info[Index].ApicId == ApicId) { 1934 BspNumber = Index; 1935 } 1936 } 1937 1938 ASSERT (BspNumber != MAX_UINT32); 1939 1940 return BspNumber; 1941 } 1942 1943 /** 1944 This function is intended to be invoked by the BSP in order 1945 to wake up the AP. The BSP accomplishes this by triggering a 1946 start-up signal, which in turn causes any APs that are 1947 currently in a loop on the PEI-prepared memory to awaken and 1948 begin running the procedure called SwitchContextPerAp. 1949 This procedure allows the AP to switch to another section of 1950 memory and continue its loop there. 1951 1952 @param[in] MpHandOff Pointer to MP hand-off data structure. 1953 **/ 1954 VOID 1955 SwitchApContext ( 1956 IN MP_HAND_OFF *MpHandOff 1957 ) 1958 { 1959 UINTN Index; 1960 UINT32 BspNumber; 1961 1962 BspNumber = GetBspNumber (MpHandOff); 1963 1964 for (Index = 0; Index < MpHandOff->CpuCount; Index++) { 1965 if (Index != BspNumber) { 1966 *(UINTN *)(UINTN)MpHandOff->Info[Index].StartupProcedureAddress = (UINTN)SwitchContextPerAp; 1967 *(UINT32 *)(UINTN)MpHandOff->Info[Index].StartupSignalAddress = MpHandOff->StartupSignalValue; 1968 } 1969 } 1970 1971 // 1972 // Wait all APs waken up if this is not the 1st broadcast of SIPI 1973 // 1974 for (Index = 0; Index < MpHandOff->CpuCount; Index++) { 1975 if (Index != BspNumber) { 1976 WaitApWakeup ((UINT32 *)(UINTN)(MpHandOff->Info[Index].StartupSignalAddress)); 1977 } 1978 } 1979 } 1980 1981 /** 1982 Get pointer to MP_HAND_OFF GUIDed HOB. 1983 1984 @return The pointer to MP_HAND_OFF structure. 1985 **/ 1986 MP_HAND_OFF * 1987 GetMpHandOffHob ( 1988 VOID 1989 ) 1990 { 1991 EFI_HOB_GUID_TYPE *GuidHob; 1992 MP_HAND_OFF *MpHandOff; 1993 1994 MpHandOff = NULL; 1995 GuidHob = GetFirstGuidHob (&mMpHandOffGuid); 1996 if (GuidHob != NULL) { 1997 MpHandOff = (MP_HAND_OFF *)GET_GUID_HOB_DATA (GuidHob); 1998 } 1999 2000 return MpHandOff; 2001 } 2002 2003 /** 1819 2004 MP Initialize Library initialization. 1820 2005 … … 1835 2020 ) 1836 2021 { 1837 CPU_MP_DATA *OldCpuMpData;2022 MP_HAND_OFF *MpHandOff; 1838 2023 CPU_INFO_IN_HOB *CpuInfoInHob; 1839 2024 UINT32 MaxLogicalProcessorNumber; … … 1854 2039 UINTN ApIdtBase; 1855 2040 1856 OldCpuMpData = GetCpuMpDataFromGuidedHob ();1857 if ( OldCpuMpData== NULL) {2041 MpHandOff = GetMpHandOffHob (); 2042 if (MpHandOff == NULL) { 1858 2043 MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber); 1859 2044 } else { 1860 MaxLogicalProcessorNumber = OldCpuMpData->CpuCount;2045 MaxLogicalProcessorNumber = MpHandOff->CpuCount; 1861 2046 } 1862 2047 … … 2002 2187 ProgramVirtualWireMode (); 2003 2188 2004 if ( OldCpuMpData== NULL) {2189 if (MpHandOff == NULL) { 2005 2190 if (MaxLogicalProcessorNumber > 1) { 2006 2191 // … … 2014 2199 // from HOB 2015 2200 // 2016 OldCpuMpData->NewCpuMpData = CpuMpData; 2017 CpuMpData->CpuCount = OldCpuMpData->CpuCount; 2018 CpuMpData->BspNumber = OldCpuMpData->BspNumber; 2019 CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob; 2020 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; 2201 if (CpuMpData->UseSevEsAPMethod) { 2202 AmdSevUpdateCpuMpData (CpuMpData); 2203 } 2204 2205 CpuMpData->CpuCount = MpHandOff->CpuCount; 2206 CpuMpData->BspNumber = GetBspNumber (MpHandOff); 2207 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; 2021 2208 for (Index = 0; Index < CpuMpData->CpuCount; Index++) { 2022 2209 InitializeSpinLock (&CpuMpData->CpuData[Index].ApLock); 2023 CpuMpData->CpuData[Index].CpuHealthy = ( CpuInfoInHob[Index].Health == 0) ? TRUE : FALSE;2210 CpuMpData->CpuData[Index].CpuHealthy = (MpHandOff->Info[Index].Health == 0) ? TRUE : FALSE; 2024 2211 CpuMpData->CpuData[Index].ApFunction = 0; 2212 CpuInfoInHob[Index].InitialApicId = MpHandOff->Info[Index].ApicId; 2213 CpuInfoInHob[Index].ApTopOfStack = CpuMpData->Buffer + (Index + 1) * CpuMpData->CpuApStackSize; 2214 CpuInfoInHob[Index].ApicId = MpHandOff->Info[Index].ApicId; 2215 CpuInfoInHob[Index].Health = MpHandOff->Info[Index].Health; 2216 } 2217 2218 DEBUG ((DEBUG_INFO, "MpHandOff->WaitLoopExecutionMode: %04d, sizeof (VOID *): %04d\n", MpHandOff->WaitLoopExecutionMode, sizeof (VOID *))); 2219 if (MpHandOff->WaitLoopExecutionMode == sizeof (VOID *)) { 2220 ASSERT (CpuMpData->ApLoopMode != ApInHltLoop); 2221 2222 CpuMpData->FinishedCount = 0; 2223 CpuMpData->InitFlag = ApInitDone; 2224 SaveCpuMpData (CpuMpData); 2225 // 2226 // In scenarios where both the PEI and DXE phases run in the same 2227 // execution mode (32bit or 64bit), the BSP triggers 2228 // a start-up signal during the DXE phase to wake up the APs. This causes any 2229 // APs that are currently in a loop on the memory prepared during the PEI 2230 // phase to awaken and run the SwitchContextPerAp procedure. This procedure 2231 // enables the APs to switch to a different memory section and continue their 2232 // looping process there. 2233 // 2234 SwitchApContext (MpHandOff); 2235 ASSERT (CpuMpData->FinishedCount == (CpuMpData->CpuCount - 1)); 2236 2237 // 2238 // Set Apstate as Idle, otherwise Aps cannot be waken-up again. 2239 // If any enabled AP is not idle, return EFI_NOT_READY during waken-up. 2240 // 2241 for (Index = 0; Index < CpuMpData->CpuCount; Index++) { 2242 SetApState (&CpuMpData->CpuData[Index], CpuStateIdle); 2243 } 2244 2245 // 2246 // Initialize global data for MP support 2247 // 2248 InitMpGlobalData (CpuMpData); 2249 return EFI_SUCCESS; 2025 2250 } 2026 2251 } … … 2051 2276 // 2052 2277 if (CpuMpData->CpuCount > 1) { 2053 if ( OldCpuMpData!= NULL) {2278 if (MpHandOff != NULL) { 2054 2279 // 2055 2280 // Only needs to use this flag for DXE phase to update the wake up … … 2068 2293 } 2069 2294 2070 if ( OldCpuMpData!= NULL) {2295 if (MpHandOff != NULL) { 2071 2296 CpuMpData->InitFlag = ApInitDone; 2072 2297 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/MpLib.h
r99404 r101291 2 2 Common header file for MP Initialize Library. 3 3 4 Copyright (c) 2016 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) 2020, AMD Inc. All rights reserved.<BR> 6 6 … … 28 28 #include <Library/LocalApicLib.h> 29 29 #include <Library/CpuLib.h> 30 #include <Library/UefiCpuLib.h>31 30 #include <Library/TimerLib.h> 32 31 #include <Library/SynchronizationLib.h> … … 41 40 42 41 #include <Guid/MicrocodePatchHob.h> 42 #include "MpHandOff.h" 43 43 44 44 #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P') 45 // 46 // To trigger the start-up signal, BSP writes the specified 47 // StartupSignalValue to the StartupSignalAddress of each processor. 48 // This address is monitored by the APs, and as soon as they receive 49 // the value that matches the MP_HAND_OFF_SIGNAL, they will wake up 50 // and switch the context from PEI to DXE phase. 51 // 52 #define MP_HAND_OFF_SIGNAL SIGNATURE_32 ('M', 'P', 'H', 'O') 45 53 46 54 #define CPU_INIT_MP_LIB_HOB_GUID \ … … 178 186 UINTN ModeEntryOffset; 179 187 UINTN RendezvousFunnelSize; 180 UINT8 *RelocateApLoopFuncAddress; 181 UINTN RelocateApLoopFuncSize; 188 UINT8 *RelocateApLoopFuncAddressGeneric; 189 UINTN RelocateApLoopFuncSizeGeneric; 190 UINT8 *RelocateApLoopFuncAddressAmdSev; 191 UINTN RelocateApLoopFuncSizeAmdSev; 182 192 UINTN ModeTransitionOffset; 183 193 UINTN SwitchToRealNoNxOffset; … … 312 322 #define AP_SAFE_STACK_SIZE 128 313 323 #define AP_RESET_STACK_SIZE AP_SAFE_STACK_SIZE 324 STATIC_ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0, "AP_SAFE_STACK_SIZE is not aligned with CPU_STACK_ALIGNMENT"); 314 325 315 326 #pragma pack(1) … … 363 374 typedef 364 375 VOID 365 (EFIAPI *ASM_RELOCATE_AP_LOOP)( 376 (EFIAPI *ASM_RELOCATE_AP_LOOP_GENERIC)( 377 IN BOOLEAN MwaitSupport, 378 IN UINTN ApTargetCState, 379 IN UINTN TopOfApStack, 380 IN UINTN NumberToFinish, 381 IN UINTN Cr3 382 ); 383 384 /** 385 Assembly code to place AP into safe loop mode for Amd processors 386 with Sev enabled. 387 Place AP into targeted C-State if MONITOR is supported, otherwise 388 place AP into hlt state. 389 Place AP in protected mode if the current is long mode. Due to AP maybe 390 wakeup by some hardware event. It could avoid accessing page table that 391 may not available during booting to OS. 392 @param[in] MwaitSupport TRUE indicates MONITOR is supported. 393 FALSE indicates MONITOR is not supported. 394 @param[in] ApTargetCState Target C-State value. 395 @param[in] PmCodeSegment Protected mode code segment value. 396 **/ 397 typedef 398 VOID 399 (EFIAPI *ASM_RELOCATE_AP_LOOP_AMDSEV)( 366 400 IN BOOLEAN MwaitSupport, 367 401 IN UINTN ApTargetCState, … … 402 436 ); 403 437 438 typedef union { 439 VOID *Data; 440 ASM_RELOCATE_AP_LOOP_AMDSEV AmdSevEntry; // 64-bit AMD Sev processors 441 ASM_RELOCATE_AP_LOOP_GENERIC GenericEntry; // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or AMD non-Sev processors 442 } RELOCATE_AP_LOOP_ENTRY; 443 404 444 /** 405 445 Get the pointer to CPU MP Data structure. … … 436 476 437 477 /** 478 Switch Context for each AP. 479 480 **/ 481 VOID 482 SwitchApContext ( 483 IN MP_HAND_OFF *MpHandOff 484 ); 485 486 /** 438 487 Get available EfiBootServicesCode memory below 4GB by specified size. 439 488 … … 463 512 GetSevEsAPMemory ( 464 513 VOID 514 ); 515 516 /** 517 Create 1:1 mapping page table in reserved memory to map the specified address range. 518 @param[in] LinearAddress The start of the linear address range. 519 @param[in] Length The length of the linear address range. 520 @return The page table to be created. 521 **/ 522 UINTN 523 CreatePageTable ( 524 IN UINTN Address, 525 IN UINTN Length 465 526 ); 466 527 … … 849 910 ); 850 911 912 /** 913 Get pointer to CPU MP Data structure from GUIDed HOB. 914 915 @param[in] CpuMpData The pointer to CPU MP Data structure. 916 **/ 917 VOID 918 AmdSevUpdateCpuMpData ( 919 IN CPU_MP_DATA *CpuMpData 920 ); 921 851 922 #endif -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
r99404 r101291 37 37 MpLib.h 38 38 Microcode.c 39 39 MpHandOff.h 40 40 [Packages] 41 41 MdePkg/MdePkg.dec … … 50 50 MtrrLib 51 51 CpuLib 52 UefiCpuLib53 52 SynchronizationLib 54 53 PeiServicesLib … … 68 67 gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES 69 68 gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures ## CONSUMES 69 gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi ## CONSUMES 70 70 gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES 71 71 gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr ## CONSUMES -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
r99404 r101291 127 127 ) 128 128 { 129 UINT64 Data64; 129 UINT64 Data64; 130 UINTN Index; 131 CPU_INFO_IN_HOB *CpuInfoInHob; 132 MP_HAND_OFF *MpHandOff; 133 UINTN MpHandOffSize; 134 135 // 136 // When APs are in a state that can be waken up by a store operation to a memory address, 137 // report the MP_HAND_OFF data for DXE to use. 138 // 139 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; 140 MpHandOffSize = sizeof (MP_HAND_OFF) + sizeof (PROCESSOR_HAND_OFF) * CpuMpData->CpuCount; 141 MpHandOff = (MP_HAND_OFF *)BuildGuidHob (&mMpHandOffGuid, MpHandOffSize); 142 ASSERT (MpHandOff != NULL); 143 ZeroMem (MpHandOff, MpHandOffSize); 144 MpHandOff->ProcessorIndex = 0; 145 146 MpHandOff->CpuCount = CpuMpData->CpuCount; 147 if (CpuMpData->ApLoopMode != ApInHltLoop) { 148 MpHandOff->StartupSignalValue = MP_HAND_OFF_SIGNAL; 149 MpHandOff->WaitLoopExecutionMode = sizeof (VOID *); 150 } 151 152 for (Index = 0; Index < MpHandOff->CpuCount; Index++) { 153 MpHandOff->Info[Index].ApicId = CpuInfoInHob[Index].ApicId; 154 MpHandOff->Info[Index].Health = CpuInfoInHob[Index].Health; 155 if (CpuMpData->ApLoopMode != ApInHltLoop) { 156 MpHandOff->Info[Index].StartupSignalAddress = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal; 157 MpHandOff->Info[Index].StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction; 158 } 159 } 130 160 131 161 // … … 759 789 DEBUG_INFO, 760 790 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n", 761 __ FUNCTION__,791 __func__, 762 792 CpuMpData->MicrocodePatchAddress, 763 793 CpuMpData->MicrocodePatchRegionSize -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
r99404 r101291 13 13 #include <Register/Amd/Fam17Msr.h> 14 14 #include <Register/Amd/Ghcb.h> 15 16 #define _IS_ALIGNED(x, y) (ALIGN_POINTER((x), (y)) == (x)) 17 18 /** 19 Perform the requested AP Creation action. 20 21 @param[in] SaveArea Pointer to VM save area (VMSA) 22 @param[in] ApicId APIC ID of the vCPU 23 @param[in] Action AP action to perform 24 25 @retval TRUE Action completed successfully 26 @retval FALSE Action did not complete successfully 27 **/ 28 STATIC 29 BOOLEAN 30 SevSnpPerformApAction ( 31 IN SEV_ES_SAVE_AREA *SaveArea, 32 IN UINT32 ApicId, 33 IN UINTN Action 34 ) 35 { 36 MSR_SEV_ES_GHCB_REGISTER Msr; 37 GHCB *Ghcb; 38 BOOLEAN InterruptState; 39 UINT64 ExitInfo1; 40 UINT64 ExitInfo2; 41 UINT32 RmpAdjustStatus; 42 UINT64 VmgExitStatus; 43 44 if (Action == SVM_VMGEXIT_SNP_AP_CREATE) { 45 // 46 // To turn the page into a recognized VMSA page, issue RMPADJUST: 47 // Target VMPL but numerically higher than current VMPL 48 // Target PermissionMask is not used 49 // 50 RmpAdjustStatus = SevSnpRmpAdjust ( 51 (EFI_PHYSICAL_ADDRESS)(UINTN)SaveArea, 52 TRUE 53 ); 54 if (RmpAdjustStatus != 0) { 55 DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed for VMSA creation\n")); 56 ASSERT (FALSE); 57 58 return FALSE; 59 } 60 } 61 62 ExitInfo1 = (UINT64)ApicId << 32; 63 ExitInfo1 |= Action; 64 ExitInfo2 = (UINT64)(UINTN)SaveArea; 65 66 Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); 67 Ghcb = Msr.Ghcb; 68 69 CcExitVmgInit (Ghcb, &InterruptState); 70 71 if (Action == SVM_VMGEXIT_SNP_AP_CREATE) { 72 Ghcb->SaveArea.Rax = SaveArea->SevFeatures; 73 CcExitVmgSetOffsetValid (Ghcb, GhcbRax); 74 } 75 76 VmgExitStatus = CcExitVmgExit ( 77 Ghcb, 78 SVM_EXIT_SNP_AP_CREATION, 79 ExitInfo1, 80 ExitInfo2 81 ); 82 83 CcExitVmgDone (Ghcb, InterruptState); 84 85 if (VmgExitStatus != 0) { 86 DEBUG ((DEBUG_INFO, "SEV-SNP: AP Destroy failed\n")); 87 ASSERT (FALSE); 88 89 return FALSE; 90 } 91 92 if (Action == SVM_VMGEXIT_SNP_AP_DESTROY) { 93 // 94 // Make the current VMSA not runnable and accessible to be 95 // reprogrammed. 96 // 97 RmpAdjustStatus = SevSnpRmpAdjust ( 98 (EFI_PHYSICAL_ADDRESS)(UINTN)SaveArea, 99 FALSE 100 ); 101 if (RmpAdjustStatus != 0) { 102 DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed for VMSA reset\n")); 103 ASSERT (FALSE); 104 105 return FALSE; 106 } 107 } 108 109 return TRUE; 110 } 15 111 16 112 /** … … 28 124 ) 29 125 { 30 SEV_ES_SAVE_AREA *SaveArea; 31 IA32_CR0 ApCr0; 32 IA32_CR0 ResetCr0; 33 IA32_CR4 ApCr4; 34 IA32_CR4 ResetCr4; 35 UINTN StartIp; 36 UINT8 SipiVector; 37 UINT32 RmpAdjustStatus; 38 UINT64 VmgExitStatus; 39 MSR_SEV_ES_GHCB_REGISTER Msr; 40 GHCB *Ghcb; 41 BOOLEAN InterruptState; 42 UINT64 ExitInfo1; 43 UINT64 ExitInfo2; 44 45 // 46 // Allocate a single page for the SEV-ES Save Area and initialize it. 47 // 48 SaveArea = AllocateReservedPages (1); 49 if (!SaveArea) { 50 return; 126 UINT8 *Pages; 127 SEV_ES_SAVE_AREA *SaveArea; 128 IA32_CR0 ApCr0; 129 IA32_CR0 ResetCr0; 130 IA32_CR4 ApCr4; 131 IA32_CR4 ResetCr4; 132 UINTN StartIp; 133 UINT8 SipiVector; 134 135 if (CpuData->SevEsSaveArea == NULL) { 136 // 137 // Allocate a page for the SEV-ES Save Area and initialize it. Due to AMD 138 // erratum #1467 (VMSA cannot be on a 2MB boundary), allocate an extra page 139 // to choose from to work around the issue. 140 // 141 Pages = AllocateReservedPages (2); 142 if (!Pages) { 143 return; 144 } 145 146 // 147 // Since page allocation works by allocating downward in the address space, 148 // try to always free the first (lower address) page to limit possible holes 149 // in the memory map. So, if the address of the second page is 2MB aligned, 150 // then use the first page and free the second page. Otherwise, free the 151 // first page and use the second page. 152 // 153 if (_IS_ALIGNED (Pages + EFI_PAGE_SIZE, SIZE_2MB)) { 154 SaveArea = (SEV_ES_SAVE_AREA *)Pages; 155 FreePages (Pages + EFI_PAGE_SIZE, 1); 156 } else { 157 SaveArea = (SEV_ES_SAVE_AREA *)(Pages + EFI_PAGE_SIZE); 158 FreePages (Pages, 1); 159 } 160 161 CpuData->SevEsSaveArea = SaveArea; 162 } else { 163 SaveArea = CpuData->SevEsSaveArea; 164 165 // 166 // Tell the hypervisor to not use the current VMSA 167 // 168 if (!SevSnpPerformApAction (SaveArea, ApicId, SVM_VMGEXIT_SNP_AP_DESTROY)) { 169 return; 170 } 51 171 } 52 172 … … 133 253 SaveArea->SevFeatures = AsmReadMsr64 (MSR_SEV_STATUS) >> 2; 134 254 135 // 136 // To turn the page into a recognized VMSA page, issue RMPADJUST: 137 // Target VMPL but numerically higher than current VMPL 138 // Target PermissionMask is not used 139 // 140 RmpAdjustStatus = SevSnpRmpAdjust ( 141 (EFI_PHYSICAL_ADDRESS)(UINTN)SaveArea, 142 TRUE 143 ); 144 ASSERT (RmpAdjustStatus == 0); 145 146 ExitInfo1 = (UINT64)ApicId << 32; 147 ExitInfo1 |= SVM_VMGEXIT_SNP_AP_CREATE; 148 ExitInfo2 = (UINT64)(UINTN)SaveArea; 149 150 Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); 151 Ghcb = Msr.Ghcb; 152 153 CcExitVmgInit (Ghcb, &InterruptState); 154 Ghcb->SaveArea.Rax = SaveArea->SevFeatures; 155 CcExitVmgSetOffsetValid (Ghcb, GhcbRax); 156 VmgExitStatus = CcExitVmgExit ( 157 Ghcb, 158 SVM_EXIT_SNP_AP_CREATION, 159 ExitInfo1, 160 ExitInfo2 161 ); 162 CcExitVmgDone (Ghcb, InterruptState); 163 164 ASSERT (VmgExitStatus == 0); 165 if (VmgExitStatus != 0) { 166 RmpAdjustStatus = SevSnpRmpAdjust ( 167 (EFI_PHYSICAL_ADDRESS)(UINTN)SaveArea, 168 FALSE 169 ); 170 if (RmpAdjustStatus == 0) { 171 FreePages (SaveArea, 1); 172 } else { 173 DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed, leaking VMSA page\n")); 174 } 175 176 SaveArea = NULL; 177 } 178 179 if (CpuData->SevEsSaveArea) { 180 RmpAdjustStatus = SevSnpRmpAdjust ( 181 (EFI_PHYSICAL_ADDRESS)(UINTN)CpuData->SevEsSaveArea, 182 FALSE 183 ); 184 if (RmpAdjustStatus == 0) { 185 FreePages (CpuData->SevEsSaveArea, 1); 186 } else { 187 DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed, leaking VMSA page\n")); 188 } 189 } 190 191 CpuData->SevEsSaveArea = SaveArea; 255 SevSnpPerformApAction (SaveArea, ApicId, SVM_VMGEXIT_SNP_AP_CREATE); 192 256 } 193 257 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
r99404 r101291 347 347 348 348 SwitchToRealProcEnd: 349 350 ;------------------------------------------------------------------------------------- 351 ; AsmRelocateApLoopAmdSev (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); 352 ;------------------------------------------------------------------------------------- 353 354 AsmRelocateApLoopAmdSevStart: 355 BITS 64 356 cmp qword [rsp + 56], 0 ; SevEsAPJumpTable 357 je NoSevEsAmdSev 358 359 ; 360 ; Perform some SEV-ES related setup before leaving 64-bit mode 361 ; 362 push rcx 363 push rdx 364 365 ; 366 ; Get the RDX reset value using CPUID 367 ; 368 mov rax, 1 369 cpuid 370 mov rsi, rax ; Save off the reset value for RDX 371 372 ; 373 ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call 374 ; - Must be done while in 64-bit long mode so that writes to 375 ; the GHCB memory will be unencrypted. 376 ; - No NAE events can be generated once this is set otherwise 377 ; the AP_RESET_HOLD SW_EXITCODE will be overwritten. 378 ; 379 mov rcx, 0xc0010130 380 rdmsr ; Retrieve current GHCB address 381 shl rdx, 32 382 or rdx, rax 383 384 mov rdi, rdx 385 xor rax, rax 386 mov rcx, 0x800 387 shr rcx, 3 388 rep stosq ; Clear the GHCB 389 390 mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD 391 mov [rdx + 0x390], rax 392 mov rax, 114 ; Set SwExitCode valid bit 393 bts [rdx + 0x3f0], rax 394 inc rax ; Set SwExitInfo1 valid bit 395 bts [rdx + 0x3f0], rax 396 inc rax ; Set SwExitInfo2 valid bit 397 bts [rdx + 0x3f0], rax 398 399 pop rdx 400 pop rcx 401 402 NoSevEsAmdSev: 403 cli ; Disable interrupt before switching to 32-bit mode 404 mov rax, [rsp + 40] ; CountTofinish 405 lock dec dword [rax] ; (*CountTofinish)-- 406 407 mov r10, [rsp + 48] ; Pm16CodeSegment 408 mov rax, [rsp + 56] ; SevEsAPJumpTable 409 mov rbx, [rsp + 64] ; WakeupBuffer 410 mov rsp, r9 ; TopOfApStack 411 412 push rax ; Save SevEsAPJumpTable 413 push rbx ; Save WakeupBuffer 414 push r10 ; Save Pm16CodeSegment 415 push rcx ; Save MwaitSupport 416 push rdx ; Save ApTargetCState 417 418 lea rax, [PmEntryAmdSev] ; rax <- The start address of transition code 419 420 push r8 421 push rax 422 423 ; 424 ; Clear R8 - R15, for reset, before going into 32-bit mode 425 ; 426 xor r8, r8 427 xor r9, r9 428 xor r10, r10 429 xor r11, r11 430 xor r12, r12 431 xor r13, r13 432 xor r14, r14 433 xor r15, r15 434 435 ; 436 ; Far return into 32-bit mode 437 ; 438 o64 retf 439 440 BITS 32 441 PmEntryAmdSev: 442 mov eax, cr0 443 btr eax, 31 ; Clear CR0.PG 444 mov cr0, eax ; Disable paging and caches 445 446 mov ecx, 0xc0000080 447 rdmsr 448 and ah, ~ 1 ; Clear LME 449 wrmsr 450 mov eax, cr4 451 and al, ~ (1 << 5) ; Clear PAE 452 mov cr4, eax 453 454 pop edx 455 add esp, 4 456 pop ecx, 457 add esp, 4 458 459 MwaitCheckAmdSev: 460 cmp cl, 1 ; Check mwait-monitor support 461 jnz HltLoopAmdSev 462 mov ebx, edx ; Save C-State to ebx 463 MwaitLoopAmdSev: 464 cli 465 mov eax, esp ; Set Monitor Address 466 xor ecx, ecx ; ecx = 0 467 xor edx, edx ; edx = 0 468 monitor 469 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] 470 shl eax, 4 471 mwait 472 jmp MwaitLoopAmdSev 473 474 HltLoopAmdSev: 475 pop edx ; PM16CodeSegment 476 add esp, 4 477 pop ebx ; WakeupBuffer 478 add esp, 4 479 pop eax ; SevEsAPJumpTable 480 add esp, 4 481 cmp eax, 0 ; Check for SEV-ES 482 je DoHltAmdSev 483 484 cli 485 ; 486 ; SEV-ES is enabled, use VMGEXIT (GHCB information already 487 ; set by caller) 488 ; 489 BITS 64 490 rep vmmcall 491 BITS 32 492 493 ; 494 ; Back from VMGEXIT AP_HLT_LOOP 495 ; Push the FLAGS/CS/IP values to use 496 ; 497 push word 0x0002 ; EFLAGS 498 xor ecx, ecx 499 mov cx, [eax + 2] ; CS 500 push cx 501 mov cx, [eax] ; IP 502 push cx 503 push word 0x0000 ; For alignment, will be discarded 504 505 push edx 506 push ebx 507 508 mov edx, esi ; Restore RDX reset value 509 510 retf 511 512 DoHltAmdSev: 513 cli 514 hlt 515 jmp DoHltAmdSev 516 517 BITS 64 518 AsmRelocateApLoopAmdSevEnd: -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
r99404 r101291 1 1 ;------------------------------------------------------------------------------ ; 2 ; Copyright (c) 2015 - 202 2, Intel Corporation. All rights reserved.<BR>2 ; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR> 3 3 ; SPDX-License-Identifier: BSD-2-Clause-Patent 4 4 ; … … 260 260 261 261 mov edx, ebx ; edx is ApIndex 262 mov ecx, esi 263 add ecx, MP_CPU_EXCHANGE_INFO_OFFSET ; rcx is address of exchange info data buffer 262 mov rcx, qword [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuMpData)] 264 263 265 264 mov edi, esi … … 280 279 281 280 ;------------------------------------------------------------------------------------- 282 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); 283 ;------------------------------------------------------------------------------------- 284 AsmRelocateApLoopStart: 285 BITS 64 286 cmp qword [rsp + 56], 0 ; SevEsAPJumpTable 287 je NoSevEs 288 289 ; 290 ; Perform some SEV-ES related setup before leaving 64-bit mode 291 ; 292 push rcx 293 push rdx 294 295 ; 296 ; Get the RDX reset value using CPUID 297 ; 298 mov rax, 1 299 cpuid 300 mov rsi, rax ; Save off the reset value for RDX 301 302 ; 303 ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call 304 ; - Must be done while in 64-bit long mode so that writes to 305 ; the GHCB memory will be unencrypted. 306 ; - No NAE events can be generated once this is set otherwise 307 ; the AP_RESET_HOLD SW_EXITCODE will be overwritten. 308 ; 309 mov rcx, 0xc0010130 310 rdmsr ; Retrieve current GHCB address 311 shl rdx, 32 312 or rdx, rax 313 314 mov rdi, rdx 315 xor rax, rax 316 mov rcx, 0x800 317 shr rcx, 3 318 rep stosq ; Clear the GHCB 319 320 mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD 321 mov [rdx + 0x390], rax 322 mov rax, 114 ; Set SwExitCode valid bit 323 bts [rdx + 0x3f0], rax 324 inc rax ; Set SwExitInfo1 valid bit 325 bts [rdx + 0x3f0], rax 326 inc rax ; Set SwExitInfo2 valid bit 327 bts [rdx + 0x3f0], rax 328 329 pop rdx 330 pop rcx 331 332 NoSevEs: 333 cli ; Disable interrupt before switching to 32-bit mode 334 mov rax, [rsp + 40] ; CountTofinish 281 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3); 282 ; This function is called during the finalizaiton of Mp initialization before booting 283 ; to OS, and aim to put Aps either in Mwait or HLT. 284 ;------------------------------------------------------------------------------------- 285 ; +----------------+ 286 ; | Cr3 | rsp+40 287 ; +----------------+ 288 ; | CountTofinish | r9 289 ; +----------------+ 290 ; | TopOfApStack | r8 291 ; +----------------+ 292 ; | ApTargetCState | rdx 293 ; +----------------+ 294 ; | MwaitSupport | rcx 295 ; +----------------+ 296 ; | the return | 297 ; +----------------+ low address 298 299 AsmRelocateApLoopGenericStart: 300 mov rax, r9 ; CountTofinish 335 301 lock dec dword [rax] ; (*CountTofinish)-- 336 302 337 mov r10, [rsp + 48] ; Pm16CodeSegment 338 mov rax, [rsp + 56] ; SevEsAPJumpTable 339 mov rbx, [rsp + 64] ; WakeupBuffer 340 mov rsp, r9 ; TopOfApStack 341 342 push rax ; Save SevEsAPJumpTable 343 push rbx ; Save WakeupBuffer 344 push r10 ; Save Pm16CodeSegment 345 push rcx ; Save MwaitSupport 346 push rdx ; Save ApTargetCState 347 348 lea rax, [PmEntry] ; rax <- The start address of transition code 349 350 push r8 351 push rax 352 353 ; 354 ; Clear R8 - R15, for reset, before going into 32-bit mode 355 ; 356 xor r8, r8 357 xor r9, r9 358 xor r10, r10 359 xor r11, r11 360 xor r12, r12 361 xor r13, r13 362 xor r14, r14 363 xor r15, r15 364 365 ; 366 ; Far return into 32-bit mode 367 ; 368 retfq 369 370 BITS 32 371 PmEntry: 372 mov eax, cr0 373 btr eax, 31 ; Clear CR0.PG 374 mov cr0, eax ; Disable paging and caches 375 376 mov ecx, 0xc0000080 377 rdmsr 378 and ah, ~ 1 ; Clear LME 379 wrmsr 380 mov eax, cr4 381 and al, ~ (1 << 5) ; Clear PAE 382 mov cr4, eax 383 384 pop edx 385 add esp, 4 386 pop ecx, 387 add esp, 4 388 389 MwaitCheck: 303 mov rax, [rsp + 40] ; Cr3 304 ; Do not push on old stack, since old stack is not mapped 305 ; in the page table pointed by cr3 306 mov cr3, rax 307 mov rsp, r8 ; TopOfApStack 308 309 MwaitCheckGeneric: 390 310 cmp cl, 1 ; Check mwait-monitor support 391 jnz HltLoop 392 mov ebx, edx ; Save C-State to ebx 393 MwaitLoop: 311 jnz HltLoopGeneric 312 mov rbx, rdx ; Save C-State to ebx 313 314 MwaitLoopGeneric: 394 315 cli 395 mov eax, esp ; Set Monitor Address 316 mov rax, rsp ; Set Monitor Address 317 sub eax, 8 ; To ensure the monitor address is in the page table 396 318 xor ecx, ecx ; ecx = 0 397 319 xor edx, edx ; edx = 0 398 320 monitor 399 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]321 mov rax, rbx ; Mwait Cx, Target C-State per eax[7:4] 400 322 shl eax, 4 401 323 mwait 402 jmp MwaitLoop 403 404 HltLoop: 405 pop edx ; PM16CodeSegment 406 add esp, 4 407 pop ebx ; WakeupBuffer 408 add esp, 4 409 pop eax ; SevEsAPJumpTable 410 add esp, 4 411 cmp eax, 0 ; Check for SEV-ES 412 je DoHlt 413 414 cli 415 ; 416 ; SEV-ES is enabled, use VMGEXIT (GHCB information already 417 ; set by caller) 418 ; 419 BITS 64 420 rep vmmcall 421 BITS 32 422 423 ; 424 ; Back from VMGEXIT AP_HLT_LOOP 425 ; Push the FLAGS/CS/IP values to use 426 ; 427 push word 0x0002 ; EFLAGS 428 xor ecx, ecx 429 mov cx, [eax + 2] ; CS 430 push cx 431 mov cx, [eax] ; IP 432 push cx 433 push word 0x0000 ; For alignment, will be discarded 434 435 push edx 436 push ebx 437 438 mov edx, esi ; Restore RDX reset value 439 440 retf 441 442 DoHlt: 324 jmp MwaitLoopGeneric 325 326 HltLoopGeneric: 443 327 cli 444 328 hlt 445 jmp DoHlt 446 447 BITS 64 448 AsmRelocateApLoopEnd: 329 jmp HltLoopGeneric 330 331 AsmRelocateApLoopGenericEnd: 449 332 450 333 ;------------------------------------------------------------------------------------- … … 457 340 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], LongModeStart - RendezvousFunnelProcStart 458 341 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart 459 lea rax, [AsmRelocateApLoopStart] 460 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax 461 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart 342 lea rax, [AsmRelocateApLoopGenericStart] 343 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], rax 344 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart 345 lea rax, [AsmRelocateApLoopAmdSevStart] 346 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressAmdSev], rax 347 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeAmdSev], AsmRelocateApLoopAmdSevEnd - AsmRelocateApLoopAmdSevStart 462 348 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart 463 349 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
r99404 r101291 757 757 ) 758 758 { 759 UINT32 MaxExtendedFunction; 760 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; 759 UINT32 MaxExtendedFunction; 760 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; 761 UINT32 MaxFunction; 762 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX ExtendedFeatureFlagsEcx; 763 MSR_IA32_TME_ACTIVATE_REGISTER TmeActivate; 761 764 762 765 AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL); … … 766 769 } else { 767 770 VirPhyAddressSize.Bits.PhysicalAddressBits = 36; 771 } 772 773 // 774 // CPUID enumeration of MAX_PA is unaffected by TME-MK activation and will continue 775 // to report the maximum physical address bits available for software to use, 776 // irrespective of the number of KeyID bits. 777 // So, we need to check if TME is enabled and adjust the PA size accordingly. 778 // 779 AsmCpuid (CPUID_SIGNATURE, &MaxFunction, NULL, NULL, NULL); 780 if (MaxFunction >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) { 781 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, NULL, &ExtendedFeatureFlagsEcx.Uint32, NULL); 782 if (ExtendedFeatureFlagsEcx.Bits.TME_EN == 1) { 783 TmeActivate.Uint64 = AsmReadMsr64 (MSR_IA32_TME_ACTIVATE); 784 if (TmeActivate.Bits.TmeEnable == 1) { 785 VirPhyAddressSize.Bits.PhysicalAddressBits -= TmeActivate.Bits.MkTmeKeyidBits; 786 } 787 } 768 788 } 769 789 … … 1252 1272 1253 1273 return (MTRR_MEMORY_CACHE_TYPE)Type; 1254 }1255 1256 /**1257 Return TRUE when the Operand is exactly power of 2.1258 1259 @retval TRUE Operand is exactly power of 2.1260 @retval FALSE Operand is not power of 2.1261 **/1262 BOOLEAN1263 MtrrLibIsPowerOfTwo (1264 IN UINT64 Operand1265 )1266 {1267 ASSERT (Operand != 0);1268 return (BOOLEAN)((Operand & (Operand - 1)) == 0);1269 1274 } 1270 1275 … … 1639 1644 } 1640 1645 1641 if ((Weight[M (Start, Stop)] == MAX_WEIGHT) && MtrrLibIsPowerOfTwo(Length)) {1646 if ((Weight[M (Start, Stop)] == MAX_WEIGHT) && IS_POW2 (Length)) { 1642 1647 if (MtrrLibGetNumberOfTypes ( 1643 1648 Ranges, -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
r99404 r101291 2 2 Unit tests of the MtrrLib instance of the MtrrLib class 3 3 4 Copyright (c) 2020 , Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2020 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 31 31 { 48, TRUE, TRUE, CacheWriteProtected, 12 }, 32 32 { 48, TRUE, TRUE, CacheWriteCombining, 12 }, 33 34 { 48, TRUE, TRUE, CacheWriteBack, 12, 7}, // 7 bits for MKTME 33 35 }; 34 36 … … 220 222 ); 221 223 GenerateValidAndConfigurableMtrrPairs ( 222 SystemParameter->PhysicalAddressBits ,224 SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits, 223 225 RawMtrrRange, 224 226 UcCount, … … 233 235 GetEffectiveMemoryRanges ( 234 236 SystemParameter->DefaultCacheType, 235 SystemParameter->PhysicalAddressBits ,237 SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits, 236 238 RawMtrrRange, 237 239 ExpectedVariableMtrrUsage, … … 279 281 CollectTestResult ( 280 282 SystemParameter->DefaultCacheType, 281 SystemParameter->PhysicalAddressBits ,283 SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits, 282 284 SystemParameter->VariableMtrrCount, 283 285 &LocalMtrrs, … … 326 328 327 329 RangeCount = Random32 (1, ARRAY_SIZE (Ranges)); 328 MaxAddress = 1ull << SystemParameter->PhysicalAddressBits;330 MaxAddress = 1ull << (SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits); 329 331 330 332 for (Index = 0; Index < RangeCount; Index++) { … … 968 970 ); 969 971 GenerateValidAndConfigurableMtrrPairs ( 970 SystemParameter->PhysicalAddressBits ,972 SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits, 971 973 RawMtrrRange, 972 974 UcCount, … … 981 983 GetEffectiveMemoryRanges ( 982 984 SystemParameter->DefaultCacheType, 983 SystemParameter->PhysicalAddressBits ,985 SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits, 984 986 RawMtrrRange, 985 987 ExpectedVariableMtrrUsage, … … 1020 1022 CollectTestResult ( 1021 1023 SystemParameter->DefaultCacheType, 1022 SystemParameter->PhysicalAddressBits ,1024 SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits, 1023 1025 SystemParameter->VariableMtrrCount, 1024 1026 &LocalMtrrs, -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
r99404 r101291 1 1 /** @file 2 2 3 Copyright (c) 2020 , Intel Corporation. All rights reserved.<BR>3 Copyright (c) 2020 - 2023, Intel Corporation. All rights reserved.<BR> 4 4 SPDX-License-Identifier: BSD-2-Clause-Patent 5 5 … … 41 41 MTRR_MEMORY_CACHE_TYPE DefaultCacheType; 42 42 UINT32 VariableMtrrCount; 43 UINT8 MkTmeKeyidBits; 43 44 } MTRR_LIB_SYSTEM_PARAMETER; 44 45 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
r99404 r101291 2 2 Unit tests of the MtrrLib instance of the MtrrLib class 3 3 4 Copyright (c) 2018 - 202 0, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2018 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 13 13 }; 14 14 15 UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR]; 16 MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR]; 17 MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR]; 18 MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr; 19 MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr; 20 CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx; 21 CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax; 15 UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR]; 16 MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR]; 17 MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR]; 18 MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr; 19 MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr; 20 MSR_IA32_TME_ACTIVATE_REGISTER mTmeActivateMsr; 21 CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx; 22 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX mCpuidExtendedFeatureFlagsEcx; 23 CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax; 22 24 23 25 BOOLEAN mRandomInput; … … 88 90 89 91 /** 92 Retrieves CPUID information using an extended leaf identifier. 93 94 Executes the CPUID instruction with EAX set to the value specified by Index 95 and ECX set to the value specified by SubIndex. This function always returns 96 Index. This function is only available on IA-32 and x64. 97 98 If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. 99 If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. 100 If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. 101 If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. 102 103 @param Index The 32-bit value to load into EAX prior to invoking the 104 CPUID instruction. 105 @param SubIndex The 32-bit value to load into ECX prior to invoking the 106 CPUID instruction. 107 @param Eax The pointer to the 32-bit EAX value returned by the CPUID 108 instruction. This is an optional parameter that may be 109 NULL. 110 @param Ebx The pointer to the 32-bit EBX value returned by the CPUID 111 instruction. This is an optional parameter that may be 112 NULL. 113 @param Ecx The pointer to the 32-bit ECX value returned by the CPUID 114 instruction. This is an optional parameter that may be 115 NULL. 116 @param Edx The pointer to the 32-bit EDX value returned by the CPUID 117 instruction. This is an optional parameter that may be 118 NULL. 119 120 @return Index. 121 122 **/ 123 UINT32 124 EFIAPI 125 UnitTestMtrrLibAsmCpuidEx ( 126 IN UINT32 Index, 127 IN UINT32 SubIndex, 128 OUT UINT32 *Eax OPTIONAL, 129 OUT UINT32 *Ebx OPTIONAL, 130 OUT UINT32 *Ecx OPTIONAL, 131 OUT UINT32 *Edx OPTIONAL 132 ) 133 { 134 switch (Index) { 135 case CPUID_SIGNATURE: 136 if (Eax != NULL) { 137 *Eax = CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS; 138 } 139 140 return Index; 141 break; 142 case CPUID_VERSION_INFO: 143 if (Edx != NULL) { 144 *Edx = mCpuidVersionInfoEdx.Uint32; 145 } 146 147 return Index; 148 break; 149 case CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS: 150 if (Ecx != NULL) { 151 *Ecx = mCpuidExtendedFeatureFlagsEcx.Uint32; 152 } 153 154 return Index; 155 break; 156 case CPUID_EXTENDED_FUNCTION: 157 if (Eax != NULL) { 158 *Eax = CPUID_VIR_PHY_ADDRESS_SIZE; 159 } 160 161 return Index; 162 break; 163 case CPUID_VIR_PHY_ADDRESS_SIZE: 164 if (Eax != NULL) { 165 *Eax = mCpuidVirPhyAddressSizeEax.Uint32; 166 } 167 168 return Index; 169 break; 170 } 171 172 // 173 // Should never fall through to here 174 // 175 ASSERT (FALSE); 176 return Index; 177 } 178 179 /** 90 180 Retrieves CPUID information. 91 181 … … 122 212 ) 123 213 { 124 switch (Index) { 125 case CPUID_VERSION_INFO: 126 if (Edx != NULL) { 127 *Edx = mCpuidVersionInfoEdx.Uint32; 128 } 129 130 return Index; 131 break; 132 case CPUID_EXTENDED_FUNCTION: 133 if (Eax != NULL) { 134 *Eax = CPUID_VIR_PHY_ADDRESS_SIZE; 135 } 136 137 return Index; 138 break; 139 case CPUID_VIR_PHY_ADDRESS_SIZE: 140 if (Eax != NULL) { 141 *Eax = mCpuidVirPhyAddressSizeEax.Uint32; 142 } 143 144 return Index; 145 break; 146 } 147 148 // 149 // Should never fall through to here 150 // 151 ASSERT (FALSE); 152 return Index; 214 return UnitTestMtrrLibAsmCpuidEx (Index, 0, Eax, Ebx, Ecx, Edx); 153 215 } 154 216 … … 199 261 if (MsrIndex == MSR_IA32_MTRRCAP) { 200 262 return mMtrrCapMsr.Uint64; 263 } 264 265 if (MsrIndex == MSR_IA32_TME_ACTIVATE) { 266 return mTmeActivateMsr.Uint64; 201 267 } 202 268 … … 318 384 // Hook BaseLib functions used by MtrrLib that require some emulation. 319 385 // 320 gUnitTestHostBaseLib.X86->AsmCpuid = UnitTestMtrrLibAsmCpuid; 386 gUnitTestHostBaseLib.X86->AsmCpuid = UnitTestMtrrLibAsmCpuid; 387 gUnitTestHostBaseLib.X86->AsmCpuidEx = UnitTestMtrrLibAsmCpuidEx; 388 321 389 gUnitTestHostBaseLib.X86->AsmReadMsr64 = UnitTestMtrrLibAsmReadMsr64; 322 390 gUnitTestHostBaseLib.X86->AsmWriteMsr64 = UnitTestMtrrLibAsmWriteMsr64; 391 392 if (SystemParameter->MkTmeKeyidBits != 0) { 393 mCpuidExtendedFeatureFlagsEcx.Bits.TME_EN = 1; 394 mTmeActivateMsr.Bits.TmeEnable = 1; 395 mTmeActivateMsr.Bits.MkTmeKeyidBits = SystemParameter->MkTmeKeyidBits; 396 } else { 397 mCpuidExtendedFeatureFlagsEcx.Bits.TME_EN = 0; 398 mTmeActivateMsr.Bits.TmeEnable = 0; 399 mTmeActivateMsr.Bits.MkTmeKeyidBits = 0; 400 } 323 401 324 402 return UNIT_TEST_PASSED; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
r99404 r101291 2 2 CPU Features Initialize functions. 3 3 4 Copyright (c) 2017 - 202 1, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 68 68 DisplayedFamily = Eax.Bits.FamilyId; 69 69 if (Eax.Bits.FamilyId == 0x0F) { 70 DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);70 DisplayedFamily += Eax.Bits.ExtendedFamilyId; 71 71 } 72 72 73 73 DisplayedModel = Eax.Bits.Model; 74 74 if ((Eax.Bits.FamilyId == 0x06) || (Eax.Bits.FamilyId == 0x0f)) { 75 DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);75 DisplayedModel += (Eax.Bits.ExtendedModelId << 4); 76 76 } 77 77 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h
r99404 r101291 10 10 #define CPU_FEATURES_LIB_H_ 11 11 12 #include <Guid/SmmBaseHob.h> 12 13 #include <Library/SmmCpuFeaturesLib.h> 13 14 #include <Library/BaseLib.h> … … 15 16 #include <Library/MemoryAllocationLib.h> 16 17 #include <Library/DebugLib.h> 18 #include <Library/HobLib.h> 17 19 18 20 /** -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c
r99404 r101291 2 2 Implementation shared across all library instances. 3 3 4 Copyright (c) 2010 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) Microsoft Corporation.<BR> 6 6 SPDX-License-Identifier: BSD-2-Clause-Patent … … 40 40 41 41 // 42 // Indicate SmBase for each Processors has been relocated or not. If TRUE, 43 // means no need to do the relocation in SmmCpuFeaturesInitializeProcessor(). 44 // 45 BOOLEAN mSmmCpuFeaturesSmmRelocated; 46 47 // 42 48 // Set default value to assume MTRRs need to be configured on each SMI 43 49 // … … 145 151 mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * GetCpuMaxLogicalProcessorNumber ()); 146 152 ASSERT (mSmrrEnabled != NULL); 153 154 // 155 // If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded 156 // in the SmBase array. 157 // 158 mSmmCpuFeaturesSmmRelocated = (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL); 147 159 } 148 160 … … 188 200 189 201 // 190 // Configure SMBASE. 191 // 192 CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET); 193 CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex]; 202 // No need to configure SMBASE if SmBase relocation has been done. 203 // 204 if (!mSmmCpuFeaturesSmmRelocated) { 205 // 206 // Configure SMBASE. 207 // 208 CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET); 209 CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex]; 210 } 194 211 195 212 // … … 401 418 } 402 419 } 420 421 /** 422 This function updates the SMRAM save state on the currently executing CPU 423 to resume execution at a specific address after an RSM instruction. This 424 function must evaluate the SMRAM save state to determine the execution mode 425 the RSM instruction resumes and update the resume execution address with 426 either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart 427 flag in the SMRAM save state must always be cleared. This function returns 428 the value of the instruction pointer from the SMRAM save state that was 429 replaced. If this function returns 0, then the SMRAM save state was not 430 modified. 431 432 This function is called during the very first SMI on each CPU after 433 SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode 434 to signal that the SMBASE of each CPU has been updated before the default 435 SMBASE address is used for the first SMI to the next CPU. 436 437 @param[in] CpuIndex The index of the CPU to hook. The value 438 must be between 0 and the NumberOfCpus 439 field in the System Management System Table 440 (SMST). 441 @param[in] CpuState Pointer to SMRAM Save State Map for the 442 currently executing CPU. 443 @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to 444 32-bit execution mode from 64-bit SMM. 445 @param[in] NewInstructionPointer Instruction pointer to use if resuming to 446 same execution mode as SMM. 447 448 @retval 0 This function did modify the SMRAM save state. 449 @retval > 0 The original instruction pointer value from the SMRAM save state 450 before it was replaced. 451 **/ 452 UINT64 453 EFIAPI 454 SmmCpuFeaturesHookReturnFromSmm ( 455 IN UINTN CpuIndex, 456 IN SMRAM_SAVE_STATE_MAP *CpuState, 457 IN UINT64 NewInstructionPointer32, 458 IN UINT64 NewInstructionPointer 459 ) 460 { 461 return 0; 462 } 463 464 /** 465 Check to see if an SMM register is supported by a specified CPU. 466 467 @param[in] CpuIndex The index of the CPU to check for SMM register support. 468 The value must be between 0 and the NumberOfCpus field 469 in the System Management System Table (SMST). 470 @param[in] RegName Identifies the SMM register to check for support. 471 472 @retval TRUE The SMM register specified by RegName is supported by the CPU 473 specified by CpuIndex. 474 @retval FALSE The SMM register specified by RegName is not supported by the 475 CPU specified by CpuIndex. 476 **/ 477 BOOLEAN 478 EFIAPI 479 SmmCpuFeaturesIsSmmRegisterSupported ( 480 IN UINTN CpuIndex, 481 IN SMM_REG_NAME RegName 482 ) 483 { 484 if (FeaturePcdGet (PcdSmmFeatureControlEnable) && (RegName == SmmRegFeatureControl)) { 485 return TRUE; 486 } 487 488 return FALSE; 489 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
r99404 r101291 2 2 # The CPU specific programming for PiSmmCpuDxeSmm module. 3 3 # 4 # Copyright (c) 2009 - 20 16, Intel Corporation. All rights reserved.<BR>4 # Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 # SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 # … … 34 34 MemoryAllocationLib 35 35 DebugLib 36 HobLib 37 38 [Guids] 39 gSmmBaseHobGuid ## CONSUMES 36 40 37 41 [Pcd] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c
r99404 r101291 17 17 18 18 #include "CpuFeaturesLib.h" 19 20 /**21 This function updates the SMRAM save state on the currently executing CPU22 to resume execution at a specific address after an RSM instruction. This23 function must evaluate the SMRAM save state to determine the execution mode24 the RSM instruction resumes and update the resume execution address with25 either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart26 flag in the SMRAM save state must always be cleared. This function returns27 the value of the instruction pointer from the SMRAM save state that was28 replaced. If this function returns 0, then the SMRAM save state was not29 modified.30 31 This function is called during the very first SMI on each CPU after32 SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode33 to signal that the SMBASE of each CPU has been updated before the default34 SMBASE address is used for the first SMI to the next CPU.35 36 @param[in] CpuIndex The index of the CPU to hook. The value37 must be between 0 and the NumberOfCpus38 field in the System Management System Table39 (SMST).40 @param[in] CpuState Pointer to SMRAM Save State Map for the41 currently executing CPU.42 @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to43 32-bit execution mode from 64-bit SMM.44 @param[in] NewInstructionPointer Instruction pointer to use if resuming to45 same execution mode as SMM.46 47 @retval 0 This function did modify the SMRAM save state.48 @retval > 0 The original instruction pointer value from the SMRAM save state49 before it was replaced.50 **/51 UINT6452 EFIAPI53 SmmCpuFeaturesHookReturnFromSmm (54 IN UINTN CpuIndex,55 IN SMRAM_SAVE_STATE_MAP *CpuState,56 IN UINT64 NewInstructionPointer32,57 IN UINT64 NewInstructionPointer58 )59 {60 return 0;61 }62 19 63 20 /** … … 92 49 93 50 /** 94 Check to see if an SMM register is supported by a specified CPU.95 96 @param[in] CpuIndex The index of the CPU to check for SMM register support.97 The value must be between 0 and the NumberOfCpus field98 in the System Management System Table (SMST).99 @param[in] RegName Identifies the SMM register to check for support.100 101 @retval TRUE The SMM register specified by RegName is supported by the CPU102 specified by CpuIndex.103 @retval FALSE The SMM register specified by RegName is not supported by the104 CPU specified by CpuIndex.105 **/106 BOOLEAN107 EFIAPI108 SmmCpuFeaturesIsSmmRegisterSupported (109 IN UINTN CpuIndex,110 IN SMM_REG_NAME RegName111 )112 {113 if (FeaturePcdGet (PcdSmmFeatureControlEnable) && (RegName == SmmRegFeatureControl)) {114 return TRUE;115 }116 117 return FALSE;118 }119 120 /**121 Read an SMM Save State register on the target processor. If this function122 returns EFI_UNSUPPORTED, then the caller is responsible for reading the123 SMM Save Sate register.124 125 @param[in] CpuIndex The index of the CPU to read the SMM Save State. The126 value must be between 0 and the NumberOfCpus field in127 the System Management System Table (SMST).128 @param[in] Register The SMM Save State register to read.129 @param[in] Width The number of bytes to read from the CPU save state.130 @param[out] Buffer Upon return, this holds the CPU register value read131 from the save state.132 133 @retval EFI_SUCCESS The register was read from Save State.134 @retval EFI_INVALID_PARAMETER Buffer is NULL.135 @retval EFI_UNSUPPORTED This function does not support reading Register.136 137 **/138 EFI_STATUS139 EFIAPI140 SmmCpuFeaturesReadSaveStateRegister (141 IN UINTN CpuIndex,142 IN EFI_SMM_SAVE_STATE_REGISTER Register,143 IN UINTN Width,144 OUT VOID *Buffer145 )146 {147 return EFI_UNSUPPORTED;148 }149 150 /**151 Writes an SMM Save State register on the target processor. If this function152 returns EFI_UNSUPPORTED, then the caller is responsible for writing the153 SMM Save Sate register.154 155 @param[in] CpuIndex The index of the CPU to write the SMM Save State. The156 value must be between 0 and the NumberOfCpus field in157 the System Management System Table (SMST).158 @param[in] Register The SMM Save State register to write.159 @param[in] Width The number of bytes to write to the CPU save state.160 @param[in] Buffer Upon entry, this holds the new CPU register value.161 162 @retval EFI_SUCCESS The register was written to Save State.163 @retval EFI_INVALID_PARAMETER Buffer is NULL.164 @retval EFI_UNSUPPORTED This function does not support writing Register.165 **/166 EFI_STATUS167 EFIAPI168 SmmCpuFeaturesWriteSaveStateRegister (169 IN UINTN CpuIndex,170 IN EFI_SMM_SAVE_STATE_REGISTER Register,171 IN UINTN Width,172 IN CONST VOID *Buffer173 )174 {175 return EFI_UNSUPPORTED;176 }177 178 /**179 51 This function is hook point called after the gEfiSmmReadyToLockProtocolGuid 180 52 notification is completely processed. -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
r99404 r101291 3 3 # is included. 4 4 # 5 # Copyright (c) 2009 - 20 18, Intel Corporation. All rights reserved.<BR>5 # Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 6 6 # SPDX-License-Identifier: BSD-2-Clause-Patent 7 7 # … … 65 65 gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable 66 66 gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable 67 gSmmBaseHobGuid ## CONSUMES 67 68 68 69 [Pcd] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
r99404 r101291 2 2 SMM STM support functions 3 3 4 Copyright (c) 2015 - 20 18, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 9 9 #include <PiMm.h> 10 10 #include <Library/BaseMemoryLib.h> 11 #include <Library/HobLib.h>12 11 #include <Library/UefiBootServicesTableLib.h> 13 12 #include <Library/SmmServicesTableLib.h> -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
r99404 r101291 2 2 # Standalone MM CPU specific programming. 3 3 # 4 # Copyright (c) 2009 - 20 16, Intel Corporation. All rights reserved.<BR>4 # Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 # Copyright (c) Microsoft Corporation.<BR> 6 6 # SPDX-License-Identifier: BSD-2-Clause-Patent … … 35 35 MemoryAllocationLib 36 36 PcdLib 37 HobLib 38 39 [Guids] 40 gSmmBaseHobGuid ## CONSUMES 37 41 38 42 [FixedPcd] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c
r99404 r101291 239 239 ); 240 240 } else { 241 DEBUG ((DEBUG_ERROR, "ERROR: TpmMeasureAndLogData failed with status % a!\n", Status));241 DEBUG ((DEBUG_ERROR, "ERROR: TpmMeasureAndLogData failed with status %r!\n", Status)); 242 242 } 243 243 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
r99404 r101291 2 2 Code for Processor S3 restoration 3 3 4 Copyright (c) 2006 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 824 824 } 825 825 826 // 827 // Restore SMBASE for BSP and all APs 828 // 829 SmmRelocateBases (); 826 DEBUG ((DEBUG_INFO, "SmmRestoreCpu: mSmmRelocated is %d\n", mSmmRelocated)); 827 828 // 829 // Check whether Smm Relocation is done or not. 830 // If not, will do the SmmBases Relocation here!!! 831 // 832 if (!mSmmRelocated) { 833 // 834 // Restore SMBASE for BSP and all APs 835 // 836 SmmRelocateBases (); 837 } else { 838 // 839 // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. 840 // 841 ExecuteFirstSmiInit (); 842 } 830 843 831 844 // … … 920 933 DEBUG_ERROR, 921 934 "ERROR:%a(): HOB(gEfiAcpiVariableGuid=%g) needed by S3 resume doesn't exist!\n", 922 __ FUNCTION__,935 __func__, 923 936 &gEfiAcpiVariableGuid 924 937 )); -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/CpuService.c
r99404 r101291 2 2 Implementation of SMM CPU Services Protocol. 3 3 4 Copyright (c) 2011 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 422 422 } 423 423 424 // 425 // There are some APs outside SMM, Wait for all avaiable APs to arrive. 426 // 427 SmmWaitForApArrival (); 428 Status = mSmmMpSyncData->AllApArrivedWithException ? EFI_SUCCESS : EFI_TIMEOUT; 424 if ((mSmmMpSyncData->EffectiveSyncMode != SmmCpuSyncModeTradition) && !SmmCpuFeaturesNeedConfigureMtrrs ()) { 425 // 426 // There are some APs outside SMM, Wait for all avaiable APs to arrive. 427 // 428 SmmWaitForApArrival (); 429 Status = mSmmMpSyncData->AllApArrivedWithException ? EFI_SUCCESS : EFI_TIMEOUT; 430 } else { 431 // 432 // BSP has already waitted for APs to arrive SMM if SmmCpuSyncMode selected or need config MTRR. 433 // 434 Status = EFI_TIMEOUT; 435 } 429 436 430 437 ON_EXIT: -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
r99404 r101291 2 2 Page table manipulation functions for IA-32 processors 3 3 4 Copyright (c) 2009 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> 6 6 … … 32 32 33 33 mPhysicalAddressBits = 32; 34 mPagingMode = PagingPae; 34 35 35 36 if (FeaturePcdGet (PcdCpuSmmProfileEnable) || … … 63 64 } 64 65 65 return Gen 4GPageTable (TRUE);66 return GenSmmPageTable (PagingPae, mPhysicalAddressBits); 66 67 } 67 68 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
r99404 r101291 2 2 SMM CPU misc functions for Ia32 arch specific. 3 3 4 Copyright (c) 2015 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 15 15 16 16 extern BOOLEAN mCetSupported; 17 extern UINTN mSmmShadowStackSize;18 17 19 18 X86_ASSEMBLY_PATCH_LABEL mPatchCetPl0Ssp; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c
r99404 r101291 19 19 ) 20 20 { 21 mSmmS3ResumeState->SmmS3Cr3 = Gen 4GPageTable (TRUE);21 mSmmS3ResumeState->SmmS3Cr3 = GenSmmPageTable (PagingPae, mPhysicalAddressBits); 22 22 23 23 return; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
r99404 r101291 2 2 SMM MP service implementation 3 3 4 Copyright (c) 2009 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> 6 6 … … 30 30 UINT32 *mPackageFirstThreadIndex = NULL; 31 31 32 extern UINTN mSmmShadowStackSize;33 34 32 /** 35 33 Performs an atomic compare exchange operation to get semaphore. … … 351 349 UINT32 DelayedCount; 352 350 UINT32 BlockedCount; 351 352 PERF_FUNCTION_BEGIN (); 353 353 354 354 DelayedCount = 0; … … 440 440 } 441 441 442 return;442 PERF_FUNCTION_END (); 443 443 } 444 444 … … 578 578 ApCount = 0; 579 579 580 PERF_FUNCTION_BEGIN (); 581 580 582 // 581 583 // Flag BSP's presence … … 776 778 777 779 // 780 // At this point, all APs should have exited from APHandler(). 781 // Migrate the SMM MP performance logging to standard SMM performance logging. 782 // Any SMM MP performance logging after this point will be migrated in next SMI. 783 // 784 PERF_CODE ( 785 MigrateMpPerf (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus, CpuIndex); 786 ); 787 788 // 778 789 // Reset the tokens buffer. 779 790 // … … 793 804 *mSmmMpSyncData->AllCpusInSync = FALSE; 794 805 mSmmMpSyncData->AllApArrivedWithException = FALSE; 806 807 PERF_FUNCTION_END (); 795 808 } 796 809 … … 1000 1013 // 1001 1014 ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run); 1002 }1003 1004 /**1005 Create 4G PageTable in SMRAM.1006 1007 @param[in] Is32BitPageTable Whether the page table is 32-bit PAE1008 @return PageTable Address1009 1010 **/1011 UINT321012 Gen4GPageTable (1013 IN BOOLEAN Is32BitPageTable1014 )1015 {1016 VOID *PageTable;1017 UINTN Index;1018 UINT64 *Pte;1019 UINTN PagesNeeded;1020 UINTN Low2MBoundary;1021 UINTN High2MBoundary;1022 UINTN Pages;1023 UINTN GuardPage;1024 UINT64 *Pdpte;1025 UINTN PageIndex;1026 UINTN PageAddress;1027 1028 Low2MBoundary = 0;1029 High2MBoundary = 0;1030 PagesNeeded = 0;1031 if (FeaturePcdGet (PcdCpuSmmStackGuard)) {1032 //1033 // Add one more page for known good stack, then find the lower 2MB aligned address.1034 //1035 Low2MBoundary = (mSmmStackArrayBase + EFI_PAGE_SIZE) & ~(SIZE_2MB-1);1036 //1037 // Add two more pages for known good stack and stack guard page,1038 // then find the lower 2MB aligned address.1039 //1040 High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize - mSmmShadowStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1);1041 PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1;1042 }1043 1044 //1045 // Allocate the page table1046 //1047 PageTable = AllocatePageTableMemory (5 + PagesNeeded);1048 ASSERT (PageTable != NULL);1049 1050 PageTable = (VOID *)((UINTN)PageTable);1051 Pte = (UINT64 *)PageTable;1052 1053 //1054 // Zero out all page table entries first1055 //1056 ZeroMem (Pte, EFI_PAGES_TO_SIZE (1));1057 1058 //1059 // Set Page Directory Pointers1060 //1061 for (Index = 0; Index < 4; Index++) {1062 Pte[Index] = ((UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1)) | mAddressEncMask |1063 (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS);1064 }1065 1066 Pte += EFI_PAGE_SIZE / sizeof (*Pte);1067 1068 //1069 // Fill in Page Directory Entries1070 //1071 for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) {1072 Pte[Index] = (Index << 21) | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;1073 }1074 1075 Pdpte = (UINT64 *)PageTable;1076 if (FeaturePcdGet (PcdCpuSmmStackGuard)) {1077 Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5);1078 GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE;1079 for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {1080 Pte = (UINT64 *)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));1081 Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS;1082 //1083 // Fill in Page Table Entries1084 //1085 Pte = (UINT64 *)Pages;1086 PageAddress = PageIndex;1087 for (Index = 0; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {1088 if (PageAddress == GuardPage) {1089 //1090 // Mark the guard page as non-present1091 //1092 Pte[Index] = PageAddress | mAddressEncMask;1093 GuardPage += (mSmmStackSize + mSmmShadowStackSize);1094 if (GuardPage > mSmmStackArrayEnd) {1095 GuardPage = 0;1096 }1097 } else {1098 Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS;1099 }1100 1101 PageAddress += EFI_PAGE_SIZE;1102 }1103 1104 Pages += EFI_PAGE_SIZE;1105 }1106 }1107 1108 if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) {1109 Pte = (UINT64 *)(UINTN)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));1110 if ((Pte[0] & IA32_PG_PS) == 0) {1111 // 4K-page entries are already mapped. Just hide the first one anyway.1112 Pte = (UINT64 *)(UINTN)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));1113 Pte[0] &= ~(UINT64)IA32_PG_P; // Hide page 01114 } else {1115 // Create 4K-page entries1116 Pages = (UINTN)AllocatePageTableMemory (1);1117 ASSERT (Pages != 0);1118 1119 Pte[0] = (UINT64)(Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS);1120 1121 Pte = (UINT64 *)Pages;1122 PageAddress = 0;1123 Pte[0] = PageAddress | mAddressEncMask; // Hide page 0 but present left1124 for (Index = 1; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {1125 PageAddress += EFI_PAGE_SIZE;1126 Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS;1127 }1128 }1129 }1130 1131 return (UINT32)(UINTN)PageTable;1132 1015 } 1133 1016 … … 1724 1607 ASSERT (CpuIndex < mMaxNumberOfCpus); 1725 1608 1609 if (mSmmRelocated) { 1610 ASSERT (mSmmInitialized != NULL); 1611 } 1612 1726 1613 // 1727 1614 // Save Cr2 because Page Fault exception in SMM may override its value, … … 1731 1618 SaveCr2 (&Cr2); 1732 1619 1620 if (mSmmRelocated && !mSmmInitialized[CpuIndex]) { 1621 // 1622 // Perform SmmInitHandler for CpuIndex 1623 // 1624 SmmInitHandler (); 1625 1626 // 1627 // Restore Cr2 1628 // 1629 RestoreCr2 (Cr2); 1630 1631 // 1632 // Mark the first SMI init for CpuIndex has been done so as to avoid the reentry. 1633 // 1634 mSmmInitialized[CpuIndex] = TRUE; 1635 1636 return; 1637 } 1638 1733 1639 // 1734 1640 // Call the user register Startup function first. … … 1741 1647 // Perform CPU specific entry hooks 1742 1648 // 1649 PERF_CODE ( 1650 MpPerfBegin (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousEntry)); 1651 ); 1743 1652 SmmCpuFeaturesRendezvousEntry (CpuIndex); 1653 PERF_CODE ( 1654 MpPerfEnd (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousEntry)); 1655 ); 1744 1656 1745 1657 // 1746 1658 // Determine if this is a valid SMI 1747 1659 // 1660 PERF_CODE ( 1661 MpPerfBegin (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (PlatformValidSmi)); 1662 ); 1748 1663 ValidSmi = PlatformValidSmi (); 1664 PERF_CODE ( 1665 MpPerfEnd (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (PlatformValidSmi)); 1666 ); 1749 1667 1750 1668 // … … 1876 1794 1877 1795 Exit: 1796 // 1797 // Note: SmmRendezvousExit perf-logging entry is the only one that will be 1798 // migrated to standard perf-logging database in next SMI by BSPHandler(). 1799 // Hence, the number of SmmRendezvousEntry entries will be larger than 1800 // the number of SmmRendezvousExit entries. Delta equals to the number 1801 // of CPU threads. 1802 // 1803 PERF_CODE ( 1804 MpPerfBegin (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousExit)); 1805 ); 1878 1806 SmmCpuFeaturesRendezvousExit (CpuIndex); 1807 PERF_CODE ( 1808 MpPerfEnd (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousExit)); 1809 ); 1879 1810 1880 1811 // -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
r99404 r101291 2 2 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU. 3 3 4 Copyright (c) 2009 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> 6 Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> 6 7 7 8 SPDX-License-Identifier: BSD-2-Clause-Patent … … 60 61 // 61 62 volatile BOOLEAN *mRebased; 62 volatile BOOLEAN mIsBsp;63 63 64 64 /// … … 85 85 86 86 EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER]; 87 88 BOOLEAN mSmmRelocated = FALSE; 89 volatile BOOLEAN *mSmmInitialized = NULL; 90 UINT32 mBspApicId = 0; 87 91 88 92 // … … 274 278 } 275 279 276 Status = SmmCpuFeaturesReadSaveStateRegister (CpuIndex, Register, Width, Buffer); 277 if (Status == EFI_UNSUPPORTED) { 278 Status = ReadSaveStateRegister (CpuIndex, Register, Width, Buffer); 279 } 280 Status = MmSaveStateReadRegister (CpuIndex, Register, Width, Buffer); 280 281 281 282 return Status; … … 326 327 } 327 328 328 Status = SmmCpuFeaturesWriteSaveStateRegister (CpuIndex, Register, Width, Buffer); 329 if (Status == EFI_UNSUPPORTED) { 330 Status = WriteSaveStateRegister (CpuIndex, Register, Width, Buffer); 331 } 329 Status = MmSaveStateWriteRegister (CpuIndex, Register, Width, Buffer); 332 330 333 331 return Status; … … 344 342 ) 345 343 { 346 UINT32 ApicId; 347 UINTN Index; 344 UINT32 ApicId; 345 UINTN Index; 346 BOOLEAN IsBsp; 348 347 349 348 // … … 353 352 ApicId = GetApicId (); 354 353 354 IsBsp = (BOOLEAN)(mBspApicId == ApicId); 355 355 356 ASSERT (mNumberOfCpus <= mMaxNumberOfCpus); 356 357 357 358 for (Index = 0; Index < mNumberOfCpus; Index++) { 358 359 if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) { 360 PERF_CODE ( 361 MpPerfBegin (Index, SMM_MP_PERF_PROCEDURE_ID (SmmInitHandler)); 362 ); 359 363 // 360 364 // Initialize SMM specific features on the currently executing CPU … … 362 366 SmmCpuFeaturesInitializeProcessor ( 363 367 Index, 364 mIsBsp,368 IsBsp, 365 369 gSmmCpuPrivate->ProcessorInfo, 366 370 &mCpuHotPlugData … … 372 376 // 373 377 CheckFeatureSupported (); 374 } 375 376 if (mIsBsp) { 378 } else if (IsBsp) { 377 379 // 378 380 // BSP rebase is already done above. … … 382 384 } 383 385 384 // 385 // Hook return after RSM to set SMM re-based flag 386 // 387 SemaphoreHook (Index, &mRebased[Index]); 386 if (!mSmmRelocated) { 387 // 388 // Hook return after RSM to set SMM re-based flag 389 // 390 SemaphoreHook (Index, &mRebased[Index]); 391 } 392 393 PERF_CODE ( 394 MpPerfEnd (Index, SMM_MP_PERF_PROCEDURE_ID (SmmInitHandler)); 395 ); 388 396 389 397 return; … … 392 400 393 401 ASSERT (FALSE); 402 } 403 404 /** 405 Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. 406 407 **/ 408 VOID 409 ExecuteFirstSmiInit ( 410 VOID 411 ) 412 { 413 UINTN Index; 414 415 PERF_FUNCTION_BEGIN (); 416 417 if (mSmmInitialized == NULL) { 418 mSmmInitialized = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * mMaxNumberOfCpus); 419 } 420 421 ASSERT (mSmmInitialized != NULL); 422 if (mSmmInitialized == NULL) { 423 PERF_FUNCTION_END (); 424 return; 425 } 426 427 // 428 // Reset the mSmmInitialized to false. 429 // 430 ZeroMem ((VOID *)mSmmInitialized, sizeof (BOOLEAN) * mMaxNumberOfCpus); 431 432 // 433 // Get the BSP ApicId. 434 // 435 mBspApicId = GetApicId (); 436 437 // 438 // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for SMM init 439 // 440 SendSmiIpi (mBspApicId); 441 SendSmiIpiAllExcludingSelf (); 442 443 // 444 // Wait for all processors to finish its 1st SMI 445 // 446 for (Index = 0; Index < mNumberOfCpus; Index++) { 447 while (!(BOOLEAN)mSmmInitialized[Index]) { 448 } 449 } 450 451 PERF_FUNCTION_END (); 394 452 } 395 453 … … 410 468 SMRAM_SAVE_STATE_MAP *CpuStatePtr; 411 469 UINT8 *U8Ptr; 412 UINT32 ApicId;413 470 UINTN Index; 414 471 UINTN BspIndex; 472 473 PERF_FUNCTION_BEGIN (); 415 474 416 475 // … … 451 510 // Retrieve the local APIC ID of current processor 452 511 // 453 ApicId = GetApicId ();512 mBspApicId = GetApicId (); 454 513 455 514 // … … 457 516 // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate 458 517 // 459 mIsBsp = FALSE;460 518 BspIndex = (UINTN)-1; 461 519 for (Index = 0; Index < mNumberOfCpus; Index++) { 462 520 mRebased[Index] = FALSE; 463 if ( ApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {521 if (mBspApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) { 464 522 SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId); 465 523 // … … 480 538 // 481 539 ASSERT (BspIndex != (UINTN)-1); 482 mIsBsp = TRUE; 483 SendSmiIpi (ApicId); 540 SendSmiIpi (mBspApicId); 484 541 // 485 542 // Wait for the BSP to finish its 1st SMI … … 493 550 CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2)); 494 551 CopyMem (U8Ptr, BakBuf, sizeof (BakBuf)); 552 PERF_FUNCTION_END (); 495 553 } 496 554 … … 564 622 UINTN ModelId; 565 623 UINT32 Cr3; 624 EFI_HOB_GUID_TYPE *GuidHob; 625 SMM_BASE_HOB_DATA *SmmBaseHobData; 626 627 GuidHob = NULL; 628 SmmBaseHobData = NULL; 629 630 PERF_FUNCTION_BEGIN (); 566 631 567 632 // … … 636 701 637 702 gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus = mMaxNumberOfCpus; 703 704 PERF_CODE ( 705 InitializeMpPerf (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus); 706 ); 638 707 639 708 // … … 792 861 793 862 // 794 // Allocate buffer for all of the tiles. 795 // 796 // Intel(R) 64 and IA-32 Architectures Software Developer's Manual 797 // Volume 3C, Section 34.11 SMBASE Relocation 798 // For Pentium and Intel486 processors, the SMBASE values must be 799 // aligned on a 32-KByte boundary or the processor will enter shutdown 800 // state during the execution of a RSM instruction. 801 // 802 // Intel486 processors: FamilyId is 4 803 // Pentium processors : FamilyId is 5 804 // 805 BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)); 806 if ((FamilyId == 4) || (FamilyId == 5)) { 807 Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB); 863 // Retrive the allocated SmmBase from gSmmBaseHobGuid. If found, 864 // means the SmBase relocation has been done. 865 // 866 GuidHob = GetFirstGuidHob (&gSmmBaseHobGuid); 867 if (GuidHob != NULL) { 868 // 869 // Check whether the Required TileSize is enough. 870 // 871 if (TileSize > SIZE_8KB) { 872 DEBUG ((DEBUG_ERROR, "The Range of Smbase in SMRAM is not enough -- Required TileSize = 0x%08x, Actual TileSize = 0x%08x\n", TileSize, SIZE_8KB)); 873 CpuDeadLoop (); 874 return RETURN_BUFFER_TOO_SMALL; 875 } 876 877 SmmBaseHobData = GET_GUID_HOB_DATA (GuidHob); 878 879 // 880 // Assume single instance of HOB produced, expect the HOB.NumberOfProcessors equals to the mMaxNumberOfCpus. 881 // 882 ASSERT (SmmBaseHobData->NumberOfProcessors == (UINT32)mMaxNumberOfCpus && SmmBaseHobData->ProcessorIndex == 0); 883 mSmmRelocated = TRUE; 808 884 } else { 809 Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB); 810 } 811 812 ASSERT (Buffer != NULL); 813 DEBUG ((DEBUG_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages))); 885 // 886 // When the HOB doesn't exist, allocate new SMBASE itself. 887 // 888 DEBUG ((DEBUG_INFO, "PiCpuSmmEntry: gSmmBaseHobGuid not found!\n")); 889 // 890 // very old processors (i486 + pentium) need 32k not 4k alignment, exclude them. 891 // 892 ASSERT (FamilyId >= 6); 893 // 894 // Allocate buffer for all of the tiles. 895 // 896 BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)); 897 Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB); 898 if (Buffer == NULL) { 899 DEBUG ((DEBUG_ERROR, "Failed to allocate %Lu pages.\n", (UINT64)BufferPages)); 900 CpuDeadLoop (); 901 return EFI_OUT_OF_RESOURCES; 902 } 903 904 ASSERT (Buffer != NULL); 905 DEBUG ((DEBUG_INFO, "New Allcoated SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages))); 906 } 814 907 815 908 // … … 846 939 // 847 940 for (Index = 0; Index < mMaxNumberOfCpus; Index++) { 848 mCpuHotPlugData.SmBase[Index] = (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET; 941 mCpuHotPlugData.SmBase[Index] = mSmmRelocated ? (UINTN)SmmBaseHobData->SmBase[Index] : (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET; 942 849 943 gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof (SMRAM_SAVE_STATE_MAP); 850 944 gSmmCpuPrivate->CpuSaveState[Index] = (VOID *)(mCpuHotPlugData.SmBase[Index] + SMRAM_SAVE_STATE_MAP_OFFSET); … … 852 946 853 947 if (Index < mNumberOfCpus) { 854 Status = MpServices->GetProcessorInfo (MpServices, Index , &gSmmCpuPrivate->ProcessorInfo[Index]);948 Status = MpServices->GetProcessorInfo (MpServices, Index | CPU_V2_EXTENDED_TOPOLOGY, &gSmmCpuPrivate->ProcessorInfo[Index]); 855 949 ASSERT_EFI_ERROR (Status); 856 950 mCpuHotPlugData.ApicId[Index] = gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId; … … 959 1053 960 1054 // 961 // Relocate SMM Base addresses to the ones allocated from SMRAM 962 // 963 mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus); 964 ASSERT (mRebased != NULL); 965 SmmRelocateBases (); 966 967 // 968 // Call hook for BSP to perform extra actions in normal mode after all 969 // SMM base addresses have been relocated on all CPUs 970 // 971 SmmCpuFeaturesSmmRelocationComplete (); 1055 // Check whether Smm Relocation is done or not. 1056 // If not, will do the SmmBases Relocation here!!! 1057 // 1058 if (!mSmmRelocated) { 1059 // 1060 // Relocate SMM Base addresses to the ones allocated from SMRAM 1061 // 1062 mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus); 1063 ASSERT (mRebased != NULL); 1064 SmmRelocateBases (); 1065 1066 // 1067 // Call hook for BSP to perform extra actions in normal mode after all 1068 // SMM base addresses have been relocated on all CPUs 1069 // 1070 SmmCpuFeaturesSmmRelocationComplete (); 1071 } 972 1072 973 1073 DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported)); … … 991 1091 ); 992 1092 if (FeaturePcdGet (PcdCpuSmmStackGuard)) { 993 SetNotPresentPage(1093 ConvertMemoryPageAttributes ( 994 1094 Cr3, 1095 mPagingMode, 995 1096 (EFI_PHYSICAL_ADDRESS)(UINTN)Stacks + mSmmStackSize + EFI_PAGES_TO_SIZE (1) + (mSmmStackSize + mSmmShadowStackSize) * Index, 996 EFI_PAGES_TO_SIZE (1) 1097 EFI_PAGES_TO_SIZE (1), 1098 EFI_MEMORY_RP, 1099 TRUE, 1100 NULL 997 1101 ); 998 1102 } 999 1103 } 1104 } 1105 1106 // 1107 // For relocated SMBASE, some MSRs & CSRs are still required to be configured in SMM Mode for SMM Initialization. 1108 // Those MSRs & CSRs must be configured before normal SMI sources happen. 1109 // So, here is to issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. 1110 // 1111 if (mSmmRelocated) { 1112 ExecuteFirstSmiInit (); 1113 1114 // 1115 // Call hook for BSP to perform extra actions in normal mode after all 1116 // SMM base addresses have been relocated on all CPUs 1117 // 1118 SmmCpuFeaturesSmmRelocationComplete (); 1000 1119 } 1001 1120 … … 1096 1215 DEBUG ((DEBUG_INFO, "SMM CPU Module exit from SMRAM with EFI_SUCCESS\n")); 1097 1216 1217 PERF_FUNCTION_END (); 1098 1218 return EFI_SUCCESS; 1219 } 1220 1221 /** 1222 Function to compare 2 EFI_SMRAM_DESCRIPTOR based on CpuStart. 1223 1224 @param[in] Buffer1 pointer to Device Path poiner to compare 1225 @param[in] Buffer2 pointer to second DevicePath pointer to compare 1226 1227 @retval 0 Buffer1 equal to Buffer2 1228 @retval <0 Buffer1 is less than Buffer2 1229 @retval >0 Buffer1 is greater than Buffer2 1230 **/ 1231 INTN 1232 EFIAPI 1233 CpuSmramRangeCompare ( 1234 IN CONST VOID *Buffer1, 1235 IN CONST VOID *Buffer2 1236 ) 1237 { 1238 if (((EFI_SMRAM_DESCRIPTOR *)Buffer1)->CpuStart > ((EFI_SMRAM_DESCRIPTOR *)Buffer2)->CpuStart) { 1239 return 1; 1240 } else if (((EFI_SMRAM_DESCRIPTOR *)Buffer1)->CpuStart < ((EFI_SMRAM_DESCRIPTOR *)Buffer2)->CpuStart) { 1241 return -1; 1242 } 1243 1244 return 0; 1099 1245 } 1100 1246 … … 1120 1266 UINT64 MaxSize; 1121 1267 BOOLEAN Found; 1268 EFI_SMRAM_DESCRIPTOR SmramDescriptor; 1122 1269 1123 1270 // … … 1141 1288 1142 1289 mSmmCpuSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); 1290 1291 // 1292 // Sort the mSmmCpuSmramRanges 1293 // 1294 QuickSort (mSmmCpuSmramRanges, mSmmCpuSmramRangeCount, sizeof (EFI_SMRAM_DESCRIPTOR), (BASE_SORT_COMPARE)CpuSmramRangeCompare, &SmramDescriptor); 1143 1295 1144 1296 // … … 1250 1402 EFI_STATUS Status; 1251 1403 1404 PERF_FUNCTION_BEGIN (); 1405 1252 1406 // 1253 1407 // Check to see if the Feature Control MSR is supported on this CPU … … 1256 1410 if (!SmmCpuFeaturesIsSmmRegisterSupported (Index, SmmRegFeatureControl)) { 1257 1411 mSmmCodeAccessCheckEnable = FALSE; 1412 PERF_FUNCTION_END (); 1258 1413 return; 1259 1414 } … … 1265 1420 if ((AsmReadMsr64 (EFI_MSR_SMM_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) == 0) { 1266 1421 mSmmCodeAccessCheckEnable = FALSE; 1422 PERF_FUNCTION_END (); 1267 1423 return; 1268 1424 } … … 1321 1477 } 1322 1478 } 1479 1480 PERF_FUNCTION_END (); 1323 1481 } 1324 1482 … … 1442 1600 { 1443 1601 if (mSmmReadyToLock) { 1602 PERF_FUNCTION_BEGIN (); 1603 1604 // 1605 // Check if all Aps enter SMM. In Relaxed-AP Sync Mode, BSP will not wait for 1606 // all Aps arrive. However,PerformRemainingTasks() needs to wait all Aps arrive before calling 1607 // SetMemMapAttributes() and ConfigSmmCodeAccessCheck() when mSmmReadyToLock 1608 // is true. In SetMemMapAttributes(), SmmSetMemoryAttributesEx() will call 1609 // FlushTlbForAll() that need to start up the aps. So it need to let all 1610 // aps arrive. Same as SetMemMapAttributes(), ConfigSmmCodeAccessCheck() 1611 // also will start up the aps. 1612 // 1613 if (EFI_ERROR (SmmCpuRendezvous (NULL, TRUE))) { 1614 DEBUG ((DEBUG_ERROR, "PerformRemainingTasks: fail to wait for all AP check in SMM!\n")); 1615 } 1616 1444 1617 // 1445 1618 // Start SMM Profile feature … … 1476 1649 ConfigSmmCodeAccessCheck (); 1477 1650 1651 // 1652 // Measure performance of SmmCpuFeaturesCompleteSmmReadyToLock() from caller side 1653 // as the implementation is provided by platform. 1654 // 1655 PERF_START (NULL, "SmmCompleteReadyToLock", NULL, 0); 1478 1656 SmmCpuFeaturesCompleteSmmReadyToLock (); 1657 PERF_END (NULL, "SmmCompleteReadyToLock", NULL, 0); 1479 1658 1480 1659 // … … 1482 1661 // 1483 1662 mSmmReadyToLock = FALSE; 1663 1664 PERF_FUNCTION_END (); 1484 1665 } 1485 1666 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
r99404 r101291 2 2 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU. 3 3 4 Copyright (c) 2009 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> 6 Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> 6 7 7 8 SPDX-License-Identifier: BSD-2-Clause-Patent … … 26 27 #include <Guid/MemoryAttributesTable.h> 27 28 #include <Guid/PiSmmMemoryAttributesTable.h> 29 #include <Guid/SmmBaseHob.h> 28 30 29 31 #include <Library/BaseLib.h> … … 45 47 #include <Library/LocalApicLib.h> 46 48 #include <Library/CpuLib.h> 47 #include <Library/UefiCpuLib.h>48 49 #include <Library/CpuExceptionHandlerLib.h> 49 50 #include <Library/ReportStatusCodeLib.h> … … 51 52 #include <Library/PeCoffGetEntryPointLib.h> 52 53 #include <Library/RegisterCpuFeaturesLib.h> 54 #include <Library/PerformanceLib.h> 55 #include <Library/CpuPageTableLib.h> 56 #include <Library/MmSaveStateLib.h> 53 57 54 58 #include <AcpiCpuData.h> … … 60 64 #include "CpuService.h" 61 65 #include "SmmProfile.h" 66 #include "SmmMpPerf.h" 62 67 63 68 // … … 261 266 extern EFI_MM_MP_PROTOCOL mSmmMp; 262 267 extern BOOLEAN m5LevelPagingNeeded; 268 extern PAGING_MODE mPagingMode; 269 extern UINTN mSmmShadowStackSize; 263 270 264 271 /// … … 350 357 351 358 /** 352 Read a CPU Save State register on the target processor. 353 354 This function abstracts the differences that whether the CPU Save State register is in the 355 IA32 CPU Save State Map or X64 CPU Save State Map. 356 357 This function supports reading a CPU Save State register in SMBase relocation handler. 358 359 @param[in] CpuIndex Specifies the zero-based index of the CPU save state. 360 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table. 361 @param[in] Width The number of bytes to read from the CPU save state. 362 @param[out] Buffer Upon return, this holds the CPU register value read from the save state. 363 364 @retval EFI_SUCCESS The register was read from Save State. 365 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor. 366 @retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type. 367 368 **/ 369 EFI_STATUS 370 EFIAPI 371 ReadSaveStateRegister ( 372 IN UINTN CpuIndex, 373 IN EFI_SMM_SAVE_STATE_REGISTER Register, 374 IN UINTN Width, 375 OUT VOID *Buffer 376 ); 377 378 /** 379 Write value to a CPU Save State register on the target processor. 380 381 This function abstracts the differences that whether the CPU Save State register is in the 382 IA32 CPU Save State Map or X64 CPU Save State Map. 383 384 This function supports writing a CPU Save State register in SMBase relocation handler. 385 386 @param[in] CpuIndex Specifies the zero-based index of the CPU save state. 387 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table. 388 @param[in] Width The number of bytes to read from the CPU save state. 389 @param[in] Buffer Upon entry, this holds the new CPU register value. 390 391 @retval EFI_SUCCESS The register was written to Save State. 392 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor. 393 @retval EFI_INVALID_PARAMETER ProcessorIndex or Width is not correct. 394 395 **/ 396 EFI_STATUS 397 EFIAPI 398 WriteSaveStateRegister ( 399 IN UINTN CpuIndex, 400 IN EFI_SMM_SAVE_STATE_REGISTER Register, 401 IN UINTN Width, 402 IN CONST VOID *Buffer 403 ); 359 C function for SMI handler. To change all processor's SMMBase Register. 360 361 **/ 362 VOID 363 EFIAPI 364 SmmInitHandler ( 365 VOID 366 ); 367 368 /** 369 Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. 370 371 **/ 372 VOID 373 ExecuteFirstSmiInit ( 374 VOID 375 ); 376 377 extern BOOLEAN mSmmRelocated; 378 extern volatile BOOLEAN *mSmmInitialized; 379 extern UINT32 mBspApicId; 404 380 405 381 extern CONST UINT8 gcSmmInitTemplate[]; … … 529 505 530 506 /** 507 Create page table based on input PagingMode and PhysicalAddressBits in smm. 508 509 @param[in] PagingMode The paging mode. 510 @param[in] PhysicalAddressBits The bits of physical address to map. 511 512 @retval PageTable Address 513 514 **/ 515 UINTN 516 GenSmmPageTable ( 517 IN PAGING_MODE PagingMode, 518 IN UINT8 PhysicalAddressBits 519 ); 520 521 /** 531 522 Initialize global data for MP synchronization. 532 523 … … 683 674 IN UINTN CpuIndex, 684 675 IN OUT VOID *ProcArguments OPTIONAL 676 ); 677 678 /** 679 This function modifies the page attributes for the memory region specified by BaseAddress and 680 Length from their current attributes to the attributes specified by Attributes. 681 682 Caller should make sure BaseAddress and Length is at page boundary. 683 684 @param[in] PageTableBase The page table base. 685 @param[in] BaseAddress The physical address that is the start address of a memory region. 686 @param[in] Length The size in bytes of the memory region. 687 @param[in] Attributes The bit mask of attributes to modify for the memory region. 688 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes. 689 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified. 690 691 @retval RETURN_SUCCESS The attributes were modified for the memory region. 692 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by 693 BaseAddress and Length cannot be modified. 694 @retval RETURN_INVALID_PARAMETER Length is zero. 695 Attributes specified an illegal combination of attributes that 696 cannot be set together. 697 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of 698 the memory resource range. 699 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory 700 resource range specified by BaseAddress and Length. 701 The bit mask of attributes is not support for the memory resource 702 range specified by BaseAddress and Length. 703 **/ 704 RETURN_STATUS 705 ConvertMemoryPageAttributes ( 706 IN UINTN PageTableBase, 707 IN PAGING_MODE PagingMode, 708 IN PHYSICAL_ADDRESS BaseAddress, 709 IN UINT64 Length, 710 IN UINT64 Attributes, 711 IN BOOLEAN IsSet, 712 OUT BOOLEAN *IsModified OPTIONAL 685 713 ); 686 714 … … 986 1014 987 1015 @param[in] PageTableBase The page table base. 988 @param[in] EnablePML5Paging If PML5 paging is enabled.1016 @param[in] PagingMode The paging mode. 989 1017 @param[in] BaseAddress The physical address that is the start address of a memory region. 990 1018 @param[in] Length The size in bytes of the memory region. 991 1019 @param[in] Attributes The bit mask of attributes to set for the memory region. 992 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.993 1020 994 1021 @retval EFI_SUCCESS The attributes were set for the memory region. … … 1008 1035 EFI_STATUS 1009 1036 SmmSetMemoryAttributesEx ( 1010 IN UINTN PageTableBase, 1011 IN BOOLEAN EnablePML5Paging, 1012 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1013 IN UINT64 Length, 1014 IN UINT64 Attributes, 1015 OUT BOOLEAN *IsSplitted OPTIONAL 1037 IN UINTN PageTableBase, 1038 IN PAGING_MODE PagingMode, 1039 IN PHYSICAL_ADDRESS BaseAddress, 1040 IN UINT64 Length, 1041 IN UINT64 Attributes 1016 1042 ); 1017 1043 … … 1021 1047 1022 1048 @param[in] PageTableBase The page table base. 1023 @param[in] EnablePML5Paging If PML5 paging is enabled.1049 @param[in] PagingMode The paging mode. 1024 1050 @param[in] BaseAddress The physical address that is the start address of a memory region. 1025 1051 @param[in] Length The size in bytes of the memory region. 1026 1052 @param[in] Attributes The bit mask of attributes to clear for the memory region. 1027 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.1028 1053 1029 1054 @retval EFI_SUCCESS The attributes were cleared for the memory region. … … 1032 1057 @retval EFI_INVALID_PARAMETER Length is zero. 1033 1058 Attributes specified an illegal combination of attributes that 1034 cannot be settogether.1059 cannot be cleared together. 1035 1060 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of 1036 1061 the memory resource range. 1037 1062 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory 1038 1063 resource range specified by BaseAddress and Length. 1039 The bit mask of attributes is not support for the memory resource1064 The bit mask of attributes is not supported for the memory resource 1040 1065 range specified by BaseAddress and Length. 1041 1066 … … 1044 1069 SmmClearMemoryAttributesEx ( 1045 1070 IN UINTN PageTableBase, 1046 IN BOOLEAN EnablePML5Paging,1071 IN PAGING_MODE PagingMode, 1047 1072 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1048 1073 IN UINT64 Length, 1049 IN UINT64 Attributes, 1050 OUT BOOLEAN *IsSplitted OPTIONAL 1074 IN UINT64 Attributes 1051 1075 ); 1052 1076 … … 1169 1193 EFI_STATUS 1170 1194 SetShadowStack ( 1171 IN UINTN Cr3,1172 IN EFI_PHYSICAL_ADDRESS BaseAddress,1173 IN UINT64 Length1174 );1175 1176 /**1177 Set not present memory.1178 1179 @param[in] Cr3 The page table base address.1180 @param[in] BaseAddress The physical address that is the start address of a memory region.1181 @param[in] Length The size in bytes of the memory region.1182 1183 @retval EFI_SUCCESS The not present memory is set.1184 **/1185 EFI_STATUS1186 SetNotPresentPage (1187 1195 IN UINTN Cr3, 1188 1196 IN EFI_PHYSICAL_ADDRESS BaseAddress, … … 1545 1553 ); 1546 1554 1555 /** 1556 Disable Write Protect on pages marked as read-only if Cr0.Bits.WP is 1. 1557 1558 @param[out] WpEnabled If Cr0.WP is enabled. 1559 @param[out] CetEnabled If CET is enabled. 1560 **/ 1561 VOID 1562 DisableReadOnlyPageWriteProtect ( 1563 OUT BOOLEAN *WpEnabled, 1564 OUT BOOLEAN *CetEnabled 1565 ); 1566 1567 /** 1568 Enable Write Protect on pages marked as read-only. 1569 1570 @param[out] WpEnabled If Cr0.WP should be enabled. 1571 @param[out] CetEnabled If CET should be enabled. 1572 **/ 1573 VOID 1574 EnableReadOnlyPageWriteProtect ( 1575 BOOLEAN WpEnabled, 1576 BOOLEAN CetEnabled 1577 ); 1578 1547 1579 #endif -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
r99404 r101291 5 5 # provides CPU specific services in SMM. 6 6 # 7 # Copyright (c) 2009 - 202 2, Intel Corporation. All rights reserved.<BR>7 # Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 8 8 # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> 9 # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> 9 10 # 10 11 # SPDX-License-Identifier: BSD-2-Clause-Patent … … 43 44 SmmMp.h 44 45 SmmMp.c 46 SmmMpPerf.h 47 SmmMpPerf.c 45 48 46 49 [Sources.Ia32] … … 90 93 PciLib 91 94 LocalApicLib 92 UefiCpuLib93 95 SmmCpuPlatformHookLib 94 96 CpuExceptionHandlerLib … … 99 101 SmmCpuFeaturesLib 100 102 PeCoffGetEntryPointLib 103 PerformanceLib 104 CpuPageTableLib 105 MmSaveStateLib 101 106 102 107 [Protocols] … … 115 120 gEdkiiPiSmmMemoryAttributesTableGuid ## CONSUMES ## SystemTable 116 121 gEfiMemoryAttributesTableGuid ## CONSUMES ## SystemTable 122 gSmmBaseHobGuid ## CONSUMES 117 123 118 124 [FeaturePcd] … … 126 132 gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock ## CONSUMES 127 133 gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES 134 gUefiCpuPkgTokenSpaceGuid.PcdSmmApPerfLogEnable ## CONSUMES 128 135 129 136 [Pcd] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
r99404 r101291 1 1 /** @file 2 2 3 Copyright (c) 2016 - 20 19, Intel Corporation. All rights reserved.<BR>3 Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR> 4 4 SPDX-License-Identifier: BSD-2-Clause-Patent 5 5 … … 27 27 EFI_MEMORY_ATTRIBUTES_TABLE *mUefiMemoryAttributesTable = NULL; 28 28 29 PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = { 30 { Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64 }, 31 { Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64 }, 32 { Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64 }, 33 }; 34 35 BOOLEAN mIsShadowStack = FALSE; 36 BOOLEAN m5LevelPagingNeeded = FALSE; 29 BOOLEAN mIsShadowStack = FALSE; 30 BOOLEAN m5LevelPagingNeeded = FALSE; 31 PAGING_MODE mPagingMode = PagingModeMax; 37 32 38 33 // … … 47 42 48 43 /** 44 Disable Write Protect on pages marked as read-only if Cr0.Bits.WP is 1. 45 46 @param[out] WpEnabled If Cr0.WP is enabled. 47 @param[out] CetEnabled If CET is enabled. 48 **/ 49 VOID 50 DisableReadOnlyPageWriteProtect ( 51 OUT BOOLEAN *WpEnabled, 52 OUT BOOLEAN *CetEnabled 53 ) 54 { 55 IA32_CR0 Cr0; 56 57 *CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE; 58 Cr0.UintN = AsmReadCr0 (); 59 *WpEnabled = (Cr0.Bits.WP != 0) ? TRUE : FALSE; 60 if (*WpEnabled) { 61 if (*CetEnabled) { 62 // 63 // CET must be disabled if WP is disabled. Disable CET before clearing CR0.WP. 64 // 65 DisableCet (); 66 } 67 68 Cr0.Bits.WP = 0; 69 AsmWriteCr0 (Cr0.UintN); 70 } 71 } 72 73 /** 74 Enable Write Protect on pages marked as read-only. 75 76 @param[out] WpEnabled If Cr0.WP should be enabled. 77 @param[out] CetEnabled If CET should be enabled. 78 **/ 79 VOID 80 EnableReadOnlyPageWriteProtect ( 81 BOOLEAN WpEnabled, 82 BOOLEAN CetEnabled 83 ) 84 { 85 IA32_CR0 Cr0; 86 87 if (WpEnabled) { 88 Cr0.UintN = AsmReadCr0 (); 89 Cr0.Bits.WP = 1; 90 AsmWriteCr0 (Cr0.UintN); 91 92 if (CetEnabled) { 93 // 94 // re-enable CET. 95 // 96 EnableCet (); 97 } 98 } 99 } 100 101 /** 49 102 Initialize a buffer pool for page table use only. 50 103 … … 68 121 ) 69 122 { 70 VOID *Buffer; 71 BOOLEAN CetEnabled; 72 BOOLEAN WpEnabled; 73 IA32_CR0 Cr0; 123 VOID *Buffer; 124 BOOLEAN WpEnabled; 125 BOOLEAN CetEnabled; 74 126 75 127 // … … 108 160 // 109 161 if (mIsReadOnlyPageTable) { 110 CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE; 111 Cr0.UintN = AsmReadCr0 (); 112 WpEnabled = (Cr0.Bits.WP != 0) ? TRUE : FALSE; 113 if (WpEnabled) { 114 if (CetEnabled) { 115 // 116 // CET must be disabled if WP is disabled. Disable CET before clearing CR0.WP. 117 // 118 DisableCet (); 119 } 120 121 Cr0.Bits.WP = 0; 122 AsmWriteCr0 (Cr0.UintN); 123 } 124 162 DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled); 125 163 SmmSetMemoryAttributes ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (PoolPages), EFI_MEMORY_RO); 126 if (WpEnabled) { 127 Cr0.UintN = AsmReadCr0 (); 128 Cr0.Bits.WP = 1; 129 AsmWriteCr0 (Cr0.UintN); 130 131 if (CetEnabled) { 132 // 133 // re-enable CET. 134 // 135 EnableCet (); 136 } 137 } 164 EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled); 138 165 } 139 166 … … 184 211 185 212 return Buffer; 186 }187 188 /**189 Return length according to page attributes.190 191 @param[in] PageAttributes The page attribute of the page entry.192 193 @return The length of page entry.194 **/195 UINTN196 PageAttributeToLength (197 IN PAGE_ATTRIBUTE PageAttribute198 )199 {200 UINTN Index;201 202 for (Index = 0; Index < sizeof (mPageAttributeTable)/sizeof (mPageAttributeTable[0]); Index++) {203 if (PageAttribute == mPageAttributeTable[Index].Attribute) {204 return (UINTN)mPageAttributeTable[Index].Length;205 }206 }207 208 return 0;209 }210 211 /**212 Return address mask according to page attributes.213 214 @param[in] PageAttributes The page attribute of the page entry.215 216 @return The address mask of page entry.217 **/218 UINTN219 PageAttributeToMask (220 IN PAGE_ATTRIBUTE PageAttribute221 )222 {223 UINTN Index;224 225 for (Index = 0; Index < sizeof (mPageAttributeTable)/sizeof (mPageAttributeTable[0]); Index++) {226 if (PageAttribute == mPageAttributeTable[Index].Attribute) {227 return (UINTN)mPageAttributeTable[Index].AddressMask;228 }229 }230 231 return 0;232 213 } 233 214 … … 355 336 356 337 /** 357 Modify memory attributes of page entry.358 359 @param[in] PageEntry The page entry.360 @param[in] Attributes The bit mask of attributes to modify for the memory region.361 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.362 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.363 **/364 VOID365 ConvertPageEntryAttribute (366 IN UINT64 *PageEntry,367 IN UINT64 Attributes,368 IN BOOLEAN IsSet,369 OUT BOOLEAN *IsModified370 )371 {372 UINT64 CurrentPageEntry;373 UINT64 NewPageEntry;374 375 CurrentPageEntry = *PageEntry;376 NewPageEntry = CurrentPageEntry;377 if ((Attributes & EFI_MEMORY_RP) != 0) {378 if (IsSet) {379 NewPageEntry &= ~(UINT64)IA32_PG_P;380 } else {381 NewPageEntry |= IA32_PG_P;382 }383 }384 385 if ((Attributes & EFI_MEMORY_RO) != 0) {386 if (IsSet) {387 NewPageEntry &= ~(UINT64)IA32_PG_RW;388 if (mIsShadowStack) {389 // Environment setup390 // ReadOnly page need set Dirty bit for shadow stack391 NewPageEntry |= IA32_PG_D;392 // Clear user bit for supervisor shadow stack393 NewPageEntry &= ~(UINT64)IA32_PG_U;394 } else {395 // Runtime update396 // Clear dirty bit for non shadow stack, to protect RO page.397 NewPageEntry &= ~(UINT64)IA32_PG_D;398 }399 } else {400 NewPageEntry |= IA32_PG_RW;401 }402 }403 404 if ((Attributes & EFI_MEMORY_XP) != 0) {405 if (mXdSupported) {406 if (IsSet) {407 NewPageEntry |= IA32_PG_NX;408 } else {409 NewPageEntry &= ~IA32_PG_NX;410 }411 }412 }413 414 *PageEntry = NewPageEntry;415 if (CurrentPageEntry != NewPageEntry) {416 *IsModified = TRUE;417 DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry));418 DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));419 } else {420 *IsModified = FALSE;421 }422 }423 424 /**425 This function returns if there is need to split page entry.426 427 @param[in] BaseAddress The base address to be checked.428 @param[in] Length The length to be checked.429 @param[in] PageEntry The page entry to be checked.430 @param[in] PageAttribute The page attribute of the page entry.431 432 @retval SplitAttributes on if there is need to split page entry.433 **/434 PAGE_ATTRIBUTE435 NeedSplitPage (436 IN PHYSICAL_ADDRESS BaseAddress,437 IN UINT64 Length,438 IN UINT64 *PageEntry,439 IN PAGE_ATTRIBUTE PageAttribute440 )441 {442 UINT64 PageEntryLength;443 444 PageEntryLength = PageAttributeToLength (PageAttribute);445 446 if (((BaseAddress & (PageEntryLength - 1)) == 0) && (Length >= PageEntryLength)) {447 return PageNone;448 }449 450 if (((BaseAddress & PAGING_2M_MASK) != 0) || (Length < SIZE_2MB)) {451 return Page4K;452 }453 454 return Page2M;455 }456 457 /**458 This function splits one page entry to small page entries.459 460 @param[in] PageEntry The page entry to be splitted.461 @param[in] PageAttribute The page attribute of the page entry.462 @param[in] SplitAttribute How to split the page entry.463 464 @retval RETURN_SUCCESS The page entry is splitted.465 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.466 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.467 **/468 RETURN_STATUS469 SplitPage (470 IN UINT64 *PageEntry,471 IN PAGE_ATTRIBUTE PageAttribute,472 IN PAGE_ATTRIBUTE SplitAttribute473 )474 {475 UINT64 BaseAddress;476 UINT64 *NewPageEntry;477 UINTN Index;478 479 ASSERT (PageAttribute == Page2M || PageAttribute == Page1G);480 481 if (PageAttribute == Page2M) {482 //483 // Split 2M to 4K484 //485 ASSERT (SplitAttribute == Page4K);486 if (SplitAttribute == Page4K) {487 NewPageEntry = AllocatePageTableMemory (1);488 DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));489 if (NewPageEntry == NULL) {490 return RETURN_OUT_OF_RESOURCES;491 }492 493 BaseAddress = *PageEntry & PAGING_2M_ADDRESS_MASK_64;494 for (Index = 0; Index < SIZE_4KB / sizeof (UINT64); Index++) {495 NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | mAddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS);496 }497 498 (*PageEntry) = (UINT64)(UINTN)NewPageEntry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;499 return RETURN_SUCCESS;500 } else {501 return RETURN_UNSUPPORTED;502 }503 } else if (PageAttribute == Page1G) {504 //505 // Split 1G to 2M506 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.507 //508 ASSERT (SplitAttribute == Page2M || SplitAttribute == Page4K);509 if (((SplitAttribute == Page2M) || (SplitAttribute == Page4K))) {510 NewPageEntry = AllocatePageTableMemory (1);511 DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));512 if (NewPageEntry == NULL) {513 return RETURN_OUT_OF_RESOURCES;514 }515 516 BaseAddress = *PageEntry & PAGING_1G_ADDRESS_MASK_64;517 for (Index = 0; Index < SIZE_4KB / sizeof (UINT64); Index++) {518 NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | mAddressEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS);519 }520 521 (*PageEntry) = (UINT64)(UINTN)NewPageEntry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;522 return RETURN_SUCCESS;523 } else {524 return RETURN_UNSUPPORTED;525 }526 } else {527 return RETURN_UNSUPPORTED;528 }529 }530 531 /**532 338 This function modifies the page attributes for the memory region specified by BaseAddress and 533 339 Length from their current attributes to the attributes specified by Attributes. … … 536 342 537 343 @param[in] PageTableBase The page table base. 538 @param[in] EnablePML5Paging If PML5 paging is enabled.344 @param[in] PagingMode The paging mode. 539 345 @param[in] BaseAddress The physical address that is the start address of a memory region. 540 346 @param[in] Length The size in bytes of the memory region. 541 347 @param[in] Attributes The bit mask of attributes to modify for the memory region. 542 348 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes. 543 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.544 349 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified. 545 350 … … 560 365 ConvertMemoryPageAttributes ( 561 366 IN UINTN PageTableBase, 562 IN BOOLEAN EnablePML5Paging,367 IN PAGING_MODE PagingMode, 563 368 IN PHYSICAL_ADDRESS BaseAddress, 564 369 IN UINT64 Length, 565 370 IN UINT64 Attributes, 566 371 IN BOOLEAN IsSet, 567 OUT BOOLEAN *IsSplitted OPTIONAL,568 372 OUT BOOLEAN *IsModified OPTIONAL 569 373 ) 570 374 { 571 UINT64 *PageEntry;572 PAGE_ATTRIBUTE PageAttribute;573 UINTN PageEntryLength;574 PAGE_ATTRIBUTE SplitAttribute;575 375 RETURN_STATUS Status; 576 BOOLEAN IsEntryModified; 376 IA32_MAP_ATTRIBUTE PagingAttribute; 377 IA32_MAP_ATTRIBUTE PagingAttrMask; 378 UINTN PageTableBufferSize; 379 VOID *PageTableBuffer; 577 380 EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress; 381 IA32_MAP_ENTRY *Map; 382 UINTN Count; 383 UINTN Index; 384 UINT64 OverlappedRangeBase; 385 UINT64 OverlappedRangeLimit; 578 386 579 387 ASSERT (Attributes != 0); … … 582 390 ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0); 583 391 ASSERT ((Length & (SIZE_4KB - 1)) == 0); 392 ASSERT (PageTableBase != 0); 584 393 585 394 if (Length == 0) { … … 600 409 } 601 410 602 // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));603 604 if (IsSplitted != NULL) {605 *IsSplitted = FALSE;606 }607 608 411 if (IsModified != NULL) { 609 412 *IsModified = FALSE; 610 413 } 611 414 612 // 613 // Below logic is to check 2M/4K page to make sure we do not waste memory. 614 // 615 while (Length != 0) { 616 PageEntry = GetPageTableEntry (PageTableBase, EnablePML5Paging, BaseAddress, &PageAttribute); 617 if (PageEntry == NULL) { 618 return RETURN_UNSUPPORTED; 619 } 620 621 PageEntryLength = PageAttributeToLength (PageAttribute); 622 SplitAttribute = NeedSplitPage (BaseAddress, Length, PageEntry, PageAttribute); 623 if (SplitAttribute == PageNone) { 624 ConvertPageEntryAttribute (PageEntry, Attributes, IsSet, &IsEntryModified); 625 if (IsEntryModified) { 626 if (IsModified != NULL) { 627 *IsModified = TRUE; 415 PagingAttribute.Uint64 = 0; 416 PagingAttribute.Uint64 = mAddressEncMask | BaseAddress; 417 PagingAttrMask.Uint64 = 0; 418 419 if ((Attributes & EFI_MEMORY_RO) != 0) { 420 PagingAttrMask.Bits.ReadWrite = 1; 421 if (IsSet) { 422 PagingAttribute.Bits.ReadWrite = 0; 423 PagingAttrMask.Bits.Dirty = 1; 424 if (mIsShadowStack) { 425 // Environment setup 426 // ReadOnly page need set Dirty bit for shadow stack 427 PagingAttribute.Bits.Dirty = 1; 428 // Clear user bit for supervisor shadow stack 429 PagingAttribute.Bits.UserSupervisor = 0; 430 PagingAttrMask.Bits.UserSupervisor = 1; 431 } else { 432 // Runtime update 433 // Clear dirty bit for non shadow stack, to protect RO page. 434 PagingAttribute.Bits.Dirty = 0; 435 } 436 } else { 437 PagingAttribute.Bits.ReadWrite = 1; 438 } 439 } 440 441 if ((Attributes & EFI_MEMORY_XP) != 0) { 442 if (mXdSupported) { 443 PagingAttribute.Bits.Nx = IsSet ? 1 : 0; 444 PagingAttrMask.Bits.Nx = 1; 445 } 446 } 447 448 if ((Attributes & EFI_MEMORY_RP) != 0) { 449 if (IsSet) { 450 PagingAttribute.Bits.Present = 0; 451 // 452 // When map a range to non-present, all attributes except Present should not be provided. 453 // 454 PagingAttrMask.Uint64 = 0; 455 PagingAttrMask.Bits.Present = 1; 456 } else { 457 // 458 // When map range to present range, provide all attributes. 459 // 460 PagingAttribute.Bits.Present = 1; 461 PagingAttrMask.Uint64 = MAX_UINT64; 462 463 // 464 // By default memory is Ring 3 accessble. 465 // 466 PagingAttribute.Bits.UserSupervisor = 1; 467 468 DEBUG_CODE_BEGIN (); 469 if (((Attributes & EFI_MEMORY_RO) == 0) || (((Attributes & EFI_MEMORY_XP) == 0) && (mXdSupported))) { 470 // 471 // When mapping a range to present and EFI_MEMORY_RO or EFI_MEMORY_XP is not specificed, 472 // check if [BaseAddress, BaseAddress + Length] contains present range. 473 // Existing Present range in [BaseAddress, BaseAddress + Length] is set to NX disable or ReadOnly. 474 // 475 Count = 0; 476 Map = NULL; 477 Status = PageTableParse (PageTableBase, mPagingMode, NULL, &Count); 478 479 while (Status == RETURN_BUFFER_TOO_SMALL) { 480 if (Map != NULL) { 481 FreePool (Map); 482 } 483 484 Map = AllocatePool (Count * sizeof (IA32_MAP_ENTRY)); 485 ASSERT (Map != NULL); 486 Status = PageTableParse (PageTableBase, mPagingMode, Map, &Count); 628 487 } 488 489 ASSERT_RETURN_ERROR (Status); 490 for (Index = 0; Index < Count; Index++) { 491 if (Map[Index].LinearAddress >= BaseAddress + Length) { 492 break; 493 } 494 495 if ((BaseAddress < Map[Index].LinearAddress + Map[Index].Length) && (BaseAddress + Length > Map[Index].LinearAddress)) { 496 OverlappedRangeBase = MAX (BaseAddress, Map[Index].LinearAddress); 497 OverlappedRangeLimit = MIN (BaseAddress + Length, Map[Index].LinearAddress + Map[Index].Length); 498 499 if (((Attributes & EFI_MEMORY_RO) == 0) && (Map[Index].Attribute.Bits.ReadWrite == 1)) { 500 DEBUG ((DEBUG_ERROR, "SMM ConvertMemoryPageAttributes: [0x%lx, 0x%lx] is set from ReadWrite to ReadOnly\n", OverlappedRangeBase, OverlappedRangeLimit)); 501 } 502 503 if (((Attributes & EFI_MEMORY_XP) == 0) && (mXdSupported) && (Map[Index].Attribute.Bits.Nx == 1)) { 504 DEBUG ((DEBUG_ERROR, "SMM ConvertMemoryPageAttributes: [0x%lx, 0x%lx] is set from NX enabled to NX disabled\n", OverlappedRangeBase, OverlappedRangeLimit)); 505 } 506 } 507 } 508 509 FreePool (Map); 629 510 } 630 511 631 // 632 // Convert success, move to next 633 // 634 BaseAddress += PageEntryLength; 635 Length -= PageEntryLength; 636 } else { 637 Status = SplitPage (PageEntry, PageAttribute, SplitAttribute); 638 if (RETURN_ERROR (Status)) { 639 return RETURN_UNSUPPORTED; 640 } 641 642 if (IsSplitted != NULL) { 643 *IsSplitted = TRUE; 644 } 645 646 if (IsModified != NULL) { 647 *IsModified = TRUE; 648 } 649 650 // 651 // Just split current page 652 // Convert success in next around 653 // 654 } 655 } 512 DEBUG_CODE_END (); 513 } 514 } 515 516 if (PagingAttrMask.Uint64 == 0) { 517 return RETURN_SUCCESS; 518 } 519 520 PageTableBufferSize = 0; 521 Status = PageTableMap (&PageTableBase, PagingMode, NULL, &PageTableBufferSize, BaseAddress, Length, &PagingAttribute, &PagingAttrMask, IsModified); 522 523 if (Status == RETURN_BUFFER_TOO_SMALL) { 524 PageTableBuffer = AllocatePageTableMemory (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 525 ASSERT (PageTableBuffer != NULL); 526 Status = PageTableMap (&PageTableBase, PagingMode, PageTableBuffer, &PageTableBufferSize, BaseAddress, Length, &PagingAttribute, &PagingAttrMask, IsModified); 527 } 528 529 if (Status == RETURN_INVALID_PARAMETER) { 530 // 531 // The only reason that PageTableMap returns RETURN_INVALID_PARAMETER here is to modify other attributes 532 // of a non-present range but remains the non-present range still as non-present. 533 // 534 DEBUG ((DEBUG_ERROR, "SMM ConvertMemoryPageAttributes: Only change EFI_MEMORY_XP/EFI_MEMORY_RO for non-present range in [0x%lx, 0x%lx] is not permitted\n", BaseAddress, BaseAddress + Length)); 535 } 536 537 ASSERT_RETURN_ERROR (Status); 538 ASSERT (PageTableBufferSize == 0); 656 539 657 540 return RETURN_SUCCESS; … … 698 581 699 582 @param[in] PageTableBase The page table base. 700 @param[in] EnablePML5Paging If PML5 paging is enabled.583 @param[in] PagingMode The paging mode. 701 584 @param[in] BaseAddress The physical address that is the start address of a memory region. 702 585 @param[in] Length The size in bytes of the memory region. 703 586 @param[in] Attributes The bit mask of attributes to set for the memory region. 704 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.705 587 706 588 @retval EFI_SUCCESS The attributes were set for the memory region. … … 721 603 SmmSetMemoryAttributesEx ( 722 604 IN UINTN PageTableBase, 723 IN BOOLEAN EnablePML5Paging,605 IN PAGING_MODE PagingMode, 724 606 IN EFI_PHYSICAL_ADDRESS BaseAddress, 725 607 IN UINT64 Length, 726 IN UINT64 Attributes, 727 OUT BOOLEAN *IsSplitted OPTIONAL 608 IN UINT64 Attributes 728 609 ) 729 610 { … … 731 612 BOOLEAN IsModified; 732 613 733 Status = ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging, BaseAddress, Length, Attributes, TRUE, IsSplitted, &IsModified);614 Status = ConvertMemoryPageAttributes (PageTableBase, PagingMode, BaseAddress, Length, Attributes, TRUE, &IsModified); 734 615 if (!EFI_ERROR (Status)) { 735 616 if (IsModified) { … … 749 630 750 631 @param[in] PageTableBase The page table base. 751 @param[in] EnablePML5Paging If PML5 paging is enabled.632 @param[in] PagingMode The paging mode. 752 633 @param[in] BaseAddress The physical address that is the start address of a memory region. 753 634 @param[in] Length The size in bytes of the memory region. 754 635 @param[in] Attributes The bit mask of attributes to clear for the memory region. 755 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.756 636 757 637 @retval EFI_SUCCESS The attributes were cleared for the memory region. … … 772 652 SmmClearMemoryAttributesEx ( 773 653 IN UINTN PageTableBase, 774 IN BOOLEAN EnablePML5Paging,654 IN PAGING_MODE PagingMode, 775 655 IN EFI_PHYSICAL_ADDRESS BaseAddress, 776 656 IN UINT64 Length, 777 IN UINT64 Attributes, 778 OUT BOOLEAN *IsSplitted OPTIONAL 657 IN UINT64 Attributes 779 658 ) 780 659 { … … 782 661 BOOLEAN IsModified; 783 662 784 Status = ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging, BaseAddress, Length, Attributes, FALSE, IsSplitted, &IsModified);663 Status = ConvertMemoryPageAttributes (PageTableBase, PagingMode, BaseAddress, Length, Attributes, FALSE, &IsModified); 785 664 if (!EFI_ERROR (Status)) { 786 665 if (IsModified) { … … 824 703 ) 825 704 { 826 IA32_CR4 Cr4; 827 UINTN PageTableBase; 828 BOOLEAN Enable5LevelPaging; 829 830 PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; 831 Cr4.UintN = AsmReadCr4 (); 832 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); 833 return SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, BaseAddress, Length, Attributes, NULL); 705 UINTN PageTableBase; 706 707 PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; 708 return SmmSetMemoryAttributesEx (PageTableBase, mPagingMode, BaseAddress, Length, Attributes); 834 709 } 835 710 … … 863 738 ) 864 739 { 865 IA32_CR4 Cr4; 866 UINTN PageTableBase; 867 BOOLEAN Enable5LevelPaging; 868 869 PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; 870 Cr4.UintN = AsmReadCr4 (); 871 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); 872 return SmmClearMemoryAttributesEx (PageTableBase, Enable5LevelPaging, BaseAddress, Length, Attributes, NULL); 740 UINTN PageTableBase; 741 742 PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; 743 return SmmClearMemoryAttributesEx (PageTableBase, mPagingMode, BaseAddress, Length, Attributes); 873 744 } 874 745 … … 892 763 893 764 mIsShadowStack = TRUE; 894 Status = SmmSetMemoryAttributesEx (Cr3, m 5LevelPagingNeeded, BaseAddress, Length, EFI_MEMORY_RO, NULL);765 Status = SmmSetMemoryAttributesEx (Cr3, mPagingMode, BaseAddress, Length, EFI_MEMORY_RO); 895 766 mIsShadowStack = FALSE; 896 767 897 return Status;898 }899 900 /**901 Set not present memory.902 903 @param[in] Cr3 The page table base address.904 @param[in] BaseAddress The physical address that is the start address of a memory region.905 @param[in] Length The size in bytes of the memory region.906 907 @retval EFI_SUCCESS The not present memory is set.908 **/909 EFI_STATUS910 SetNotPresentPage (911 IN UINTN Cr3,912 IN EFI_PHYSICAL_ADDRESS BaseAddress,913 IN UINT64 Length914 )915 {916 EFI_STATUS Status;917 918 Status = SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, BaseAddress, Length, EFI_MEMORY_RP, NULL);919 768 return Status; 920 769 } … … 1081 930 1082 931 /** 932 This function set [Base, Limit] to the input MemoryAttribute. 933 934 @param Base Start address of range. 935 @param Limit Limit address of range. 936 @param Attribute The bit mask of attributes to modify for the memory region. 937 @param Map Pointer to the array of Cr3 IA32_MAP_ENTRY. 938 @param Count Count of IA32_MAP_ENTRY in Map. 939 **/ 940 VOID 941 SetMemMapWithNonPresentRange ( 942 UINT64 Base, 943 UINT64 Limit, 944 UINT64 Attribute, 945 IA32_MAP_ENTRY *Map, 946 UINTN Count 947 ) 948 { 949 UINTN Index; 950 UINT64 NonPresentRangeStart; 951 952 NonPresentRangeStart = 0; 953 for (Index = 0; Index < Count; Index++) { 954 if ((Map[Index].LinearAddress > NonPresentRangeStart) && 955 (Base < Map[Index].LinearAddress) && (Limit > NonPresentRangeStart)) 956 { 957 // 958 // We should NOT set attributes for non-present ragne. 959 // 960 // 961 // There is a non-present ( [NonPresentStart, Map[Index].LinearAddress] ) range before current Map[Index] 962 // and it is overlapped with [Base, Limit]. 963 // 964 if (Base < NonPresentRangeStart) { 965 SmmSetMemoryAttributes ( 966 Base, 967 NonPresentRangeStart - Base, 968 Attribute 969 ); 970 } 971 972 Base = Map[Index].LinearAddress; 973 } 974 975 NonPresentRangeStart = Map[Index].LinearAddress + Map[Index].Length; 976 if (NonPresentRangeStart >= Limit) { 977 break; 978 } 979 } 980 981 Limit = MIN (NonPresentRangeStart, Limit); 982 983 if (Base < Limit) { 984 // 985 // There is no non-present range in current [Base, Limit] anymore. 986 // 987 SmmSetMemoryAttributes ( 988 Base, 989 Limit - Base, 990 Attribute 991 ); 992 } 993 } 994 995 /** 1083 996 This function sets memory attribute according to MemoryAttributesTable. 1084 997 **/ … … 1094 1007 UINTN Index; 1095 1008 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; 1009 UINTN PageTable; 1010 EFI_STATUS Status; 1011 IA32_MAP_ENTRY *Map; 1012 UINTN Count; 1013 UINT64 MemoryAttribute; 1014 BOOLEAN WpEnabled; 1015 BOOLEAN CetEnabled; 1096 1016 1097 1017 SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); … … 1100 1020 return; 1101 1021 } 1022 1023 PERF_FUNCTION_BEGIN (); 1102 1024 1103 1025 DEBUG ((DEBUG_INFO, "MemoryAttributesTable:\n")); … … 1120 1042 } 1121 1043 1044 Count = 0; 1045 Map = NULL; 1046 PageTable = AsmReadCr3 (); 1047 Status = PageTableParse (PageTable, mPagingMode, NULL, &Count); 1048 while (Status == RETURN_BUFFER_TOO_SMALL) { 1049 if (Map != NULL) { 1050 FreePool (Map); 1051 } 1052 1053 Map = AllocatePool (Count * sizeof (IA32_MAP_ENTRY)); 1054 ASSERT (Map != NULL); 1055 Status = PageTableParse (PageTable, mPagingMode, Map, &Count); 1056 } 1057 1058 ASSERT_RETURN_ERROR (Status); 1059 1060 DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled); 1061 1122 1062 MemoryMap = MemoryMapStart; 1123 1063 for (Index = 0; Index < MemoryMapEntryCount; Index++) { 1124 1064 DEBUG ((DEBUG_VERBOSE, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap->PhysicalStart, MemoryMap->NumberOfPages)); 1125 switch (MemoryMap->Type) { 1126 case EfiRuntimeServicesCode: 1127 SmmSetMemoryAttributes ( 1128 MemoryMap->PhysicalStart, 1129 EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages), 1130 EFI_MEMORY_RO 1131 ); 1132 break; 1133 case EfiRuntimeServicesData: 1134 SmmSetMemoryAttributes ( 1135 MemoryMap->PhysicalStart, 1136 EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages), 1137 EFI_MEMORY_XP 1138 ); 1139 break; 1140 default: 1141 SmmSetMemoryAttributes ( 1142 MemoryMap->PhysicalStart, 1143 EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages), 1144 EFI_MEMORY_XP 1145 ); 1146 break; 1147 } 1065 if (MemoryMap->Type == EfiRuntimeServicesCode) { 1066 MemoryAttribute = EFI_MEMORY_RO; 1067 } else { 1068 ASSERT ((MemoryMap->Type == EfiRuntimeServicesData) || (MemoryMap->Type == EfiConventionalMemory)); 1069 // 1070 // Set other type memory as NX. 1071 // 1072 MemoryAttribute = EFI_MEMORY_XP; 1073 } 1074 1075 // 1076 // There may exist non-present range overlaps with the MemoryMap range. 1077 // Do not change other attributes of non-present range while still remaining it as non-present 1078 // 1079 SetMemMapWithNonPresentRange ( 1080 MemoryMap->PhysicalStart, 1081 MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages), 1082 MemoryAttribute, 1083 Map, 1084 Count 1085 ); 1148 1086 1149 1087 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize); 1150 1088 } 1089 1090 EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled); 1091 FreePool (Map); 1151 1092 1152 1093 PatchSmmSaveStateMap (); 1153 1094 PatchGdtIdtMap (); 1154 1095 1155 return;1096 PERF_FUNCTION_END (); 1156 1097 } 1157 1098 … … 1454 1395 UINTN Index; 1455 1396 EFI_MEMORY_DESCRIPTOR *Entry; 1397 BOOLEAN WpEnabled; 1398 BOOLEAN CetEnabled; 1399 1400 PERF_FUNCTION_BEGIN (); 1456 1401 1457 1402 DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n")); 1403 1404 DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled); 1458 1405 1459 1406 if (mUefiMemoryMap != NULL) { … … 1535 1482 } 1536 1483 1484 EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled); 1485 1537 1486 // 1538 1487 // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress(). 1539 1488 // 1489 1490 PERF_FUNCTION_END (); 1540 1491 } 1541 1492 … … 1675 1626 1676 1627 /** 1628 Create page table based on input PagingMode and PhysicalAddressBits in smm. 1629 1630 @param[in] PagingMode The paging mode. 1631 @param[in] PhysicalAddressBits The bits of physical address to map. 1632 1633 @retval PageTable Address 1634 1635 **/ 1636 UINTN 1637 GenSmmPageTable ( 1638 IN PAGING_MODE PagingMode, 1639 IN UINT8 PhysicalAddressBits 1640 ) 1641 { 1642 UINTN PageTableBufferSize; 1643 UINTN PageTable; 1644 VOID *PageTableBuffer; 1645 IA32_MAP_ATTRIBUTE MapAttribute; 1646 IA32_MAP_ATTRIBUTE MapMask; 1647 RETURN_STATUS Status; 1648 UINTN GuardPage; 1649 UINTN Index; 1650 UINT64 Length; 1651 1652 Length = LShiftU64 (1, PhysicalAddressBits); 1653 PageTable = 0; 1654 PageTableBufferSize = 0; 1655 MapMask.Uint64 = MAX_UINT64; 1656 MapAttribute.Uint64 = mAddressEncMask; 1657 MapAttribute.Bits.Present = 1; 1658 MapAttribute.Bits.ReadWrite = 1; 1659 MapAttribute.Bits.UserSupervisor = 1; 1660 MapAttribute.Bits.Accessed = 1; 1661 MapAttribute.Bits.Dirty = 1; 1662 1663 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, Length, &MapAttribute, &MapMask, NULL); 1664 ASSERT (Status == RETURN_BUFFER_TOO_SMALL); 1665 DEBUG ((DEBUG_INFO, "GenSMMPageTable: 0x%x bytes needed for initial SMM page table\n", PageTableBufferSize)); 1666 PageTableBuffer = AllocatePageTableMemory (EFI_SIZE_TO_PAGES (PageTableBufferSize)); 1667 ASSERT (PageTableBuffer != NULL); 1668 Status = PageTableMap (&PageTable, PagingMode, PageTableBuffer, &PageTableBufferSize, 0, Length, &MapAttribute, &MapMask, NULL); 1669 ASSERT (Status == RETURN_SUCCESS); 1670 ASSERT (PageTableBufferSize == 0); 1671 1672 if (FeaturePcdGet (PcdCpuSmmStackGuard)) { 1673 // 1674 // Mark the 4KB guard page between known good stack and smm stack as non-present 1675 // 1676 for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) { 1677 GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE + Index * (mSmmStackSize + mSmmShadowStackSize); 1678 Status = ConvertMemoryPageAttributes (PageTable, PagingMode, GuardPage, SIZE_4KB, EFI_MEMORY_RP, TRUE, NULL); 1679 } 1680 } 1681 1682 if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) { 1683 // 1684 // Mark [0, 4k] as non-present 1685 // 1686 Status = ConvertMemoryPageAttributes (PageTable, PagingMode, 0, SIZE_4KB, EFI_MEMORY_RP, TRUE, NULL); 1687 } 1688 1689 return (UINTN)PageTable; 1690 } 1691 1692 /** 1677 1693 This function retrieves the attributes of the memory region specified by 1678 1694 BaseAddress and Length. If different attributes are got from different part … … 1800 1816 // Set entire pool including header, used-memory and left free-memory as ReadOnly in SMM page table. 1801 1817 // 1802 ConvertMemoryPageAttributes (PageTableBase, m 5LevelPagingNeeded, Address, PoolSize, EFI_MEMORY_RO, TRUE, NULL, NULL);1818 ConvertMemoryPageAttributes (PageTableBase, mPagingMode, Address, PoolSize, EFI_MEMORY_RO, TRUE, NULL); 1803 1819 Pool = Pool->NextPool; 1804 1820 } while (Pool != HeadPool); … … 1857 1873 ) 1858 1874 { 1875 BOOLEAN WpEnabled; 1859 1876 BOOLEAN CetEnabled; 1860 1877 … … 1863 1880 } 1864 1881 1882 PERF_FUNCTION_BEGIN (); 1865 1883 DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n")); 1866 1884 … … 1869 1887 // We need *write* page table memory, to mark itself to be *read only*. 1870 1888 // 1871 CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE; 1872 if (CetEnabled) { 1873 // 1874 // CET must be disabled if WP is disabled. 1875 // 1876 DisableCet (); 1877 } 1878 1879 AsmWriteCr0 (AsmReadCr0 () & ~CR0_WP); 1889 DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled); 1880 1890 1881 1891 // Set memory used by page table as Read Only. … … 1886 1896 // Enable write protection, after page table attribute updated. 1887 1897 // 1888 AsmWriteCr0 (AsmReadCr0 () | CR0_WP);1898 EnableReadOnlyPageWriteProtect (TRUE, CetEnabled); 1889 1899 mIsReadOnlyPageTable = TRUE; 1890 1900 … … 1893 1903 // 1894 1904 FlushTlbForAll (); 1895 1896 if (CetEnabled) { 1897 // 1898 // re-enable CET. 1899 // 1900 EnableCet (); 1901 } 1902 1903 return; 1904 } 1905 PERF_FUNCTION_END (); 1906 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
r99404 r101291 374 374 // 375 375 return FALSE; 376 } 377 378 /** 379 Function to compare 2 MEMORY_PROTECTION_RANGE based on range base. 380 381 @param[in] Buffer1 pointer to Device Path poiner to compare 382 @param[in] Buffer2 pointer to second DevicePath pointer to compare 383 384 @retval 0 Buffer1 equal to Buffer2 385 @retval <0 Buffer1 is less than Buffer2 386 @retval >0 Buffer1 is greater than Buffer2 387 **/ 388 INTN 389 EFIAPI 390 ProtectionRangeCompare ( 391 IN CONST VOID *Buffer1, 392 IN CONST VOID *Buffer2 393 ) 394 { 395 if (((MEMORY_PROTECTION_RANGE *)Buffer1)->Range.Base > ((MEMORY_PROTECTION_RANGE *)Buffer2)->Range.Base) { 396 return 1; 397 } else if (((MEMORY_PROTECTION_RANGE *)Buffer1)->Range.Base < ((MEMORY_PROTECTION_RANGE *)Buffer2)->Range.Base) { 398 return -1; 399 } 400 401 return 0; 376 402 } 377 403 … … 398 424 UINT64 High4KBPageSize; 399 425 UINT64 Low4KBPageSize; 426 MEMORY_PROTECTION_RANGE MemProtectionRange; 400 427 401 428 NumberOfDescriptors = 0; … … 534 561 mSplitMemRangeCount = NumberOfSpliteRange; 535 562 563 // 564 // Sort the mProtectionMemRange 565 // 566 QuickSort (mProtectionMemRange, mProtectionMemRangeCount, sizeof (MEMORY_PROTECTION_RANGE), (BASE_SORT_COMPARE)ProtectionRangeCompare, &MemProtectionRange); 567 536 568 DEBUG ((DEBUG_INFO, "SMM Profile Memory Ranges:\n")); 537 569 for (Index = 0; Index < mProtectionMemRangeCount; Index++) { … … 555 587 ) 556 588 { 557 UINT64 Pml5Entry; 558 UINT64 Pml4Entry; 559 UINT64 *Pml5; 560 UINT64 *Pml4; 561 UINT64 *Pdpt; 562 UINT64 *Pd; 563 UINT64 *Pt; 564 UINTN Address; 565 UINTN Pml5Index; 566 UINTN Pml4Index; 567 UINTN PdptIndex; 568 UINTN PdIndex; 569 UINTN PtIndex; 570 UINTN NumberOfPdptEntries; 571 UINTN NumberOfPml4Entries; 572 UINTN NumberOfPml5Entries; 573 UINTN SizeOfMemorySpace; 574 BOOLEAN Nx; 575 IA32_CR4 Cr4; 576 BOOLEAN Enable5LevelPaging; 577 578 Cr4.UintN = AsmReadCr4 (); 579 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); 580 581 if (sizeof (UINTN) == sizeof (UINT64)) { 582 if (!Enable5LevelPaging) { 583 Pml5Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P; 584 Pml5 = &Pml5Entry; 585 } else { 586 Pml5 = (UINT64 *)(UINTN)mSmmProfileCr3; 587 } 588 589 SizeOfMemorySpace = HighBitSet64 (gPhyMask) + 1; 590 ASSERT (SizeOfMemorySpace <= 52); 591 592 // 593 // Calculate the table entries of PML5E, PML4E and PDPTE. 594 // 595 NumberOfPml5Entries = 1; 596 if (SizeOfMemorySpace > 48) { 597 if (Enable5LevelPaging) { 598 NumberOfPml5Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 48); 599 } 600 601 SizeOfMemorySpace = 48; 602 } 603 604 NumberOfPml4Entries = 1; 605 if (SizeOfMemorySpace > 39) { 606 NumberOfPml4Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 39); 607 SizeOfMemorySpace = 39; 608 } 609 610 NumberOfPdptEntries = 1; 611 ASSERT (SizeOfMemorySpace > 30); 612 NumberOfPdptEntries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 30); 589 RETURN_STATUS Status; 590 UINTN Index; 591 UINTN PageTable; 592 UINT64 Base; 593 UINT64 Length; 594 UINT64 Limit; 595 UINT64 PreviousAddress; 596 UINT64 MemoryAttrMask; 597 BOOLEAN WpEnabled; 598 BOOLEAN CetEnabled; 599 600 PERF_FUNCTION_BEGIN (); 601 602 PageTable = AsmReadCr3 (); 603 if (sizeof (UINTN) == sizeof (UINT32)) { 604 Limit = BASE_4GB; 613 605 } else { 614 Pml4Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P; 615 Pml4 = &Pml4Entry; 616 Pml5Entry = (UINTN)Pml4 | IA32_PG_P; 617 Pml5 = &Pml5Entry; 618 NumberOfPml5Entries = 1; 619 NumberOfPml4Entries = 1; 620 NumberOfPdptEntries = 4; 621 } 622 623 // 624 // Go through page table and change 2MB-page into 4KB-page. 625 // 626 for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) { 627 if ((Pml5[Pml5Index] & IA32_PG_P) == 0) { 628 // 629 // If PML5 entry does not exist, skip it 630 // 631 continue; 632 } 633 634 Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK); 635 for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) { 636 if ((Pml4[Pml4Index] & IA32_PG_P) == 0) { 637 // 638 // If PML4 entry does not exist, skip it 639 // 640 continue; 641 } 642 643 Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); 644 for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) { 645 if ((*Pdpt & IA32_PG_P) == 0) { 646 // 647 // If PDPT entry does not exist, skip it 648 // 649 continue; 650 } 651 652 if ((*Pdpt & IA32_PG_PS) != 0) { 653 // 654 // This is 1G entry, skip it 655 // 656 continue; 657 } 658 659 Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); 660 if (Pd == 0) { 661 continue; 662 } 663 664 for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) { 665 if ((*Pd & IA32_PG_P) == 0) { 666 // 667 // If PD entry does not exist, skip it 668 // 669 continue; 670 } 671 672 Address = (UINTN)LShiftU64 ( 673 LShiftU64 ( 674 LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex, 675 9 676 ) + PdIndex, 677 21 678 ); 679 680 // 681 // If it is 2M page, check IsAddressSplit() 682 // 683 if (((*Pd & IA32_PG_PS) != 0) && IsAddressSplit (Address)) { 684 // 685 // Based on current page table, create 4KB page table for split area. 686 // 687 ASSERT (Address == (*Pd & PHYSICAL_ADDRESS_MASK)); 688 689 Pt = AllocatePageTableMemory (1); 690 ASSERT (Pt != NULL); 691 692 // Split it 693 for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++) { 694 Pt[PtIndex] = Address + ((PtIndex << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS); 695 } // end for PT 696 697 *Pd = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS; 698 } // end if IsAddressSplit 699 } // end for PD 700 } // end for PDPT 701 } // end for PML4 702 } // end for PML5 703 704 // 705 // Go through page table and set several page table entries to absent or execute-disable. 706 // 606 Limit = (IsRestrictedMemoryAccess ()) ? LShiftU64 (1, mPhysicalAddressBits) : BASE_4GB; 607 } 608 609 DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled); 610 // 611 // [0, 4k] may be non-present. 612 // 613 PreviousAddress = ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) ? BASE_4KB : 0; 614 707 615 DEBUG ((DEBUG_INFO, "Patch page table start ...\n")); 708 for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) { 709 if ((Pml5[Pml5Index] & IA32_PG_P) == 0) { 710 // 711 // If PML5 entry does not exist, skip it 712 // 713 continue; 714 } 715 716 Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK); 717 for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) { 718 if ((Pml4[Pml4Index] & IA32_PG_P) == 0) { 719 // 720 // If PML4 entry does not exist, skip it 721 // 722 continue; 723 } 724 725 Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); 726 for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) { 727 if ((*Pdpt & IA32_PG_P) == 0) { 728 // 729 // If PDPT entry does not exist, skip it 730 // 731 continue; 732 } 733 734 if ((*Pdpt & IA32_PG_PS) != 0) { 735 // 736 // This is 1G entry, set NX bit and skip it 737 // 738 if (mXdSupported) { 739 *Pdpt = *Pdpt | IA32_PG_NX; 740 } 741 742 continue; 743 } 744 745 Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); 746 if (Pd == 0) { 747 continue; 748 } 749 750 for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) { 751 if ((*Pd & IA32_PG_P) == 0) { 752 // 753 // If PD entry does not exist, skip it 754 // 755 continue; 756 } 757 758 Address = (UINTN)LShiftU64 ( 759 LShiftU64 ( 760 LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex, 761 9 762 ) + PdIndex, 763 21 764 ); 765 766 if ((*Pd & IA32_PG_PS) != 0) { 767 // 2MB page 768 769 if (!IsAddressValid (Address, &Nx)) { 770 // 771 // Patch to remove Present flag and RW flag 772 // 773 *Pd = *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS); 774 } 775 776 if (Nx && mXdSupported) { 777 *Pd = *Pd | IA32_PG_NX; 778 } 779 } else { 780 // 4KB page 781 Pt = (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); 782 if (Pt == 0) { 783 continue; 784 } 785 786 for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++, Pt++) { 787 if (!IsAddressValid (Address, &Nx)) { 788 *Pt = *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS); 789 } 790 791 if (Nx && mXdSupported) { 792 *Pt = *Pt | IA32_PG_NX; 793 } 794 795 Address += SIZE_4KB; 796 } // end for PT 797 } // end if PS 798 } // end for PD 799 } // end for PDPT 800 } // end for PML4 801 } // end for PML5 616 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { 617 for (Index = 0; Index < mProtectionMemRangeCount; Index++) { 618 MemoryAttrMask = 0; 619 if (mProtectionMemRange[Index].Nx == TRUE) { 620 MemoryAttrMask |= EFI_MEMORY_XP; 621 } 622 623 if (mProtectionMemRange[Index].Present == FALSE) { 624 MemoryAttrMask = EFI_MEMORY_RP; 625 } 626 627 Base = mProtectionMemRange[Index].Range.Base; 628 Length = mProtectionMemRange[Index].Range.Top - Base; 629 if (MemoryAttrMask != 0) { 630 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, Base, Length, MemoryAttrMask, TRUE, NULL); 631 ASSERT_RETURN_ERROR (Status); 632 } 633 634 if (Base > PreviousAddress) { 635 // 636 // Mark the ranges not in mProtectionMemRange as non-present. 637 // 638 MemoryAttrMask = EFI_MEMORY_RP; 639 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, MemoryAttrMask, TRUE, NULL); 640 ASSERT_RETURN_ERROR (Status); 641 } 642 643 PreviousAddress = Base + Length; 644 } 645 646 // 647 // This assignment is for setting the last remaining range 648 // 649 MemoryAttrMask = EFI_MEMORY_RP; 650 } else { 651 MemoryAttrMask = EFI_MEMORY_XP; 652 for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) { 653 Base = mSmmCpuSmramRanges[Index].CpuStart; 654 if (Base > PreviousAddress) { 655 // 656 // Mark the ranges not in mSmmCpuSmramRanges as NX. 657 // 658 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, MemoryAttrMask, TRUE, NULL); 659 ASSERT_RETURN_ERROR (Status); 660 } 661 662 PreviousAddress = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize; 663 } 664 } 665 666 if (PreviousAddress < Limit) { 667 // 668 // Set the last remaining range to EFI_MEMORY_RP/EFI_MEMORY_XP. 669 // This path applies to both SmmProfile enable/disable case. 670 // 671 Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Limit - PreviousAddress, MemoryAttrMask, TRUE, NULL); 672 ASSERT_RETURN_ERROR (Status); 673 } 674 675 EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled); 802 676 803 677 // … … 811 685 mXdEnabled = TRUE; 812 686 813 return;687 PERF_FUNCTION_END (); 814 688 } 815 689 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
r99404 r101291 15 15 #include <Library/DxeServicesTableLib.h> 16 16 #include <Library/CpuLib.h> 17 #include <Library/UefiCpuLib.h>18 17 #include <IndustryStandard/Acpi.h> 19 18 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
r99404 r101291 3 3 4 4 Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR> 5 Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> 6 5 7 SPDX-License-Identifier: BSD-2-Clause-Patent 6 8 … … 50 52 51 53 /// 52 /// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY53 ///54 #define SMM_CPU_OFFSET(Field) OFFSET_OF (SMRAM_SAVE_STATE_MAP, Field)55 56 ///57 /// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_REGISTER_RANGE58 ///59 #define SMM_REGISTER_RANGE(Start, End) { Start, End, End - Start + 1 }60 61 ///62 /// Structure used to describe a range of registers63 ///64 typedef struct {65 EFI_SMM_SAVE_STATE_REGISTER Start;66 EFI_SMM_SAVE_STATE_REGISTER End;67 UINTN Length;68 } CPU_SMM_SAVE_STATE_REGISTER_RANGE;69 70 ///71 /// Structure used to build a lookup table to retrieve the widths and offsets72 /// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value73 ///74 75 #define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX 176 #define SMM_SAVE_STATE_REGISTER_IOMISC_INDEX 277 #define SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX 378 #define SMM_SAVE_STATE_REGISTER_MAX_INDEX 479 80 typedef struct {81 UINT8 Width32;82 UINT8 Width64;83 UINT16 Offset32;84 UINT16 Offset64Lo;85 UINT16 Offset64Hi;86 BOOLEAN Writeable;87 } CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;88 89 ///90 /// Structure used to build a lookup table for the IOMisc width information91 ///92 typedef struct {93 UINT8 Width;94 EFI_SMM_SAVE_STATE_IO_WIDTH IoWidth;95 } CPU_SMM_SAVE_STATE_IO_WIDTH;96 97 ///98 54 /// Variables from SMI Handler 99 55 /// … … 110 66 111 67 /// 112 /// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER113 /// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY114 ///115 CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] = {116 SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_SAVE_STATE_REGISTER_LDTINFO),117 SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES, EFI_SMM_SAVE_STATE_REGISTER_RIP),118 SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS, EFI_SMM_SAVE_STATE_REGISTER_CR4),119 { (EFI_SMM_SAVE_STATE_REGISTER)0, (EFI_SMM_SAVE_STATE_REGISTER)0, 0}120 };121 122 ///123 /// Lookup table used to retrieve the widths and offsets associated with each124 /// supported EFI_SMM_SAVE_STATE_REGISTER value125 ///126 CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] = {127 { 0, 0, 0, 0, 0, FALSE }, // Reserved128 129 //130 // Internally defined CPU Save State Registers. Not defined in PI SMM CPU Protocol.131 //132 { 4, 4, SMM_CPU_OFFSET (x86.SMMRevId), SMM_CPU_OFFSET (x64.SMMRevId), 0, FALSE }, // SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX = 1133 { 4, 4, SMM_CPU_OFFSET (x86.IOMisc), SMM_CPU_OFFSET (x64.IOMisc), 0, FALSE }, // SMM_SAVE_STATE_REGISTER_IOMISC_INDEX = 2134 { 4, 8, SMM_CPU_OFFSET (x86.IOMemAddr), SMM_CPU_OFFSET (x64.IOMemAddr), SMM_CPU_OFFSET (x64.IOMemAddr) + 4, FALSE }, // SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX = 3135 136 //137 // CPU Save State registers defined in PI SMM CPU Protocol.138 //139 { 0, 8, 0, SMM_CPU_OFFSET (x64.GdtBaseLoDword), SMM_CPU_OFFSET (x64.GdtBaseHiDword), FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_GDTBASE = 4140 { 0, 8, 0, SMM_CPU_OFFSET (x64.IdtBaseLoDword), SMM_CPU_OFFSET (x64.IdtBaseHiDword), FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_IDTBASE = 5141 { 0, 8, 0, SMM_CPU_OFFSET (x64.LdtBaseLoDword), SMM_CPU_OFFSET (x64.LdtBaseHiDword), FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_LDTBASE = 6142 { 0, 0, 0, 0, 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7143 { 0, 0, 0, 0, 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8144 { 0, 0, 0, 0, 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9145 { 0, 0, 0, 0, 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_LDTINFO = 10146 147 { 4, 4, SMM_CPU_OFFSET (x86._ES), SMM_CPU_OFFSET (x64._ES), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_ES = 20148 { 4, 4, SMM_CPU_OFFSET (x86._CS), SMM_CPU_OFFSET (x64._CS), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_CS = 21149 { 4, 4, SMM_CPU_OFFSET (x86._SS), SMM_CPU_OFFSET (x64._SS), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_SS = 22150 { 4, 4, SMM_CPU_OFFSET (x86._DS), SMM_CPU_OFFSET (x64._DS), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_DS = 23151 { 4, 4, SMM_CPU_OFFSET (x86._FS), SMM_CPU_OFFSET (x64._FS), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_FS = 24152 { 4, 4, SMM_CPU_OFFSET (x86._GS), SMM_CPU_OFFSET (x64._GS), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_GS = 25153 { 0, 4, 0, SMM_CPU_OFFSET (x64._LDTR), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26154 { 4, 4, SMM_CPU_OFFSET (x86._TR), SMM_CPU_OFFSET (x64._TR), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_TR_SEL = 27155 { 4, 8, SMM_CPU_OFFSET (x86._DR7), SMM_CPU_OFFSET (x64._DR7), SMM_CPU_OFFSET (x64._DR7) + 4, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_DR7 = 28156 { 4, 8, SMM_CPU_OFFSET (x86._DR6), SMM_CPU_OFFSET (x64._DR6), SMM_CPU_OFFSET (x64._DR6) + 4, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_DR6 = 29157 { 0, 8, 0, SMM_CPU_OFFSET (x64._R8), SMM_CPU_OFFSET (x64._R8) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R8 = 30158 { 0, 8, 0, SMM_CPU_OFFSET (x64._R9), SMM_CPU_OFFSET (x64._R9) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R9 = 31159 { 0, 8, 0, SMM_CPU_OFFSET (x64._R10), SMM_CPU_OFFSET (x64._R10) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R10 = 32160 { 0, 8, 0, SMM_CPU_OFFSET (x64._R11), SMM_CPU_OFFSET (x64._R11) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R11 = 33161 { 0, 8, 0, SMM_CPU_OFFSET (x64._R12), SMM_CPU_OFFSET (x64._R12) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R12 = 34162 { 0, 8, 0, SMM_CPU_OFFSET (x64._R13), SMM_CPU_OFFSET (x64._R13) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R13 = 35163 { 0, 8, 0, SMM_CPU_OFFSET (x64._R14), SMM_CPU_OFFSET (x64._R14) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R14 = 36164 { 0, 8, 0, SMM_CPU_OFFSET (x64._R15), SMM_CPU_OFFSET (x64._R15) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R15 = 37165 { 4, 8, SMM_CPU_OFFSET (x86._EAX), SMM_CPU_OFFSET (x64._RAX), SMM_CPU_OFFSET (x64._RAX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RAX = 38166 { 4, 8, SMM_CPU_OFFSET (x86._EBX), SMM_CPU_OFFSET (x64._RBX), SMM_CPU_OFFSET (x64._RBX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RBX = 39167 { 4, 8, SMM_CPU_OFFSET (x86._ECX), SMM_CPU_OFFSET (x64._RCX), SMM_CPU_OFFSET (x64._RCX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RCX = 40168 { 4, 8, SMM_CPU_OFFSET (x86._EDX), SMM_CPU_OFFSET (x64._RDX), SMM_CPU_OFFSET (x64._RDX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RDX = 41169 { 4, 8, SMM_CPU_OFFSET (x86._ESP), SMM_CPU_OFFSET (x64._RSP), SMM_CPU_OFFSET (x64._RSP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RSP = 42170 { 4, 8, SMM_CPU_OFFSET (x86._EBP), SMM_CPU_OFFSET (x64._RBP), SMM_CPU_OFFSET (x64._RBP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RBP = 43171 { 4, 8, SMM_CPU_OFFSET (x86._ESI), SMM_CPU_OFFSET (x64._RSI), SMM_CPU_OFFSET (x64._RSI) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RSI = 44172 { 4, 8, SMM_CPU_OFFSET (x86._EDI), SMM_CPU_OFFSET (x64._RDI), SMM_CPU_OFFSET (x64._RDI) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RDI = 45173 { 4, 8, SMM_CPU_OFFSET (x86._EIP), SMM_CPU_OFFSET (x64._RIP), SMM_CPU_OFFSET (x64._RIP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RIP = 46174 175 { 4, 8, SMM_CPU_OFFSET (x86._EFLAGS), SMM_CPU_OFFSET (x64._RFLAGS), SMM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RFLAGS = 51176 { 4, 8, SMM_CPU_OFFSET (x86._CR0), SMM_CPU_OFFSET (x64._CR0), SMM_CPU_OFFSET (x64._CR0) + 4, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_CR0 = 52177 { 4, 8, SMM_CPU_OFFSET (x86._CR3), SMM_CPU_OFFSET (x64._CR3), SMM_CPU_OFFSET (x64._CR3) + 4, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_CR3 = 53178 { 0, 4, 0, SMM_CPU_OFFSET (x64._CR4), 0, FALSE }, // EFI_SMM_SAVE_STATE_REGISTER_CR4 = 54179 };180 181 ///182 /// Lookup table for the IOMisc width information183 ///184 CONST CPU_SMM_SAVE_STATE_IO_WIDTH mSmmCpuIoWidth[] = {185 { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 0186 { 1, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // SMM_IO_LENGTH_BYTE = 1187 { 2, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16 }, // SMM_IO_LENGTH_WORD = 2188 { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 3189 { 4, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32 }, // SMM_IO_LENGTH_DWORD = 4190 { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 5191 { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 6192 { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 } // Undefined = 7193 };194 195 ///196 /// Lookup table for the IOMisc type information197 ///198 CONST EFI_SMM_SAVE_STATE_IO_TYPE mSmmCpuIoType[] = {199 EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_DX = 0200 EFI_SMM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_IN_DX = 1201 EFI_SMM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_OUTS = 2202 EFI_SMM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_INS = 3203 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 4204 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 5205 EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_OUTS = 6206 EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_INS = 7207 EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 8208 EFI_SMM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 9209 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 10210 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 11211 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 12212 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 13213 (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 14214 (EFI_SMM_SAVE_STATE_IO_TYPE)0 // Undefined = 15215 };216 217 ///218 68 /// The mode of the CPU at the time an SMI occurs 219 69 /// 220 70 UINT8 mSmmSaveStateRegisterLma; 221 222 /**223 Read information from the CPU save state.224 225 @param Register Specifies the CPU register to read form the save state.226 227 @retval 0 Register is not valid228 @retval >0 Index into mSmmCpuWidthOffset[] associated with Register229 230 **/231 UINTN232 GetRegisterIndex (233 IN EFI_SMM_SAVE_STATE_REGISTER Register234 )235 {236 UINTN Index;237 UINTN Offset;238 239 for (Index = 0, Offset = SMM_SAVE_STATE_REGISTER_MAX_INDEX; mSmmCpuRegisterRanges[Index].Length != 0; Index++) {240 if ((Register >= mSmmCpuRegisterRanges[Index].Start) && (Register <= mSmmCpuRegisterRanges[Index].End)) {241 return Register - mSmmCpuRegisterRanges[Index].Start + Offset;242 }243 244 Offset += mSmmCpuRegisterRanges[Index].Length;245 }246 247 return 0;248 }249 250 /**251 Read a CPU Save State register on the target processor.252 253 This function abstracts the differences that whether the CPU Save State register is in the254 IA32 CPU Save State Map or X64 CPU Save State Map.255 256 This function supports reading a CPU Save State register in SMBase relocation handler.257 258 @param[in] CpuIndex Specifies the zero-based index of the CPU save state.259 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.260 @param[in] Width The number of bytes to read from the CPU save state.261 @param[out] Buffer Upon return, this holds the CPU register value read from the save state.262 263 @retval EFI_SUCCESS The register was read from Save State.264 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.265 @retval EFI_INVALID_PARAMETER This or Buffer is NULL.266 267 **/268 EFI_STATUS269 ReadSaveStateRegisterByIndex (270 IN UINTN CpuIndex,271 IN UINTN RegisterIndex,272 IN UINTN Width,273 OUT VOID *Buffer274 )275 {276 SMRAM_SAVE_STATE_MAP *CpuSaveState;277 278 if (RegisterIndex == 0) {279 return EFI_NOT_FOUND;280 }281 282 CpuSaveState = gSmst->CpuSaveState[CpuIndex];283 284 if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {285 //286 // If 32-bit mode width is zero, then the specified register can not be accessed287 //288 if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {289 return EFI_NOT_FOUND;290 }291 292 //293 // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed294 //295 if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {296 return EFI_INVALID_PARAMETER;297 }298 299 //300 // Write return buffer301 //302 ASSERT (CpuSaveState != NULL);303 CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Width);304 } else {305 //306 // If 64-bit mode width is zero, then the specified register can not be accessed307 //308 if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {309 return EFI_NOT_FOUND;310 }311 312 //313 // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed314 //315 if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {316 return EFI_INVALID_PARAMETER;317 }318 319 //320 // Write at most 4 of the lower bytes of the return buffer321 //322 CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, MIN (4, Width));323 if (Width > 4) {324 //325 // Write at most 4 of the upper bytes of the return buffer326 //327 CopyMem ((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);328 }329 }330 331 return EFI_SUCCESS;332 }333 334 /**335 Read a CPU Save State register on the target processor.336 337 This function abstracts the differences that whether the CPU Save State register is in the338 IA32 CPU Save State Map or X64 CPU Save State Map.339 340 This function supports reading a CPU Save State register in SMBase relocation handler.341 342 @param[in] CpuIndex Specifies the zero-based index of the CPU save state.343 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.344 @param[in] Width The number of bytes to read from the CPU save state.345 @param[out] Buffer Upon return, this holds the CPU register value read from the save state.346 347 @retval EFI_SUCCESS The register was read from Save State.348 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.349 @retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type.350 351 **/352 EFI_STATUS353 EFIAPI354 ReadSaveStateRegister (355 IN UINTN CpuIndex,356 IN EFI_SMM_SAVE_STATE_REGISTER Register,357 IN UINTN Width,358 OUT VOID *Buffer359 )360 {361 UINT32 SmmRevId;362 SMRAM_SAVE_STATE_IOMISC IoMisc;363 EFI_SMM_SAVE_STATE_IO_INFO *IoInfo;364 365 //366 // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA367 //368 if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {369 //370 // Only byte access is supported for this register371 //372 if (Width != 1) {373 return EFI_INVALID_PARAMETER;374 }375 376 *(UINT8 *)Buffer = mSmmSaveStateRegisterLma;377 378 return EFI_SUCCESS;379 }380 381 //382 // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO383 //384 if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {385 //386 // Get SMM Revision ID387 //388 ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof (SmmRevId), &SmmRevId);389 390 //391 // See if the CPU supports the IOMisc register in the save state392 //393 if (SmmRevId < SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC) {394 return EFI_NOT_FOUND;395 }396 397 //398 // Get the IOMisc register value399 //400 ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_IOMISC_INDEX, sizeof (IoMisc.Uint32), &IoMisc.Uint32);401 402 //403 // Check for the SMI_FLAG in IOMisc404 //405 if (IoMisc.Bits.SmiFlag == 0) {406 return EFI_NOT_FOUND;407 }408 409 //410 // Only support IN/OUT, but not INS/OUTS/REP INS/REP OUTS.411 //412 if ((mSmmCpuIoType[IoMisc.Bits.Type] != EFI_SMM_SAVE_STATE_IO_TYPE_INPUT) &&413 (mSmmCpuIoType[IoMisc.Bits.Type] != EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT))414 {415 return EFI_NOT_FOUND;416 }417 418 //419 // Compute index for the I/O Length and I/O Type lookup tables420 //421 if ((mSmmCpuIoWidth[IoMisc.Bits.Length].Width == 0) || (mSmmCpuIoType[IoMisc.Bits.Type] == 0)) {422 return EFI_NOT_FOUND;423 }424 425 //426 // Make sure the incoming buffer is large enough to hold IoInfo before accessing427 //428 if (Width < sizeof (EFI_SMM_SAVE_STATE_IO_INFO)) {429 return EFI_INVALID_PARAMETER;430 }431 432 //433 // Zero the IoInfo structure that will be returned in Buffer434 //435 IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;436 ZeroMem (IoInfo, sizeof (EFI_SMM_SAVE_STATE_IO_INFO));437 438 //439 // Use lookup tables to help fill in all the fields of the IoInfo structure440 //441 IoInfo->IoPort = (UINT16)IoMisc.Bits.Port;442 IoInfo->IoWidth = mSmmCpuIoWidth[IoMisc.Bits.Length].IoWidth;443 IoInfo->IoType = mSmmCpuIoType[IoMisc.Bits.Type];444 ReadSaveStateRegister (CpuIndex, EFI_SMM_SAVE_STATE_REGISTER_RAX, mSmmCpuIoWidth[IoMisc.Bits.Length].Width, &IoInfo->IoData);445 return EFI_SUCCESS;446 }447 448 //449 // Convert Register to a register lookup table index450 //451 return ReadSaveStateRegisterByIndex (CpuIndex, GetRegisterIndex (Register), Width, Buffer);452 }453 454 /**455 Write value to a CPU Save State register on the target processor.456 457 This function abstracts the differences that whether the CPU Save State register is in the458 IA32 CPU Save State Map or X64 CPU Save State Map.459 460 This function supports writing a CPU Save State register in SMBase relocation handler.461 462 @param[in] CpuIndex Specifies the zero-based index of the CPU save state.463 @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.464 @param[in] Width The number of bytes to read from the CPU save state.465 @param[in] Buffer Upon entry, this holds the new CPU register value.466 467 @retval EFI_SUCCESS The register was written to Save State.468 @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.469 @retval EFI_INVALID_PARAMETER ProcessorIndex or Width is not correct.470 471 **/472 EFI_STATUS473 EFIAPI474 WriteSaveStateRegister (475 IN UINTN CpuIndex,476 IN EFI_SMM_SAVE_STATE_REGISTER Register,477 IN UINTN Width,478 IN CONST VOID *Buffer479 )480 {481 UINTN RegisterIndex;482 SMRAM_SAVE_STATE_MAP *CpuSaveState;483 484 //485 // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored486 //487 if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {488 return EFI_SUCCESS;489 }490 491 //492 // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported493 //494 if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {495 return EFI_NOT_FOUND;496 }497 498 //499 // Convert Register to a register lookup table index500 //501 RegisterIndex = GetRegisterIndex (Register);502 if (RegisterIndex == 0) {503 return EFI_NOT_FOUND;504 }505 506 CpuSaveState = gSmst->CpuSaveState[CpuIndex];507 508 //509 // Do not write non-writable SaveState, because it will cause exception.510 //511 if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) {512 return EFI_UNSUPPORTED;513 }514 515 //516 // Check CPU mode517 //518 if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {519 //520 // If 32-bit mode width is zero, then the specified register can not be accessed521 //522 if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {523 return EFI_NOT_FOUND;524 }525 526 //527 // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed528 //529 if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {530 return EFI_INVALID_PARAMETER;531 }532 533 //534 // Write SMM State register535 //536 ASSERT (CpuSaveState != NULL);537 CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);538 } else {539 //540 // If 64-bit mode width is zero, then the specified register can not be accessed541 //542 if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {543 return EFI_NOT_FOUND;544 }545 546 //547 // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed548 //549 if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {550 return EFI_INVALID_PARAMETER;551 }552 553 //554 // Write at most 4 of the lower bytes of SMM State register555 //556 CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));557 if (Width > 4) {558 //559 // Write at most 4 of the upper bytes of SMM State register560 //561 CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);562 }563 }564 565 return EFI_SUCCESS;566 }567 71 568 72 /** -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
r99404 r101291 2 2 Page Fault (#PF) handler for X64 processors 3 3 4 Copyright (c) 2009 - 202 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> 6 6 … … 13 13 #define PAGE_TABLE_PAGES 8 14 14 #define ACC_MAX_BIT BIT3 15 16 extern UINTN mSmmShadowStackSize;17 15 18 16 LIST_ENTRY mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool); … … 171 169 172 170 /** 173 Set static page table.174 175 @param[in] PageTable Address of page table.176 @param[in] PhysicalAddressBits The maximum physical address bits supported.177 **/178 VOID179 SetStaticPageTable (180 IN UINTN PageTable,181 IN UINT8 PhysicalAddressBits182 )183 {184 UINT64 PageAddress;185 UINTN NumberOfPml5EntriesNeeded;186 UINTN NumberOfPml4EntriesNeeded;187 UINTN NumberOfPdpEntriesNeeded;188 UINTN IndexOfPml5Entries;189 UINTN IndexOfPml4Entries;190 UINTN IndexOfPdpEntries;191 UINTN IndexOfPageDirectoryEntries;192 UINT64 *PageMapLevel5Entry;193 UINT64 *PageMapLevel4Entry;194 UINT64 *PageMap;195 UINT64 *PageDirectoryPointerEntry;196 UINT64 *PageDirectory1GEntry;197 UINT64 *PageDirectoryEntry;198 199 //200 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses201 // when 5-Level Paging is disabled.202 //203 ASSERT (PhysicalAddressBits <= 52);204 if (!m5LevelPagingNeeded && (PhysicalAddressBits > 48)) {205 PhysicalAddressBits = 48;206 }207 208 NumberOfPml5EntriesNeeded = 1;209 if (PhysicalAddressBits > 48) {210 NumberOfPml5EntriesNeeded = (UINTN)LShiftU64 (1, PhysicalAddressBits - 48);211 PhysicalAddressBits = 48;212 }213 214 NumberOfPml4EntriesNeeded = 1;215 if (PhysicalAddressBits > 39) {216 NumberOfPml4EntriesNeeded = (UINTN)LShiftU64 (1, PhysicalAddressBits - 39);217 PhysicalAddressBits = 39;218 }219 220 NumberOfPdpEntriesNeeded = 1;221 ASSERT (PhysicalAddressBits > 30);222 NumberOfPdpEntriesNeeded = (UINTN)LShiftU64 (1, PhysicalAddressBits - 30);223 224 //225 // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.226 //227 PageMap = (VOID *)PageTable;228 229 PageMapLevel4Entry = PageMap;230 PageMapLevel5Entry = NULL;231 if (m5LevelPagingNeeded) {232 //233 // By architecture only one PageMapLevel5 exists - so lets allocate storage for it.234 //235 PageMapLevel5Entry = PageMap;236 }237 238 PageAddress = 0;239 240 for ( IndexOfPml5Entries = 0241 ; IndexOfPml5Entries < NumberOfPml5EntriesNeeded242 ; IndexOfPml5Entries++, PageMapLevel5Entry++)243 {244 //245 // Each PML5 entry points to a page of PML4 entires.246 // So lets allocate space for them and fill them in in the IndexOfPml4Entries loop.247 // When 5-Level Paging is disabled, below allocation happens only once.248 //249 if (m5LevelPagingNeeded) {250 PageMapLevel4Entry = (UINT64 *)((*PageMapLevel5Entry) & ~mAddressEncMask & gPhyMask);251 if (PageMapLevel4Entry == NULL) {252 PageMapLevel4Entry = AllocatePageTableMemory (1);253 ASSERT (PageMapLevel4Entry != NULL);254 ZeroMem (PageMapLevel4Entry, EFI_PAGES_TO_SIZE (1));255 256 *PageMapLevel5Entry = (UINT64)(UINTN)PageMapLevel4Entry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;257 }258 }259 260 for (IndexOfPml4Entries = 0; IndexOfPml4Entries < (NumberOfPml5EntriesNeeded == 1 ? NumberOfPml4EntriesNeeded : 512); IndexOfPml4Entries++, PageMapLevel4Entry++) {261 //262 // Each PML4 entry points to a page of Page Directory Pointer entries.263 //264 PageDirectoryPointerEntry = (UINT64 *)((*PageMapLevel4Entry) & ~mAddressEncMask & gPhyMask);265 if (PageDirectoryPointerEntry == NULL) {266 PageDirectoryPointerEntry = AllocatePageTableMemory (1);267 ASSERT (PageDirectoryPointerEntry != NULL);268 ZeroMem (PageDirectoryPointerEntry, EFI_PAGES_TO_SIZE (1));269 270 *PageMapLevel4Entry = (UINT64)(UINTN)PageDirectoryPointerEntry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;271 }272 273 if (m1GPageTableSupport) {274 PageDirectory1GEntry = PageDirectoryPointerEntry;275 for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {276 if ((IndexOfPml4Entries == 0) && (IndexOfPageDirectoryEntries < 4)) {277 //278 // Skip the < 4G entries279 //280 continue;281 }282 283 //284 // Fill in the Page Directory entries285 //286 *PageDirectory1GEntry = PageAddress | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;287 }288 } else {289 PageAddress = BASE_4GB;290 for (IndexOfPdpEntries = 0; IndexOfPdpEntries < (NumberOfPml4EntriesNeeded == 1 ? NumberOfPdpEntriesNeeded : 512); IndexOfPdpEntries++, PageDirectoryPointerEntry++) {291 if ((IndexOfPml4Entries == 0) && (IndexOfPdpEntries < 4)) {292 //293 // Skip the < 4G entries294 //295 continue;296 }297 298 //299 // Each Directory Pointer entries points to a page of Page Directory entires.300 // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.301 //302 PageDirectoryEntry = (UINT64 *)((*PageDirectoryPointerEntry) & ~mAddressEncMask & gPhyMask);303 if (PageDirectoryEntry == NULL) {304 PageDirectoryEntry = AllocatePageTableMemory (1);305 ASSERT (PageDirectoryEntry != NULL);306 ZeroMem (PageDirectoryEntry, EFI_PAGES_TO_SIZE (1));307 308 //309 // Fill in a Page Directory Pointer Entries310 //311 *PageDirectoryPointerEntry = (UINT64)(UINTN)PageDirectoryEntry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;312 }313 314 for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {315 //316 // Fill in the Page Directory entries317 //318 *PageDirectoryEntry = PageAddress | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;319 }320 }321 }322 }323 }324 }325 326 /**327 171 Create PageTable for SMM use. 328 172 … … 335 179 ) 336 180 { 337 EFI_PHYSICAL_ADDRESS Pages; 338 UINT64 *PTEntry; 181 UINTN PageTable; 339 182 LIST_ENTRY *FreePage; 340 183 UINTN Index; … … 342 185 IA32_IDT_GATE_DESCRIPTOR *IdtEntry; 343 186 EFI_STATUS Status; 187 UINT64 *PdptEntry; 344 188 UINT64 *Pml4Entry; 345 189 UINT64 *Pml5Entry; 190 UINT8 PhysicalAddressBits; 346 191 347 192 // … … 355 200 mPhysicalAddressBits = CalculateMaximumSupportAddress (); 356 201 PatchInstructionX86 (gPatch5LevelPagingNeeded, m5LevelPagingNeeded, 1); 202 if (m5LevelPagingNeeded) { 203 mPagingMode = m1GPageTableSupport ? Paging5Level1GB : Paging5Level; 204 } else { 205 mPagingMode = m1GPageTableSupport ? Paging4Level1GB : Paging4Level; 206 } 207 357 208 DEBUG ((DEBUG_INFO, "5LevelPaging Needed - %d\n", m5LevelPagingNeeded)); 358 209 DEBUG ((DEBUG_INFO, "1GPageTable Support - %d\n", m1GPageTableSupport)); 359 210 DEBUG ((DEBUG_INFO, "PcdCpuSmmRestrictedMemoryAccess - %d\n", mCpuSmmRestrictedMemoryAccess)); 360 211 DEBUG ((DEBUG_INFO, "PhysicalAddressBits - %d\n", mPhysicalAddressBits)); 361 // 362 // Generate PAE page table for the first 4GB memory space 363 // 364 Pages = Gen4GPageTable (FALSE); 365 366 // 367 // Set IA32_PG_PMNT bit to mask this entry 368 // 369 PTEntry = (UINT64 *)(UINTN)Pages; 212 213 // 214 // Generate initial SMM page table. 215 // Only map [0, 4G] when PcdCpuSmmRestrictedMemoryAccess is FALSE. 216 // 217 PhysicalAddressBits = mCpuSmmRestrictedMemoryAccess ? mPhysicalAddressBits : 32; 218 PageTable = GenSmmPageTable (mPagingMode, PhysicalAddressBits); 219 220 if (m5LevelPagingNeeded) { 221 Pml5Entry = (UINT64 *)PageTable; 222 // 223 // Set Pml5Entry sub-entries number for smm PF handler usage. 224 // 225 SetSubEntriesNum (Pml5Entry, 1); 226 Pml4Entry = (UINT64 *)((*Pml5Entry) & ~mAddressEncMask & gPhyMask); 227 } else { 228 Pml4Entry = (UINT64 *)PageTable; 229 } 230 231 // 232 // Set IA32_PG_PMNT bit to mask first 4 PdptEntry. 233 // 234 PdptEntry = (UINT64 *)((*Pml4Entry) & ~mAddressEncMask & gPhyMask); 370 235 for (Index = 0; Index < 4; Index++) { 371 PTEntry[Index] |= IA32_PG_PMNT; 372 } 373 374 // 375 // Fill Page-Table-Level4 (PML4) entry 376 // 377 Pml4Entry = (UINT64 *)AllocatePageTableMemory (1); 378 ASSERT (Pml4Entry != NULL); 379 *Pml4Entry = Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS; 380 ZeroMem (Pml4Entry + 1, EFI_PAGE_SIZE - sizeof (*Pml4Entry)); 381 382 // 383 // Set sub-entries number 384 // 385 SetSubEntriesNum (Pml4Entry, 3); 386 PTEntry = Pml4Entry; 387 388 if (m5LevelPagingNeeded) { 389 // 390 // Fill PML5 entry 391 // 392 Pml5Entry = (UINT64 *)AllocatePageTableMemory (1); 393 ASSERT (Pml5Entry != NULL); 394 *Pml5Entry = (UINTN)Pml4Entry | mAddressEncMask | PAGE_ATTRIBUTE_BITS; 395 ZeroMem (Pml5Entry + 1, EFI_PAGE_SIZE - sizeof (*Pml5Entry)); 396 // 397 // Set sub-entries number 398 // 399 SetSubEntriesNum (Pml5Entry, 1); 400 PTEntry = Pml5Entry; 401 } 402 403 if (mCpuSmmRestrictedMemoryAccess) { 404 // 405 // When access to non-SMRAM memory is restricted, create page table 406 // that covers all memory space. 407 // 408 SetStaticPageTable ((UINTN)PTEntry, mPhysicalAddressBits); 409 } else { 236 PdptEntry[Index] |= IA32_PG_PMNT; 237 } 238 239 if (!mCpuSmmRestrictedMemoryAccess) { 240 // 241 // Set Pml4Entry sub-entries number for smm PF handler usage. 242 // 243 SetSubEntriesNum (Pml4Entry, 3); 244 410 245 // 411 246 // Add pages to page pool … … 464 299 // Return the address of PML4/PML5 (to set CR3) 465 300 // 466 return (UINT32) (UINTN)PTEntry;301 return (UINT32)PageTable; 467 302 } 468 303 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
r99404 r101291 2 2 SMM CPU misc functions for x64 arch specific. 3 3 4 Copyright (c) 2015 - 20 19, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR> 5 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 6 … … 13 13 14 14 extern BOOLEAN mCetSupported; 15 extern UINTN mSmmShadowStackSize;16 15 17 16 X86_ASSEMBLY_PATCH_LABEL mPatchCetPl0Ssp; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c
r99404 r101291 36 36 ) 37 37 { 38 EFI_PHYSICAL_ADDRESS Pages; 39 UINT64 *PTEntry; 40 41 // 42 // Generate PAE page table for the first 4GB memory space 43 // 44 Pages = Gen4GPageTable (FALSE); 45 46 // 47 // Fill Page-Table-Level4 (PML4) entry 48 // 49 PTEntry = (UINT64 *)AllocatePageTableMemory (1); 50 ASSERT (PTEntry != NULL); 51 *PTEntry = Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS; 52 ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry)); 53 54 // 38 // 39 // Generate level4 page table for the first 4GB memory space 55 40 // Return the address of PML4 (to set CR3) 56 41 // 57 mSmmS3ResumeState->SmmS3Cr3 = (UINT32)(UINTN)PTEntry; 42 // 43 // The SmmS3Cr3 is only used by S3Resume PEIM to switch CPU from 32bit to 64bit 44 // 45 mSmmS3ResumeState->SmmS3Cr3 = (UINT32)GenSmmPageTable (Paging4Level, 32); 58 46 59 47 return; -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm
r80721 r101291 3 3 ; Sets the CR3 register for 64-bit paging 4 4 ; 5 ; Copyright (c) 2008 - 20 13, Intel Corporation. All rights reserved.<BR>5 ; Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR> 6 6 ; SPDX-License-Identifier: BSD-2-Clause-Patent 7 7 ; … … 18 18 ; These pages are built into the ROM image in X64/PageTables.asm 19 19 ; 20 mov eax, ADDR_OF(TopLevelPageDirectory) 20 %ifdef USE_5_LEVEL_PAGE_TABLE 21 mov eax, 0 22 cpuid 23 cmp eax, 07h ; check if basic CPUID leaf contains leaf 07 24 jb NotSupport5LevelPaging ; 5level paging not support, downgrade to 4level paging 25 mov eax, 07h ; check cpuid leaf 7, subleaf 0 26 mov ecx, 0 27 cpuid 28 bt ecx, 16 ; [Bits 16] Supports 5-level paging if 1. 29 jnc NotSupport5LevelPaging ; 5level paging not support, downgrade to 4level paging 30 mov eax, ADDR_OF(Pml5) 21 31 mov cr3, eax 32 mov eax, cr4 33 bts eax, 12 ; Set LA57=1. 34 mov cr4, eax 35 jmp SetCr3Done 36 NotSupport5LevelPaging: 37 %endif 38 39 mov eax, ADDR_OF(Pml4) 40 mov cr3, eax 41 SetCr3Done: 22 42 23 43 OneTimeCallRet SetCr3ForPageTables64 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/ReadMe.txt
r99404 r101291 1 1 2 2 === HOW TO USE VTF0 === 3 Add this line to your DSC [Components.IA32] or [Components.X64] section: 4 UefiCpuPkg/ResetVector/Vtf0/ResetVector.inf 3 5 4 6 Add this line to your FDF FV section: 5 INF RuleOverride=RESET_VECTOR USE = IA32 UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf 6 (For X64 SEC/PEI change IA32 to X64 => 'USE = X64') 7 INF RuleOverride=RESET_VECTOR UefiCpuPkg/ResetVector/Vtf0/ResetVector.inf 7 8 8 9 In your FDF FFS file rules sections add: 9 [Rule.Common.SEC.RESET_VECTOR]10 FILE RAW = $(NAMED_GUID) {11 RAW RAW |.raw12 }10 [Rule.Common.SEC.RESET_VECTOR] 11 FILE RAW = $(NAMED_GUID) { 12 RAW BIN |.bin 13 } 13 14 14 15 === VTF0 Boot Flow === … … 26 27 DI - 'BP': boot-strap processor, or 'AP': application processor 27 28 EBP/RBP - Pointer to the start of the Boot Firmware Volume 28 29 === HOW TO BUILD VTF0 ===30 31 Dependencies:32 * Python 3 or newer33 * Nasm 2.03 or newer34 35 To rebuild the VTF0 binaries:36 1. Change to VTF0 source dir: UefiCpuPkg/ResetVector/Vtf037 2. nasm and python should be in executable path38 3. Run this command:39 python Build.py40 4. Binaries output will be in UefiCpuPkg/ResetVector/Vtf0/Bin41 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf
r80721 r101291 2 2 # Reset Vector 3 3 # 4 # Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 4 # Note: 5 # Conf/build_rule.txt contains the build rule [Nasm-to-Binary-Code-File] 6 # to generate .bin file from .nasmb source. 7 # 8 # The platform FDF MUST have a FDF rule as follows to build the .bin 9 # file as ResetVector .ffs file: 10 # 11 # [Rule.Common.SEC.RESET_VECTOR] 12 # FILE RAW = $(NAMED_GUID) { 13 # RAW BIN |.bin 14 # } 15 # 16 # Following line in FDF forces to use the above rule for the ResetVector: 17 # 18 # INF RuleOverride=RESET_VECTOR UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf 19 # 20 # 21 # Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR> 5 22 # 6 23 # SPDX-License-Identifier: BSD-2-Clause-Patent … … 30 47 [UserExtensions.TianoCore."ExtraFiles"] 31 48 ResetVectorExtra.uni 49 50 [BuildOptions] 51 # Different build options can be specified: 52 # * for different architectures: 53 # -DARCH_X64, -DARCH_IA32 54 # * for using 1G page table: 55 # -DPAGE_TABLE_1G 56 # * for different debug channels: 57 # -DDEBUG_SERIAL, -DDEBUG_PORT80, or not specify any debug channel -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb
r99404 r101291 3 3 ; This file includes all other code files to assemble the reset vector code 4 4 ; 5 ; Copyright (c) 2008 - 20 13, Intel Corporation. All rights reserved.<BR>5 ; Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR> 6 6 ; SPDX-License-Identifier: BSD-2-Clause-Patent 7 7 ; … … 39 39 40 40 %ifdef ARCH_X64 41 %ifdef PAGE_TABLE_1G 42 %include "X64/PageTables1G.asm" 43 %else 44 %include "X64/PageTables2M.asm" 45 %endif 41 %include "X64/PageTables.asm" 46 42 %endif 47 43 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecCore.inf
r99404 r101291 49 49 DebugAgentLib 50 50 CpuLib 51 UefiCpuLib52 51 PeCoffGetEntryPointLib 53 52 PeCoffExtraActionLib … … 57 56 PeiServicesTablePointerLib 58 57 HobLib 58 CpuPageTableLib 59 59 60 60 [Ppis] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecCoreNative.inf
r99404 r101291 46 46 DebugAgentLib 47 47 CpuLib 48 UefiCpuLib49 48 PeCoffGetEntryPointLib 50 49 PeCoffExtraActionLib … … 54 53 PeiServicesTablePointerLib 55 54 HobLib 55 CpuPageTableLib 56 56 57 57 [Ppis] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecMain.c
r99404 r101291 71 71 72 72 return EFI_SUCCESS; 73 } 74 75 /** 76 Migrate page table to permanent memory mapping entire physical address space. 77 78 @retval EFI_SUCCESS The PageTable was migrated successfully. 79 @retval EFI_UNSUPPORTED Unsupport to migrate page table to permanent memory if IA-32e Mode not actived. 80 @retval EFI_OUT_OF_RESOURCES The PageTable could not be migrated due to lack of available memory. 81 82 **/ 83 EFI_STATUS 84 MigratePageTable ( 85 VOID 86 ) 87 { 88 EFI_STATUS Status; 89 IA32_CR4 Cr4; 90 BOOLEAN Page5LevelSupport; 91 UINT32 RegEax; 92 CPUID_EXTENDED_CPU_SIG_EDX RegEdx; 93 BOOLEAN Page1GSupport; 94 PAGING_MODE PagingMode; 95 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; 96 UINT32 MaxExtendedFunctionId; 97 UINTN PageTable; 98 EFI_PHYSICAL_ADDRESS Buffer; 99 UINTN BufferSize; 100 IA32_MAP_ATTRIBUTE MapAttribute; 101 IA32_MAP_ATTRIBUTE MapMask; 102 103 VirPhyAddressSize.Uint32 = 0; 104 PageTable = 0; 105 BufferSize = 0; 106 MapAttribute.Uint64 = 0; 107 MapMask.Uint64 = MAX_UINT64; 108 MapAttribute.Bits.Present = 1; 109 MapAttribute.Bits.ReadWrite = 1; 110 111 // 112 // Check Page5Level Support or not. 113 // 114 Cr4.UintN = AsmReadCr4 (); 115 Page5LevelSupport = (Cr4.Bits.LA57 ? TRUE : FALSE); 116 117 // 118 // Check Page1G Support or not. 119 // 120 Page1GSupport = FALSE; 121 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); 122 if (RegEax >= CPUID_EXTENDED_CPU_SIG) { 123 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx.Uint32); 124 if (RegEdx.Bits.Page1GB != 0) { 125 Page1GSupport = TRUE; 126 } 127 } 128 129 // 130 // Decide Paging Mode according Page5LevelSupport & Page1GSupport. 131 // 132 if (Page5LevelSupport) { 133 PagingMode = Page1GSupport ? Paging5Level1GB : Paging5Level; 134 } else { 135 PagingMode = Page1GSupport ? Paging4Level1GB : Paging4Level; 136 } 137 138 // 139 // Get Maximum Physical Address Bits 140 // Get the number of address lines; Maximum Physical Address is 2^PhysicalAddressBits - 1. 141 // If CPUID does not supported, then use a max value of 36 as per SDM 3A, 4.1.4. 142 // 143 AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunctionId, NULL, NULL, NULL); 144 if (MaxExtendedFunctionId >= CPUID_VIR_PHY_ADDRESS_SIZE) { 145 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL); 146 } else { 147 VirPhyAddressSize.Bits.PhysicalAddressBits = 36; 148 } 149 150 if ((PagingMode == Paging4Level1GB) || (PagingMode == Paging4Level)) { 151 // 152 // The max lineaddress bits is 48 for 4 level page table. 153 // 154 VirPhyAddressSize.Bits.PhysicalAddressBits = MIN (VirPhyAddressSize.Bits.PhysicalAddressBits, 48); 155 } 156 157 // 158 // Get required buffer size for the pagetable that will be created. 159 // 160 Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, 0, LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits), &MapAttribute, &MapMask, NULL); 161 ASSERT (Status == EFI_BUFFER_TOO_SMALL); 162 if (Status != EFI_BUFFER_TOO_SMALL) { 163 return Status; 164 } 165 166 // 167 // Allocate required Buffer. 168 // 169 Status = PeiServicesAllocatePages ( 170 EfiBootServicesData, 171 EFI_SIZE_TO_PAGES (BufferSize), 172 &Buffer 173 ); 174 if (EFI_ERROR (Status)) { 175 return EFI_OUT_OF_RESOURCES; 176 } 177 178 // 179 // Create PageTable in permanent memory. 180 // 181 Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, 0, LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits), &MapAttribute, &MapMask, NULL); 182 ASSERT_EFI_ERROR (Status); 183 if (EFI_ERROR (Status) || (PageTable == 0)) { 184 return EFI_OUT_OF_RESOURCES; 185 } 186 187 // 188 // Write the Pagetable to CR3. 189 // 190 AsmWriteCr3 (PageTable); 191 192 DEBUG (( 193 DEBUG_INFO, 194 "MigratePageTable: Created PageTable = 0x%lx, BufferSize = %x, PagingMode = 0x%lx, Support Max Physical Address Bits = %d\n", 195 PageTable, 196 BufferSize, 197 (UINTN)PagingMode, 198 VirPhyAddressSize.Bits.PhysicalAddressBits 199 )); 200 201 return Status; 73 202 } 74 203 … … 171 300 DEBUG_INFO, 172 301 "%a() TempRAM Base: 0x%x, TempRAM Size: 0x%x, BootFirmwareVolume 0x%x\n", 173 __ FUNCTION__,302 __func__, 174 303 TempRamBase, 175 304 SizeOfRam, … … 243 372 DEBUG_INFO, 244 373 "%a() BFV Base: 0x%x, BFV Size: 0x%x, TempRAM Base: 0x%x, TempRAM Size: 0x%x, PeiTempRamBase: 0x%x, PeiTempRamSize: 0x%x, StackBase: 0x%x, StackSize: 0x%x\n", 245 __ FUNCTION__,374 __func__, 246 375 SecCoreData.BootFirmwareVolumeBase, 247 376 SecCoreData.BootFirmwareVolumeSize, … … 346 475 DEBUG_INFO, 347 476 "%a() PeiCoreEntryPoint: 0x%x\n", 348 __ FUNCTION__,477 __func__, 349 478 PeiCoreEntryPoint 350 479 )); … … 395 524 DEBUG_INFO, 396 525 "%a() PeiTemporaryRamBase: 0x%x, PeiTemporaryRamSize: 0x%x\n", 397 __ FUNCTION__,526 __func__, 398 527 SecCoreData->PeiTemporaryRamBase, 399 528 SecCoreData->PeiTemporaryRamSize … … 409 538 DEBUG_INFO, 410 539 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n", 411 __ FUNCTION__,540 __func__, 412 541 SecCoreData->StackBase, 413 542 (UINT32)SecCoreData->StackSize … … 454 583 EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor; 455 584 REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi; 585 IA32_CR0 Cr0; 456 586 457 587 // … … 496 626 497 627 // 628 // Migrate page table to permanent memory mapping entire physical address space if CR0.PG is set. 629 // 630 Cr0.UintN = AsmReadCr0 (); 631 if (Cr0.Bits.PG != 0) { 632 // 633 // Assume CPU runs in 64bit mode if paging is enabled. 634 // 635 ASSERT (sizeof (UINTN) == sizeof (UINT64)); 636 637 Status = MigratePageTable (); 638 if (EFI_ERROR (Status)) { 639 DEBUG ((DEBUG_ERROR, "SecTemporaryRamDone: Failed to migrate page table to permanent memory: %r.\n", Status)); 640 CpuDeadLoop (); 641 } 642 } 643 644 // 498 645 // Disable Temporary RAM after Stack and Heap have been migrated at this point. 499 646 // -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecMain.h
r99404 r101291 20 20 #include <Guid/FirmwarePerformance.h> 21 21 22 #include <Library/BaseLib.h> 22 23 #include <Library/DebugLib.h> 23 24 #include <Library/PcdLib.h> … … 25 26 #include <Library/PlatformSecLib.h> 26 27 #include <Library/CpuLib.h> 27 #include <Library/UefiCpuLib.h>28 28 #include <Library/PeCoffGetEntryPointLib.h> 29 29 #include <Library/PeCoffExtraActionLib.h> … … 34 34 #include <Library/HobLib.h> 35 35 #include <Library/PeiServicesLib.h> 36 #include <Library/CpuPageTableLib.h> 37 #include <Register/Intel/Cpuid.h> 38 #include <Register/Intel/Msr.h> 36 39 37 40 #define SEC_IDT_ENTRY_COUNT 34 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
r99404 r101291 46 46 Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber); 47 47 UT_ASSERT_NOT_EFI_ERROR (Status); 48 DEBUG ((DEBUG_INFO, "%a: BspNumber = 0x%x\n", __ FUNCTION__, BspNumber));48 DEBUG ((DEBUG_INFO, "%a: BspNumber = 0x%x\n", __func__, BspNumber)); 49 49 50 50 Status = MpServicesUnitTestGetNumberOfProcessors ( … … 57 57 DEBUG_INFO, 58 58 "%a: NumberOfProcessors = 0x%x, NumberOfEnabledProcessors = 0x%x\n", 59 __ FUNCTION__,59 __func__, 60 60 NumberOfProcessors, 61 61 NumberOfEnabledProcessors … … 90 90 IndexOfDisabledAPs++; 91 91 92 DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled and temporarily enable it.\n", __ FUNCTION__, ProcessorNumber));92 DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled and temporarily enable it.\n", __func__, ProcessorNumber)); 93 93 Status = MpServicesUnitTestEnableDisableAP ( 94 94 LocalContext->MpServices, … … 135 135 if (BspNumber != LocalContext->BspNumber) { 136 136 LocalContext->BspNumber = BspNumber; 137 DEBUG ((DEBUG_INFO, "%a: New BspNumber = 0x%x\n", __ FUNCTION__, BspNumber));137 DEBUG ((DEBUG_INFO, "%a: New BspNumber = 0x%x\n", __func__, BspNumber)); 138 138 } 139 139 … … 149 149 if (NumberOfProcessors != LocalContext->NumberOfProcessors) { 150 150 LocalContext->NumberOfProcessors = NumberOfProcessors; 151 DEBUG ((DEBUG_INFO, "%a: New NumberOfProcessors = 0x%x\n", __ FUNCTION__, NumberOfProcessors));151 DEBUG ((DEBUG_INFO, "%a: New NumberOfProcessors = 0x%x\n", __func__, NumberOfProcessors)); 152 152 } 153 153 154 154 if (NumberOfEnabledProcessors != LocalContext->NumberOfProcessors) { 155 DEBUG ((DEBUG_INFO, "%a: New NumberOfEnabledProcessors = 0x%x\n", __ FUNCTION__, NumberOfEnabledProcessors));155 DEBUG ((DEBUG_INFO, "%a: New NumberOfEnabledProcessors = 0x%x\n", __func__, NumberOfEnabledProcessors)); 156 156 157 157 for (ProcessorNumber = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) { … … 164 164 165 165 if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) { 166 DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled unexpectedly and reenable it.\n", __ FUNCTION__, ProcessorNumber));166 DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled unexpectedly and reenable it.\n", __func__, ProcessorNumber)); 167 167 Status = MpServicesUnitTestEnableDisableAP ( 168 168 LocalContext->MpServices, … … 205 205 DEBUG_INFO, 206 206 "%a: Disable AP(0x%x) to restore its state.\n", 207 __ FUNCTION__,207 __func__, 208 208 LocalContext->DisabledApNumber[IndexOfDisabledAPs] 209 209 )); -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/UefiCpuPkg.dec
r99404 r101291 2 2 # This Package provides UEFI compatible CPU modules and libraries. 3 3 # 4 # Copyright (c) 2007 - 2022, Intel Corporation. All rights reserved.<BR> 4 # Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved.<BR> 5 # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> 5 6 # 6 7 # SPDX-License-Identifier: BSD-2-Clause-Patent … … 19 20 20 21 [LibraryClasses] 21 ## @libraryclass Defines some routines that are generic for IA32 family CPU22 ## to be UEFI specification compliant.23 ##24 UefiCpuLib|Include/Library/UefiCpuLib.h25 26 22 ## @libraryclass Defines some routines that are used to register/manage/program 27 23 ## CPU features. … … 65 61 ## @libraryclass Provides function for manipulating x86 paging structures. 66 62 CpuPageTableLib|Include/Library/CpuPageTableLib.h 63 64 ## @libraryclass Provides functions for manipulating smram savestate registers. 65 MmSaveStateLib|Include/Library/MmSaveStateLib.h 66 67 [LibraryClasses.RISCV64] 68 ## @libraryclass Provides functions to manage MMU features on RISCV64 CPUs. 69 ## 70 RiscVMmuLib|Include/Library/BaseRiscVMmuLib.h 67 71 68 72 [Guids] … … 78 82 ## Include/Guid/MicrocodePatchHob.h 79 83 gEdkiiMicrocodePatchHobGuid = { 0xd178f11d, 0x8716, 0x418e, { 0xa1, 0x31, 0x96, 0x7d, 0x2a, 0xc4, 0x28, 0x43 }} 84 85 ## Include/Guid/SmmBaseHob.h 86 gSmmBaseHobGuid = { 0xc2217ba7, 0x03bb, 0x4f63, {0xa6, 0x47, 0x7c, 0x25, 0xc5, 0xfc, 0x9d, 0x73 }} 80 87 81 88 [Protocols] … … 178 185 gUefiCpuPkgTokenSpaceGuid.PcdSmmFeatureControlEnable|TRUE|BOOLEAN|0x32132110 179 186 187 ## Indicates if SMM perf logging in APs will be enabled.<BR><BR> 188 # TRUE - SMM perf logging in APs will be enabled.<BR> 189 # FALSE - SMM perf logging in APs will not be enabled.<BR> 190 # @Prompt Enable SMM perf logging in APs. 191 gUefiCpuPkgTokenSpaceGuid.PcdSmmApPerfLogEnable|TRUE|BOOLEAN|0x32132114 192 180 193 [PcdsFixedAtBuild] 181 194 ## List of exception vectors which need switching stack. … … 201 214 # @Prompt Configure the SEV-ES work area base 202 215 gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize|0x0|UINT32|0x30002006 216 217 ## Determining APs' first-time wakeup by SIPI or INIT-SIPI-SIPI. 218 # Following a power-up or RESET of an MP system, The APs complete a 219 # minimal self-configuration, then wait for a startup signal (a SIPI 220 # message) from the BSP processor. 221 # 222 # TRUE - Broadcast SIPI. 223 # FALSE - Broadcast INIT-SIPI-SIPI. 224 # 225 # @Prompt BSP Broadcast Method for the first-time wakeup of APs 226 gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|TRUE|BOOLEAN|0x30002007 203 227 204 228 [PcdsFixedAtBuild, PcdsPatchableInModule] … … 341 365 gUefiCpuPkgTokenSpaceGuid.PcdIsPowerOnReset|FALSE|BOOLEAN|0x0000001B 342 366 367 ## This PCD indicates whether CPU processor trace is enabled on BSP only when CPU processor trace is enabled.<BR><BR> 368 # This PCD is ignored if CPU processor trace is disabled.<BR><BR> 369 # TRUE - CPU processor trace is enabled on BSP only.<BR> 370 # FASLE - CPU processor trace is enabled on all CPU.<BR> 371 # @Prompt Enable CPU processor trace only on BSP. 372 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceBspOnly|FALSE|BOOLEAN|0x60000019 373 374 ## This PCD indicates if enable performance collecting when CPU processor trace is enabled.<BR><BR> 375 # CYC/TSC timing packets will be generated to collect performance data if this PCD is TRUE. 376 # This PCD is ignored if CPU processor trace is disabled.<BR><BR> 377 # TRUE - Performance collecting will be enabled in processor trace.<BR> 378 # FASLE - Performance collecting will be disabled in processor trace.<BR> 379 # @Prompt Enable performance collecting when processor trace is enabled. 380 gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTracePerformanceCollecting|FALSE|BOOLEAN|0x60000020 381 343 382 [PcdsFixedAtBuild.X64, PcdsPatchableInModule.X64, PcdsDynamic.X64, PcdsDynamicEx.X64] 344 383 ## Indicate access to non-SMRAM memory is restricted to reserved, runtime and ACPI NVS type after SmmReadyToLock. -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/UefiCpuPkg.dsc
r99404 r101291 2 2 # UefiCpuPkg Package 3 3 # 4 # Copyright (c) 2007 - 2022, Intel Corporation. All rights reserved.<BR> 4 # Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved.<BR> 5 # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> 5 6 # 6 7 # SPDX-License-Identifier: BSD-2-Clause-Patent … … 32 33 DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf 33 34 DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf 34 UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf35 35 IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf 36 36 MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf … … 70 70 [LibraryClasses.common.SEC] 71 71 PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf 72 !if $(TOOL_CHAIN_TAG) == "XCODE5"73 CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf74 !else75 72 CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf 76 !endif77 73 HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf 78 74 PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf … … 105 101 HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf 106 102 CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf 103 MmSaveStateLib|UefiCpuPkg/Library/MmSaveStateLib/IntelMmSaveStateLib.inf 107 104 108 105 [LibraryClasses.common.MM_STANDALONE] … … 141 138 UefiCpuPkg/CpuMpPei/CpuMpPei.inf 142 139 UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf 143 UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf144 140 UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf 145 141 UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf 146 142 UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf 147 143 UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf 148 !if $(TOOL_CHAIN_TAG) != "XCODE5"149 144 UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf 150 !endif151 145 UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf 152 146 UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf 153 UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf154 147 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf 155 148 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf … … 177 170 SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf 178 171 } 172 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf { 173 <Defines> 174 FILE_GUID = B7242C74-BD21-49EE-84B4-07162E8C080D 175 <LibraryClasses> 176 SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf 177 MmSaveStateLib|UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf 178 } 179 179 UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf 180 UefiCpuPkg/ResetVector/Vtf0/ Bin/ResetVector.inf180 UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf 181 181 UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf 182 182 UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf … … 192 192 UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.inf 193 193 } 194 UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf 195 UefiCpuPkg/Library/MmSaveStateLib/IntelMmSaveStateLib.inf 196 UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf 194 197 195 198 [Components.X64] … … 199 202 UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/BaseRiscV64CpuExceptionHandlerLib.inf 200 203 UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf 204 UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf 201 205 UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf 202 206 UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf -
trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
r99404 r101291 510 510 DEBUG_INFO, 511 511 "%a() Stack Base: 0x%x, Stack Size: 0x%x\n", 512 __ FUNCTION__,512 __func__, 513 513 TempStackTop, 514 514 sizeof (TempStack)
Note:
See TracChangeset
for help on using the changeset viewer.